From 562fc998bf841f78698bb8006a6ef1d84ff03fc3 Mon Sep 17 00:00:00 2001
From: Arthur Maniet <me@whisno.be>
Date: Fri, 5 Dec 2014 15:10:32 +0100
Subject: [PATCH] [IMP/FIX] account: bank statement reconciliation widget:
 adopt a more logical approach to reconciliation balancing, as explained in
 https://github.com/odoo/odoo/issues/4017#issuecomment-66599534 Fixes #4017

---
 .../account_bank_statement_reconciliation.css | 11 ++-
 ...account_bank_statement_reconciliation.scss | 13 ++-
 .../account/static/src/js/account_widgets.js  | 97 +++++++++----------
 .../account_bank_statement_reconciliation.xml |  3 +-
 4 files changed, 67 insertions(+), 57 deletions(-)

diff --git a/addons/account/static/src/css/account_bank_statement_reconciliation.css b/addons/account/static/src/css/account_bank_statement_reconciliation.css
index 6ce216410e7f..50202d158482 100644
--- a/addons/account/static/src/css/account_bank_statement_reconciliation.css
+++ b/addons/account/static/src/css/account_bank_statement_reconciliation.css
@@ -220,10 +220,14 @@
           padding-bottom: 3px; }
       .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption {
         text-align: left;
-        font-size: 1.1em;
-        font-weight: bold;
         height: 26px;
         margin: 0 15px 4px 15px; }
+        .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption .partner_name {
+          font-size: 1.1em;
+          font-weight: bold; }
+        .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption .tip_reconciliation_not_balanced {
+          float: right;
+          padding-right: 7px; }
         .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption button {
           float: right; }
           .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption button:disabled {
@@ -231,8 +235,7 @@
         .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption > span, .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view caption > input {
           position: relative;
           top: 7px;
-          /* meh */
-          font-weight: bold; }
+          /* meh */ }
       .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .accounting_view td.cell_credit {
         border-left: 1px solid #000; }
     .openerp .oe_bank_statement_reconciliation .oe_bank_statement_reconciliation_line .match .match_controls {
diff --git a/addons/account/static/src/css/account_bank_statement_reconciliation.scss b/addons/account/static/src/css/account_bank_statement_reconciliation.scss
index ced682034a6f..c52be9263da6 100644
--- a/addons/account/static/src/css/account_bank_statement_reconciliation.scss
+++ b/addons/account/static/src/css/account_bank_statement_reconciliation.scss
@@ -362,11 +362,19 @@ $aestetic_animation_speed: 300ms;
 
             caption {
                 text-align: left;
-                font-size: 1.1em;
-                font-weight: bold;
                 height: 26px;
                 margin: 0 $actionColWidth 4px $actionColWidth;
 
+                .partner_name {
+                    font-size: 1.1em;
+                    font-weight: bold;
+                }
+
+                .tip_reconciliation_not_balanced {
+                    float: right;
+                    padding-right: 7px;
+                }
+
                 button {
                     float: right;
 
@@ -377,7 +385,6 @@ $aestetic_animation_speed: 300ms;
 
                 > span, > input {
                     position: relative; top: 7px; /* meh */
-                    font-weight: bold;
                 }
             }
 
diff --git a/addons/account/static/src/js/account_widgets.js b/addons/account/static/src/js/account_widgets.js
index 1b26a2a094f7..ce9be4793faf 100644
--- a/addons/account/static/src/js/account_widgets.js
+++ b/addons/account/static/src/js/account_widgets.js
@@ -1246,50 +1246,62 @@ openerp.account = function (instance) {
     
         /** Properties changed */
     
-        // Updates the validation button and the "open balance" line
+        // Updates the validation button, the "open balance" line and the  partial reconciliation sign
         balanceChanged: function() {
             var self = this;
-            var balance = self.get("balance");
+                
+            // 'reset' the widget to invalid state
+            self.is_valid = false;
+            self.$(".tip_reconciliation_not_balanced").show();
             self.$(".tbody_open_balance").empty();
-            // Special case hack : no identified partner
-            if (self.st_line.has_no_partner) {
-                if (Math.abs(balance).toFixed(3) === "0.000") {
-                    self.$(".button_ok").addClass("oe_highlight");
-                    self.$(".button_ok").removeAttr("disabled");
-                    self.$(".button_ok").text("OK");
-                    self.is_valid = true;
+            self.$(".button_ok").text("OK").removeClass("oe_highlight").attr("disabled", "disabled");
+
+            // Find out if the counterpart is lower than, equal or greater than the transaction being reconciled
+            var balance_type = undefined;
+            if (Math.abs(self.get("balance")).toFixed(3) === "0.000") balance_type = "equal";
+            else if (self.get("balance") * self.st_line.amount > 0) balance_type = "greater";
+            else if (self.get("balance") * self.st_line.amount < 0) balance_type = "lower";
+
+            // Adjust to different cases
+            if (balance_type === "equal") {
+                displayValidState(true);
+            } else if (balance_type === "greater") {
+                createOpenBalance("Create Write-off");
+            } else if (balance_type === "lower") {
+                if (self.st_line.has_no_partner) {
+                    createOpenBalance("Choose counterpart");
                 } else {
-                    self.$(".button_ok").removeClass("oe_highlight");
-                    self.$(".button_ok").attr("disabled", "disabled");
-                    self.$(".button_ok").text("OK");
-                    self.is_valid = false;
-                    var debit = (balance > 0 ? self.formatCurrency(balance, self.st_line.currency_id) : "");
-                    var credit = (balance < 0 ? self.formatCurrency(-1*balance, self.st_line.currency_id) : "");
-                    var $line = $(QWeb.render("bank_statement_reconciliation_line_open_balance", {
-                        debit: debit,
-                        credit: credit,
-                        account_code: self.map_account_id_code[self.st_line.open_balance_account_id]
-                    }));
-                    $line.find('.js_open_balance')[0].innerHTML = _t("Choose counterpart");
-                    self.$(".tbody_open_balance").append($line);
+                    displayValidState(false, "Keep open");
+                    createOpenBalance("Open balance");
                 }
-                return;
             }
-    
-            if (Math.abs(balance).toFixed(3) === "0.000") {
-                self.$(".button_ok").addClass("oe_highlight");
-                self.$(".button_ok").text("OK");
-            } else {
-                self.$(".button_ok").removeClass("oe_highlight");
-                self.$(".button_ok").text("Keep open");
-                var debit = (balance > 0 ? self.formatCurrency(balance, self.st_line.currency_id) : "");
-                var credit = (balance < 0 ? self.formatCurrency(-1*balance, self.st_line.currency_id) : "");
+
+            // Show or hide partial reconciliation
+            if (self.get("mv_lines_selected").length > 0) {
+                var propose_partial = self.getCreatedLines().length === 0 && self.get("mv_lines_selected").length === 1 && balance_type === "greater" && ! self.get("mv_lines_selected")[0].partial_reconcile;
+                self.get("mv_lines_selected")[0].propose_partial_reconcile = propose_partial;
+                self.updateAccountingViewMatchedLines();
+            }
+
+            function displayValidState(higlight_ok_button, ok_button_text) {
+                self.is_valid = true;
+                self.$(".tip_reconciliation_not_balanced").hide();
+                self.$(".button_ok").removeAttr("disabled");
+                if (higlight_ok_button) self.$(".button_ok").addClass("oe_highlight");
+                if (ok_button_text !== undefined) self.$(".button_ok").text(ok_button_text)
+            }
+
+            function createOpenBalance(name) {
+                var balance = self.get("balance");
+                var amount = self.formatCurrency(Math.abs(balance), self.st_line.currency_id);
                 var $line = $(QWeb.render("bank_statement_reconciliation_line_open_balance", {
-                    debit: debit,
-                    credit: credit,
+                    debit: balance > 0 ? amount : "",
+                    credit: balance < 0 ? amount : "",
                     account_code: self.map_account_id_code[self.st_line.open_balance_account_id]
                 }));
-                self.$(".tbody_open_balance").append($line);
+                if (name !== undefined)
+                    $line.find(".cell_label").text(name);
+                self.$(".tbody_open_balance").empty().append($line);
             }
         },
     
@@ -1532,21 +1544,8 @@ openerp.account = function (instance) {
             });
             // Dealing with floating-point
             balance = Math.round(balance*1000)/1000;
+
             self.set("balance", balance);
-    
-            // Propose partial reconciliation if necessary
-            if (self.getCreatedLines().length === 0 &&
-                lines_selected_num === 1 &&
-                self.st_line.amount * balance > 0 &&
-                self.st_line.amount * (mv_lines_selected[0].debit - mv_lines_selected[0].credit) < 0 &&
-                ! mv_lines_selected[0].partial_reconcile) {
-                
-                mv_lines_selected[0].propose_partial_reconcile = true;
-                self.updateAccountingViewMatchedLines();
-            } else if (lines_selected_num === 1) {
-                mv_lines_selected[0].propose_partial_reconcile = false;
-                self.updateAccountingViewMatchedLines();
-            }
         },
 
         // Loads move lines according to the widget's state
diff --git a/addons/account/static/src/xml/account_bank_statement_reconciliation.xml b/addons/account/static/src/xml/account_bank_statement_reconciliation.xml
index 1a0653494b7f..603f158b2db3 100644
--- a/addons/account/static/src/xml/account_bank_statement_reconciliation.xml
+++ b/addons/account/static/src/xml/account_bank_statement_reconciliation.xml
@@ -64,6 +64,7 @@
                     <table class="accounting_view">
                         <caption>
                             <button class="button_ok"></button>
+                            <span class="tip_reconciliation_not_balanced">You must balance the reconciliation</span>
                             <span t-if="! line.has_no_partner" class="partner_name">
                                 <t t-esc="line.partner_name"/>
                                 <span class="change_partner glyphicon glyphicon-pencil"></span>
@@ -190,7 +191,7 @@
             <td class="cell_action"><span class="toggle_create glyphicon glyphicon-play"></span></td>
             <td class="cell_account_code"><t t-esc="account_code"/></td>
             <td class="cell_due_date"></td>
-            <td class="cell_label js_open_balance">Open balance</td>
+            <td class="cell_label">Open balance</td>
             <td class="cell_debit"><t t-esc="debit"/></td>
             <td class="cell_credit"><t t-esc="credit"/></td>
             <td class="cell_info_popover"></td>
-- 
GitLab