From 1ca3b3df3421961caec3b747a364071c80f5c7da Mon Sep 17 00:00:00 2001
From: stephanchrst
Date: Tue, 10 May 2022 17:14:58 +0700
Subject: initial commit
---
base_accounting_kit/static/src/js/account_asset.js | 87 +
.../static/src/js/account_dashboard.js | 1844 +++++++++++++++++++
.../static/src/js/payment_matching.js | 505 ++++++
base_accounting_kit/static/src/js/payment_model.js | 1881 ++++++++++++++++++++
.../static/src/js/payment_render.js | 929 ++++++++++
.../static/src/scss/account_asset.scss | 9 +
base_accounting_kit/static/src/scss/style.scss | 1164 ++++++++++++
.../static/src/xml/payment_matching.xml | 402 +++++
base_accounting_kit/static/src/xml/template.xml | 324 ++++
9 files changed, 7145 insertions(+)
create mode 100644 base_accounting_kit/static/src/js/account_asset.js
create mode 100644 base_accounting_kit/static/src/js/account_dashboard.js
create mode 100644 base_accounting_kit/static/src/js/payment_matching.js
create mode 100644 base_accounting_kit/static/src/js/payment_model.js
create mode 100644 base_accounting_kit/static/src/js/payment_render.js
create mode 100644 base_accounting_kit/static/src/scss/account_asset.scss
create mode 100644 base_accounting_kit/static/src/scss/style.scss
create mode 100644 base_accounting_kit/static/src/xml/payment_matching.xml
create mode 100644 base_accounting_kit/static/src/xml/template.xml
(limited to 'base_accounting_kit/static/src')
diff --git a/base_accounting_kit/static/src/js/account_asset.js b/base_accounting_kit/static/src/js/account_asset.js
new file mode 100644
index 0000000..a60c8b6
--- /dev/null
+++ b/base_accounting_kit/static/src/js/account_asset.js
@@ -0,0 +1,87 @@
+odoo.define('base_accounting_kit.account_asset', function(require) {
+"use strict";
+
+/**
+ * The purpose of this widget is to shows a toggle button on depreciation and
+ * installment lines for posted/unposted line. When clicked, it calls the method
+ * create_move on the object account.asset.depreciation.line.
+ * Note that this widget can only work on the account.asset.depreciation.line
+ * model as some of its fields are harcoded.
+ */
+
+var AbstractField = require('web.AbstractField');
+var core = require('web.core');
+var registry = require('web.field_registry');
+
+var _t = core._t;
+
+var AccountAssetWidget = AbstractField.extend({
+ events: _.extend({}, AbstractField.prototype.events, {
+ 'click': '_onClick',
+ }),
+ description: "",
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ isSet: function () {
+ return true; // it should always be displayed, whatever its value
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ * @private
+ */
+ _render: function () {
+ var className = '';
+ var disabled = true;
+ var title;
+ if (this.recordData.move_posted_check) {
+ className = 'o_is_posted';
+ title = _t('Posted');
+ } else if (this.recordData.move_check) {
+ className = 'o_unposted';
+ title = _t('Accounting entries waiting for manual verification');
+ } else {
+ disabled = false;
+ title = _t('Unposted');
+ }
+ var $button = $('', {
+ type: 'button',
+ title: title,
+ disabled: disabled,
+ }).addClass('btn btn-sm btn-link fa fa-circle o_deprec_lines_toggler ' + className);
+ this.$el.html($button);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {MouseEvent} event
+ */
+ _onClick: function (event) {
+ event.stopPropagation();
+ this.trigger_up('button_clicked', {
+ attrs: {
+ name: 'create_move',
+ type: 'object',
+ },
+ record: this.record,
+ });
+ },
+});
+
+registry.add("deprec_lines_toggler", AccountAssetWidget);
+
+});
diff --git a/base_accounting_kit/static/src/js/account_dashboard.js b/base_accounting_kit/static/src/js/account_dashboard.js
new file mode 100644
index 0000000..79f7b1a
--- /dev/null
+++ b/base_accounting_kit/static/src/js/account_dashboard.js
@@ -0,0 +1,1844 @@
+odoo.define('AccountingDashboard.AccountingDashboard', function(require) {
+ 'use strict';
+ var AbstractAction = require('web.AbstractAction');
+ var ajax = require('web.ajax');
+ var core = require('web.core');
+ var rpc = require('web.rpc');
+ var web_client = require('web.web_client');
+ var _t = core._t;
+ var QWeb = core.qweb;
+ var self = this;
+ var currency;
+ var ActionMenu = AbstractAction.extend({
+
+ contentTemplate: 'Invoicedashboard',
+
+ events: {
+ 'click .invoice_dashboard': 'onclick_dashboard',
+ 'click #prog_bar': 'onclick_prog_bar',
+ 'click #invoice_this_month': 'onclick_invoice_this_month',
+ 'click #invoice_this_year': 'onclick_invoice_this_year',
+ 'click #invoice_last_month': 'onclick_invoice_last_month',
+ 'click #invoice_last_year': 'onclick_invoice_last_year',
+ 'click #onclick_banks_balance': 'onclick_bank_balance',
+ 'click #income_this_month': 'onclick_income_this_month',
+ 'click #income_this_year': 'onclick_income_this_year',
+ 'click #income_last_month': 'onclick_income_last_month',
+ 'click #income_last_year': 'onclick_income_last_year',
+ 'click #total_aged_payable': 'onclick_total_aged_payable',
+ 'click #in_ex_bar_chart': 'onclick_in_ex_bar_chart',
+ 'click #aged_recevable_pie_chart': 'onclick_aged_recevable_pie_chart',
+ 'click #invoice_bar_chart': 'onclick_invoice_bar_chart',
+ 'click .overdue_line_cust': 'onclick_overdue_line_cust',
+ 'click .top_customers': 'onclick_top_customers',
+ 'click .top_customers_amount': 'onclick_top_customers_amount',
+ 'click #bank_balance_hide': 'onclick_bank_balance_hide',
+ 'click #cash_balance_hide': 'onclick_cash_balance_hide',
+ 'click #in_ex_hide': 'onclick_in_ex_hide',
+ 'click #aged_payable_hide': 'onclick_aged_payable_hide',
+ 'change #aged_receivable_values': function(e) {
+ e.stopPropagation();
+ var $target = $(e.target);
+ var value = $target.val();
+ // this.$('.aged_receivable_this_month').empty();
+ this.onclick_aged_payable(this.$('#aged_receivable_values').val());
+ },
+ 'change #aged_payable_value': function(e) {
+ e.stopPropagation();
+ var $target = $(e.target);
+ var value = $target.val();
+ this.$('.aged_receivable_this_month').empty();
+ this.onclick_aged_receivable(this.$('#aged_payable_value').val());
+ },
+ 'change #top_10_customer_value': function(e) {
+ e.stopPropagation();
+ var $target = $(e.target);
+ var value = $target.val();
+ this.$('.top_10_customers_this_month').empty();
+ this.onclick_top_10_month(this.$('#top_10_customer_value').val());
+ },
+ 'change #toggle-two': 'onclick_toggle_two',
+ 'click #unreconciled_counts_this_year': 'unreconciled_year',
+ 'click #unreconciled_items_': 'unreconciled_month',
+ 'click #total_customer_invoice_paid_current_month': 'invoice_month_paid',
+ 'click #total_customer_invoice_current_month': 'invoice_month',
+ 'click #total_supplier_invoice_paid_current_month': 'bill_month_paid',
+ 'click #total_supplier_invoice_current_month': 'bill_month',
+ 'click #total_customer_invoice_paid_current_year': 'invoice_year_paid',
+ 'click #total_customer_invoice_current_year': 'invoice_year',
+ 'click #total_supplier_invoice_paid_current_year': 'bill_year_paid',
+ 'click #total_supplier_invoice_current_year': 'bill_year',
+ 'click #net_profit_current_year': 'profit_income_year',
+ 'click #net_profit_current_months': 'profit_income_month',
+ 'click #total_incomes_this_year': 'total_income_year',
+ 'click #total_incomes_': 'total_income_month',
+ 'click #total_expense_this_year': 'expense_year',
+ 'click #total_expenses_': 'expense_month',
+ },
+ profit_income_year: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_profit_income_year",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Net Profit or Loss'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ profit_income_month: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_profit_income_month",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Net Profit or Loss'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ total_income_year: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_total_income_year",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Total Income'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ total_income_month: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_total_income_month",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Total Income'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ expense_year: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_expense_year",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Total Expenses'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ expense_month: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_expense_month",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Total Expenses'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ unreconciled_year: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_unreconcile_year",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Unreconciled'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ unreconciled_month: function(ev) {
+ var posted = false;
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_unreconcile_month",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move.line',
+ name: _t('Unreconciled'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ invoice_month_paid: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_invoice_month_paid",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Paid'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ invoice_month: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_invoice_month",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Invoice'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ bill_month_paid: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_bill_month_paid",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Paid'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ bill_month: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_bill_month",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Invoice'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ bill_year: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_bill_year",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Invoice'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ bill_year_paid: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_bill_year_paid",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Paid'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ invoice_year: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_invoice_year",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Invoice'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+ invoice_year_paid: function(ev) {
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ var self = this;
+ rpc.query({
+ model: "account.move",
+ method: "click_invoice_year_paid",
+ args: [posted],
+ }).then(function(result) {
+ self.do_action({
+ res_model: 'account.move',
+ name: _t('Paid'),
+ views: [
+ [false, 'list'],
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ domain: [
+ ['id', 'in', result]
+ ],
+ });
+ })
+ },
+
+ onclick_toggle_two: function(ev) {
+
+ this.onclick_aged_payable(this.$('#aged_receivable_values').val());
+
+ this.onclick_aged_receivable(this.$('#aged_payable_value').val());
+ this.onclick_invoice_this_year(ev);
+ this.onclick_invoice_this_month(ev);
+
+ this.onclick_income_this_month(ev);
+ this.onclick_income_last_month(ev);
+ this.onclick_income_last_year(ev);
+ this.onclick_income_this_year(ev);
+ },
+
+ onclick_top_10_month: function(f) {
+ var selected = $('.btn.btn-tool.income');
+ var data = $(selected[0]).data();
+ var posted = false;
+ var self = this;
+ var f = f;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: "account.move",
+ method: "get_currency",
+ }).then(function(result) {
+ currency = result;
+ })
+ rpc.query({
+ model: "account.move",
+ method: "get_top_10_customers_month",
+ args: [posted, f]
+ })
+ .then(function(result) {
+ $('#top_10_customers').hide();
+ $('#top_10_customers_last_month').hide();
+ $('#top_10_customers_this_month').show();
+ $('#top_10_customers_this_month').empty();
+
+ var due_count = 0;
+ _.forEach(result, function(x) {
+ due_count++;
+ var amount = self.format_currency(currency, x.amount);
+ $('#top_10_customers_this_month').append('' + x.customers + '
' + '' + amount + '
' + '');
+ $('#line_' + x.parent).on("click", function() {
+ self.do_action({
+ res_model: 'res.partner',
+ name: _t('Partner'),
+ views: [
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ res_id: x.parent,
+ });
+ });
+ });
+
+
+ })
+ },
+
+ onclick_income_last_year: function(ev) {
+ ev.preventDefault();
+ var selected = $('.btn.btn-tool.income');
+ var data = $(selected[0]).data();
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: 'account.move',
+ method: 'get_income_last_year',
+ args: [posted],
+ })
+ .then(function(result) {
+
+ $('#net_profit_current_months').hide();
+ $('#net_profit_last_month').hide();
+ $('#net_profit_last_year').show();
+ $('#net_profit_this_year').hide();
+
+ var ctx = document.getElementById("canvas").getContext('2d');
+
+ // Define the data
+ var income = result.income; // Add data values to array
+ var expense = result.expense;
+ var profit = result.profit;
+
+ var labels = result.month; // Add labels to array
+ // End Defining data
+
+ // End Defining data
+ if (window.myCharts != undefined)
+ window.myCharts.destroy();
+ window.myCharts = new Chart(ctx, {
+ //var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: labels,
+ datasets: [{
+ label: 'Income', // Name the series
+ data: income, // Specify the data values array
+ backgroundColor: '#66aecf',
+ borderColor: '#66aecf',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Expense', // Name the series
+ data: expense, // Specify the data values array
+ backgroundColor: '#6993d6',
+ borderColor: '#6993d6',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Profit/Loss', // Name the series
+ data: profit, // Specify the data values array
+ backgroundColor: '#0bd465',
+ borderColor: '#0bd465',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'line', // Set this data to a line chart
+ fill: false
+ }
+ ]
+ },
+ options: {
+ responsive: true, // Instruct chart js to respond nicely.
+ maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height
+ }
+ });
+
+ })
+ },
+
+ onclick_income_last_month: function(ev) {
+ ev.preventDefault();
+ var selected = $('.btn.btn-tool.income');
+ var data = $(selected[0]).data();
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: 'account.move',
+ method: 'get_income_last_month',
+ args: [posted],
+ })
+ .then(function(result) {
+ $('#net_profit_current_months').hide();
+ $('#net_profit_last_month').show();
+ $('#net_profit_this_year').hide();
+ $('#net_profit_last_year').hide();
+
+ var ctx = document.getElementById("canvas").getContext('2d');
+
+ // Define the data
+ var income = result.income; // Add data values to array
+ var expense = result.expense;
+ var profit = result.profit;
+
+ var labels = result.date; // Add labels to array
+ // End Defining data
+
+ // End Defining data
+ if (window.myCharts != undefined)
+ window.myCharts.destroy();
+ window.myCharts = new Chart(ctx, {
+ //var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: labels,
+ datasets: [{
+ label: 'Income', // Name the series
+ data: income, // Specify the data values array
+ backgroundColor: '#66aecf',
+ borderColor: '#66aecf',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Expense', // Name the series
+ data: expense, // Specify the data values array
+ backgroundColor: '#6993d6',
+ borderColor: '#6993d6',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Profit/Loss', // Name the series
+ data: profit, // Specify the data values array
+ backgroundColor: '#0bd465',
+ borderColor: '#0bd465',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'line', // Set this data to a line chart
+ fill: false
+ }
+ ]
+ },
+ options: {
+ responsive: true, // Instruct chart js to respond nicely.
+ maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height
+ }
+ });
+
+ })
+ },
+ onclick_income_this_year: function(ev) {
+ ev.preventDefault();
+ var selected = $('.btn.btn-tool.income');
+ var data = $(selected[0]).data();
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+
+
+ rpc.query({
+ model: 'account.move',
+ method: 'get_income_this_year',
+ args: [posted],
+
+ })
+ .then(function(result) {
+
+
+ $('#net_profit_current_months').hide();
+ $('#net_profit_last_month').hide();
+ $('#net_profit_last_year').hide();
+ $('#net_profit_this_year').show();
+
+ var ctx = document.getElementById("canvas").getContext('2d');
+
+ // Define the data
+ var income = result.income; // Add data values to array
+ var expense = result.expense;
+ var profit = result.profit;
+
+ var labels = result.month; // Add labels to array
+
+
+ if (window.myCharts != undefined)
+ window.myCharts.destroy();
+ window.myCharts = new Chart(ctx, {
+ //var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: labels,
+ datasets: [{
+ label: 'Income', // Name the series
+ data: income, // Specify the data values array
+ backgroundColor: '#66aecf',
+ borderColor: '#66aecf',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Expense', // Name the series
+ data: expense, // Specify the data values array
+ backgroundColor: '#6993d6',
+ borderColor: '#6993d6',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Profit/Loss', // Name the series
+ data: profit, // Specify the data values array
+ backgroundColor: '#0bd465',
+ borderColor: '#0bd465',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'line', // Set this data to a line chart
+ fill: false
+ }
+ ]
+ },
+ options: {
+ responsive: true, // Instruct chart js to respond nicely.
+ maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height
+ }
+ });
+
+ })
+ },
+
+
+ onclick_invoice_this_year: function(ev) {
+ ev.preventDefault();
+ var selected = $('.btn.btn-tool.selected');
+ var data = $(selected[0]).data();
+ var posted = false;
+ var self = this;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+
+ rpc.query({
+ model: "account.move",
+ method: "get_currency",
+ }).then(function(result) {
+ currency = result;
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "get_total_invoice_current_year",
+ args: [posted],
+ })
+ .then(function(result) {
+
+ $('#total_supplier_invoice_paid').hide();
+ $('#total_supplier_invoice').hide();
+ $('#total_customer_invoice_paid').hide();
+ $('#total_customer_invoice').hide();
+ $('#tot_invoice').hide();
+ $('#tot_supplier_inv').hide();
+
+ $('#total_supplier_invoice_paid_current_month').hide();
+ $('#total_supplier_invoice_current_month').hide();
+ $('#total_customer_invoice_paid_current_month').hide();
+ $('#total_customer_invoice_current_month').hide();
+ $('#tot_invoice_current_month').hide();
+ $('#tot_supplier_inv_current_month').hide();
+
+
+ $('#total_supplier_invoice_paid_current_year').empty();
+ $('#total_supplier_invoice_current_year').empty();
+ $('#total_customer_invoice_paid_current_year').empty();
+ $('#total_customer_invoice_current_year').empty();
+ $('#tot_invoice_current_year').empty();
+ $('#tot_supplier_inv_current_year').empty();
+
+ $('#total_supplier_invoice_paid_current_year').show();
+ $('#total_supplier_invoice_current_year').show();
+ $('#total_customer_invoice_paid_current_year').show();
+ $('#total_customer_invoice_current_year').show();
+ $('#tot_invoice_current_year').show();
+ $('#tot_supplier_inv_current_year').show();
+ var tot_invoice_current_year = result[0][0]
+ var tot_credit_current_year = result[1][0]
+ var tot_supplier_inv_current_year = result[2][0]
+ var tot_supplier_refund_current_year = result[3][0]
+ var tot_customer_invoice_paid_current_year = result[4][0]
+ var tot_supplier_invoice_paid_current_year = result[5][0]
+ var tot_customer_credit_paid_current_year = result[6][0]
+ var tot_supplier_refund_paid_current_year = result[7][0]
+ var customer_invoice_total_current_year = (tot_invoice_current_year - tot_credit_current_year).toFixed(2)
+ var customer_invoice_paid_current_year = (tot_customer_invoice_paid_current_year - tot_customer_credit_paid_current_year).toFixed(2)
+ var invoice_percentage_current_year = ((customer_invoice_total_current_year / customer_invoice_paid_current_year) * 100).toFixed(2)
+ var supplier_invoice_total_current_year = (tot_supplier_inv_current_year - tot_supplier_refund_current_year).toFixed(2)
+ var supplier_invoice_paid_current_year = (tot_supplier_invoice_paid_current_year - tot_supplier_refund_paid_current_year).toFixed(2)
+ var supplier_percentage_current_year = ((supplier_invoice_total_current_year / supplier_invoice_paid_current_year) * 100).toFixed(2)
+
+ $('#tot_supplier_inv_current_year').attr("value", supplier_invoice_paid_current_year);
+ $('#tot_supplier_inv_current_year').attr("max", supplier_invoice_total_current_year);
+
+ $('#tot_invoice_current_year').attr("value", customer_invoice_paid_current_year);
+ $('#tot_invoice_current_year').attr("max", customer_invoice_total_current_year);
+
+ customer_invoice_paid_current_year = self.format_currency(currency, customer_invoice_paid_current_year);
+ customer_invoice_total_current_year = self.format_currency(currency, customer_invoice_total_current_year);
+ supplier_invoice_paid_current_year = self.format_currency(currency, supplier_invoice_paid_current_year);
+ supplier_invoice_total_current_year = self.format_currency(currency, supplier_invoice_total_current_year);
+
+ $('#total_customer_invoice_paid_current_year').append('' + '' + customer_invoice_paid_current_year + 'Total Paid
');
+ $('#total_customer_invoice_current_year').append('' + '' + customer_invoice_total_current_year + 'Total Invoice
');
+
+ $('#total_supplier_invoice_paid_current_year').append('' + '' + supplier_invoice_paid_current_year + 'Total Paid
');
+ $('#total_supplier_invoice_current_year').append('' + '' + supplier_invoice_total_current_year + 'Total Invoice
');
+
+ })
+ },
+ onclick_invoice_this_month: function(ev) {
+ ev.preventDefault();
+ var selected = $('.btn.btn-tool.selected');
+ var data = $(selected[0]).data();
+ var posted = false;
+ var self = this;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: "account.move",
+ method: "get_currency",
+ }).then(function(result) {
+ currency = result;
+ })
+ rpc.query({
+ model: "account.move",
+ method: "get_total_invoice_current_month",
+ args: [posted],
+ })
+ .then(function(result) {
+ $('#total_supplier_invoice_paid').hide();
+ $('#total_supplier_invoice').hide();
+ $('#total_customer_invoice_paid').hide();
+ $('#total_customer_invoice').hide();
+ $('#tot_invoice').hide();
+ $('#tot_supplier_inv').hide();
+ $('#total_supplier_invoice_paid_current_month').empty();
+ $('#total_supplier_invoice_current_month').empty();
+ $('#total_customer_invoice_paid_current_month').empty();
+ $('#total_customer_invoice_current_month').empty();
+ $('#tot_invoice_current_month').empty();
+ $('#tot_supplier_inv_current_month').empty();
+ $('#total_supplier_invoice_paid_current_year').hide();
+ $('#total_supplier_invoice_current_year').hide();
+ $('#total_customer_invoice_paid_current_year').hide();
+ $('#total_customer_invoice_current_year').hide();
+ $('#tot_invoice_current_year').hide();
+ $('#tot_supplier_inv_current_year').hide();
+ $('#total_supplier_invoice_paid_current_month').show();
+ $('#total_supplier_invoice_current_month').show();
+ $('#total_customer_invoice_paid_current_month').show();
+ $('#total_customer_invoice_current_month').show();
+ $('#tot_invoice_current_month').show();
+ $('#tot_supplier_inv_current_month').show();
+ var tot_invoice_current_month = result[0][0]
+ var tot_credit_current_month = result[1][0]
+ var tot_supplier_inv_current_month = result[2][0]
+ var tot_supplier_refund_current_month = result[3][0]
+ var tot_customer_invoice_paid_current_month = result[4][0]
+ var tot_supplier_invoice_paid_current_month = result[5][0]
+ var tot_customer_credit_paid_current_month = result[6][0]
+ var tot_supplier_refund_paid_current_month = result[7][0]
+ var customer_invoice_total_current_month = (tot_invoice_current_month - tot_credit_current_month).toFixed(2)
+ var customer_invoice_paid_current_month = (tot_customer_invoice_paid_current_month - tot_customer_credit_paid_current_month).toFixed(2)
+ var invoice_percentage_current_month = ((customer_invoice_total_current_month / customer_invoice_paid_current_month) * 100).toFixed(2)
+ var supplier_invoice_total_current_month = (tot_supplier_inv_current_month - tot_supplier_refund_current_month).toFixed(2)
+ var supplier_invoice_paid_current_month = (tot_supplier_invoice_paid_current_month - tot_supplier_refund_paid_current_month).toFixed(2)
+ var supplier_percentage_current_month = ((supplier_invoice_total_current_month / supplier_invoice_paid_current_month) * 100).toFixed(2)
+
+ $('#tot_supplier_inv_current_month').attr("value", supplier_invoice_paid_current_month);
+ $('#tot_supplier_inv_current_month').attr("max", supplier_invoice_total_current_month);
+
+ $('#tot_invoice_current_month').attr("value", customer_invoice_paid_current_month);
+ $('#tot_invoice_current_month').attr("max", customer_invoice_total_current_month);
+
+ customer_invoice_paid_current_month = self.format_currency(currency, customer_invoice_paid_current_month);
+ customer_invoice_total_current_month = self.format_currency(currency, customer_invoice_total_current_month);
+ supplier_invoice_paid_current_month = self.format_currency(currency, supplier_invoice_paid_current_month);
+ supplier_invoice_total_current_month = self.format_currency(currency, supplier_invoice_total_current_month);
+
+
+ $('#total_customer_invoice_paid_current_month').append('' + '' + customer_invoice_paid_current_month + 'Total Paid
');
+ $('#total_customer_invoice_current_month').append('' + '' + customer_invoice_total_current_month + 'Total Invoice
');
+
+ $('#total_supplier_invoice_paid_current_month').append('' + '' + supplier_invoice_paid_current_month + 'Total Paid
');
+ $('#total_supplier_invoice_current_month').append('' + '' + supplier_invoice_total_current_month + 'Total Invoice
');
+
+ })
+ },
+
+ onclick_income_this_month: function(ev) {
+ ev.preventDefault();
+ var selected = $('.btn.btn-tool.income');
+ var data = $(selected[0]).data();
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: 'account.move',
+ method: 'get_income_this_month',
+ args: [posted],
+
+ })
+ .then(function(result) {
+
+
+ var ctx = document.getElementById("canvas").getContext('2d');
+
+ // Define the data
+ var income = result.income; // Add data values to array
+ var expense = result.expense;
+ var profit = result.profit;
+
+ var labels = result.date; // Add labels to array
+ // End Defining data
+
+ // End Defining data
+ if (window.myCharts != undefined)
+ window.myCharts.destroy();
+ window.myCharts = new Chart(ctx, {
+ //var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: labels,
+ datasets: [{
+ label: 'Income', // Name the series
+ data: income, // Specify the data values array
+ backgroundColor: '#66aecf',
+ borderColor: '#66aecf',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Expense', // Name the series
+ data: expense, // Specify the data values array
+ backgroundColor: '#6993d6',
+ borderColor: '#6993d6',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Profit/Loss', // Name the series
+ data: profit, // Specify the data values array
+ backgroundColor: '#0bd465',
+ borderColor: '#0bd465',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'line', // Set this data to a line chart
+ fill: false
+ }
+ ]
+ },
+ options: {
+ responsive: true, // Instruct chart js to respond nicely.
+ maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height
+ }
+ });
+
+ })
+ },
+
+ onclick_aged_payable: function(f) {
+
+ // ev.preventDefault();
+ var arg = f;
+ var selected = $('.btn.btn-tool.expense');
+ var data = $(selected[0]).data();
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: 'account.move',
+ method: 'get_overdues_this_month_and_year',
+ args: [posted, f],
+ })
+ .then(function(result) {
+ // Doughnut Chart
+ $(document).ready(function() {
+ var options = {
+ // legend: false,
+ responsive: false
+ };
+ if (window.donut != undefined)
+ window.donut.destroy();
+
+
+ window.donut = new Chart($("#canvas1"), {
+ type: 'doughnut',
+ tooltipFillColor: "rgba(51, 51, 51, 0.55)",
+ data: {
+ labels: result.due_partner,
+ datasets: [{
+ data: result.due_amount,
+ backgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ],
+ hoverBackgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ]
+ }]
+ },
+ options: {
+ responsive: false
+ }
+ });
+ });
+ // Doughnut Chart
+
+ })
+ },
+
+
+ onclick_aged_receivable: function(f) {
+ var selected = $('.btn.btn-tool.expense');
+ var data = $(selected[0]).data();
+ var posted = false;
+ var f = f
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+ rpc.query({
+ model: 'account.move',
+ method: 'get_latebillss',
+ args: [posted, f],
+
+ })
+ .then(function(result) {
+ function myFunction() {
+ document.getElementByClass("btn btn-tool dropdown-toggle").text
+ document.getElementById("aged_receivable_this_month").text
+ }
+
+ $(document).ready(function() {
+ var options = {
+ // legend: false,
+ responsive: true,
+ legend: {
+ position: 'bottom'
+ }
+ };
+
+
+ if (window.donuts != undefined)
+ window.donuts.destroy();
+
+
+ window.donuts = new Chart($("#horizontalbarChart"), {
+ type: 'doughnut',
+ tooltipFillColor: "rgba(51, 51, 51, 0.55)",
+ data: {
+ labels: result.bill_partner,
+ datasets: [{
+ data: result.bill_amount,
+ backgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ],
+ hoverBackgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ]
+ }]
+ },
+ options: {
+ responsive: false
+ }
+ });
+ });
+
+
+ })
+ },
+
+ renderElement: function(ev) {
+ var self = this;
+ $.when(this._super())
+ .then(function(ev) {
+
+
+ $('#toggle-two').bootstrapToggle({
+ on: 'View All Entries',
+ off: 'View Posted Entries'
+ });
+
+
+ var posted = false;
+ if ($('#toggle-two')[0].checked == true) {
+ posted = "posted"
+ }
+
+
+ rpc.query({
+ model: "account.move",
+ method: "get_currency",
+ })
+ .then(function(result) {
+ currency = result;
+
+ })
+
+
+ rpc.query({
+ model: "account.move",
+ method: "get_income_this_month",
+ args: [posted],
+ })
+ .then(function(result) {
+
+
+ var ctx = document.getElementById("canvas").getContext('2d');
+
+ // Define the data
+ var income = result.income; // Add data values to array
+ var expense = result.expense;
+ var profit = result.profit;
+
+ var labels = result.date; // Add labels to array
+ // End Defining data
+
+ // End Defining data
+ if (window.myCharts != undefined)
+ window.myCharts.destroy();
+ window.myCharts = new Chart(ctx, {
+ //var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: labels,
+ datasets: [{
+ label: 'Income', // Name the series
+ data: income, // Specify the data values array
+ backgroundColor: '#66aecf',
+ borderColor: '#66aecf',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Expense', // Name the series
+ data: expense, // Specify the data values array
+ backgroundColor: '#6993d6',
+ borderColor: '#6993d6',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'bar', // Set this data to a line chart
+ fill: false
+ },
+ {
+ label: 'Profit/Loss', // Name the series
+ data: profit, // Specify the data values array
+ backgroundColor: '#0bd465',
+ borderColor: '#0bd465',
+
+ borderWidth: 1, // Specify bar border width
+ type: 'line', // Set this data to a line chart
+ fill: false
+ }
+ ]
+ },
+ options: {
+ responsive: true, // Instruct chart js to respond nicely.
+ maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height
+ }
+ });
+
+ })
+ var arg = 'this_month';
+ rpc.query({
+ model: 'account.move',
+ method: 'get_overdues_this_month_and_year',
+ args: [posted, arg],
+ }).then(function(result) {
+
+ //
+ })
+ var arg = 'this_month';
+ rpc.query({
+ model: 'account.move',
+ method: 'get_overdues_this_month_and_year',
+ args: [posted, arg],
+ })
+ .then(function(result) {
+ // Doughnut Chart
+ $(document).ready(function() {
+ var options = {
+ // legend: false,
+ responsive: true,
+ legend: {
+ position: 'bottom'
+ }
+ };
+ if (window.donut != undefined)
+ window.donut.destroy();
+ window.donut = new Chart($("#canvas1"), {
+ type: 'doughnut',
+ tooltipFillColor: "rgba(51, 51, 51, 0.55)",
+ data: {
+ labels: result.due_partner,
+ datasets: [{
+ data: result.due_amount,
+ backgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ],
+ hoverBackgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ]
+ }]
+ },
+ options: {
+ responsive: false
+ }
+ });
+ });
+ })
+ rpc.query({
+ model: "account.move",
+ method: "get_total_invoice_current_month",
+ args: [posted],
+ }).then(function(result) {
+
+ $('#total_supplier_invoice_paid').hide();
+ $('#total_supplier_invoice').hide();
+ $('#total_customer_invoice_paid').hide();
+ $('#total_customer_invoice').hide();
+ $('#tot_invoice').hide();
+ $('#tot_supplier_inv').hide();
+
+ $('#total_supplier_invoice_paid_current_month').empty();
+ $('#total_supplier_invoice_current_month').empty();
+ $('#total_customer_invoice_paid_current_month').empty();
+ $('#total_customer_invoice_current_month').empty();
+ $('#tot_invoice_current_month').empty();
+ $('#tot_supplier_inv_current_month').empty();
+
+ $('#total_supplier_invoice_paid_current_year').hide();
+ $('#total_supplier_invoice_current_year').hide();
+ $('#total_customer_invoice_paid_current_year').hide();
+ $('#total_customer_invoice_current_year').hide();
+ $('#tot_invoice_current_year').hide();
+ $('#tot_supplier_inv_current_year').hide();
+
+
+ $('#total_supplier_invoice_paid_current_month').show();
+ $('#total_supplier_invoice_current_month').show();
+ $('#total_customer_invoice_paid_current_month').show();
+ $('#total_customer_invoice_current_month').show();
+ $('#tot_invoice_current_month').show();
+ $('#tot_supplier_inv_current_month').show();
+
+
+ var tot_invoice_current_month = result[0][0]
+ var tot_credit_current_month = result[1][0]
+ var tot_supplier_inv_current_month = result[2][0]
+ var tot_supplier_refund_current_month = result[3][0]
+ var tot_customer_invoice_paid_current_month = result[4][0]
+ var tot_supplier_invoice_paid_current_month = result[5][0]
+ var tot_customer_credit_paid_current_month = result[6][0]
+ var tot_supplier_refund_paid_current_month = result[7][0]
+ var customer_invoice_total_current_month = (tot_invoice_current_month - tot_credit_current_month).toFixed(2)
+ var customer_invoice_paid_current_month = (tot_customer_invoice_paid_current_month - tot_customer_credit_paid_current_month).toFixed(2)
+ var invoice_percentage_current_month = ((customer_invoice_total_current_month / customer_invoice_paid_current_month) * 100).toFixed(2)
+ var supplier_invoice_total_current_month = (tot_supplier_inv_current_month - tot_supplier_refund_current_month).toFixed(2)
+ var supplier_invoice_paid_current_month = (tot_supplier_invoice_paid_current_month - tot_supplier_refund_paid_current_month).toFixed(2)
+ var supplier_percentage_current_month = ((supplier_invoice_total_current_month / supplier_invoice_paid_current_month) * 100).toFixed(2)
+
+ $('#tot_supplier_inv_current_month').attr("value", supplier_invoice_paid_current_month);
+ $('#tot_supplier_inv_current_month').attr("max", supplier_invoice_total_current_month);
+
+ $('#tot_invoice_current_month').attr("value", customer_invoice_paid_current_month);
+ $('#tot_invoice_current_month').attr("max", customer_invoice_total_current_month);
+ currency = result[8]
+ customer_invoice_paid_current_month = self.format_currency(currency, customer_invoice_paid_current_month);
+ customer_invoice_total_current_month = self.format_currency(currency, customer_invoice_total_current_month);
+ supplier_invoice_paid_current_month = self.format_currency(currency, supplier_invoice_paid_current_month);
+ supplier_invoice_total_current_month = self.format_currency(currency, supplier_invoice_total_current_month);
+
+ $('#total_customer_invoice_paid_current_month').append('' + '' + customer_invoice_paid_current_month + 'Total Paid
');
+ $('#total_customer_invoice_current_month').append('' + '' + customer_invoice_total_current_month + 'Total Invoice
');
+
+ $('#total_supplier_invoice_paid_current_month').append('' + '' + supplier_invoice_paid_current_month + 'Total Paid
');
+ $('#total_supplier_invoice_current_month').append('' + '' + supplier_invoice_total_current_month + 'Total Invoice
');
+
+ })
+ var arg = 'last_month'
+ rpc.query({
+ model: 'account.move',
+ method: 'get_latebillss',
+ args: [posted, arg],
+ })
+ .then(function(result) {
+
+ $(document).ready(function() {
+ var options = {
+ // legend: false,
+ responsive: true,
+ legend: {
+ position: 'bottom'
+ }
+ };
+ if (window.donuts != undefined)
+ window.donuts.destroy();
+ window.donuts = new Chart($("#horizontalbarChart"), {
+ type: 'doughnut',
+ tooltipFillColor: "rgba(51, 51, 51, 0.55)",
+ data: {
+ labels: result.bill_partner,
+ datasets: [{
+ data: result.bill_amount,
+ backgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ],
+ hoverBackgroundColor: [
+ '#66aecf ', '#6993d6 ', '#666fcf', '#7c66cf', '#9c66cf',
+ '#bc66cf ', '#b75fcc', ' #cb5fbf ', ' #cc5f7f ', ' #cc6260',
+ '#cc815f', '#cca15f ', '#ccc25f', '#b9cf66', '#99cf66',
+ ' #75cb5f ', '#60cc6c', '#804D8000', '#80B33300', '#80CC80CC', '#f2552c', '#00cccc',
+ '#1f2e2e', '#993333', '#00cca3', '#1a1a00', '#3399ff',
+ '#8066664D', '#80991AFF', '#808E666FF', '#804DB3FF', '#801AB399',
+ '#80E666B3', '#8033991A', '#80CC9999', '#80B3B31A', '#8000E680',
+ '#804D8066', '#80809980', '#80E6FF80', '#801AFF33', '#80999933',
+ '#80FF3380', '#80CCCC00', '#8066E64D', '#804D80CC', '#809900B3',
+ '#80E64D66', '#804DB380', '#80FF4D4D', '#8099E6E6', '#806666FF'
+ ]
+ }]
+ },
+ options: {
+ responsive: false
+ }
+ });
+ });
+ })
+ rpc.query({
+ model: "account.move",
+ method: "get_overdues",
+
+ }).then(function(result) {
+ var due_count = 0;
+ _.forEach(result, function(x) {
+ due_count++;
+ $('#overdues').append('' + x.due_partner + '' + ' ' + '' + x.due_amount + ' ' + currency + '' + '');
+
+ // $('#overdues_amounts').append('' + x.amount + '' + ''+' '+currency+ '' + '' );
+
+ });
+
+ $('#due_count').append('' + due_count + ' Due(s)');
+ })
+ var f = 'this_month'
+ rpc.query({
+ model: "account.move",
+ method: "get_top_10_customers_month",
+ args: [posted, f]
+ }).then(function(result) {
+ var due_count = 0;
+ var amount;
+ $('#top_10_customers_this_month').empty();
+
+ _.forEach(result, function(x) {
+ $('#top_10_customers_this_month').show();
+ due_count++;
+ amount = self.format_currency(currency, x.amount);
+ $('#top_10_customers_this_month').append('' + x.customers + '
' + '' + amount + '
' + '');
+ $('#line_' + x.parent).on("click", function() {
+ self.do_action({
+ res_model: 'res.partner',
+ name: _t('Partner'),
+ views: [
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ res_id: x.parent,
+ });
+ });
+
+ });
+ })
+ rpc.query({
+ model: "account.move",
+ method: "bank_balance",
+ args: [posted]
+ })
+ .then(function(result) {
+ var banks = result['banks'];
+ var amount;
+ var balance = result['banking'];
+ var bnk_ids = result['bank_ids'];
+ for (var k = 0; k < banks.length; k++) {
+ amount = self.format_currency(currency, balance[k]);
+ // $('#charts').append('' + banks[k] + ''+ ' ' + ''+ balance[k] +'' + '' );
+ $('#current_bank_balance').empty()
+
+ $('#current_bank_balance').append('' + banks[k] + '
' + amount + '
');
+ // $('#current_bank_balance').append('' + banks[k] +' '+ balance[k] + '' );
+ $('#drop_charts_balance').append('' + balance[k].toFixed(2) + '');
+ $('#b_' + bnk_ids[k]).on("click", function(ev) {
+ self.do_action({
+ res_model: 'account.account',
+ name: _t('Account'),
+ views: [
+ [false, 'form']
+ ],
+ type: 'ir.actions.act_window',
+ res_id: parseInt(this.id.replace('b_', '')),
+ });
+ });
+ }
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "get_latebills",
+
+ }).then(function(result) {
+ var late_count = 0;
+
+ _.forEach(result, function(x) {
+ late_count++;
+ $('#latebills').append('' + x.partner + '' + x.amount + ' ' + currency + '' + '' + '');
+ });
+ $('#late_count').append('' + late_count + ' Late(s)');
+ })
+ rpc.query({
+ model: "account.move",
+ method: "get_total_invoice",
+ })
+ .then(function(result) {
+ var total_invoice = result[0].sum;
+ total_invoice = total_invoice
+ $('#total_invoice').append('' + total_invoice + ' ' + currency + ' ')
+ })
+ rpc.query({
+ model: "account.move",
+ method: "get_total_invoice_this_month",
+ args: [posted],
+ })
+ .then(function(result) {
+ var invoice_this_month = result[0].sum;
+ if (invoice_this_month) {
+ var total_invoices_this_month = invoice_this_month.toFixed(2)
+ $('#total_invoices_').append('' + total_invoices_this_month + ' ' + currency + ' This month
')
+ }
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "get_total_invoice_last_month",
+ })
+ .then(function(result) {
+ var invoice_last_month = result[0].sum;
+ var total_invoices_last_month = invoice_last_month
+ $('#total_invoices_last').append('' + total_invoices_last_month + ' ' + currency + 'Last month
')
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "unreconcile_items"
+ })
+ .then(function(result) {
+
+ var unreconciled_count = result[0].count;
+ $('#unreconciled_items').append('' + unreconciled_count + ' Item(s) ')
+ })
+ rpc.query({
+ model: "account.move",
+ method: "unreconcile_items_this_month",
+ args: [posted],
+ })
+ .then(function(result) {
+ var unreconciled_counts_ = result[0].count;
+ $('#unreconciled_items_').empty()
+
+ $('#unreconciled_items_').append('' + unreconciled_counts_ + ' Item(s)This month
')
+ })
+ rpc.query({
+ model: "account.move",
+ method: "unreconcile_items_this_year",
+ args: [posted],
+ })
+ .then(function(result) {
+
+ var unreconciled_counts_this_year = result[0].count;
+ $('#unreconciled_counts_this_year').empty()
+
+ $('#unreconciled_counts_this_year').append('' + unreconciled_counts_this_year + ' Item(s)This Year
')
+ // $('#unreconciled_counts_this_year').append('' + unreconciled_counts_this_year + ' Item(s)This Year
')
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "unreconcile_items_last_year"
+ })
+ .then(function(result) {
+ var unreconciled_counts_last_year = result[0].count;
+ $('#unreconciled_counts_last_year').empty()
+
+ $('#unreconciled_counts_last_year').append('' + unreconciled_counts_last_year + ' Item(s)Last Year
')
+
+ })
+ rpc.query({
+ model: "account.move",
+ method: "month_income"
+ })
+ .then(function(result) {
+ var income = result[0].debit - result[0].credit;
+ income = -income;
+ income = self.format_currency(currency, income);
+ $('#total_income').append('' + income + '')
+ })
+ rpc.query({
+ model: "account.move",
+ method: "month_income_this_month",
+ args: [posted],
+ })
+ .then(function(result) {
+ var incomes_ = result[0].debit - result[0].credit;
+ if (incomes_) {
+ incomes_ = -incomes_;
+ incomes_ = self.format_currency(currency, incomes_);
+ $('#total_incomes_').empty()
+
+ $('#total_incomes_').append('' + incomes_ + 'This month
')
+
+ } else {
+ incomes_ = -incomes_;
+ incomes_ = self.format_currency(currency, incomes_);
+ $('#total_incomes_').empty()
+
+ $('#total_incomes_').append('' + incomes_ + 'This month
')
+ }
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "month_income_last_month"
+ })
+ .then(function(result) {
+ var incomes_last = result[0].debit - result[0].credit;
+ incomes_last = -incomes_last;
+ incomes_last = self.format_currency(currency, incomes_last);
+ $('#total_incomes_last').append('' + incomes_last + 'Last month
')
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "month_expense"
+ })
+ .then(function(result) {
+ var expense = result[0].debit - result[0].credit;
+ var expenses = expense;
+ expenses = self.format_currency(currency, expenses);
+
+ $('#total_expense').append('' + expenses + '')
+ })
+ rpc.query({
+ model: "account.move",
+ method: "month_expense_this_month",
+ args: [posted],
+ }).then(function(result) {
+ var expense_this_month = result[0].debit - result[0].credit;
+ if (expense_this_month) {
+
+ var expenses_this_month_ = expense_this_month;
+ expenses_this_month_ = self.format_currency(currency, expenses_this_month_);
+ $('#total_expenses_').empty()
+
+ $('#total_expenses_').append('' + expenses_this_month_ + 'This month
')
+ } else {
+ var expenses_this_month_ = expense_this_month;
+ expenses_this_month_ = self.format_currency(currency, expenses_this_month_);
+ $('#total_expenses_').empty()
+
+ $('#total_expenses_').append('' + expenses_this_month_ + 'This month
')
+
+ }
+ })
+ rpc.query({
+ model: "account.move",
+ method: "month_expense_this_year",
+ args: [posted],
+ }).then(function(result) {
+ var expense_this_year = result[0].debit - result[0].credit;
+ if (expense_this_year) {
+
+ var expenses_this_year_ = expense_this_year;
+ expenses_this_year_ = self.format_currency(currency, expenses_this_year_);
+ $('#total_expense_this_year').empty();
+
+ $('#total_expense_this_year').append('' + expenses_this_year_ + 'This Year
')
+ } else {
+ var expenses_this_year_ = expense_this_year;
+ expenses_this_year_ = self.format_currency(currency, expenses_this_year_);
+ $('#total_expense_this_year').empty();
+
+ $('#total_expense_this_year').append('' + expenses_this_year_ + 'This Year
')
+ }
+ })
+ rpc.query({
+ model: "account.move",
+ method: "month_income_last_year"
+ })
+ .then(function(result) {
+ var incomes_last_year = result[0].debit - result[0].credit;
+ incomes_last_year = -incomes_last_year
+ incomes_last_year = self.format_currency(currency, incomes_last_year);
+ $('#total_incomes_last_year').empty();
+
+ $('#total_incomes_last_year').append('' + incomes_last_year + 'Last Year
')
+ })
+ rpc.query({
+ model: "account.move",
+ method: "month_income_this_year",
+ args: [posted],
+ })
+ .then(function(result) {
+ var incomes_this_year = result[0].debit - result[0].credit;
+ if (incomes_this_year) {
+ incomes_this_year = -incomes_this_year;
+ incomes_this_year = self.format_currency(currency, incomes_this_year);
+ $('#total_incomes_this_year').empty();
+
+ $('#total_incomes_this_year').append('' + incomes_this_year + 'This Year
')
+ } else {
+ incomes_this_year = -incomes_this_year;
+ incomes_this_year = self.format_currency(currency, incomes_this_year);
+ $('#total_incomes_this_year').empty();
+
+ $('#total_incomes_this_year').append('' + incomes_this_year + 'This Year
')
+ }
+
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "profit_income_this_month",
+ args: [posted],
+ }).then(function(result) {
+ var net_profit = true
+ if (result[1] == undefined) {
+ result[1] = 0;
+ if ((result[0]) > (result[1])) {
+ net_profit = result[1] - result[0]
+ }
+
+ }
+
+ if (result[0] == undefined) {
+
+ result[0] = 0;
+ }
+
+ if ((-result[1]) > (result[0])) {
+ net_profit = -result[1] - result[0]
+ } else if ((result[1]) > (result[0])) {
+ net_profit = -result[1] - result[0]
+ } else {
+ net_profit = -result[1] - result[0]
+ }
+ var profit_this_months = net_profit;
+ if (profit_this_months) {
+ var net_profit_this_months = profit_this_months;
+ net_profit_this_months = self.format_currency(currency, net_profit_this_months);
+ $('#net_profit_current_months').empty();
+ // $('#net_profit_current_months').append('Net Profit/Loss
' + net_profit_this_months + '')
+ $('#net_profit_current_months').append('' + net_profit_this_months + ' This Month
')
+
+ } else {
+ var net_profit_this_months = profit_this_months;
+ net_profit_this_months = self.format_currency(currency, net_profit_this_months);
+ $('#net_profit_current_months').empty();
+ // $('#net_profit_current_months').append('Net Profit/Loss
' + net_profit_this_months + '')
+ $('#net_profit_current_months').append('' + net_profit_this_months + ' This Month
')
+ }
+ })
+
+ rpc.query({
+ model: "account.move",
+ method: "profit_income_this_year",
+ args: [posted],
+ })
+ .then(function(result) {
+ var net_profit = true
+
+
+ if (result[1] == undefined) {
+ result[1] = 0;
+ if ((result[0]) > (result[1])) {
+ net_profit = result[1] - result[0]
+ }
+
+ }
+
+ if (result[0] == undefined) {
+
+ result[0] = 0;
+ }
+
+ if ((-result[1]) > (result[0])) {
+ net_profit = -result[1] - result[0]
+ } else if ((result[1]) > (result[0])) {
+ net_profit = -result[1] - result[0]
+ } else {
+ net_profit = -result[1] - result[0]
+ }
+ var profit_this_year = net_profit;
+ if (profit_this_year) {
+ var net_profit_this_year = profit_this_year;
+ net_profit_this_year = self.format_currency(currency, net_profit_this_year);
+ $('#net_profit_current_year').empty();
+ // $('#net_profit_this_year').append('Net Profit/Loss
' + net_profit_this_year + '')
+ $('#net_profit_current_year').append('' + net_profit_this_year + ' This Year
')
+ } else {
+ var net_profit_this_year = profit_this_year;
+ net_profit_this_year = self.format_currency(currency, net_profit_this_year);
+ $('#net_profit_current_year').empty();
+ // $('#net_profit_this_year').append('Net Profit/Loss
' + net_profit_this_year + '')
+ $('#net_profit_current_year').append('' + net_profit_this_year + ' This Year
')
+
+ }
+ })
+ });
+ },
+
+ format_currency: function(currency, amount) {
+ if (typeof(amount) != 'number') {
+ amount = parseFloat(amount);
+ }
+ var formatted_value = (parseInt(amount)).toLocaleString(currency.language, {
+ minimumFractionDigits: 2
+ })
+ if (currency.position === "after") {
+ return formatted_value += ' ' + currency.symbol;
+ } else {
+ return currency.symbol + ' ' + formatted_value;
+ }
+ },
+
+ willStart: function() {
+ var self = this;
+ self.drpdn_show = false;
+ return Promise.all([ajax.loadLibs(this), this._super()]);
+ },
+ });
+ core.action_registry.add('invoice_dashboard', ActionMenu);
+
+});
\ No newline at end of file
diff --git a/base_accounting_kit/static/src/js/payment_matching.js b/base_accounting_kit/static/src/js/payment_matching.js
new file mode 100644
index 0000000..80a1732
--- /dev/null
+++ b/base_accounting_kit/static/src/js/payment_matching.js
@@ -0,0 +1,505 @@
+odoo.define('base_accounting_kit.ReconciliationClientAction', function (require) {
+"use strict";
+
+var AbstractAction = require('web.AbstractAction');
+var ReconciliationModel = require('base_accounting_kit.ReconciliationModel');
+var ReconciliationRenderer = require('base_accounting_kit.ReconciliationRenderer');
+var core = require('web.core');
+var QWeb = core.qweb;
+
+
+/**
+ * Widget used as action for 'account.bank.statement' reconciliation
+ */
+var StatementAction = AbstractAction.extend({
+ hasControlPanel: true,
+ withSearchBar: true,
+ loadControlPanel: true,
+ title: core._t('Bank Reconciliation'),
+ contentTemplate: 'reconciliation',
+ custom_events: {
+ change_mode: '_onAction',
+ change_filter: '_onAction',
+ change_offset: '_onAction',
+ change_partner: '_onAction',
+ add_proposition: '_onAction',
+ remove_proposition: '_onAction',
+ update_proposition: '_onAction',
+ create_proposition: '_onAction',
+ getPartialAmount: '_onActionPartialAmount',
+ quick_create_proposition: '_onAction',
+ partial_reconcile: '_onAction',
+ validate: '_onValidate',
+ close_statement: '_onCloseStatement',
+ load_more: '_onLoadMore',
+ reload: 'reload',
+ search: '_onSearch',
+ navigation_move:'_onNavigationMove',
+ },
+ config: _.extend({}, AbstractAction.prototype.config, {
+ // used to instantiate the model
+ Model: ReconciliationModel.StatementModel,
+ // used to instantiate the action interface
+ ActionRenderer: ReconciliationRenderer.StatementRenderer,
+ // used to instantiate each widget line
+ LineRenderer: ReconciliationRenderer.LineRenderer,
+ // used context params
+ params: ['statement_line_ids'],
+ // number of statements/partners/accounts to display
+ defaultDisplayQty: 10,
+ // number of moves lines displayed in 'match' mode
+ limitMoveLines: 15,
+ }),
+
+ _onNavigationMove: function (ev) {
+ var non_reconciled_keys = _.keys(_.pick(this.model.lines, function(value, key, object) {return !value.reconciled}));
+ var currentIndex = _.indexOf(non_reconciled_keys, ev.data.handle);
+ var widget = false;
+ switch (ev.data.direction) {
+ case 'up':
+ ev.stopPropagation();
+ widget = this._getWidget(non_reconciled_keys[currentIndex-1]);
+ break;
+ case 'down':
+ ev.stopPropagation();
+ widget = this._getWidget(non_reconciled_keys[currentIndex+1]);
+ break;
+ case 'validate':
+ ev.stopPropagation();
+ widget = this._getWidget(non_reconciled_keys[currentIndex]);
+ widget.$('caption .o_buttons button:visible').click();
+ break;
+ }
+ if (widget) widget.$el.focus();
+ },
+
+ /**
+ * @override
+ * @param {Object} params
+ * @param {Object} params.context
+ *
+ */
+ init: function (parent, params) {
+ this._super.apply(this, arguments);
+ this.action_manager = parent;
+ this.params = params;
+ this.searchModelConfig.modelName = 'account.bank.statement.line';
+ this.controlPanelProps.cp_content = {};
+// this.controlPanelParams.modelName = 'account.bank.statement.line';
+ this.model = new this.config.Model(this, {
+ modelName: "account.reconciliation.widget",
+ defaultDisplayQty: params.params && params.params.defaultDisplayQty || this.config.defaultDisplayQty,
+ limitMoveLines: params.params && params.params.limitMoveLines || this.config.limitMoveLines,
+ });
+ this.widgets = [];
+ // Adding values from the context is necessary to put this information in the url via the action manager so that
+ // you can retrieve it if the person shares his url or presses f5
+ _.each(params.params, function (value, name) {
+ params.context[name] = name.indexOf('_ids') !== -1 ? _.map((value+'').split(','), parseFloat) : value;
+ });
+ params.params = {};
+ _.each(this.config.params, function (name) {
+ if (params.context[name]) {
+ params.params[name] = params.context[name];
+ }
+ });
+ },
+
+ /**
+ * instantiate the action renderer
+ *
+ * @override
+ */
+ willStart: function () {
+ var self = this;
+ var def = this.model.load(this.params.context).then(this._super.bind(this));
+ return def.then(function () {
+ if (!self.model.context || !self.model.context.active_id) {
+ self.model.context = {'active_id': self.params.context.active_id,
+ 'active_model': self.params.context.active_model};
+ }
+ var journal_id = self.params.context.journal_id;
+ if (self.model.context.active_id && self.model.context.active_model === 'account.journal') {
+ journal_id = journal_id || self.model.context.active_id;
+ }
+ if (journal_id) {
+ var promise = self._rpc({
+ model: 'account.journal',
+ method: 'read',
+ args: [journal_id, ['display_name']],
+ });
+ } else {
+ var promise = Promise.resolve();
+ }
+ return promise.then(function (result) {
+ var title = result && result[0] ? result[0]['display_name'] : self.params.display_name || ''
+ self._setTitle(title);
+ self.renderer = new self.config.ActionRenderer(self, self.model, {
+ 'bank_statement_line_id': self.model.bank_statement_line_id,
+ 'valuenow': self.model.valuenow,
+ 'valuemax': self.model.valuemax,
+ 'defaultDisplayQty': self.model.defaultDisplayQty,
+ 'title': title,
+ });
+ });
+ });
+ },
+
+ reload: function() {
+ // On reload destroy all rendered line widget, reload data and then rerender widget
+ var self = this;
+
+ self.$('.o_reconciliation_lines').addClass('d-none'); // prevent the browser from recomputing css after each destroy for HUGE perf improvement on a lot of lines
+ _.each(this.widgets, function(widget) {
+ widget.destroy();
+ });
+ this.widgets = [];
+ self.$('.o_reconciliation_lines').removeClass('d-none');
+ return this.model.reload().then(function() {
+ return self._renderLinesOrRainbow();
+ });
+ },
+
+ _renderLinesOrRainbow: function() {
+ var self = this;
+ return self._renderLines().then(function() {
+ var initialState = self.renderer._initialState;
+ var valuenow = self.model.statement ? self.model.statement.value_min : initialState.valuenow;
+ var valuemax = self.model.statement ? self.model.statement.value_max : initialState.valuemax;
+ // No more lines to reconcile, trigger the rainbowman.
+ if(valuenow === valuemax){
+ initialState.valuenow = valuenow;
+ initialState.context = self.model.getContext();
+ self.renderer.showRainbowMan(initialState);
+ self.remove_cp();
+ }else{
+ // Create a notification if some lines have been reconciled automatically.
+ if(initialState.valuenow > 0)
+ self.renderer._renderNotifications(self.model.statement.notifications);
+ self._openFirstLine();
+ self.renderer.$('[data-toggle="tooltip"]').tooltip();
+ self.do_show();
+ }
+ });
+ },
+
+ /**
+ * append the renderer and instantiate the line renderers
+ *
+ * @override
+ */
+ start: function () {
+ var self = this;
+ var args = arguments;
+ var sup = this._super;
+
+ return this.renderer.prependTo(self.$('.o_form_sheet')).then(function() {
+ return self._renderLinesOrRainbow().then(function() {
+ self.do_show();
+ return sup.apply(self, args);
+ });
+ });
+ },
+
+ /**
+ * update the control panel and breadcrumbs
+ *
+ * @override
+ */
+ do_show: function () {
+ this._super.apply(this, arguments);
+ if (this.action_manager) {
+ this.$pager = $(QWeb.render('reconciliation.control.pager', {widget: this.renderer}));
+ this.controlPanelProps.cp_content = {$pager: this.$pager};
+// this.updateControlPanel({
+// clear: true,
+// cp_content: {
+// $pager: this.$pager,
+// },
+// });
+ this.renderer.$progress = this.$pager;
+ $(this.renderer.$progress).parent().css('width', '100%').css('padding-left', '0');
+ }
+ },
+
+ remove_cp: function() {
+ this.controlPanelProps.cp_content = {};
+// this.updateControlPanel({
+// clear: true,
+// });
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {string} handle
+ * @returns {Widget} widget line
+ */
+ _getWidget: function (handle) {
+ return _.find(this.widgets, function (widget) {return widget.handle===handle;});
+ },
+
+ /**
+ *
+ */
+ _loadMore: function(qty) {
+ var self = this;
+ return this.model.loadMore(qty).then(function () {
+ return self._renderLines();
+ });
+ },
+ /**
+ * sitch to 'match' the first available line
+ *
+ * @private
+ */
+ _openFirstLine: function (previous_handle) {
+ var self = this;
+ previous_handle = previous_handle || 'rline0';
+ var handle = _.compact(_.map(this.model.lines, function (line, handle) {
+ return (line.reconciled || (parseInt(handle.substr(5)) < parseInt(previous_handle.substr(5)))) ? null : handle;
+ }))[0];
+ if (handle) {
+ var line = this.model.getLine(handle);
+ this.model.changeMode(handle, 'default').then(function () {
+ self._getWidget(handle).update(line);
+ }).guardedCatch(function(){
+ self._getWidget(handle).update(line);
+ }).then(function() {
+ self._getWidget(handle).$el.focus();
+ }
+ );
+ }
+ return handle;
+ },
+
+ _forceUpdate: function() {
+ var self = this;
+ _.each(this.model.lines, function(handle) {
+ var widget = self._getWidget(handle['handle']);
+ if (widget && handle.need_update) {
+ widget.update(handle);
+ widget.need_update = false;
+ }
+ })
+ },
+ /**
+ * render line widget and append to view
+ *
+ * @private
+ */
+ _renderLines: function () {
+ var self = this;
+ var linesToDisplay = this.model.getStatementLines();
+ var linePromises = [];
+ _.each(linesToDisplay, function (line, handle) {
+ var widget = new self.config.LineRenderer(self, self.model, line);
+ widget.handle = handle;
+ self.widgets.push(widget);
+ linePromises.push(widget.appendTo(self.$('.o_reconciliation_lines')));
+ });
+ if (this.model.hasMoreLines() === false) {
+ this.renderer.hideLoadMoreButton(true);
+ }
+ else {
+ this.renderer.hideLoadMoreButton(false);
+ }
+ return Promise.all(linePromises);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * dispatch on the camelcased event name to model method then update the
+ * line renderer with the new state. If the mode was switched from 'inactive'
+ * to 'create' or 'match_rp' or 'match_other', the other lines switch to
+ * 'inactive' mode
+ *
+ * @private
+ * @param {OdooEvent} event
+ */
+ _onAction: function (event) {
+ var self = this;
+ var handle = event.target.handle;
+ var current_line = this.model.getLine(handle);
+ this.model[_.str.camelize(event.name)](handle, event.data.data).then(function () {
+ var widget = self._getWidget(handle);
+ if (widget) {
+ widget.update(current_line);
+ }
+ if (current_line.mode !== 'inactive') {
+ _.each(self.model.lines, function (line, _handle) {
+ if (line.mode !== 'inactive' && _handle !== handle) {
+ self.model.changeMode(_handle, 'inactive');
+ var widget = self._getWidget(_handle);
+ if (widget) {
+ widget.update(line);
+ }
+ }
+ });
+ }
+ });
+ },
+
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onSearch: function (ev) {
+ var self = this;
+ ev.stopPropagation();
+ this.model.domain = ev.data.domain;
+ this.model.display_context = 'search';
+ self.reload().then(function() {
+ self.renderer._updateProgressBar({
+ 'valuenow': self.model.valuenow,
+ 'valuemax': self.model.valuemax,
+ });
+ });
+ },
+
+ _onActionPartialAmount: function(event) {
+ var self = this;
+ var handle = event.target.handle;
+ var line = this.model.getLine(handle);
+ var amount = this.model.getPartialReconcileAmount(handle, event.data);
+ self._getWidget(handle).updatePartialAmount(event.data.data, amount);
+ },
+
+ /**
+ * call 'closeStatement' model method
+ *
+ * @private
+ * @param {OdooEvent} event
+ */
+ _onCloseStatement: function (event) {
+ var self = this;
+ return this.model.closeStatement().then(function (result) {
+ self.do_action({
+ name: 'Bank Statements',
+ res_model: 'account.bank.statement.line',
+ res_id: result,
+ views: [[false, 'form']],
+ type: 'ir.actions.act_window',
+ view_mode: 'form',
+ });
+ $('.o_reward').remove();
+ });
+ },
+ /**
+ * Load more statement and render them
+ *
+ * @param {OdooEvent} event
+ */
+ _onLoadMore: function (event) {
+ return this._loadMore(this.model.defaultDisplayQty);
+ },
+ /**
+ * call 'validate' model method then destroy the
+ * validated lines and update the action renderer with the new status bar
+ * values and notifications then open the first available line
+ *
+ * @private
+ * @param {OdooEvent} event
+ */
+ _onValidate: function (event) {
+ var self = this;
+ var handle = event.target.handle;
+ this.model.validate(handle).then(function (result) {
+ self.renderer.update({
+ 'valuenow': self.model.valuenow,
+ 'valuemax': self.model.valuemax,
+ 'title': self.title,
+ 'time': Date.now()-self.time,
+ 'notifications': result.notifications,
+ 'context': self.model.getContext(),
+ });
+ self._forceUpdate();
+ _.each(result.handles, function (handle) {
+ var widget = self._getWidget(handle);
+ if (widget) {
+ widget.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(handle);
+ });
+ },
+});
+
+
+/**
+ * Widget used as action for 'account.move.line' and 'res.partner' for the
+ * manual reconciliation and mark data as reconciliate
+ */
+var ManualAction = StatementAction.extend({
+ title: core._t('Journal Items to Reconcile'),
+ withSearchBar: false,
+ config: _.extend({}, StatementAction.prototype.config, {
+ Model: ReconciliationModel.ManualModel,
+ ActionRenderer: ReconciliationRenderer.ManualRenderer,
+ LineRenderer: ReconciliationRenderer.ManualLineRenderer,
+ params: ['company_ids', 'mode', 'partner_ids', 'account_ids'],
+ defaultDisplayQty: 30,
+ limitMoveLines: 15,
+ }),
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * call 'validate' model method then destroy the
+ * reconcilied lines, update the not reconcilied and update the action
+ * renderer with the new status bar values and notifications then open the
+ * first available line
+ *
+ * @private
+ * @param {OdooEvent} event
+ */
+ _onValidate: function (event) {
+ var self = this;
+ var handle = event.target.handle;
+ var method = 'validate';
+ this.model[method](handle).then(function (result) {
+ _.each(result.reconciled, function (handle) {
+ self._getWidget(handle).destroy();
+ });
+ _.each(result.updated, function (handle) {
+ self._getWidget(handle).update(self.model.getLine(handle));
+ });
+ self.renderer.update({
+ valuenow: _.compact(_.invoke(self.widgets, 'isDestroyed')).length,
+ valuemax: self.widgets.length,
+ title: self.title,
+ time: Date.now()-self.time,
+ });
+ if(!_.any(result.updated, function (handle) {
+ return self.model.getLine(handle).mode !== 'inactive';
+ })) {
+ self._openFirstLine(handle);
+ }
+ });
+ },
+});
+
+core.action_registry.add('bank_statement_reconciliation_view', StatementAction);
+core.action_registry.add('manual_reconciliation_view', ManualAction);
+
+return {
+ StatementAction: StatementAction,
+ ManualAction: ManualAction,
+};
+});
diff --git a/base_accounting_kit/static/src/js/payment_model.js b/base_accounting_kit/static/src/js/payment_model.js
new file mode 100644
index 0000000..07785c4
--- /dev/null
+++ b/base_accounting_kit/static/src/js/payment_model.js
@@ -0,0 +1,1881 @@
+odoo.define('base_accounting_kit.ReconciliationModel', function (require) {
+"use strict";
+
+var BasicModel = require('web.BasicModel');
+var field_utils = require('web.field_utils');
+var utils = require('web.utils');
+var session = require('web.session');
+var WarningDialog = require('web.CrashManager').WarningDialog;
+var core = require('web.core');
+var _t = core._t;
+
+
+/**
+ * Model use to fetch, format and update 'account.reconciliation.widget',
+ * datas allowing reconciliation
+ *
+ * The statement internal structure::
+ *
+ * {
+ * valuenow: integer
+ * valuenow: valuemax
+ * [bank_statement_line_id]: {
+ * id: integer
+ * display_name: string
+ * }
+ * reconcileModels: [object]
+ * accounts: {id: code}
+ * }
+ *
+ * The internal structure of each line is::
+ *
+ * {
+ * balance: {
+ * type: number - show/hide action button
+ * amount: number - real amount
+ * amount_str: string - formated amount
+ * account_code: string
+ * },
+ * st_line: {
+ * partner_id: integer
+ * partner_name: string
+ * }
+ * mode: string ('inactive', 'match_rp', 'match_other', 'create')
+ * reconciliation_proposition: {
+ * id: number|string
+ * partial_amount: number
+ * invalid: boolean - through the invalid line (without account, label...)
+ * account_code: string
+ * date: string
+ * date_maturity: string
+ * label: string
+ * amount: number - real amount
+ * amount_str: string - formated amount
+ * [already_paid]: boolean
+ * [partner_id]: integer
+ * [partner_name]: string
+ * [account_code]: string
+ * [journal_id]: {
+ * id: integer
+ * display_name: string
+ * }
+ * [ref]: string
+ * [is_partially_reconciled]: boolean
+ * [to_check]: boolean
+ * [amount_currency_str]: string|false (amount in record currency)
+ * }
+ * mv_lines_match_rp: object - idem than reconciliation_proposition
+ * mv_lines_match_other: object - idem than reconciliation_proposition
+ * limitMoveLines: integer
+ * filter: string
+ * [createForm]: {
+ * account_id: {
+ * id: integer
+ * display_name: string
+ * }
+ * tax_ids: {
+ * id: integer
+ * display_name: string
+ * }
+ * analytic_account_id: {
+ * id: integer
+ * display_name: string
+ * }
+ * analytic_tag_ids: {
+ * }
+ * label: string
+ * amount: number,
+ * [journal_id]: {
+ * id: integer
+ * display_name: string
+ * }
+ * }
+ * }
+ */
+var StatementModel = BasicModel.extend({
+ avoidCreate: false,
+ quickCreateFields: ['account_id', 'amount', 'analytic_account_id', 'label', 'tax_ids', 'force_tax_included', 'analytic_tag_ids', 'to_check'],
+
+ // overridden in ManualModel
+ modes: ['create', 'match_rp', 'match_other'],
+
+ /**
+ * @override
+ *
+ * @param {Widget} parent
+ * @param {object} options
+ */
+ init: function (parent, options) {
+ this._super.apply(this, arguments);
+ this.reconcileModels = [];
+ this.lines = {};
+ this.valuenow = 0;
+ this.valuemax = 0;
+ this.alreadyDisplayed = [];
+ this.domain = [];
+ this.defaultDisplayQty = options && options.defaultDisplayQty || 10;
+ this.limitMoveLines = options && options.limitMoveLines || 15;
+ this.display_context = 'init';
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * add a reconciliation proposition from the matched lines
+ * We also display a warning if the user tries to add 2 line with different
+ * account type
+ *
+ * @param {string} handle
+ * @param {number} mv_line_id
+ * @returns {Promise}
+ */
+ addProposition: function (handle, mv_line_id) {
+ var self = this;
+ var line = this.getLine(handle);
+ var prop = _.clone(_.find(line['mv_lines_'+line.mode], {'id': mv_line_id}));
+ this._addProposition(line, prop);
+ line['mv_lines_'+line.mode] = _.filter(line['mv_lines_'+line.mode], l => l['id'] != mv_line_id);
+
+ // remove all non valid lines
+ line.reconciliation_proposition = _.filter(line.reconciliation_proposition, function (prop) {return prop && !prop.invalid;});
+
+ // Onchange the partner if not already set on the statement line.
+ if(!line.st_line.partner_id && line.reconciliation_proposition
+ && line.reconciliation_proposition.length == 1 && prop.partner_id && line.type === undefined){
+ return this.changePartner(handle, {'id': prop.partner_id, 'display_name': prop.partner_name}, true);
+ }
+
+ return Promise.all([
+ this._computeLine(line),
+ this._performMoveLine(handle, 'match_rp', line.mode == 'match_rp'? 1 : 0),
+ this._performMoveLine(handle, 'match_other', line.mode == 'match_other'? 1 : 0)
+ ]);
+ },
+ /**
+ * change the filter for the target line and fetch the new matched lines
+ *
+ * @param {string} handle
+ * @param {string} filter
+ * @returns {Promise}
+ */
+ changeFilter: function (handle, filter) {
+ var line = this.getLine(handle);
+ line['filter_'+line.mode] = filter;
+ line['mv_lines_'+line.mode] = [];
+ return this._performMoveLine(handle, line.mode);
+ },
+ /**
+ * change the mode line ('inactive', 'match_rp', 'match_other', 'create'),
+ * and fetch the new matched lines or prepare to create a new line
+ *
+ * ``match_rp``
+ * display the matched lines from receivable/payable accounts, the user
+ * can select the lines to apply there as proposition
+ * ``match_other``
+ * display the other matched lines, the user can select the lines to apply
+ * there as proposition
+ * ``create``
+ * display fields and quick create button to create a new proposition
+ * for the reconciliation
+ *
+ * @param {string} handle
+ * @param {'inactive' | 'match_rp' | 'create'} mode
+ * @returns {Promise}
+ */
+ changeMode: function (handle, mode) {
+ var self = this;
+ var line = this.getLine(handle);
+ if (mode === 'default') {
+ var match_requests = self.modes.filter(x => x.startsWith('match')).map(x => this._performMoveLine(handle, x))
+ return Promise.all(match_requests).then(function() {
+ return self.changeMode(handle, self._getDefaultMode(handle));
+ });
+ }
+ if (mode === 'next') {
+ var available_modes = self._getAvailableModes(handle)
+ mode = available_modes[(available_modes.indexOf(line.mode) + 1) % available_modes.length];
+ }
+ line.mode = mode;
+ if (['match_rp', 'match_other'].includes(line.mode)) {
+ if (!(line['mv_lines_' + line.mode] && line['mv_lines_' + line.mode].length)) {
+ return this._performMoveLine(handle, line.mode);
+ } else {
+ return this._formatMoveLine(handle, line.mode, []);
+ }
+ }
+ if (line.mode === 'create') {
+ return this.createProposition(handle);
+ }
+ return Promise.resolve();
+ },
+ /**
+ * fetch the more matched lines
+ *
+ * @param {string} handle
+ * @returns {Promise}
+ */
+ changeOffset: function (handle) {
+ var line = this.getLine(handle);
+ return this._performMoveLine(handle, line.mode);
+ },
+ /**
+ * change the partner on the line and fetch the new matched lines
+ *
+ * @param {string} handle
+ * @param {bool} preserveMode
+ * @param {Object} partner
+ * @param {string} partner.display_name
+ * @param {number} partner.id
+ * @returns {Promise}
+ */
+ changePartner: function (handle, partner, preserveMode) {
+ var self = this;
+ var line = this.getLine(handle);
+ line.st_line.partner_id = partner && partner.id;
+ line.st_line.partner_name = partner && partner.display_name || '';
+ line.mv_lines_match_rp = [];
+ line.mv_lines_match_other = [];
+ return Promise.resolve(partner && this._changePartner(handle, partner.id))
+ .then(function() {
+ if(line.st_line.partner_id){
+ _.each(line.reconciliation_proposition, function(prop){
+ if(prop.partner_id != line.st_line.partner_id){
+ line.reconciliation_proposition = [];
+ return false;
+ }
+ });
+ }
+ return self._computeLine(line);
+ })
+ .then(function () {
+ return self.changeMode(handle, preserveMode ? line.mode : 'default', true);
+ })
+
+ },
+ /**
+ * close the statement
+ * @returns {Promise} resolves to the res_id of the closed statements
+ */
+ closeStatement: function () {
+ var self = this;
+ return this._rpc({
+ model: 'account.bank.statement.line',
+ method: 'button_confirm_bank',
+ args: [self.bank_statement_line_id.id],
+ })
+ .then(function () {
+ return self.bank_statement_line_id.id;
+ });
+ },
+ /**
+ *
+ * then open the first available line
+ *
+ * @param {string} handle
+ * @returns {Promise}
+ */
+ createProposition: function (handle) {
+ var line = this.getLine(handle);
+ var prop = _.filter(line.reconciliation_proposition, '__focus');
+ prop = this._formatQuickCreate(line);
+ line.reconciliation_proposition.push(prop);
+ line.createForm = _.pick(prop, this.quickCreateFields);
+ return this._computeLine(line);
+ },
+ /**
+ * Return context information and journal_id
+ * @returns {Object} context
+ */
+ 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
+ * overridden in ManualModel
+ *
+ * @returns {boolean} true if load more button needs to be displayed
+ */
+ hasMoreLines: function () {
+ 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
+ *
+ * @param {Object} handle
+ * @returns {Object}
+ */
+ getLine: function (handle) {
+ return this.lines[handle];
+ },
+ /**
+ * load data from
+ *
+ * - 'account.bank.statement' fetch the line id and bank_statement_id info
+ * - 'account.reconcile.model' fetch all reconcile model (for quick add)
+ * - 'account.account' fetch all account code
+ * - 'account.reconciliation.widget' fetch each line data
+ *
+ * overridden in ManualModel
+ * @param {Object} context
+ * @param {number[]} context.statement_line_ids
+ * @returns {Promise}
+ */
+ load: function (context) {
+ var self = this;
+ this.context = context;
+ this.statement_line_ids = context.statement_line_ids;
+ if (this.statement_line_ids === undefined) {
+ // This could be undefined if the user pressed F5, take everything as fallback instead of rainbowman
+ return self._rpc({
+ model: 'account.bank.statement.line',
+ method: 'search_read',
+ fields: ['id'],
+ domain: [['journal_id', '=?', context.active_id]],
+ }).then(function (result) {
+ self.statement_line_ids = result.map(r => r.id);
+ return self.reload()
+ })
+ } else {
+ return self.reload();
+ }
+
+ },
+ /**
+ * Load more bank statement line
+ *
+ * @param {integer} qty quantity to load
+ * @returns {Promise}
+ */
+ 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
+ * overridden in ManualModel
+ *
+ * @param {Array} ids ids of bank statement line passed to rpc call
+ * @param {Array} excluded_ids list of move_line ids that needs to be excluded from search
+ * @returns {Promise}
+ */
+ loadData: function(ids) {
+ var self = this;
+ var excluded_ids = this._getExcludedIds();
+ return self._rpc({
+ model: 'account.reconciliation.widget',
+ method: 'get_bank_statement_line_data',
+ args: [ids, excluded_ids],
+ context: self.context,
+ })
+ .then(function(res){
+ return self._formatLine(res['lines']);
+ })
+ },
+ /**
+ * Reload all data
+ */
+ reload: function() {
+ var self = this;
+ self.alreadyDisplayed = [];
+ self.lines = {};
+ self.pagerIndex = 0;
+ var def_statement = this._rpc({
+ model: 'account.reconciliation.widget',
+ method: 'get_bank_statement_data',
+ kwargs: {"bank_statement_line_ids":self.statement_line_ids, "srch_domain":self.domain},
+ context: self.context,
+ })
+ .then(function (statement) {
+ self.statement = statement;
+ self.bank_statement_line_id = self.statement_line_ids.length === 1 ? {id: self.statement_line_ids[0], display_name: statement.statement_name} : false;
+ self.valuenow = self.valuenow || statement.value_min;
+ self.valuemax = self.valuemax || statement.value_max;
+ self.context.journal_id = statement.journal_id;
+ _.each(statement.lines, function (res) {
+ var handle = _.uniqueId('rline');
+ self.lines[handle] = {
+ id: res.st_line.id,
+ partner_id: res.st_line.partner_id,
+ handle: handle,
+ reconciled: false,
+ mode: 'inactive',
+ mv_lines_match_rp: [],
+ mv_lines_match_other: [],
+ filter_match_rp: "",
+ filter_match_other: "",
+ reconciliation_proposition: [],
+ reconcileModels: [],
+ };
+ });
+ });
+ var domainReconcile = [];
+ if (self.context && self.context.company_ids) {
+ domainReconcile.push(['company_id', 'in', self.context.company_ids]);
+ }
+ if (self.context && self.context.active_model === 'account.journal' && self.context.active_ids) {
+ domainReconcile.push('|');
+ domainReconcile.push(['match_journal_ids', '=', false]);
+ domainReconcile.push(['match_journal_ids', 'in', self.context.active_ids]);
+ }
+ var def_reconcileModel = this._loadReconciliationModel({domainReconcile: domainReconcile});
+ var def_account = this._rpc({
+ model: 'account.account',
+ method: 'search_read',
+ fields: ['code'],
+ })
+ .then(function (accounts) {
+ self.accounts = _.object(_.pluck(accounts, 'id'), _.pluck(accounts, 'code'));
+ });
+ var def_taxes = self._loadTaxes();
+ return Promise.all([def_statement, def_reconcileModel, def_account, def_taxes]).then(function () {
+ _.each(self.lines, function (line) {
+ line.reconcileModels = self.reconcileModels;
+ });
+ var ids = _.pluck(self.lines, 'id');
+ ids = ids.splice(0, self.defaultDisplayQty);
+ self.pagerIndex = ids.length;
+ return self._formatLine(self.statement.lines);
+ });
+ },
+ _readAnalyticTags: function (params) {
+ var self = this;
+ this.analyticTags = {};
+ if (!params || !params.res_ids || !params.res_ids.length) {
+ return $.when();
+ }
+ var fields = (params && params.fields || []).concat(['id', 'display_name']);
+ return this._rpc({
+ model: 'account.analytic.tag',
+ method: 'read',
+ args: [
+ params.res_ids,
+ fields,
+ ],
+ }).then(function (tags) {
+ for (var i=0; i= Math.abs(amount)) {
+ amount = Math.abs(amount);
+ } else if (partial <= Math.abs(prop.amount) && partial >= 0) {
+ amount = partial;
+ } else {
+ amount = Math.abs(amount);
+ }
+ return field_utils.format.monetary(amount, {}, formatOptions);
+ }
+ },
+ /**
+ * Force the partial reconciliation to display the reconciliate button.
+ *
+ * @param {string} handle
+ * @returns {Promise}
+ */
+ partialReconcile: function(handle, data) {
+ var line = this.getLine(handle);
+ var prop = _.find(line.reconciliation_proposition, {'id' : data.mvLineId});
+ if (prop) {
+ var amount = data.amount;
+ try {
+ amount = field_utils.parse.float(data.amount);
+ }
+ catch (err) {
+ amount = NaN;
+ }
+ // Amount can't be greater than line.amount and can not be negative and must be a number
+ // the amount we receive will be a string, so take sign of previous line amount in consideration in order to put
+ // the amount in the correct left or right column
+ if (amount >= Math.abs(prop.amount) || amount <= 0 || isNaN(amount)) {
+ delete prop.partial_amount_str;
+ delete prop.partial_amount;
+ if (isNaN(amount) || amount < 0) {
+ this.do_warn(_.str.sprintf(_t('The amount %s is not a valid partial amount'), data.amount));
+ }
+ return this._computeLine(line);
+ }
+ else {
+ var format_options = { currency_id: line.st_line.currency_id };
+ prop.partial_amount = (prop.amount > 0 ? 1 : -1)*amount;
+ prop.partial_amount_str = field_utils.format.monetary(Math.abs(prop.partial_amount), {}, format_options);
+ }
+ }
+ return this._computeLine(line);
+ },
+ /**
+ * Change the value of the editable proposition line or create a new one.
+ *
+ * If the editable line comes from a reconcile model with 2 lines
+ * and their 'amount_type' is "percent"
+ * and their total equals 100% (this doesn't take into account the taxes
+ * who can be included or not)
+ * Then the total is recomputed to have 100%.
+ *
+ * @param {string} handle
+ * @param {*} values
+ * @returns {Promise}
+ */
+ updateProposition: function (handle, values) {
+ var self = this;
+ var line = this.getLine(handle);
+ var prop = _.last(_.filter(line.reconciliation_proposition, '__focus'));
+ if ('to_check' in values && values.to_check === false) {
+ // check if we have another line with to_check and if yes don't change value of this proposition
+ prop.to_check = line.reconciliation_proposition.some(function(rec_prop, index) {
+ return rec_prop.id !== prop.id && rec_prop.to_check;
+ });
+ }
+ if (!prop) {
+ prop = this._formatQuickCreate(line);
+ line.reconciliation_proposition.push(prop);
+ }
+ _.each(values, function (value, fieldName) {
+ if (fieldName === 'analytic_tag_ids') {
+ switch (value.operation) {
+ case "ADD_M2M":
+ // handle analytic_tag selection via drop down (single dict) and
+ // full widget (array of dict)
+ var vids = _.isArray(value.ids) ? value.ids : [value.ids];
+ _.each(vids, function (val) {
+ if (!_.findWhere(prop.analytic_tag_ids, {id: val.id})) {
+ prop.analytic_tag_ids.push(val);
+ }
+ });
+ break;
+ case "FORGET":
+ var id = self.localData[value.ids[0]].ref;
+ prop.analytic_tag_ids = _.filter(prop.analytic_tag_ids, function (val) {
+ return val.id !== id;
+ });
+ break;
+ }
+ }
+ else if (fieldName === 'tax_ids') {
+ switch(value.operation) {
+ case "ADD_M2M":
+ prop.__tax_to_recompute = true;
+ var vids = _.isArray(value.ids) ? value.ids : [value.ids];
+ _.each(vids, function(val){
+ if (!_.findWhere(prop.tax_ids, {id: val.id})) {
+ value.ids.price_include = self.taxes[val.id] ? self.taxes[val.id].price_include : false;
+ prop.tax_ids.push(val);
+ }
+ });
+ break;
+ case "FORGET":
+ prop.__tax_to_recompute = true;
+ var id = self.localData[value.ids[0]].ref;
+ prop.tax_ids = _.filter(prop.tax_ids, function (val) {
+ return val.id !== id;
+ });
+ break;
+ }
+ }
+ else {
+ prop[fieldName] = values[fieldName];
+ }
+ });
+ if ('account_id' in values) {
+ prop.account_code = prop.account_id ? this.accounts[prop.account_id.id] : '';
+ }
+ if ('amount' in values) {
+ prop.base_amount = values.amount;
+ if (prop.reconcileModelId) {
+ this._computeReconcileModels(handle, prop.reconcileModelId);
+ }
+ }
+ if ('force_tax_included' in values || 'amount' in values || 'account_id' in values) {
+ prop.__tax_to_recompute = true;
+ }
+ line.createForm = _.pick(prop, this.quickCreateFields);
+ // If you check/uncheck the force_tax_included box, reset the createForm amount.
+ if(prop.base_amount)
+ line.createForm.amount = prop.base_amount;
+ if (prop.tax_ids.length !== 1 ) {
+ // When we have 0 or more than 1 taxes, reset the base_amount and force_tax_included, otherwise weird behavior can happen
+ prop.amount = prop.base_amount;
+ line.createForm.force_tax_included = false;
+ }
+ return this._computeLine(line);
+ },
+ /**
+ * Format the value and send it to 'account.reconciliation.widget' model
+ * Update the number of validated lines
+ * overridden in ManualModel
+ *
+ * @param {(string|string[])} handle
+ * @returns {Promise
+
+
+
+
+
Congrats, you're all done!
+
You reconciled transactions in .
+
+
That's on average seconds per transaction.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ |
+ () |
+ |
+ |
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | Last Reconciliation: |
+ |
+ |
+
+
+
+
+
+
+
+
+ |
+ |
+ Open balanceChoose counterpart or Create Write-off |
+ |
+ |
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | |
+
+
+ New
+
+
+ |
+
+
+
+ :
+
+
+
+ :
+
+ |
+
+
+
+
+ |
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+ | Account | |
+ | Date | |
+ | Due Date | |
+ | Journal | |
+ | Partner | |
+ | Label | |
+ | Ref | |
+ | Amount | () |
+ | Residual |
+ ()
+ |
+
+ | This payment is registered but not reconciled. |
+
+
+
+
+
+
+
+ | Date | |
+ | Partner | |
+ | Transaction | |
+ | Description | |
+ | Amount | () |
+ | Account | |
+ | Note | |
+
+
+
+
+
+
+
+
+ statement lines
+
+ have been reconciled automatically.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/base_accounting_kit/static/src/xml/template.xml b/base_accounting_kit/static/src/xml/template.xml
new file mode 100644
index 0000000..d468f00
--- /dev/null
+++ b/base_accounting_kit/static/src/xml/template.xml
@@ -0,0 +1,324 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Customer Invoice
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
Supplier Invoice
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
--
cgit v1.2.3