From a562f5ced1c61d2ac3854a17d193beda4d64b5e1 Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Fri, 30 Jun 2017 13:35:09 +0200 Subject: [PATCH] [FIX] account: fix the broken reconciliation widget Lot of features were not working and this commit fixes that - Create entries upon reconciliation - Add buttons at the end of the process to view/close bank statement - Fix partial reconcile - When changing partner, correctly fetch counterpart account and fix search domain - Add ability to reconcile without choosing a line (will automatically create a line) - some other small fixes --- .../account/models/account_bank_statement.py | 5 +- .../reconciliation/reconciliation_action.js | 23 ++++- .../js/reconciliation/reconciliation_model.js | 97 ++++++++++++++++--- .../reconciliation/reconciliation_renderer.js | 65 +++++++++++-- .../static/src/xml/account_reconciliation.xml | 10 ++ .../static/tests/reconciliation_tests.js | 64 +++++++++--- 6 files changed, 222 insertions(+), 42 deletions(-) diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 5113ac05963..dc1678c92e9 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -335,6 +335,7 @@ class AccountBankStatement(models.Model): 'st_lines_ids': st_lines_left.ids, 'notifications': [], 'statement_name': len(statements) == 1 and statements[0].name or False, + 'journal_id': statements and statements[0].journal_id.id or False, 'num_already_reconciled_lines': 0, } @@ -470,7 +471,7 @@ class AccountBankStatementLine(models.Model): 'details': { 'name': _("Automatically reconciled items"), 'model': 'account.move', - 'ids': automatic_reconciliation_entries.mapped('journal_entry_ids').ids + 'ids': automatic_reconciliation_entries.mapped('journal_entry_ids').mapped('move_id').ids } }] return { @@ -586,7 +587,7 @@ class AccountBankStatementLine(models.Model): if str: str_domain = self.env['account.move.line'].domain_move_lines_for_reconciliation(str=str) if not partner_id: - str_domain = expression.OR([str_domain, ('partner_id.name', 'ilike', str)]) + str_domain = expression.OR([str_domain, [('partner_id.name', 'ilike', str)]]) domain = expression.AND([domain, str_domain]) if excluded_ids: domain = expression.AND([[('id', 'not in', excluded_ids)], domain]) diff --git a/addons/account/static/src/js/reconciliation/reconciliation_action.js b/addons/account/static/src/js/reconciliation/reconciliation_action.js index b2c79471929..51175be7794 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_action.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_action.js @@ -29,6 +29,7 @@ var StatementAction = Widget.extend(ControlPanelMixin, { validate: '_onValidate', validate_all_balanced: '_onValidate', change_name: '_onChangeName', + close_statement: '_onCloseStatement', }, config: { // used to instanciate the model @@ -202,7 +203,26 @@ var StatementAction = Widget.extend(ControlPanelMixin, { }); }); }, - + /** + * call 'closeStatement' model method + * + * @private + * @param {OdooEvent} event + */ + _onCloseStatement: function (event) { + var self = this; + return this.model.closeStatement().then(function (result) { + self.do_action({ + name: 'Bank Statements', + res_model: 'account.bank.statement', + res_id: result, + views: [[false, 'form']], + type: 'ir.actions.act_window', + view_type: 'form', + view_mode: 'form', + }); + }); + }, /** * call 'validate' or 'autoReconciliation' model method then destroy the * validated lines and update the action renderer with the new status bar @@ -222,6 +242,7 @@ var StatementAction = Widget.extend(ControlPanelMixin, { 'title': self.title, 'time': Date.now()-self.time, 'notifications': result.notifications, + 'context': self.model.getContext(), }); _.each(result.handles, function (handle) { self._getWidget(handle).destroy(); diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index 11e4f4bb55f..e12f8f21009 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -230,11 +230,31 @@ var StatementModel = BasicModel.extend({ var line = this.getLine(handle); line.st_line.partner_id = partner && partner.id; line.st_line.partner_name = partner && partner.display_name || ''; - return this._performMoveLine(handle).then(function () { - if (line.mode === 'create') { - return self.createProposition(handle); - } - }); + return this._changePartner(handle, partner.id) + .then(function() { + line.reconciliation_proposition = []; + return self._performMoveLine(handle) + }) + .then(function () { + if (line.mode === 'create') { + return self.createProposition(handle); + } + }); + }, + /** + * close the statement + * @returns {Deferred} resolves to the res_id of the closed statements + */ + closeStatement: function () { + var self = this; + return this._rpc({ + model: 'account.bank.statement', + method: 'button_confirm_bank', + args: [self.bank_statement_id.id], + }) + .then(function () { + return self.bank_statement_id.id + }); }, /** * @@ -256,6 +276,13 @@ var StatementModel = BasicModel.extend({ line.createForm = _.pick(prop, this.quickCreateFields); return this._computeLine(line); }, + /** + * Return context information and journal_id + * @returns {Object} context + */ + getContext: function () { + return this.context; + }, /** * get the line data for this handle * @@ -282,6 +309,8 @@ var StatementModel = BasicModel.extend({ if (!statement_ids) { return $.when(); } + this.context = context; + var def_statement = this._rpc({ model: 'account.bank.statement', method: 'reconciliation_widget_preprocess', @@ -292,6 +321,7 @@ var StatementModel = BasicModel.extend({ self.bank_statement_id = statement_ids.length === 1 ? {id: statement_ids[0], display_name: statement.statement_name} : false; self.valuenow = 0; self.valuemax = statement.st_lines_ids.length; + self.context.journal_id = statement.journal_id; _.each(statement.st_lines_ids, function (id) { self.lines[_.uniqueId('rline')] = { 'id': id, @@ -484,14 +514,19 @@ var StatementModel = BasicModel.extend({ _.each(handles, function (handle) { var line = self.getLine(handle); var props = _.filter(line.reconciliation_proposition, function (prop) {return !prop.is_tax && !prop.invalid;}); + if (props.length === 0) { + props.push(self._formatQuickCreate(line, { + account_id: [line.st_line.open_balance_account_id, self.accounts[line.st_line.open_balance_account_id]], + })); + } ids.push(line.id); values.push({ "partner_id": line.st_line.partner_id, "counterpart_aml_dicts": _.map(_.filter(props, function (prop) { - return !isNaN(prop.id) && prop.partial_reconcile; + return !isNaN(prop.id) && !prop.already_paid; }), self._formatToProcessReconciliation.bind(self, line)), "payment_aml_ids": _.pluck(_.filter(props, function (prop) { - return !isNaN(prop.id) && !prop.partial_reconcile; + return !isNaN(prop.id) && prop.already_paid; }), 'id'), "new_aml_dicts": _.map(_.filter(props, function (prop) { return isNaN(prop.id); @@ -557,6 +592,29 @@ var StatementModel = BasicModel.extend({ }); return this._computeLine(line); }, + /** + * When changing partner, read property_account_receivable and payable + * of that partner because the counterpart account might cahnge depending + * on the partner + * + * @private + * @param {string} handle + * @param {integer} partner_id + * @returns {Deferred} + */ + _changePartner: function (handle, partner_id) { + var self = this; + return this._rpc({ + model: 'res.partner', + method: 'read', + args: [partner_id, ["property_account_receivable_id", "property_account_payable_id"]], + }).then(function (result) { + if (result.length > 0) { + var line = self.getLine(handle); + self.lines[handle].st_line.open_balance_account_id = line.amount < 0 ? result[0]['property_account_payable_id'][0] : result[0]['property_account_receivable_id'][0]; + } + }); + }, /** * Calculates the balance; format each proposition amount_str and mark as * invalid the line with empty account_id, amount or label @@ -573,7 +631,7 @@ var StatementModel = BasicModel.extend({ // compute taxes var tax_defs = []; var reconciliation_proposition = []; - var format_options = { + var formatOptions = { currency_id: line.st_line.currency_id, }; _.each(line.reconciliation_proposition, function (prop) { @@ -610,10 +668,10 @@ var StatementModel = BasicModel.extend({ }); prop.amount = tax.base; - prop.amount_str = field_utils.format.monetary(Math.abs(prop.amount), {}, format_options); + prop.amount_str = field_utils.format.monetary(Math.abs(prop.amount), {}, formatOptions); prop.invalid = !self._isValid(prop); - tax_prop.amount_str = field_utils.format.monetary(Math.abs(tax_prop.amount), {}, format_options); + tax_prop.amount_str = field_utils.format.monetary(Math.abs(tax_prop.amount), {}, formatOptions); tax_prop.invalid = prop.invalid; reconciliation_proposition.push(tax_prop); @@ -644,7 +702,7 @@ var StatementModel = BasicModel.extend({ total = Math.round(total*1000)/1000 || 0; line.balance = { 'amount': total, - 'amount_str': field_utils.format.monetary(Math.abs(total), {}, format_options), + 'amount_str': field_utils.format.monetary(Math.abs(total), {}, formatOptions), 'account_code': self.accounts[line.st_line.open_balance_account_id], }; line.balance.type = line.balance.amount ? (line.balance.amount > 0 && line.st_line.partner_id ? 0 : -1) : 1; @@ -759,6 +817,9 @@ var StatementModel = BasicModel.extend({ _formatQuickCreate: function (line, values) { values = values || {}; var account = this._formatNameGet(values.account_id); + var formatOptions = { + currency_id: line.st_line.currency_id, + }; var prop = { 'id': _.uniqueId('createLine'), 'label': values.label || line.st_line.name, @@ -771,7 +832,7 @@ var StatementModel = BasicModel.extend({ 'credit': 0, 'base_amount': values.amount_type !== "percentage" ? (values.amount || line.balance.amount) : - line.st_line.amount * values.amount / 100, + line.balance.amount * values.amount / 100, 'percent': values.amount_type === "percentage" ? values.amount : null, 'link': values.link, 'display': true, @@ -781,9 +842,10 @@ var StatementModel = BasicModel.extend({ '__focus': '__focus' in values ? values.__focus : true, }; if (prop.base_amount) { + // Call to format and parse needed to round the value to the currency precision var sign = prop.base_amount < 0 ? -1 : 1; - var amount = field_utils.format.monetary(Math.abs(prop.base_amount), {}, line); - prop.base_amount = sign * field_utils.parse.monetary(amount); + var amount = field_utils.format.monetary(Math.abs(prop.base_amount), {}, formatOptions); + prop.base_amount = sign * field_utils.parse.monetary(amount, {}, formatOptions); } prop.amount = prop.base_amount; return prop; @@ -843,7 +905,10 @@ var StatementModel = BasicModel.extend({ * @returns {object} */ _formatToProcessReconciliation: function (line, prop) { - var amount = prop.partial_reconcile ? -line.st_line.amount : prop.amount; + var amount = -prop.amount; + if (prop.partial_reconcile === true) { + amount = -line.st_line.amount; + } var result = { name : prop.label, debit : amount > 0 ? amount : 0, @@ -854,7 +919,7 @@ var StatementModel = BasicModel.extend({ } else { result.account_id = prop.account_id.id; if (prop.journal_id) { - result.journal_id = prop.account_id.id; + result.journal_id = prop.journal_id.id; } } if (!isNaN(prop.id)) result.counterpart_aml_id = prop.id; diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js index c082d92764b..915dd2c7966 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js @@ -22,6 +22,8 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { 'click div:first h1.statement_name': '_onClickStatementName', 'click div:first h1.statement_name_edition button': '_onValidateName', "click *[rel='do_action']": "_onDoAction", + 'click button.button_back_to_statement': '_onGoToBankStatement', + 'click button.button_close_statement': '_onCloseBankStatement', }, /** * @override @@ -107,7 +109,8 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { var $done = $(qweb.render("reconciliation.done", { 'duration': moment(dt).utc().format(time.strftime_to_moment_format(_t.database.parameters.time_format)), 'number': state.valuenow, - 'timePerTransaction': Math.round(dt/1000/state.valuemax) + 'timePerTransaction': Math.round(dt/1000/state.valuemax), + 'context': state.context, })); $done.appendTo(this.$el.first()); this.$('.o_automatic_reconciliation').hide(); @@ -158,11 +161,12 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { }, /** * @private + * Click on close bank statement button, this will + * close and then open form view of bank statement + * @param {MouseEvent} event */ - _onValidateName: function () { - var name = this.model.get(this.handleNameRecord).data.name; - this.trigger_up('change_name', {'data': name}); - this.$('.statement_name, .statement_name_edition').toggle(); + _onCloseBankStatement: function (e) { + this.trigger_up('close_statement'); }, /** * @private @@ -183,6 +187,34 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { view_mode: "list" }); }, + /** + * Open the list view for account.bank.statement model + * @private + * @param {MouseEvent} event + */ + _onGoToBankStatement: function (e) { + var journalId = $(e.target).attr('data_journal_id'); + if (journalId) { + journalId = parseInt(journalId); + } + this.do_action({ + name: 'Bank Statements', + res_model: 'account.bank.statement', + views: [[false, 'list'], [false, 'form']], + type: 'ir.actions.act_window', + context: {search_default_journal_id: journalId}, + view_type: 'list', + view_mode: 'form', + }); + }, + /** + * @private + */ + _onValidateName: function () { + var name = this.model.get(this.handleNameRecord).data.name; + this.trigger_up('change_name', {'data': name}); + this.$('.statement_name, .statement_name_edition').toggle(); + }, }); @@ -305,6 +337,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, { } if ((state.balance.amount !== 0 || line.partial_reconcile) && props.length === 1 && + line.already_paid === false && ( (state.st_line.amount > 0 && state.st_line.amount < props[0].amount) || (state.st_line.amount < 0 && state.st_line.amount > props[0].amount)) @@ -365,6 +398,16 @@ var LineRenderer = Widget.extend(FieldManagerMixin, { // Private //-------------------------------------------------------------------------- + /** + * @private + * @param {jQueryElement} $el + */ + _destroyPopover: function ($el) { + var popover = $el.data('bs.popover'); + if (popover) { + popover.destroy(); + } + }, /** * @private * @param {integer} partnerID @@ -550,16 +593,20 @@ var LineRenderer = Widget.extend(FieldManagerMixin, { * @param {MouseEvent} event */ _onSelectMoveLine: function (event) { - var mv_line_id = $(event.target).closest('.mv_line').data('line-id'); - this.trigger_up('add_proposition', {'data': mv_line_id}); + var $el = $(event.target) + this._destroyPopover($el); + var moveLineId = $el.closest('.mv_line').data('line-id'); + this.trigger_up('add_proposition', {'data': moveLineId}); }, /** * @private * @param {MouseEvent} event */ _onSelectProposition: function (event) { - var mv_line_id = $(event.target).closest('.mv_line').data('line-id'); - this.trigger_up('remove_proposition', {'data': mv_line_id}); + var $el = $(event.target) + this._destroyPopover($el); + var moveLineId = $el.closest('.mv_line').data('line-id'); + this.trigger_up('remove_proposition', {'data': moveLineId}); }, /** * @private diff --git a/addons/account/static/src/xml/account_reconciliation.xml b/addons/account/static/src/xml/account_reconciliation.xml index ea3c111eccc..e36430cd7cc 100644 --- a/addons/account/static/src/xml/account_reconciliation.xml +++ b/addons/account/static/src/xml/account_reconciliation.xml @@ -49,6 +49,16 @@

Congrats, you're all done !

It took you to reconcile transactions.
That's on average seconds per transaction.

+ +

+ + + + + + +

+
diff --git a/addons/account/static/tests/reconciliation_tests.js b/addons/account/static/tests/reconciliation_tests.js index 79841262c4f..0eeb805112c 100644 --- a/addons/account/static/tests/reconciliation_tests.js +++ b/addons/account/static/tests/reconciliation_tests.js @@ -9,6 +9,9 @@ var data = { image: {string: "image", type: 'integer'}, customer: {string: "customer", type: 'boolean'}, supplier: {string: "supplier", type: 'boolean'}, + parent_id: {string: "Parent", type: 'boolean'}, + property_account_receivable_id: {string: 'Account receivable', type: 'many2one', relation: 'account.account'}, + property_account_payable_id: {string: 'Account payable', type: 'many2one', relation: 'account.account'}, }, records: [ {id: 1, display_name: "partner 1", image: 'AAA', customer: true}, @@ -16,7 +19,7 @@ var data = { {id: 3, display_name: "partner 3", image: 'CCC', customer: true}, {id: 4, display_name: "partner 4", image: 'DDD', customer: true}, {id: 8, display_name: "Agrolait", image: 'EEE', customer: true}, - {id: 12, display_name: "Camptocamp", image: 'FFF', supplier: true}, + {id: 12, display_name: "Camptocamp", image: 'FFF', supplier: true, property_account_receivable_id: 287, property_account_payable_id: 287}, ], mark_as_reconciled: function () { return $.when(); @@ -339,7 +342,10 @@ var mv_lines = { '[]': [], '[5,"",0,6]': [ {'account_type': "receivable", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-02-07", 'date': "2017-01-08", 'total_amount_str': "$ 650.00", 'partner_id': 8, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0002", 'partner_name': "Agrolait", 'total_amount_currency_str': "", 'id': 109, 'credit': 0.0, 'journal_id': [1, "Customer Invoices"], 'amount_str': "$ 650.00", 'debit': 650.0, 'account_code': "101200", 'ref': "", 'already_paid': false}, - {'account_type': "receivable", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-02-07", 'date': "2017-01-08", 'total_amount_str': "$ 525.00", 'partner_id': 8, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0003", 'partner_name': "Agrolait", 'total_amount_currency_str': "", 'id': 112, 'credit': 0.0, 'journal_id': [1, "Customer Invoices"], 'amount_str': "$ 525.00", 'debit': 525.0, 'account_code': "101200", 'ref': "", 'already_paid': false} + {'account_type': "receivable", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-02-07", 'date': "2017-01-08", 'total_amount_str': "$ 525.00", 'partner_id': 8, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0003", 'partner_name': "Agrolait", 'total_amount_currency_str': "", 'id': 112, 'credit': 0.0, 'journal_id': [1, "Customer Invoices"], 'amount_str': "$ 525.00", 'debit': 525.0, 'account_code': "101200", 'ref': "", 'already_paid': false}, + {'account_type': "receivable", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-02-07", 'date': "2017-01-08", 'total_amount_str': "$ 650.00", 'partner_id': 12, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0012", 'partner_name': "Camptocamp", 'total_amount_currency_str': "", 'id': 134, 'credit': 0.0, 'journal_id': [1, "Customer Invoices"], 'amount_str': "$ 650.00", 'debit': 650.0, 'account_id': [287, "101200 Account Receivable"], 'account_code': "101200", 'ref': "", 'already_paid': false}, + {'account_type': "receivable", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-02-28", 'date': "2017-01-01", 'total_amount_str': "$ 4,610.00", 'partner_id': 12, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0001", 'partner_name': "Camptocamp", 'total_amount_currency_str': "", 'id': 106, 'credit': 0.0, 'journal_id': [1, "Customer Invoices"], 'amount_str': "$ 4,610.00", 'debit': 4610.0, 'account_id': [287, "101200 Account Receivable"], 'account_code': "101200", 'ref': "", 'already_paid': false}, + {'account_type': "payable", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-02-28", 'date': "2017-01-01", 'total_amount_str': "$ 10,000.00", 'partner_id': 12, 'account_name': "Account Payable", 'name': "BILL/2017/0001", 'partner_name': "Camptocamp", 'total_amount_currency_str': "", 'id': 114, 'credit': 10000.0, 'journal_id': [2, "Vendor Bills"], 'amount_str': "$ 10,000.00", 'debit': 0.0, 'account_id': [284, "101110 Stock Valuation Account"], 'account_code': "111100", 'ref': "", 'already_paid': false} ], '[5,"b",0,6]': [ {'account_type': "liquidity", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-01-23", 'date': "2017-01-23", 'total_amount_str': "$ 100.00", 'partner_id': 8, 'account_name': "Bank", 'name': "BNK1/2017/0003: CUST.IN/2017/0001", 'partner_name': "Agrolait", 'total_amount_currency_str': "", 'id': 394, 'credit': 0.0, 'journal_id': "Bank", 'amount_str': "$ 100.00", 'debit': 100.0, 'account_code': "101401", 'ref': "", 'already_paid': true}, @@ -602,7 +608,19 @@ QUnit.module('account', { testUtils.intercept(clientAction, 'call_service', function (event) { assert.deepEqual(event.data.args[1].args, - [[5],[{partner_id: 8, counterpart_aml_dicts: [], payment_aml_ids: [109,112], new_aml_dicts: []}]], + [[5],[{partner_id: 8, counterpart_aml_dicts: [{ + "counterpart_aml_id": 109, + "credit": 650, + "debit": 0, + "name": "INV/2017/0002" + }, + { + "counterpart_aml_id": 112, + "credit": 525, + "debit": 0, + "name": "INV/2017/0003" + }], + payment_aml_ids: [], new_aml_dicts: []}]], "Should call process_reconciliations with ids"); }); @@ -625,13 +643,8 @@ QUnit.module('account', { [6], [{ partner_id: false, - counterpart_aml_dicts:[{ - name: "BNK1/2017/0002: SUPP.OUT/2017/0002", - debit: 32.58, - credit: 0, - counterpart_aml_id: 392 - }], - payment_aml_ids: [], + counterpart_aml_dicts:[], + payment_aml_ids: [392], new_aml_dicts: [] }] ], "should call process_reconciliations with partial reconcile values"); @@ -652,14 +665,14 @@ QUnit.module('account', { assert.notOk( widget.$('.cell_left .line_info_button').length, "should not display the partial reconciliation alert"); widget.$('.accounting_view thead td:first').trigger('click'); widget.$('.match .cell_account_code:first').trigger('click'); - assert.equal( widget.$('.accounting_view tbody .cell_left .line_info_button').length, 1, "should display the partial reconciliation alert"); + assert.equal( widget.$('.accounting_view tbody .cell_left .line_info_button').length, 0, "should not display the partial reconciliation alert"); assert.ok( widget.$('button.btn-primary:not(hidden)').length, "should not display the reconcile button"); assert.ok( widget.$('.text-danger:not(hidden)').length, "should display counterpart alert"); widget.$('.accounting_view .cell_left .line_info_button').trigger('click'); - assert.strictEqual(widget.$('.accounting_view .cell_left .line_info_button').length, 1, "should display a partial reconciliation alert"); - assert.ok(widget.$('.accounting_view .cell_left .line_info_button').hasClass('do_partial_reconcile_false'), "should display the partial reconciliation information"); + assert.strictEqual(widget.$('.accounting_view .cell_left .line_info_button').length, 0, "should not display a partial reconciliation alert"); + assert.notOk(widget.$('.accounting_view .cell_left .line_info_button').hasClass('do_partial_reconcile_false'), "should not display the partial reconciliation information"); assert.ok( widget.$('button.btn-default:not(hidden)').length, "should display the validate button"); - assert.strictEqual( widget.$el.data('mode'), "inactive", "should be inactive mode"); + assert.strictEqual( widget.$el.data('mode'), "match", "should be inactive mode"); widget.$('button.btn-default:not(hidden)').trigger('click'); clientAction.destroy(); @@ -722,6 +735,29 @@ QUnit.module('account', { clientAction.destroy(); }); + QUnit.test('Reconciliation change partner', function (assert) { + assert.expect(4); + + var clientAction = new ReconciliationClientAction.StatementAction(null, this.params.options); + + testUtils.addMockEnvironment(clientAction, { + data: this.params.data, + }); + + clientAction.appendTo($('#qunit-fixture')); + var widget = clientAction.widgets[0]; + assert.strictEqual(widget.$('.o_input_dropdown input').val(), "Agrolait", "the partner many2one should display agrolait"); + assert.strictEqual(widget.$('.match table tr').length, 2, "agrolait should have 2 propositions for reconciliation"); + + // Simulate changing partner + widget.$('.o_input_dropdown input').trigger('click'); + $('.ui-autocomplete .ui-menu-item a:contains(Camptocamp)').trigger('mouseenter').trigger('click'); + clientAction._onAction({target: widget, name: 'change_partner', data: {data: {display_name: 'Camptocamp', id: 12}}, stopped: false}); + assert.strictEqual(widget.$('.o_input_dropdown input').val(), "Camptocamp", "the partner many2one should display Camptocamp"); + assert.strictEqual(widget.$('.match table tr').length, 3, "camptocamp should have 3 propositions for reconciliation"); + + clientAction.destroy(); + }); QUnit.test('Reconciliation create line', function (assert) { assert.expect(23);