summaryrefslogtreecommitdiff
path: root/addons/account/static
diff options
context:
space:
mode:
authorLaurent Smet <las@openerp.com>2018-09-20 17:11:52 +0200
committerqdp-odoo <qdp@odoo.com>2018-09-20 17:11:52 +0200
commit7053ae782887c389ab8fcd8f4e832b46287e2efb (patch)
tree025c4ec98c6ef61625e87d024ce1c7541e0c63ed /addons/account/static
parente19ecefa8e78b9369fa8274c879e61799f743a06 (diff)
[IMP] account: management of reconciliation rules
Bank statement lines need to be matched with entries; We have to automate this operation as much as possible. At the same time, create an algorithm that fit everyone needs is quite impossible. For that reason we will let users choose the rules they want with the improvement of reconciliation models. Note that we did it only for bank statement reconliation, not for manual reconciliations. Was task: 1877375 Was PR #26669
Diffstat (limited to 'addons/account/static')
-rw-r--r--addons/account/static/src/js/reconciliation/reconciliation_action.js14
-rw-r--r--addons/account/static/src/js/reconciliation/reconciliation_model.js83
-rw-r--r--addons/account/static/src/js/reconciliation/reconciliation_renderer.js97
-rw-r--r--addons/account/static/src/js/reconciliation/tour_reconciliation.js22
-rw-r--r--addons/account/static/src/xml/account_reconciliation.xml55
-rw-r--r--addons/account/static/tests/reconciliation_tests.js276
6 files changed, 173 insertions, 374 deletions
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_action.js b/addons/account/static/src/js/reconciliation/reconciliation_action.js
index 88668a2da97..bdca26fa15f 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_action.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_action.js
@@ -7,6 +7,7 @@ var ReconciliationRenderer = require('account.ReconciliationRenderer');
var ControlPanelMixin = require('web.ControlPanelMixin');
var Widget = require('web.Widget');
var core = require('web.core');
+var _t = core._t;
/**
@@ -109,7 +110,18 @@ var StatementAction = AbstractAction.extend(ControlPanelMixin, {
this.renderer.prependTo(self.$('.o_form_sheet'));
this._renderLines();
- this._openFirstLine();
+
+ // No more lines to reconcile, trigger the rainbowman.
+ var initialState = this.renderer._initialState;
+ if(initialState.valuenow === initialState.valuemax){
+ initialState.context = this.model.getContext();
+ this.renderer.showRainbowMan(initialState);
+ }else{
+ // Create a notification if some lines has been reconciled automatically.
+ if(initialState.valuenow > 0)
+ this.renderer._renderNotifications(this.model.statement.notifications);
+ this._openFirstLine();
+ }
},
/**
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js
index e8a6838a139..dcc93343189 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_model.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js
@@ -358,13 +358,13 @@ var StatementModel = BasicModel.extend({
.then(function (statement) {
self.statement = statement;
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.valuenow = statement.value_min;
+ self.valuemax = statement.value_max;
self.context.journal_id = statement.journal_id;
- _.each(statement.st_lines_ids, function (id) {
+ _.each(statement.lines, function (res) {
var handle = _.uniqueId('rline');
self.lines[handle] = {
- id: id,
+ id: res.st_line.id,
handle: handle,
reconciled: false,
mode: 'inactive',
@@ -412,7 +412,7 @@ var StatementModel = BasicModel.extend({
var ids = _.pluck(self.lines, 'id');
ids = ids.splice(0, self.defaultDisplayQty);
self.pagerIndex = ids.length;
- return self.loadData(ids, []);
+ return self._formatLine(self.statement.lines);
});
},
/**
@@ -445,7 +445,9 @@ var StatementModel = BasicModel.extend({
args: [ids, excluded_ids],
context: self.context,
})
- .then(self._formatLine.bind(self));
+ .then(function(res){
+ return self._formatLine(res['lines']);
+ })
},
/**
* Add lines into the propositions from the reconcile model
@@ -545,24 +547,14 @@ var StatementModel = BasicModel.extend({
var line = this.getLine(handle);
// Retrieve the toggle proposition
- var selected;
- var targetLineAmount = line.st_line.amount;
- line.reconciliation_proposition.every(function (prop) {
- if (!prop.invalid) {
- if (((line.balance.amount < 0 || !line.partial_reconcile) && prop.amount > 0 && targetLineAmount > 0 && targetLineAmount < prop.amount) ||
- ((line.balance.amount > 0 || !line.partial_reconcile) && prop.amount < 0 && targetLineAmount < 0 && targetLineAmount > prop.amount)) {
- selected = prop;
- return false;
- }
- targetLineAmount -= prop.amount;
- }
- return true;
- });
+ var selected = _.filter(line.reconciliation_proposition, function(prop){return prop.display_triangle});
// If no toggled proposition found, reject it
- if (selected == null)
+ if(selected.length != 1)
return $.Deferred().reject();
+ selected = selected[0];
+
// Inverse partial_reconcile value
selected.partial_reconcile = !selected.partial_reconcile;
if (!selected.partial_reconcile) {
@@ -985,41 +977,32 @@ var StatementModel = BasicModel.extend({
self._formatLineProposition(line, line.reconciliation_proposition);
if (!line.reconciliation_proposition.length) {
delete line.reconciliation_proposition;
- }else{
- // loop state propositions
- var debit_props = _.filter(line.reconciliation_proposition, function(p){
- return p.amount > 0 && line.st_line.amount;
- });
- var credit_props = _.filter(line.reconciliation_proposition, function(p){
- return p.amount < 0 && line.st_line.amount < 0;
- });
- var sum_debit_props = debit_props.length > 0 ? debit_props.map(function(p){return p.amount}).reduce(function(p1, p2){return p1 + p2}) : 0;
- var sum_credit_props = credit_props.length > 0 ? credit_props.map(function(p){return p.amount}).reduce(function(p1, p2){return p1 + p2}) : 0;
-
- // Want to display the triangle for partial reconciliation or not.
- if(line.st_line.amount_currency > 0 && line.st_line.amount_currency < sum_debit_props && debit_props.length == 1)
- debit_props[0].display_triangle = true;
- else if(line.st_line.amount_currency < 0 && line.st_line.amount_currency > sum_credit_props && credit_props.length == 1)
- credit_props[0].display_triangle = true;
}
// No partner set on st_line and all matching amls have the same one: set it on the st_line.
- if(!line.st_line.partner_id && line.reconciliation_proposition){
- var hasDifferentPartners = function(prop){
- return !prop.partner_id || prop.partner_id != line.reconciliation_proposition[0].partner_id;
- }
-
- if(!_.any(line.reconciliation_proposition, hasDifferentPartners)){
- defs.push(self.changePartner(line.handle, {
- 'id': line.reconciliation_proposition[0].partner_id,
- 'display_name': line.reconciliation_proposition[0].partner_name,
- }, true));
- }
- }
+ defs.push(
+ self._computeLine(line)
+ .then(function(){
+ if(!line.st_line.partner_id && line.reconciliation_proposition.length > 0){
+ var hasDifferentPartners = function(prop){
+ return !prop.partner_id || prop.partner_id != line.reconciliation_proposition[0].partner_id;
+ }
- defs.push(self._computeLine(line));
+ if(!_.any(line.reconciliation_proposition, hasDifferentPartners)){
+ return self.changePartner(line.handle, {
+ 'id': line.reconciliation_proposition[0].partner_id,
+ 'display_name': line.reconciliation_proposition[0].partner_name,
+ }, true);
+ }
+ }
+ return true;
+ })
+ .then(function(){
+ return data.status === 'write_off'? self.quickCreateProposition(line.handle, data.model_id) : true;
+ })
+ );
});
- return $.when.apply($, defs);
+ return $.when(defs);
},
/**
* Format the server value then compute the line
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
index e7b9067ca3d..e59934610b6 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
@@ -84,6 +84,29 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, {
hideLoadMoreButton: function () {
this.$('.js_load_more').hide();
},
+ showRainbowMan(state){
+ var dt = Date.now()-this.time;
+ var $done = $(qweb.render("reconciliation.done", {
+ 'duration': moment(dt).utc().format(time.getLangTimeFormat()),
+ 'number': state.valuenow,
+ 'timePerTransaction': Math.round(dt/1000/state.valuemax),
+ 'context': state.context,
+ }));
+ $done.find('.button_close_statement').click(this._onCloseBankStatement.bind(this));
+ $done.find('.button_back_to_statement').click(this._onGoToBankStatement.bind(this));
+ this.$el.children().hide();
+ // display rainbowman after full reconciliation
+ if (session.show_effect) {
+ this.trigger_up('show_effect', {
+ type: 'rainbow_man',
+ fadeout: 'no',
+ message: $done,
+ });
+ this.$el.css('min-height', '450px');
+ } else {
+ $done.appendTo(this.$el);
+ }
+ },
/**
* update the statement rendering
*
@@ -103,27 +126,7 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, {
.css('width', (state.valuenow/state.valuemax*100) + '%');
if (state.valuenow === state.valuemax && !this.$('.done_message').length) {
- var dt = Date.now()-this.time;
- var $done = $(qweb.render("reconciliation.done", {
- 'duration': moment(dt).utc().format(time.getLangTimeFormat()),
- 'number': state.valuenow,
- 'timePerTransaction': Math.round(dt/1000/state.valuemax),
- 'context': state.context,
- }));
- $done.find('.button_close_statement').click(this._onCloseBankStatement.bind(this));
- $done.find('.button_back_to_statement').click(this._onGoToBankStatement.bind(this));
- this.$el.children().hide();
- // display rainbowman after full reconciliation
- if (session.show_effect) {
- this.trigger_up('show_effect', {
- type: 'rainbow_man',
- fadeout: 'no',
- message: $done,
- });
- this.$el.css('min-height', '450px');
- } else {
- $done.appendTo(this.$el);
- }
+ this.showRainbowMan(state);
}
if (state.notifications) {
@@ -145,11 +148,7 @@ var StatementRenderer = Widget.extend(FieldManagerMixin, {
_renderNotifications: function(notifications) {
this.$(".notification_area").empty();
for (var i=0; i<notifications.length; i++) {
- var $notification = $(qweb.render("reconciliation.notification", {
- type: notifications[i].type,
- message: notifications[i].message,
- details: notifications[i].details,
- })).hide();
+ var $notification = $(qweb.render("reconciliation.notification", notifications[i])).hide();
$notification.appendTo(this.$(".notification_area")).slideDown(300);
}
},
@@ -363,38 +362,48 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
// reconciliation_proposition
var $props = this.$('.accounting_view tbody').empty();
- // loop state propositions
+ // Search propositions that could be a partial credit/debit.
var props = [];
- var partialDebitProps = 0;
- var partialCreditProps = 0;
+ var partialDebitProp;
+ var partialCreditProp;
+ var balance = state.balance.amount_currency;
_.each(state.reconciliation_proposition, function (prop) {
if (prop.display) {
props.push(prop);
- if (prop.amount > 0 && prop.amount > state.st_line.amount) {
- partialDebitProps++;
- } else if (prop.amount < 0 && prop.amount < state.st_line.amount) {
- partialCreditProps++;
- }
+ /*
+ Examples:
+ statement line | 100 | |
+ move line 1 | | 200 | <- can be a partial of 100
+ balance: -100
+
+ statement line | 500 | |
+ move line 1 | | 300 | <- is not a eligible to be a partial due to the second line.
+ move line 2 | | 300 | <- can be a partial of 200
+ balance: -100
+
+ statement line | 500 | |
+ move line 1 | | 700 | <- must not be a partial (debit = 800 > 700 = credit).
+ move line 2 | 300 | |
+ balance: 100
+ */
+ if(!prop.display_new && balance < 0 && prop.amount > 0 && balance + prop.amount > 0)
+ partialDebitProp = prop;
+ else if(!prop.display_new && balance > 0 && prop.amount < 0 && balance + prop.amount < 0)
+ partialCreditProp = prop;
}
});
- var targetLineAmount = state.st_line.amount;
-
_.each(props, function (line) {
- var display_triangle = (line.already_paid === false &&
- ((state.balance.amount_currency < 0 || line.partial_reconcile)
- && line.amount > 0 && state.st_line.amount > 0 && targetLineAmount < line.amount && partialDebitProps <= 1) ||
- ((state.balance.amount_currency > 0 || line.partial_reconcile)
- && line.amount < 0 && state.st_line.amount < 0 && targetLineAmount > line.amount && partialCreditProps <= 1));
- var $line = $(qweb.render("reconciliation.line.mv_line", {'line': line, 'state': state, 'display_triangle': display_triangle}));
+ line.display_triangle = (line.already_paid === false &&
+ ((state.balance.amount_currency < 0 || line.partial_reconcile) && partialDebitProp && partialDebitProp === line) ||
+ ((state.balance.amount_currency > 0 || line.partial_reconcile) && partialCreditProp && partialCreditProp === line));
+ var $line = $(qweb.render("reconciliation.line.mv_line", {'line': line, 'state': state}));
if (!isNaN(line.id)) {
$('<span class="line_info_button fa fa-info-circle"/>')
.appendTo($line.find('.cell_info_popover'))
.attr("data-content", qweb.render('reconciliation.line.mv_line.details', {'line': line}));
}
- targetLineAmount -= line.amount;
-
$props.append($line);
});
diff --git a/addons/account/static/src/js/reconciliation/tour_reconciliation.js b/addons/account/static/src/js/reconciliation/tour_reconciliation.js
index ab6efaef113..533b68274ba 100644
--- a/addons/account/static/src/js/reconciliation/tour_reconciliation.js
+++ b/addons/account/static/src/js/reconciliation/tour_reconciliation.js
@@ -9,24 +9,15 @@ Tour.register('bank_statement_reconciliation', {
test: true,
// Go to the reconciliation page of the statement: "BNK/2014/001"
}, [
- // Reconciliation of 'SAJ/2018/002'
- // Select the 'INV/2018/0002' line and click on reconcile.
+ // Reconciliation of 'INV/2018/0002'
+ // Click on reconcile (matching done automatically by the reconciliation rule).
{
- content: "open the last line in match mode to test the reconcile button",
- trigger: '.toggle_match:last',
- extra_trigger: '.o_reconciliation',
- },
- {
- content: "select the 'INV/2018/0002' line",
- trigger: '.o_reconciliation_line:last .match .cell_label:contains("INV/2018/0002")'
- },
- {
content: "reconcile the line",
- trigger: '.o_reconciliation_line:last .o_reconcile:visible',
+ trigger: '.o_reconciliation_line:nth-child(1) .o_reconcile:visible',
},
- // Reconciliation of 'First 2000 € of SAJ/2014/0001'
+ // Reconciliation of 'First 2000 $ of INV/2018/0001'
// Make a partial reconciliation
{
@@ -35,10 +26,6 @@ Tour.register('bank_statement_reconciliation', {
trigger: '.o_reconciliation_line:last .cell_label:contains("First")'
},
{
- content: "select a line with with a higher amount",
- trigger: '.o_reconciliation_line:last .match .cell_label:contains("INV/2018/0001")'
- },
- {
content: "click on partial reconcile",
trigger: '.o_reconciliation_line:last .accounting_view .do_partial_reconcile_true'
},
@@ -67,7 +54,6 @@ Tour.register('bank_statement_reconciliation', {
},
{
content: "select a line linked to Deco Addict ",
- extra_trigger: '.o_reconciliation_line:nth-child(2) .match:not(:has(tr:eq(1)))',
trigger: ".o_reconciliation_line:nth-child(2) .match .line_info_button[data-content*='Deco Addict']"
},
{
diff --git a/addons/account/static/src/xml/account_reconciliation.xml b/addons/account/static/src/xml/account_reconciliation.xml
index 3d5cc28ec3d..39cff76a6a6 100644
--- a/addons/account/static/src/xml/account_reconciliation.xml
+++ b/addons/account/static/src/xml/account_reconciliation.xml
@@ -32,7 +32,6 @@
<div t-if="widget._initialState.valuemax &gt; widget._initialState.defaultDisplayQty">
<button class="btn btn-secondary js_load_more">Load more</button>
</div>
- <div class="float-right text-muted">Tip: Hit CTRL-Enter to reconcile all the balanced items in the sheet.</div>
</div>
<div t-else="" class="o_view_noreconciliation">
<p>Nothing to do!</p>
@@ -157,7 +156,11 @@
<div class="quick_add">
<div class="btn-group o_reconcile_models" t-if="state.reconcileModels">
<t t-foreach="state.reconcileModels" t-as="reconcileModel">
- <button class="btn btn-primary" t-att-data-reconcile-model-id="reconcileModel.id"><t t-esc="reconcileModel.name"/></button>
+ <button class="btn btn-primary"
+ t-if="reconcileModel.rule_type === 'writeoff_button' &amp;&amp; (reconcileModel.match_journal_ids.length == 0 || reconcileModel.match_journal_ids.includes(state.st_line.journal_id))"
+ t-att-data-reconcile-model-id="reconcileModel.id">
+ <t t-esc="reconcileModel.name"/>
+ </button>
</t>
<p t-if="!state.reconcileModels.length" style="color: #bbb;">To speed up reconciliation, define <a style="cursor: pointer;" class="reconcile_model_create">reconciliation models</a>.</p>
</div>
@@ -214,7 +217,7 @@
<t t-name="reconciliation.line.mv_line.triangle">
- <t t-if="display_triangle || line.display_triangle">
+ <t t-if="line.display_triangle">
<t t-if="line.partial_reconcile">
<span t-att-class="'do_partial_reconcile_'+(!line.partial_reconcile)+' line_info_button fa fa-exclamation-triangle'"
data-content="Undo the partial reconciliation."/>
@@ -231,7 +234,12 @@
<tr t-if="line.display !== false" t-attf-class="mv_line #{line.already_paid ? ' already_reconciled' : ''} #{line.__invalid ? 'invalid' : ''} #{line.is_tax ? 'is_tax' : ''}" t-att-data-line-id="line.id" t-att-data-selected="selected">
<td class="cell_action"><span class="fa fa-add-remove" role="img" aria-label="Set" title="Set"/></td>
<td class="cell_account_code"><t t-esc="line.account_code"/></td>
- <td class="cell_due_date"><t t-esc="line.date_maturity === false ? line.date : line.date_maturity"/></td>
+ <td class="cell_due_date">
+ <t t-if="typeof(line.id) != 'number'">
+ <span class="badge badge-secondary">New</span>
+ </t>
+ <t t-else="" t-esc="line.date_maturity === false ? line.date : line.date_maturity"/>
+ </td>
<td class="cell_label">
<t t-if="line.partner_id &amp;&amp; line.partner_id !== state.st_line.partner_id">
<t t-if="line.partner_name.length">
@@ -297,16 +305,41 @@
</table>
</t>
+
+<t t-name="reconciliation.notification.reconciled">
+ <t t-if="details !== undefined">
+ <a rel="do_action" href="#" aria-label="External link" title="External link"
+ t-att-data-action_name="details.name"
+ t-att-data-model="details.model"
+ t-att-data-ids="details.ids">
+ <t t-esc="nb_reconciled_lines"/>
+ statement lines
+ </a>
+ have been reconciled automatically.
+ </t>
+</t>
+
+
+<t t-name="reconciliation.notification.default">
+ <t t-esc="message"/>
+ <t t-if="details !== undefined">
+ <a class="fa fa-external-link" rel="do_action" href="#" aria-label="External link" title="External link"
+ t-att-data-action_name="details.name"
+ t-att-data-model="details.model"
+ t-att-data-ids="details.ids">
+ </a>
+ </t>
+</t>
+
+
<t t-name="reconciliation.notification">
<div t-att-class="'notification alert-dismissible alert alert-' + type" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span title="Close" class="fa fa-times"></span></button>
- <t t-esc="message" />
- <t t-if="details !== undefined">
- <a class="fa fa-external-link" rel="do_action" href="#" aria-label="External link" title="External link"
- t-att-data-action_name="details.name"
- t-att-data-model="details.model"
- t-att-data-ids="details.ids">
- </a>
+ <t t-if="template">
+ <t t-call="{{template}}"/>
+ </t>
+ <t t-else="">
+ <t t-call="reconciliation.notification.default"/>
</t>
</div>
</t>
diff --git a/addons/account/static/tests/reconciliation_tests.js b/addons/account/static/tests/reconciliation_tests.js
index 2e554a05776..6feac45cf0a 100644
--- a/addons/account/static/tests/reconciliation_tests.js
+++ b/addons/account/static/tests/reconciliation_tests.js
@@ -159,6 +159,7 @@ var db = {
fields: {
id: {string: "ID", type: 'integer'},
name: {string: "Button Label", type: 'char'},
+ rule_type: {string: "Type", type: 'selection', selection: [['writeoff_button', 'Create a Button'], ['writeoff_suggestion', 'Write off Suggestion'], ['invoice_matching', 'Invoice matching']], default:'writeoff_button'},
has_second_line: {string: "Add a second line", type: 'boolean'},
account_id: {string: "Account", type: 'many2one', relation:'account.account'},
journal_id: {string: "Journal", type: 'many2one', relation:'account.journal'},
@@ -174,14 +175,15 @@ 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'}
},
records: [
- {'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 4, 'analytic_account_id': false, 'display_name': "Int\u00e9rrets", '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},
- {'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 2, 'analytic_account_id': false, 'display_name': "Perte et Profit", 'second_tax_id': false, 'has_second_line': false, 'journal_id': false, 'label': false, 'second_label': false, 'second_account_id': false, 'account_id': 283, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "percentage", 'name': "Perte et Profit", 'amount': 100.0, 'second_amount': 100.0},
- {'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 5, 'analytic_account_id': false, 'display_name': "Fs bank", '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.", '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},
- {'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 3, 'analytic_account_id': false, 'display_name': "ATOS", '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", '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},
+ {'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': []},
+ {'second_analytic_account_id': false, 'second_amount_type': "percentage", 'second_journal_id': false, 'id': 2, 'analytic_account_id': false, 'display_name': "Perte et Profit", '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': 283, 'company_id': [1, "Demo SPRL"], 'tax_id': false, 'amount_type': "percentage", 'name': "Perte et Profit", 'amount': 100.0, 'second_amount': 100.0, 'match_journal_ids': []},
+ {'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': []},
]
},
'account.reconciliation.widget': {
@@ -222,10 +224,17 @@ var db = {
},
get_bank_statement_line_data: function (args) {
var ids = args[0];
- return $.when(_.filter(Datas.used.data_widget, function (w) {return _.contains(ids, w.st_line.id);}));
+ var results = {
+ value_min: 0,
+ value_max: ids.length,
+ lines: _.filter(Datas.used.data_widget, function (w) {return _.contains(ids, w.st_line.id);})
+ };
+ return $.when(results);
},
get_bank_statement_data: function () {
- return $.when(Datas.used.data_preprocess);
+ var results = Datas.used.data_preprocess;
+ results.lines = _.filter(Datas.used.data_widget, function (w) {return _.contains(results.st_lines_ids, w.st_line.id);});
+ return $.when(results);
},
get_move_lines_for_manual_reconciliation: function (args) {
var excluded_ids = args.splice(2, 1)[0];
@@ -267,6 +276,8 @@ var db = {
};
var data_preprocess = {
+ value_min: 0,
+ value_max: 4,
notifications: [],
num_already_reconciled_lines: 0,
st_lines_ids: [5, 6, 7, 8],
@@ -865,7 +876,7 @@ QUnit.module('account', {
},
});
- clientAction.appendTo($('body'));
+ clientAction.appendTo($('#qunit-fixture'));
var widget = clientAction.widgets[0];
@@ -1048,7 +1059,7 @@ QUnit.module('account', {
assert.notOk(widget.$('.accounting_view tfoot .cell_label').text(), "should not display 'Open Balance' line because the rest to reconcile is null");
assert.strictEqual(widget.$('.accounting_view tbody tr').length, 1, "should have only the created reconcile line");
- assert.strictEqual(widget.$('.accounting_view tbody tr').text().replace(/[\n\r\s$,]+/g, ' '), " 101200 SAJ/2014/002 and SAJ/2014/003 1175.00 ",
+ assert.strictEqual(widget.$('.accounting_view tbody tr').text().replace(/[\n\r\s$,]+/g, ' '), " 101200 New SAJ/2014/002 and SAJ/2014/003 1175.00 ",
"the new line should have the selected account, name and amout");
assert.ok(widget.$('caption button.btn-primary:visible').length, "should display the 'Reconcile' button");
@@ -1071,7 +1082,7 @@ QUnit.module('account', {
assert.strictEqual(widget.$('.accounting_view tbody .cell_right').text().trim().replace(/[\n\r\s\u00a0]+/g, ' '), "$ 1100.00", "should display the value 1100.00 in right column");
assert.strictEqual(widget.$('.accounting_view tfoot .cell_right').text(), "$ 75.00", "should display 'Open Balance' line because the rest to reconcile is 75.00");
assert.strictEqual(widget.$('.accounting_view tbody tr').length, 1, "should have ever only the created reconcile line");
- assert.strictEqual(widget.$('.accounting_view tbody tr').text().replace(/[\n\r\s$,]+/g, ' '), " 101200 SAJ/2014/002 and SAJ/2014/003 1100.00 ",
+ assert.strictEqual(widget.$('.accounting_view tbody tr').text().replace(/[\n\r\s$,]+/g, ' '), " 101200 New SAJ/2014/002 and SAJ/2014/003 1100.00 ",
"the new line should be update the amout");
assert.ok(widget.$('caption button.btn-secondary:visible').length, "should display the 'validate' button");
@@ -1085,7 +1096,7 @@ QUnit.module('account', {
assert.strictEqual(widget.$('.accounting_view tfoot .cell_label').text(), "Open balance", "should display 'Open Balance'");
assert.strictEqual(widget.$('.accounting_view tfoot .cell_right').text(), "$ 175.00", "should display 'Open Balance' line because the rest to reconcile is 175.00");
assert.strictEqual(widget.$('.accounting_view tbody tr').length, 2, "should have 2 created reconcile lines");
- assert.strictEqual(widget.$('.accounting_view tbody tr:eq(1)').text().replace(/[\n\r\s$,]+/g, ' '), " 101000 test0 100.00 ",
+ assert.strictEqual(widget.$('.accounting_view tbody tr:eq(1)').text().replace(/[\n\r\s$,]+/g, ' '), " 101000 New test0 100.00 ",
"the new line should have the selected account, name and amout");
widget.$('.accounting_view tfoot td:first').trigger('click');
@@ -1236,7 +1247,7 @@ QUnit.module('account', {
widget.$('.create .create_amount input').val('100').trigger('input');
assert.strictEqual(widget.$('.accounting_view tbody').text().replace(/[\n\r\s$,]+/g, ' '),
- " 101120 ATOS Banque 1075.00 101120 Tax 20.00% 215.00 101130 ATOS Frais 90.91 101300 Tax 10.00% include 9.09 ",
+ " 101120 New ATOS Banque 1075.00 101120 New Tax 20.00% 215.00 101130 New ATOS Frais 90.91 101300 New Tax 10.00% include 9.09 ",
"should update the value of the 4 lines (because the line must have 100% of the value)");
assert.strictEqual(widget.$('.accounting_view tfoot .cell_label, .accounting_view tfoot .cell_left').text().replace(/[\n\r\s$,]+/g, ' '),
"Open balance215.00", "should change the 'Open balance' line because the 20.00% tax is not an include tax");
@@ -1249,7 +1260,7 @@ QUnit.module('account', {
widget.$('.create .quick_add button:contains(Double)').trigger('click');
assert.strictEqual(widget.$('.accounting_view tbody').text().replace(/[\n\r\s$,]+/g, ' '),
- " 101120 Double Banque 1145.62 101130 Double Frais 29.38 ",
+ " 101120 New Double Banque 1145.62 101130 New Double Frais 29.38 ",
"should have a sum of reconciliation proposition amounts equal to the line amount");
clientAction.destroy();
@@ -1306,240 +1317,6 @@ 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,
- session: {
- currencies: {
- 3: {
- digits: [69, 2],
- position: "before",
- symbol: "$"
- }
- }
- },
- });
-
- 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.$('.accounting_view:has(.o_reconcile:visible) thead .cell_action').click();
- 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.$('thead .cell_action:eq(1)').click();
- 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();
- });
-
QUnit.test('Reconciliation: Payment < inv1 + inv2(partial)', function (assert) {
assert.expect(4);
@@ -1780,8 +1557,7 @@ QUnit.module('account', {
// Add first prop
widget.$('.match .cell_account_code:first').trigger('click');
- assert.notOk( widget.$('.cell_right .line_info_button').length,
- "should not display the partial reconciliation alert");
+ assert.equal( widget.$('.cell_right .line_info_button').length, 1, "should display the partial reconciliation alert");
// Add second prop
widget.$('.match .cell_account_code:first').trigger('click');