Browse Source

Merge 2194377f34 into 1ac8744ae8

pull/365/merge
Jordi Ballester Alomar 3 years ago
committed by GitHub
parent
commit
46a8b6f76b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 76
      bank_statement_reconciliation_summary/README.rst
  2. 3
      bank_statement_reconciliation_summary/__init__.py
  3. 21
      bank_statement_reconciliation_summary/__manifest__.py
  4. 3
      bank_statement_reconciliation_summary/report/__init__.py
  5. 33
      bank_statement_reconciliation_summary/report/report.xml
  6. 123
      bank_statement_reconciliation_summary/report/summary_report.py
  7. 220
      bank_statement_reconciliation_summary/report/summary_report.xml
  8. 3
      bank_statement_reconciliation_summary/wizard/__init__.py
  9. 44
      bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard.py
  10. 43
      bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard_view.xml

76
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 <https://github.com/OCA/account-financial-reporting/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 <https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_tax_report_no_zeroes%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Jordi Ballester Alomar <contact@eficent.com>
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.

3
bank_statement_reconciliation_summary/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import report
from . import wizard

21
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,
}

3
bank_statement_reconciliation_summary/report/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import summary_report

33
bank_statement_reconciliation_summary/report/report.xml

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="summary_report_paperformat" model="report.paperformat">
<field name="name">Bank Statement Reconcillation Summary Paperformat</field>
<field name="default" eval="True" />
<field name="format">A4</field>
<field name="page_height">0</field>
<field name="page_width">0</field>
<field name="orientation">Portrait</field>
<field name="margin_top">0</field>
<field name="margin_bottom">0</field>
<field name="margin_left">5</field>
<field name="margin_right">5</field>
<field name="header_line" eval="False" />
<field name="header_spacing">0</field>
<field name="dpi">90</field>
</record>
<report id="report_bank_stmt_reconcile_summary"
string="Bank Statement Reconcillation Summary"
model="bank.statement.reconciliation.summary.wizard"
report_type="qweb-pdf"
file="bank_statement_reconciliation_summary.summary_report"
name="bank_statement_reconciliation_summary.summary_report"/>
<record id="report_bank_stmt_reconcile_summary" model="ir.actions.report.xml">
<field name="paperformat_id" ref="summary_report_paperformat"/>
</record>
</data>
</odoo>

123
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)

220
bank_statement_reconciliation_summary/report/summary_report.xml

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="summary_report">
<t t-call="report.html_container">
<t t-call="report.internal_layout">
<t t-foreach="docs" t-as="o">
<div class="page">
<link rel='stylesheet' href='/web/static/lib/bootstrap/css/bootstrap.css'/>
<style>
.lines {
border-top: solid;
border-top-width: 2px;
border-top-color: #edf3f8;
color: #5993c0;
}
</style>
<div class='row' style='background-color: #e6ffe6;box-shadow: 0px 2px 2px #cccccc;'>
<div style='padding:5px;'>
<div class='col-xs-3'><h4>Date</h4></div>
<div class='col-xs-3'><h4>Description</h4></div>
<div class='col-xs-3'><h4>Reference</h4></div>
<div class='col-xs-3 text-right'><h4>Amount</h4></div>
</div>
</div>
<div class='row mt16'>
<div class='col-xs-12'><h5><b><t t-esc='o.name'/> - Balance in Odoo</b></h5>
</div>
</div>
<t t-set='total_bank_odoo' t-value='0.00'/>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'/>
<div class='col-xs-3'><t
t-esc='o.default_credit_account_id.code'/>-<t t-esc='o.default_credit_account_id.name'/></div>
<div class='col-xs-3'/>
<t t-set='total_bank_odoo'
t-value='bank_end_balance[o.id]'/>
<div class='col-xs-3 text-right'><t
t-esc='total_bank_odoo'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></div>
<div class='col-xs-3'/>
</div>
</div>
<t t-set='total_bank_odoo' t-value='0.00'/>
<div class='row' style='border-top: groove;'>
<div class='col-xs-12'>
<div class='col-xs-3'/>
<div class='col-xs-6'><h5><b>Total Balance in Odoo</b></h5></div>
<div class='col-xs-3'/>
<t t-set='total_bank_odoo'
t-value='bank_end_balance[o.id]'/>
<div class='col-xs-3 text-right'>
<h5><b>
<t t-esc='total_bank_odoo'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/>
</b></h5></div>
<div class='col-xs-3'/>
</div>
</div>
<t t-set='total_payment' t-value='0.00'/>
<t t-if='plus_outstanding_payments[o.id]'>
<div class='row mt16'>
<div class='col-xs-12'><h5><b>Plus Outstanding Payments</b></h5></div>
</div>
<t t-foreach='plus_outstanding_payments[o.id]'
t-as='payment'>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'><t t-esc='payment.date'/></div>
<div class='col-xs-3'><t t-esc='payment.name'/></div>
<div class='col-xs-3'><t t-esc='payment.ref'/></div>
<div class='col-xs-3 text-right'>
<t t-esc='payment.credit'/>
<t t-if="payment.amount_currency">
(
<t t-esc='payment.amount_currency'
t-esc-options='{"widget": "monetary", "display_currency": "payment.currency_id"}'/>
)
</t>
</div>
<t t-set='total_payment' t-value='total_payment + payment.credit'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/>
</div>
</div>
</t>
<div class='row' style='border-top: groove;'>
<div class='col-xs-12'>
<div class='col-xs-6'><h5><b>Total Outstanding Payments</b></h5></div>
<div class='col-xs-3 col-xs-offset-3 text-right'><h5><b><t t-esc='total_payment'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></b></h5></div>
</div>
</div>
</t>
<t t-set='total_receipt' t-value='0.00'/>
<t t-if='less_outstanding_receipts[o.id]'>
<div class='row'>
<div class='col-xs-12'><h5><b>Less Outstanding Receipts</b></h5></div>
</div>
<t t-foreach='less_outstanding_receipts[o.id]'
t-as='receipt'>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'><t t-esc='receipt.date'/></div>
<div class='col-xs-3'><t t-esc='receipt.name'/></div>
<div class='col-xs-3'><t t-esc='receipt.ref'/></div>
<div class='col-xs-3 text-right'>
<t t-esc='receipt.debit'/>
<t t-if='receipt.amount_currency'>
(
<t t-esc='receipt.amount_currency'
t-esc-options='{"widget": "monetary", "display_currency": "receipt.currency_id"}'/>
)
</t>
</div>
<t t-set='total_receipt' t-value='total_receipt + receipt.debit'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/>
</div>
</div>
</t>
<div class='row' style='border-top: groove;'>
<div class='col-xs-12'>
<div class='col-xs-6'><h5><b>Total Outstanding Receipts</b></h5></div>
<div class='col-xs-3 col-xs-offset-3 text-right'><h5><b><t t-esc='total_receipt'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></b></h5></div>
</div>
</div>
</t>
<t t-set='bank_stmt_line_total' t-value='0.00'/>
<t t-if='plus_unreconciled_statement_lines[o.id]'>
<div class='row'>
<div class='col-xs-12'><h5><b>Plus Un-Reconciled Bank Statement Lines</b></h5></div>
</div>
<t t-foreach='plus_unreconciled_statement_lines[o.id]' t-as='line'>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'><t t-esc='line.date'/></div>
<div class='col-xs-3'><t t-esc='line.name'/></div>
<div class='col-xs-3'><t t-esc='line.ref'/></div>
<div class='col-xs-3 text-right'>
<t t-esc='line.amount'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/>
<t t-if='line.amount_currency'>
(
<t t-esc='line.amount_currency'
t-esc-options='{"widget": "monetary", "display_currency": "line.currency_id or o.company_id.currency_id"}'/>
)
</t>
</div>
<t t-set='bank_stmt_line_total' t-value='bank_stmt_line_total + line.amount'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/>
</div>
</div>
</t>
<div class='row' style='border-top: groove;'>
<div class='col-xs-12'>
<div class='col-xs-6'><h5><b>Total Un-Reconciled Bank Statement Lines</b></h5></div>
<div class='col-xs-3 col-xs-offset-3 text-right'><h5><b><t t-esc='bank_stmt_line_total'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></b></h5></div>
</div>
</div>
</t>
<t t-set='computed_statement_balance' t-value='total_bank_odoo + total_payment - total_receipt + bank_stmt_line_total'/>
<t
t-if='(balance_end_real - computed_statement_balance) == 0.0'>
<div class='row mt8' style='border-top: solid;border-bottom: solid;'>
<div class='col-xs-3'/>
<div class='col-xs-3'><h5><b>Statement Balance</b></h5></div>
<div class='col-xs-3'/>
<div class='col-xs-3 text-right'>
<t t-esc='computed_statement_balance'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></div>
</div>
</t>
<t t-if='(balance_end_real - computed_statement_balance) != 0.0'>
<div class='row mt16'>
<div class='col-xs-12'><h5><b>Statement Balance</b></h5>
</div>
</div>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'/>
<div class='col-xs-3'>Computed</div>
<div class='col-xs-3'/>
<div class='col-xs-3 text-right'>
<t t-esc='computed_statement_balance'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></div>
</div>
</div>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'/>
<div class='col-xs-3'>Actual</div>
<div class='col-xs-3'/>
<div class='col-xs-3 text-right'>
<t t-esc='balance_end_real'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></div>
</div>
</div>
<div class='row lines'>
<div class='col-xs-12'>
<div class='col-xs-3'/>
<div class='col-xs-3'>Unencoded Statement Amount</div>
<div class='col-xs-3'/>
<div class='col-xs-3 text-right'>
<t t-esc='balance_end_real - computed_statement_balance'
t-esc-options='{"widget": "monetary", "display_currency": "o.currency_id or o.company_id.currency_id"}'/></div>
</div>
</div>
</t>
</div>
</t>
</t>
</t>
</template>
</data>
</odoo>

3
bank_statement_reconciliation_summary/wizard/__init__.py

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import bank_statement_reconciliation_summary_wizard

44
bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard.py

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# 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

43
bank_statement_reconciliation_summary/wizard/bank_statement_reconciliation_summary_wizard_view.xml

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Eficent Business and IT Consulting Services, S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="bank_statement_reconciliation_summary_wizard_form"
model="ir.ui.view">
<field name="name">bank.statement.reconciliation.summary.wizard.form</field>
<field name="model">bank.statement.reconciliation.summary.wizard</field>
<field name="arch" type="xml">
<form string="Bank Reconciliation Report">
<group name="main">
<field name="start_date"/>
<field name="end_date"/>
<field name="journal_id"/>
<field name="balance_end_real"/>
</group>
<footer>
<button name="open_qweb" string="Open" type="object"
class="btn-primary"/>
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record id="bank_statement_reconciliation_summary_action"
model="ir.actions.act_window">
<field name="name">Bank Statement Reconciliation</field>
<field name="res_model">bank.statement.reconciliation.summary.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem id="bank_statment_reconciliation_summary_wizard_menu"
action="bank_statement_reconciliation_summary_action" parent="account_financial_report_qweb.menu_oca_reports" groups="account.group_account_manager,account.group_account_user" sequence="100"/>
</odoo>
Loading…
Cancel
Save