summaryrefslogtreecommitdiff
path: root/addons/account/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/account/static/src')
-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
5 files changed, 147 insertions, 124 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>