diff --git a/bank_statement_reconciliation_summary/README.rst b/bank_statement_reconciliation_summary/README.rst new file mode 100644 index 00000000..13d20063 --- /dev/null +++ b/bank_statement_reconciliation_summary/README.rst @@ -0,0 +1,76 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +===================================== +Bank Statement Reconciliation Summary +===================================== + +The Bank Reconciliation Summary shows how your actual bank statement balance +and the balance of the bank account in Odoo match, after taking into account +any unreconciled items. + +This report is useful if your bank account's statement balance and balance +in Odoo do not match, and you need to check for duplicate or manually created +transactions that might cause the discrepancy. + +This report was created, inspired by Xero’s bank reconciliation summary, +https://help.xero.com/Report_BankRec, and from a basic explanation of the +bank statement reconciliation summary: +http://www.accountingcoach.com/bank-reconciliation/explanation. + + +Usage +===== + +#. Go to *Accounting / Reports / OCA accounting reports / Bank Statement Reconciliation* +#. Enter the end date for your analysis, the bank journal and the actual bank + balance at that date. + +The report displays the following sections: + +* Balance in Odoo +* Plus Outstanding Payments - payments in odoo not yet reconciled +* Less Outstanding Receipts - payments in odoo not yet reconciled +* Plus Un-Reconciled Statement Lines - statement lines not yet reconciled +* Statement Balance + +If the theoretical Statement Balance does not match with Odoo, it will +display the Computed (theoretical) balance, the Actual Balance and +the Unencoded Statement Amount. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/91/10.0 + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback +`here `_. + +Credits +======= + +Contributors +------------ + +* Jordi Ballester Alomar + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/bank_statement_reconciliation_summary/__init__.py b/bank_statement_reconciliation_summary/__init__.py new file mode 100644 index 00000000..cbe4ef03 --- /dev/null +++ b/bank_statement_reconciliation_summary/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import report +from . import wizard diff --git a/bank_statement_reconciliation_summary/__manifest__.py b/bank_statement_reconciliation_summary/__manifest__.py new file mode 100644 index 00000000..055d5a55 --- /dev/null +++ b/bank_statement_reconciliation_summary/__manifest__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 Eficent Business and IT Consulting Services S.L. +# Copyright 2016 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +{ + 'name': 'Bank Statement Reconciliation Summary', + 'category': 'Account', + 'summary': 'Bank Statement Reconciliation Summary', + 'version': '10.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'Eficent, ' + 'Serpent Consulting Services Pvt. Ltd.,' + 'Odoo Community Association (OCA)', + 'depends': ['account', 'account_financial_report_qweb'], + 'data': [ + 'report/summary_report.xml', + 'report/report.xml', + 'wizard/bank_statement_reconciliation_summary_wizard_view.xml', + ], + 'installable': True, +} diff --git a/bank_statement_reconciliation_summary/report/__init__.py b/bank_statement_reconciliation_summary/report/__init__.py new file mode 100644 index 00000000..922e2253 --- /dev/null +++ b/bank_statement_reconciliation_summary/report/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import summary_report diff --git a/bank_statement_reconciliation_summary/report/report.xml b/bank_statement_reconciliation_summary/report/report.xml new file mode 100644 index 00000000..d8e024b0 --- /dev/null +++ b/bank_statement_reconciliation_summary/report/report.xml @@ -0,0 +1,33 @@ + + + + + + Bank Statement Reconcillation Summary Paperformat + + A4 + 0 + 0 + Portrait + 0 + 0 + 5 + 5 + + 0 + 90 + + + + + + + + + + diff --git a/bank_statement_reconciliation_summary/report/summary_report.py b/bank_statement_reconciliation_summary/report/summary_report.py new file mode 100644 index 00000000..0b53518b --- /dev/null +++ b/bank_statement_reconciliation_summary/report/summary_report.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# Copyright 2016 Eficent Business and IT Consulting Services S.L. +# Copyright 2016 Serpent Consulting Services Pvt. Ltd. +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). +import time +from odoo import api, models + + +class SummaryReport(models.AbstractModel): + _name = 'report.bank_statement_reconciliation_summary.summary_report' + + @api.model + def _plus_outstanding_payments_domain(self, journal, start_date, + end_date): + account_id = journal.default_debit_account_id.id + domain_search = [ + ('account_id', '=', account_id), + ('move_id.statement_line_id', '=', False), + ('credit', '>', 0.00), + ('date', '<=', end_date), + ] + if start_date: + domain_search += [('date', '>=', start_date)] + return domain_search + + @api.model + def _plus_outstanding_payments(self, journals, start_date, end_date): + rec = {} + for journal in journals: + domain_search = self._plus_outstanding_payments_domain( + journal, start_date, end_date) + account_move_line_records = self.env['account.move.line'].search( + domain_search, order='date') + rec[journal.id] = account_move_line_records + return rec + + @api.model + def _less_outstanding_receipts_domain(self, journal, start_date, + end_date): + account_id = journal.default_debit_account_id.id + domain_search = [ + ('account_id', '=', account_id), + ('move_id.statement_line_id', '=', False), + ('debit', '>', 0.00), + ('date', '<=', end_date), + ] + if start_date: + domain_search += [('date', '>=', start_date)] + return domain_search + + @api.model + def _less_outstanding_receipts(self, journals, start_date, end_date): + rec = {} + for journal in journals: + domain_search = self._less_outstanding_receipts_domain( + journal, start_date, end_date) + account_move_line_records = self.env['account.move.line'].search( + domain_search, order='date') + rec[journal.id] = account_move_line_records + return rec + + @api.model + def _plus_unreconciled_statement_lines(self, journals, start_date, + end_date): + rec = {} + for journal in journals: + domain_search = [ + ('date', '<=', end_date), + ('journal_id', '=', journal.id), + ('journal_entry_ids', '=', False)] + if start_date: + domain_search += [('date', '>=', start_date)] + statement_lines = self.env['account.bank.statement.line'].search( + domain_search) + rec[journal.id] = statement_lines + return rec + + @api.model + def _get_bank_end_balance(self, journals, end_date): + rec = {} + for journal in journals: + bank_account = journal.default_credit_account_id + amount_field = 'balance' + query = """ + SELECT sum(%s) FROM account_move_line + WHERE account_id=%%s + AND date<=%%s""" % (amount_field,) + self.env.cr.execute(query, (bank_account.id, end_date)) + query_results = self.env.cr.dictfetchall() + if query_results: + account_bal = query_results[0].get('sum') or 0.0 + else: + account_bal = 0.0 + rec[journal.id] = account_bal + return rec + + @api.multi + def render_html(self, docids, data=None): + Report = self.env['report'] + report_name = 'bank_statement_reconciliation_summary.summary_report' + report = Report._get_report_from_name(report_name) + records = self.env['account.journal'].browse(docids) + docargs = { + 'doc_ids': docids, + 'doc_model': report.model, + 'data': data, + 'docs': records, + 'time': time, + 'plus_outstanding_payments': + self._plus_outstanding_payments(records, data['start_date'], + data['end_date']), + 'less_outstanding_receipts': + self._less_outstanding_receipts(records, data['start_date'], + data['end_date']), + 'plus_unreconciled_statement_lines': + self._plus_unreconciled_statement_lines(records, + data['start_date'], + data['end_date']), + 'bank_end_balance': self._get_bank_end_balance( + records, data['end_date']), + 'balance_end_real': data['balance_end_real'] + } + return self.env['report'].render(report_name, docargs) diff --git a/bank_statement_reconciliation_summary/report/summary_report.xml b/bank_statement_reconciliation_summary/report/summary_report.xml new file mode 100644 index 00000000..f65ff5d7 --- /dev/null +++ b/bank_statement_reconciliation_summary/report/summary_report.xml @@ -0,0 +1,220 @@ + + + + + + + + diff --git a/bank_statement_reconciliation_summary/wizard/__init__.py b/bank_statement_reconciliation_summary/wizard/__init__.py new file mode 100644 index 00000000..31841a4e --- /dev/null +++ b/bank_statement_reconciliation_summary/wizard/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import bank_statement_reconciliation_summary_wizard diff --git a/bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard.py b/bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard.py new file mode 100644 index 00000000..2e37b479 --- /dev/null +++ b/bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# © 2017 Akretion (Alexis de Lattre ) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class BankReconciliationReportWizard(models.TransientModel): + _name = "bank.statement.reconciliation.summary.wizard" + _description = "Bank Statement Reconciliation Summary Wizard" + + @api.model + def _default_journal_id(self): + journal = self.env['account.journal'].search([ + ('type', '=', 'bank'), + ('company_id', '=', self.env.user.company_id.id)], limit=1) + return journal + + start_date = fields.Date() + end_date = fields.Date( + required=True, + default=fields.Date.context_today) + journal_id = fields.Many2one( + 'account.journal', string='Bank Journal', + domain=[('type', '=', 'bank')], required=True, + default=_default_journal_id) + balance_end_real = fields.Float('Bank Ending Balance') + + def open_qweb(self): + action = { + 'type': 'ir.actions.report.xml', + 'report_name': + 'bank_statement_reconciliation_summary.summary_report', + 'docids': self.journal_id.ids, + 'datas': { + 'docids': self.journal_id.ids, + 'ids': self.journal_id.ids, + 'end_date': self.end_date, + 'start_date': self.start_date, + 'balance_end_real': self.balance_end_real, + }, + 'context': self._context, + } + return action diff --git a/bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard_view.xml b/bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard_view.xml new file mode 100644 index 00000000..67ccfcad --- /dev/null +++ b/bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard_view.xml @@ -0,0 +1,43 @@ + + + + + + + + bank.statement.reconciliation.summary.wizard.form + bank.statement.reconciliation.summary.wizard + +
+ + + + + + +
+
+
+
+
+ + + Bank Statement Reconciliation + bank.statement.reconciliation.summary.wizard + form + new + + + + + +