diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index d5415fba0a6..3ba6dcb1399 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -499,7 +499,6 @@ class AccountBankStatementLine(models.Model): 'st_line': st_line.get_statement_line_for_reconciliation_widget(), 'reconciliation_proposition': rp }) - return ret def get_statement_line_for_reconciliation_widget(self): diff --git a/addons/account/models/account_config_settings.py b/addons/account/models/account_config_settings.py index d0fcbf36a44..a59fda008e3 100644 --- a/addons/account/models/account_config_settings.py +++ b/addons/account/models/account_config_settings.py @@ -79,10 +79,8 @@ class AccountConfigSettings(models.TransientModel): self.env.ref('base.group_user').write({'implied_ids': [(4, self.env.ref('product.group_sale_pricelist').id)]}) """ Set the product taxes if they have changed """ ir_values_obj = self.env['ir.values'] - if self.default_sale_tax_id: - ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id], for_all_users=True, company_id=self.company_id.id) - if self.default_purchase_tax_id: - ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id], for_all_users=True, company_id=self.company_id.id) + ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id] if self.default_sale_tax_id else False, for_all_users=True, company_id=self.company_id.id) + ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id] if self.default_purchase_tax_id else False, for_all_users=True, company_id=self.company_id.id) """ install a chart of accounts for the given company (if required) """ if self.chart_template_id and self.chart_template_id != self.company_id.chart_template_id: wizard = self.env['wizard.multi.charts.accounts'].create({ diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index ee0d1903fd0..3ad85d3cfa2 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -338,9 +338,9 @@ class AccountInvoice(models.Model): related='partner_id.commercial_partner_id', store=True, readonly=True, help="The commercial entity that will be used on Journal Entries for this invoice") - outstanding_credits_debits_widget = fields.Text(compute='_get_outstanding_info_JSON') - payments_widget = fields.Text(compute='_get_payment_info_JSON') - has_outstanding = fields.Boolean(compute='_get_outstanding_info_JSON') + outstanding_credits_debits_widget = fields.Text(compute='_get_outstanding_info_JSON', groups="account.group_account_invoice") + payments_widget = fields.Text(compute='_get_payment_info_JSON', groups="account.group_account_invoice") + has_outstanding = fields.Boolean(compute='_get_outstanding_info_JSON', groups="account.group_account_invoice") #fields use to set the sequence, on the first invoice of the journal sequence_number_next = fields.Char(string='Next Number', compute="_get_sequence_prefix", inverse="_set_sequence_next") @@ -741,7 +741,7 @@ class AccountInvoice(models.Model): self.ensure_one() credit_aml = self.env['account.move.line'].browse(credit_aml_id) if not credit_aml.currency_id and self.currency_id != self.company_id.currency_id: - credit_aml.with_context(allow_amount_currency=True).write({ + credit_aml.with_context(allow_amount_currency=True, check_move_validity=False).write({ 'amount_currency': self.company_id.currency_id.with_context(date=credit_aml.date).compute(credit_aml.balance, self.currency_id), 'currency_id': self.currency_id.id}) if credit_aml.payment_id: diff --git a/addons/account/static/src/js/account_payment_field.js b/addons/account/static/src/js/account_payment_field.js index fb038f3e642..10bd54cbeff 100644 --- a/addons/account/static/src/js/account_payment_field.js +++ b/addons/account/static/src/js/account_payment_field.js @@ -46,7 +46,7 @@ var ShowPaymentLineWidget = AbstractField.extend({ k.index = v; k.amount = field_utils.format.float(k.amount, {digits: k.digits}); if (k.date){ - k.date = field_utils.format.date(field_utils.parse.date(k.date, {isUTC: true})); + k.date = field_utils.format.date(field_utils.parse.date(k.date, {}, {isUTC: true})); } }); this.$el.html(QWeb.render('ShowPaymentInfo', { diff --git a/addons/account/static/src/js/reconciliation/reconciliation_action.js b/addons/account/static/src/js/reconciliation/reconciliation_action.js index 51175be7794..8763d5acaa1 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_action.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_action.js @@ -30,6 +30,7 @@ var StatementAction = Widget.extend(ControlPanelMixin, { validate_all_balanced: '_onValidate', change_name: '_onChangeName', close_statement: '_onCloseStatement', + load_more: '_onLoadMore', }, config: { // used to instanciate the model @@ -71,6 +72,7 @@ var StatementAction = Widget.extend(ControlPanelMixin, { 'bank_statement_id': self.model.bank_statement_id, 'valuenow': self.model.valuenow, 'valuemax': self.model.valuemax, + 'defaultDisplayQty': self.model.defaultDisplayQty, 'title': self.title, }); }); @@ -89,12 +91,7 @@ var StatementAction = Widget.extend(ControlPanelMixin, { this.update_control_panel({breadcrumbs: breadcrumbs, search_view_hidden: true}, {clear: true}); this.renderer.prependTo(self.$('.o_form_sheet')); - _.each(this.model.lines, function (line, handle) { - var widget = new self.config.LineRenderer(self, self.model, line); - widget.handle = handle; - self.widgets.push(widget); - widget.appendTo(self.$('.o_reconciliation_lines')); - }); + this._renderLines(); this._openFirstLine(); }, @@ -134,6 +131,15 @@ var StatementAction = Widget.extend(ControlPanelMixin, { return _.find(this.widgets, function (widget) {return widget.handle===handle;}); }, + /** + * + */ + _loadMore: function(qty) { + var self = this; + return this.model.loadMore(qty).then(function () { + self._renderLines(); + }); + }, /** * sitch to 'match' the first available line * @@ -153,6 +159,24 @@ var StatementAction = Widget.extend(ControlPanelMixin, { } return handle; }, + /** + * render line widget and append to view + * + * @private + */ + _renderLines: function () { + var self = this; + var linesToDisplay = this.model.getStatementLines(); + _.each(linesToDisplay, function (line, handle) { + var widget = new self.config.LineRenderer(self, self.model, line); + widget.handle = handle; + self.widgets.push(widget); + widget.appendTo(self.$('.o_reconciliation_lines')); + }); + if (this.model.hasMoreLines() === false) { + this.renderer.hideLoadMoreButton(); + } + }, //-------------------------------------------------------------------------- // Handlers @@ -223,6 +247,14 @@ var StatementAction = Widget.extend(ControlPanelMixin, { }); }); }, + /** + * Load more statement and render them + * + * @param {OdooEvent} event + */ + _onLoadMore: function (event) { + return this._loadMore(this.model.defaultDisplayQty); + }, /** * call 'validate' or 'autoReconciliation' model method then destroy the * validated lines and update the action renderer with the new status bar @@ -246,7 +278,15 @@ var StatementAction = Widget.extend(ControlPanelMixin, { }); _.each(result.handles, function (handle) { self._getWidget(handle).destroy(); + var index = _.findIndex(self.widgets, function (widget) {return widget.handle===handle;}); + self.widgets.splice(index, 1); }); + // Get number of widget and if less than constant and if there are more to laod, load until constant + if (self.widgets.length < self.model.defaultDisplayQty + && self.model.valuemax - self.model.valuenow >= self.model.defaultDisplayQty) { + var toLoad = self.model.defaultDisplayQty - self.widgets.length; + self._loadMore(toLoad); + } self._openFirstLine(); }); }, diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index e12f8f21009..019e761f3d3 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -100,6 +100,8 @@ var StatementModel = BasicModel.extend({ this.lines = {}; this.valuenow = 0; this.valuemax = 0; + this.alreadyDisplayed = []; + this.defaultDisplayQty = 10; }, //-------------------------------------------------------------------------- @@ -230,10 +232,10 @@ 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._changePartner(handle, partner.id) + return $.when(partner && this._changePartner(handle, partner.id)) .then(function() { line.reconciliation_proposition = []; - return self._performMoveLine(handle) + return self.changeMode(handle, 'match'); }) .then(function () { if (line.mode === 'create') { @@ -253,7 +255,7 @@ var StatementModel = BasicModel.extend({ args: [self.bank_statement_id.id], }) .then(function () { - return self.bank_statement_id.id + return self.bank_statement_id.id; }); }, /** @@ -283,6 +285,34 @@ var StatementModel = BasicModel.extend({ getContext: function () { return this.context; }, + /** + * Return the lines that needs to be displayed by the widget + * + * @returns {Object} lines that are loaded and not yet displayed + */ + getStatementLines: function () { + var self = this; + var linesToDisplay = _.pick(this.lines, function(value, key, object) { + if (value.visible === true && self.alreadyDisplayed.indexOf(key) === -1) { + self.alreadyDisplayed.push(key); + return object; + } + }); + return linesToDisplay; + }, + /** + * Return a boolean telling if load button needs to be displayed or not + * + * @returns {boolean} true if load more button needs to be displayed + */ + hasMoreLines: function () { + var self = this; + var notDisplayed = _.filter(this.lines, function(line) { return !line.visible; }); + if (notDisplayed.length > 0) { + return true; + } + return false; + }, /** * get the line data for this handle * @@ -355,14 +385,42 @@ var StatementModel = BasicModel.extend({ line.reconcileModels = self.reconcileModels; }); var ids = _.pluck(self.lines, 'id'); - return self._rpc({ - model: 'account.bank.statement.line', - method: 'get_data_for_reconciliation_widget', - args: [ids], - }) - .then(self._formatLine.bind(self)); + ids = ids.splice(0, self.defaultDisplayQty); + self.pagerIndex = ids.length; + return self.loadData(ids, []); }); }, + /** + * Load more bank statement line + * + * @param {integer} quantity to load + * @returns {Deferred} + */ + loadMore: function(qty) { + if (qty === undefined) { + qty = this.defaultDisplayQty; + } + var ids = _.pluck(this.lines, 'id'); + ids = ids.splice(this.pagerIndex, qty); + this.pagerIndex += qty; + return this.loadData(ids, this._getExcludedIds()); + }, + /** + * RPC method to load informations on lines + * + * @param {Array} ids of bank statement line passed to rpc call + * @param {Array} list of move_line ids that needs to be excluded from search + * @returns {Deferred} + */ + loadData: function(ids, excluded_ids) { + var self = this; + return self._rpc({ + model: 'account.bank.statement.line', + method: 'get_data_for_reconciliation_widget', + args: [ids, excluded_ids], + }) + .then(self._formatLine.bind(self)); + }, /** * Add lines into the propositions from the reconcile model * Can add 2 lines, and each with its taxes. The second line become editable @@ -770,6 +828,7 @@ var StatementModel = BasicModel.extend({ var line = _.find(self.lines, function (l) { return l.id === data.st_line.id; }); + line.visible = true; _.extend(line, data); self._formatLineProposition(line, line.reconciliation_proposition); if (!line.reconciliation_proposition.length) { @@ -850,6 +909,26 @@ var StatementModel = BasicModel.extend({ prop.amount = prop.base_amount; return prop; }, + /** + * Return list of account_move_line that has been selected and needs to be removed + * from other calls. + * + * @private + * @returns {Array} list of excluded ids + */ + _getExcludedIds: function () { + var excludedIds = []; + _.each(this.lines, function(line) { + if (line.reconciliation_proposition) { + _.each(line.reconciliation_proposition, function(prop) { + if (parseInt(prop['id'])) { + excludedIds.push(prop['id']); + } + }) + } + }); + return excludedIds; + }, /** * Defined whether the line is to be displayed or not. Here, we only display * the line if it comes from the server or if an account is defined when it @@ -1168,7 +1247,8 @@ var ManualModel = StatementModel.extend({ 'filter': "", 'reconcileModels': [], 'account_id': this._formatNameGet([data.account_id, data.account_name]), - 'st_line': data + 'st_line': data, + 'visible': true }); this._formatLineProposition(line, line.reconciliation_proposition); if (!line.reconciliation_proposition.length) { diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js index e0ecf61d354..2530a6043c2 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js @@ -24,6 +24,7 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { "click *[rel='do_action']": "_onDoAction", 'click button.button_back_to_statement': '_onGoToBankStatement', 'click button.button_close_statement': '_onCloseBankStatement', + 'click button.js_load_more': '_onLoadMore', }, /** * @override @@ -87,6 +88,12 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- + /* + * hide the button to load more statement line + */ + hideLoadMoreButton: function () { + this.$('.js_load_more').hide(); + }, /** * update the statement rendering * @@ -214,6 +221,14 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, { view_mode: 'form', }); }, + /** + * Load more statement lines for reconciliation + * @private + * @param {MouseEvent} event + */ + _onLoadMore: function (e) { + this.trigger_up('load_more'); + }, /** * @private */ diff --git a/addons/account/static/src/less/account_reconciliation.less b/addons/account/static/src/less/account_reconciliation.less index 4ecf02c8416..66b39301fbb 100644 --- a/addons/account/static/src/less/account_reconciliation.less +++ b/addons/account/static/src/less/account_reconciliation.less @@ -166,7 +166,6 @@ vertical-align: top; padding-right: 10px; font-weight: bold; - white-space: nowrap; } } @@ -209,7 +208,7 @@ .o-transition(max-height, 250ms); } &[data-mode="match"] > .match { - max-height: 130px; + max-height: none; .o-transition(max-height, 400ms); } &[data-mode="create"] > .create { diff --git a/addons/account/static/src/xml/account_reconciliation.xml b/addons/account/static/src/xml/account_reconciliation.xml index e73a42c785b..e41bb97cc3d 100644 --- a/addons/account/static/src/xml/account_reconciliation.xml +++ b/addons/account/static/src/xml/account_reconciliation.xml @@ -25,6 +25,9 @@
+
+ +
Tip: Hit CTRL-Enter to reconcile all the balanced items in the sheet.
@@ -203,7 +206,16 @@ - : : + + + + : + + + + : + + diff --git a/addons/account/static/tests/reconciliation_tests.js b/addons/account/static/tests/reconciliation_tests.js index 0eeb805112c..511656906d9 100644 --- a/addons/account/static/tests/reconciliation_tests.js +++ b/addons/account/static/tests/reconciliation_tests.js @@ -1,7 +1,9 @@ odoo.define('account.reconciliation_tests.data', function () { "use strict"; -var data = { +var Datas = {}; + +var db = { 'res.partner': { fields: { id: {string: "ID", type: 'integer'}, @@ -58,7 +60,7 @@ var data = { {id: 7, display_name: "Tax 10.00% include", amount: 10, price_include: true, account_id: 288}, ], json_friendly_compute_all: function (args) { - var tax = _.find(data['account.tax'].records, {'id': args[0][0]}); + var tax = _.find(db['account.tax'].records, {'id': args[0][0]}); var amount = args[1]; var tax_base = tax.price_include ? amount*100/(100+tax.amount) : amount; return $.when({ @@ -103,7 +105,7 @@ var data = { 'account.bank.statement': { fields: {}, reconciliation_widget_preprocess: function () { - return $.when(data_preprocess); + return $.when(Datas.used.data_preprocess); }, }, 'account.bank.statement.line': { @@ -122,19 +124,19 @@ var data = { var partner_id = args.splice(1, 1)[0]; var excluded_ids = args.splice(1, 1)[0]; var key = JSON.stringify(args); - if (!mv_lines[key]) { + if (!Datas.used.mv_lines[key]) { throw new Error("Unknown parameters for get_move_lines_for_reconciliation_widget: '"+ key + "'"); } - return $.when(_.filter(mv_lines[key], function (line) { + return $.when(_.filter(Datas.used.mv_lines[key], function (line) { return excluded_ids.indexOf(line.id) === -1 && (!partner_id || partner_id === line.partner_id); })); }, get_data_for_reconciliation_widget: function (args) { var ids = args[0]; - return $.when(_.filter(data_widget, function (w) {return _.contains(ids, w.st_line.id);})); + return $.when(_.filter(Datas.used.data_widget, function (w) {return _.contains(ids, w.st_line.id);})); }, reconciliation_widget_auto_reconcile: function () { - return $.when(auto_reconciliation); + return $.when(Datas.used.auto_reconciliation); }, process_reconciliations: function (args) { var datas = args[1]; @@ -142,8 +144,8 @@ var data = { ids = ids.concat(_.flatten(_.pluck(datas, 'payment_aml_ids'))); ids = _.compact(ids); - for (var key in move_lines_for_manual_reconciliation) { - move_lines_for_manual_reconciliation[key] = _.filter(move_lines_for_manual_reconciliation[key], function (mv_line) { + for (var key in Datas.used.move_lines_for_manual_reconciliation) { + Datas.used.move_lines_for_manual_reconciliation[key] = _.filter(Datas.used.move_lines_for_manual_reconciliation[key], function (mv_line) { return ids.indexOf(mv_line.id) === -1; }); } @@ -154,18 +156,18 @@ var data = { fields: {}, get_data_for_manual_reconciliation_widget: function (args) { var key = JSON.stringify(args); - if (!data_for_manual_reconciliation_widget[key]) { + if (!Datas.used.data_for_manual_reconciliation_widget[key]) { throw new Error("Unknown parameters for get_data_for_manual_reconciliation_widget: '"+ key + "'"); } - return $.when(data_for_manual_reconciliation_widget[key]); + return $.when(Datas.used.data_for_manual_reconciliation_widget[key]); }, get_move_lines_for_manual_reconciliation: function (args) { var excluded_ids = args.splice(2, 1)[0]; var key = JSON.stringify(args); - if (!move_lines_for_manual_reconciliation[key]) { + if (!Datas.used.move_lines_for_manual_reconciliation[key]) { throw new Error("Unknown parameters for get_move_lines_for_manual_reconciliation: '"+ key + "'"); } - return $.when(_.filter(move_lines_for_manual_reconciliation[key], function (line) { + return $.when(_.filter(Datas.used.move_lines_for_manual_reconciliation[key], function (line) { return excluded_ids.indexOf(line.id) === -1; })); }, @@ -174,8 +176,8 @@ var data = { var datas = args[0]; for (var i in datas) { var data = datas[i]; - for (var key in move_lines_for_manual_reconciliation) { - move_lines_for_manual_reconciliation[key] = _.filter(move_lines_for_manual_reconciliation[key], function (mv_line) { + for (var key in Datas.used.move_lines_for_manual_reconciliation) { + Datas.used.move_lines_for_manual_reconciliation[key] = _.filter(Datas.used.move_lines_for_manual_reconciliation[key], function (mv_line) { return data.mv_line_ids.indexOf(mv_line.id) === -1; }); } @@ -367,7 +369,12 @@ var mv_lines = { '[7,"",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': 12, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0012", 'partner_name': "Camptocamp", 'total_amount_currency_str': "", 'id': 133, '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} + {'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}, + {'account_type': "liquidity", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-01-23", 'date': "2017-01-23", 'total_amount_str': "$ 376.00", 'partner_id': 7, 'account_name': "Bank", 'name': "BNK1/2017/0002: SUPP.OUT/2017/0002", 'partner_name': "ASUSTeK", 'total_amount_currency_str': "", 'id': 392, 'credit': 376.0, 'journal_id': "Bank", 'amount_str': "$ 376.00", 'debit': 0.0, 'account_code': "101401", 'ref': "BILL/2017/0003", 'already_paid': true}, + {'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}, + {'account_type': "liquidity", 'amount_currency_str': "", 'currency_id': false, 'date_maturity': "2017-01-23", 'date': "2017-01-23", 'total_amount_str': "$ 525.50", 'partner_id': 8, 'account_name': "Bank", 'name': "BNK1/2017/0004: CUST.IN/2017/0002", 'partner_name': "Agrolait", 'total_amount_currency_str': "", 'id': 396, 'credit': 0.0, 'journal_id': "Bank", 'amount_str': "$ 525.50", 'debit': 525.5, 'account_code': "101401", 'ref': "INV/2017/0003", 'already_paid': true}, + {'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-22", 'date': "2017-01-23", 'total_amount_str': "$ 525.00", 'partner_id': 8, 'account_name': "101200 Account Receivable", 'name': "INV/2017/0004", 'partner_name': "Agrolait", 'total_amount_currency_str': "", 'id': 399, 'credit': 0.0, 'journal_id': [1, "Customer Invoices"], 'amount_str': "$ 525.00", 'debit': 525.0, 'account_code': "101200", 'ref': "", 'already_paid': false}, ], '[8,"",0,6]': [], }; @@ -468,23 +475,22 @@ var options = { } }; -return { - params: { - data: data, - data_preprocess: data_preprocess, - data_widget: data_widget, - mv_lines: mv_lines, - auto_reconciliation: auto_reconciliation, - data_for_manual_reconciliation_widget: data_for_manual_reconciliation_widget, - move_lines_for_manual_reconciliation: move_lines_for_manual_reconciliation, - session: session, - options: options, - }, - // this is the main function for this module. Its job is to export (and clone) all data for a test. - getParams: function () { - return $.extend(true, {}, this.params); - } +Datas.params = { + data: db, + data_preprocess: data_preprocess, + data_widget: data_widget, + mv_lines: mv_lines, + auto_reconciliation: auto_reconciliation, + data_for_manual_reconciliation_widget: data_for_manual_reconciliation_widget, + move_lines_for_manual_reconciliation: move_lines_for_manual_reconciliation, + session: session, + options: options, }; + // this is the main function for this module. Its job is to export (and clone) all data for a test. +Datas.getParams = function () { + return (this.used = $.extend(true, {}, this.params)); +}; +return Datas; }); odoo.define('account.reconciliation_tests', function (require) { @@ -534,7 +540,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation fields', function (assert) { assert.expect(6); @@ -561,7 +566,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation basic data', function (assert) { assert.expect(14); @@ -630,7 +634,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation partial', function (assert) { assert.expect(10); @@ -701,7 +704,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation currencies', function (assert) { assert.expect(2); @@ -736,7 +738,7 @@ QUnit.module('account', { }); QUnit.test('Reconciliation change partner', function (assert) { - assert.expect(4); + assert.expect(10); var clientAction = new ReconciliationClientAction.StatementAction(null, this.params.options); @@ -754,7 +756,21 @@ QUnit.module('account', { $('.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"); + assert.strictEqual(widget.$('.match table tr.mv_line').length, 3, "camptocamp should have 3 propositions for reconciliation"); + + widget = clientAction.widgets[2]; + widget.$('.accounting_view thead td:first').trigger('click'); + widget.$('.accounting_view .mv_line .cell_label').trigger('click'); + assert.strictEqual(widget.$('.o_input_dropdown input').val(), "Camptocamp", "the partner many2one should display agrolait"); + assert.strictEqual(widget.$('.match table tr').length, 3, "Camptocamp should have 3 propositions for reconciliation"); + assert.strictEqual(widget.$('.match .match_controls .fa:not(.disabled)').length, 0, "should not display the right arrow"); + + // Simulate remove partner + widget.$('.o_input_dropdown input').trigger('click'); + widget.$('.o_input_dropdown input').val('').trigger('keyup').trigger('blur'); + assert.strictEqual(widget.$('.o_input_dropdown input').val(), "", "the partner many2one should be empty"); + assert.strictEqual(widget.$('.match table tr.mv_line').length, 5, "should have 5 propositions for reconciliation if partner is false"); + assert.strictEqual(widget.$('.match .match_controls .fa:not(.disabled)').length, 1, "should not display the right arrow"); clientAction.destroy(); }); @@ -839,7 +855,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation create line with taxes', function (assert) { assert.expect(13); @@ -883,7 +898,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation create line from reconciliation model', function (assert) { assert.expect(6); @@ -900,7 +914,7 @@ QUnit.module('account', { widget.$('.create .quick_add button:contains(ATOS)').trigger('click'); assert.strictEqual(widget.$('.accounting_view tbody .cell_label, .accounting_view tbody .cell_right').text().replace(/[\n\r\s$,]+/g, ' '), - "ATOS Banque1145.62Tax 20.00%229.12ATOS Frais26.71Tax 10.00% include2.67", "should display 4 lines"); + " ATOS Banque 1145.62 Tax 20.00% 229.12 ATOS Frais 26.71 Tax 10.00% include 2.67", "should display 4 lines"); assert.strictEqual(widget.$('.accounting_view tfoot .cell_label, .accounting_view tfoot .cell_left').text().replace(/[\n\r\s$,]+/g, ' '), "Create Write-off229.12", "should display the 'Create Write-off' line with value in left column"); @@ -926,7 +940,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation auto reconciliation', function (assert) { assert.expect(6); @@ -958,7 +971,6 @@ QUnit.module('account', { clientAction.destroy(); }); - QUnit.test('Reconciliation manual', function (assert) { assert.expect(8); @@ -992,5 +1004,229 @@ QUnit.module('account', { clientAction.destroy(); }); + + + QUnit.test('Reconciliation pager', function (assert) { + assert.expect(6); + + this.params.data['account.bank.statement.line'].records.push( + {id: 9, display_name: "add 9"}, + {id: 10, display_name: "add 10"}, + {id: 11, display_name: "add 11"}, + {id: 12, display_name: "add 12"}, + {id: 13, display_name: "add 13"}, + {id: 14, display_name: "add 14"}, + {id: 15, display_name: "add 15"}, + {id: 16, display_name: "add 16"} + ); + + var data_preprocess = this.params.data_preprocess; + data_preprocess.st_lines_ids.push(9, 10, 11, 12, 13, 14, 15, 16); + + this.params.data_widget.push( + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 9", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 9, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 10", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 10, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 11", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 11, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 12", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 12, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 13", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 13, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 14", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 14, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 15", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 15, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + }, + { + 'st_line': { + 'currency_id': 3, + 'communication_partner_name': false, + 'open_balance_account_id': 287, + 'name': "add 16", + 'partner_name': "Camptocamp", + 'partner_id': 12, + 'has_no_partner': false, + 'journal_id': 84, + 'account_name': "Bank", + 'note': "", + 'amount': 650.0, + 'amount_str': "$ 650.00", + 'amount_currency_str': "", + 'date': "2017-01-01", + 'account_code': "101401", + 'ref': "", + 'id': 16, + 'statement_id': 2 + }, + 'reconciliation_proposition': [] + } + ); + + var clientAction = new ReconciliationClientAction.StatementAction(null, this.params.options); + testUtils.addMockEnvironment(clientAction, { + 'data': this.params.data, + }); + + clientAction.appendTo($('#qunit-fixture')); + + assert.strictEqual(clientAction.$('.o_reconciliation_line').length, 10, "should display 10 lines"); + assert.strictEqual(clientAction.$('.js_load_more:visible').length, 1, "should display the load more button"); + clientAction.$('.o_reconcile:visible').click(); + assert.strictEqual(clientAction.$('.o_reconcile:visible').length, 0, "should remove the reconciled line"); + assert.strictEqual(clientAction.$('.o_reconciliation_line').length, 10, "should load one line to complete the 10"); + clientAction.$('.js_load_more').click(); + assert.strictEqual(clientAction.$('.o_reconciliation_line').length, 11, "should load the last record"); + assert.strictEqual(clientAction.$('.js_load_more:visible').length, 0, "should hide the load more button"); + + clientAction.destroy(); + }); }); }); diff --git a/addons/account/views/account_invoice_view.xml b/addons/account/views/account_invoice_view.xml index 634e785e333..4ab3bda6e6a 100644 --- a/addons/account/views/account_invoice_view.xml +++ b/addons/account/views/account_invoice_view.xml @@ -223,7 +223,7 @@