diff --git a/account_banking_reconciliation/README.rst b/account_banking_reconciliation/README.rst new file mode 100644 index 00000000..8a96742f --- /dev/null +++ b/account_banking_reconciliation/README.rst @@ -0,0 +1,207 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============================= +Bank Statement Reconciliation +============================= + +This module is designed to provide an easy method in which Odoo accounting users +can manually reconcile/validate their financial transactions from their financial +institution/transaction providers (e.g. Paypal, A financial institution, google +wallet, etc) against Odoo GL Chart of Account bank accounts. + +Users will be able to validate and indicate if a transaction has "Cleared the +Bank" using a checkmark on a new Reconcile Financial Account Statement view on +each individual financial transaction. Users will also be able to mark +transactions on a bank account for future research. + +The idea is that as a first step users will manually look at their paper statement +and line-by-line check off which financial transactions have cleared the bank in +Odoo using the new Bank Reconciliation Wizard. These changes will be displayed on +the new Reconcile Financial Account Statement tree view screen. This is the +process in which many companies reconcile (aka Audit) their bank account statements +and accounting system today and represents good segregation of duties. + +Users can save their in-process reconciliations. + +Background +---------- + +Using the search view filters - users will also be able to effectively sort, +filter the transactions on a particular GL Financial Account. This new screen +will display the journal items associated with a particular bank account. +Several of the field labels have been relabeled to a more common vernacular. + +The need for this module is driven by the following: + +* Users want to easily record whether bank transactions sent to their bank have + "cleared the bank"- definition of "cleared the bank": presented to the bank for + payment and paid by the bank - added/subtracted funds on a bank account. +* Users want the ability to validate if the bank processed the transactions them + correctly (e.g. properly encoded transaction - e.g. company sent a payment of + $20.20 to the bank. Was it processed for $20.20?). This can be considered + "Auditing the bank statement". We don't assume the bank correctly processed any + transaction. +* Users want to understand what payments they've made are still outstanding and + have not been paid by the bank. +* The financial auditing segregation standard of separating the duties of: + recording customer payments and making deposits; recording supplier payments + and writing checks; and monitoring bank account activity. This segregation of + duties is necessary to monitor and help prevent fraud. + +Assumptions +----------- + +#. Companies using Odoo have setup a one-to-one relationship between their + bank accounts and their Odoo GL accounts. Each bank account should have a + corresponding GL account that is not shared with another account. + Example: + + +----------------------+------------------------------------------------------------+ + | Odoo GL Account # | Corresponding Bank Account | + +======================+============================================================+ + | 10100 | Bank (AR) Account Checking 5434 (held at Institution A) | + +----------------------+------------------------------------------------------------+ + | 10200 | Master Bank Account 2343 (held at Institution A) | + +----------------------+------------------------------------------------------------+ + | 10300 | Bank Payable Account Checking 5678 (held at Institution A)| + +----------------------+------------------------------------------------------------+ + | 10400 | Bank Payroll Account 6656 (held at Institution B) | + +----------------------+------------------------------------------------------------+ + | 10500 | Paypal Account 3343 (held at Paypal) | + +----------------------+------------------------------------------------------------+ + | 10600 | Google Wallet Account 6788 | + +----------------------+------------------------------------------------------------+ + | 10700 | AMEX Corporate Card Account 9989 | + +----------------------+------------------------------------------------------------+ + +#. Companies have included a Non-Deposited Funds Account in their GL account + (typically in current assets in their bank account areas). This account is + used to store payments that have been recorded in Odoo - but not yet + deposited into the financial institution. (NOTE: this account is important to + have if the user "batches check deposits"- which is the process of making a + large single deposits of customer payment into the bank (e.g. $20,000USD), but + it is made up of smaller checks (e.g. 20 checks of $1,000 each). Many banks + just record the total deposit amount ($20,000) and don¬タルt provide the + breakdown of the individual checks that make up the larger deposit. This + setup approach enables users to drill down and see the individual checks that + make up a larger deposit. + +Recommendations +--------------- + +From a cash management and financial control perspective, it is recommended that +users establish the following four (4) bank accounts at their financial +institution at a minimum to handle financial transactions. (NOTE: we recommend +users place the last 4 digits of their bank account in the GL account name of the +account. It helps accountants in their management of the system): + +* Bank (AR) Account Checking 5434. This is a checking account designated as the + account where payments made to the company are deposited (e.g. a customer + payment made by check is deposited here, or a customer paying by electronic + transaction EFT/ACH is deposited into this GL). +* Master Bank Account 2343. This is the master account in which the company + keeps the majority of their funds. Often with the most limited access. +* Bank Payable Account Checking 5678. This is a checking account designated for + the company to pay their expenses from. (e.g. Company writes a check to pay a + supplier for their office supplies). +* Bank Payroll Account 6656. This is a checking account designated for a company + to pay their employees and payroll. + +Note +---- + +There has been common confusion in the Odoo community about managing bank +statements in the base Odoo system. This module hopes to alleviate this gap and +provide users with a sound alternative to maintain fiscal control, be easy to +understand, and allow for future growth. + +Why this approach? +------------------ + +Users in Odoo have several options in which to record financial transactions that +affect the balances of a bank account (GL Bank Account entries). We believe our +approach allows these to work in conjunction with each other: Import Electronic +Bank Statements to enter payments (this approach follows the philosophy that you +first find out that a transaction has occurred from your bank which is very +common in Europe due to the electronic nature of transactions). + +* Payment Order Payments (using the direct Method) - Payments are instantly recorded + and financial transactions posted into the GL +* Voucher Payments - Payments are instantly recorded and financial transactions + posted into the GL +* Sales Receipts/Refunds +* Transfers between accounts (a new module is being developed to help manage this) +* Funds moved from the Undeposited Funds GL account to a Bank Account GL account. +* Direct Journal Entries + +Usage +===== + +* Go to Accounting + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/98/10.0 + +Roadmap +======= + +* Include a wizard to pre-filter the tree view, and include additional reports for + accountants. And include the ability to execute quick entry of common statement + related transactions such as recording bank service fees (an Expense), and + Interest Income Earned on the bank account (Income), when allowed by law. + Often, companies will print their reconciliation, staple it to their bank + statement and file the documents for future review and audit. +* Include more information to add further clarity throughout Odoo for financial + transactions, and include the ability to quickly compare an imported bank + statement with a GL Bank Account's recorded transaction, including + autoreconciling them - and providing the information available for review. + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Nova Point Group +* Balaji Kannan +* Bhavesh Odedra +* Sandeep Mangukiya + +Funders +------- + +The development of this module has been financially supported by: + +* Nova Point Group +* Ursa Information Systems + +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/account_banking_reconciliation/__init__.py b/account_banking_reconciliation/__init__.py new file mode 100644 index 00000000..f82490e2 --- /dev/null +++ b/account_banking_reconciliation/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2015 Ursa Information Systems (http://www.ursainfosystems.com>) +# Copyright (C) 2011 NovaPoint Group LLC () +# Copyright (C) 2004-2010 OpenERP SA () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/account_banking_reconciliation/__manifest__.py b/account_banking_reconciliation/__manifest__.py new file mode 100644 index 00000000..abb44f01 --- /dev/null +++ b/account_banking_reconciliation/__manifest__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2015 Ursa Information Systems (http://www.ursainfosystems.com>) +# Copyright (C) 2011 NovaPoint Group LLC () +# Copyright (C) 2004-2010 OpenERP SA () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Bank Account Reconciliation", + "version": "10.0.1.0.0", + "license": "AGPL-3", + "category": "Accounting and Financial Management", + "author": "NovaPoint Group LLC, Ursa Information Systems, Odoo Community Association (OCA)", + "website": "http://www.novapointgroup.com", + "depends": [ + "account_voucher", + ], + "data": [ + "security/account_banking_reconciliation.xml", + "security/ir.model.access.csv", + "views/account_banking_reconciliation.xml", + "views/account_move_line.xml", + "report/bank_statement_report.xml"], + "demo": [], + "installable": False, +} diff --git a/account_banking_reconciliation/models/__init__.py b/account_banking_reconciliation/models/__init__.py new file mode 100644 index 00000000..9194bb96 --- /dev/null +++ b/account_banking_reconciliation/models/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2015 Ursa Information Systems (http://www.ursainfosystems.com>) +# Copyright (C) 2011 NovaPoint Group LLC () +# Copyright (C) 2004-2010 OpenERP SA () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import account_move_line, account_banking_reconciliation \ No newline at end of file diff --git a/account_banking_reconciliation/models/account_banking_reconciliation.py b/account_banking_reconciliation/models/account_banking_reconciliation.py new file mode 100644 index 00000000..d7991fd1 --- /dev/null +++ b/account_banking_reconciliation/models/account_banking_reconciliation.py @@ -0,0 +1,473 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014 Ursa Information Systems () +# Copyright (C) 2011 NovaPoint Group LLC () +# Copyright (C) 2004-2010 OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# +############################################################################## +import time + +from openerp.osv import fields, osv +from openerp.tools.translate import _ +import openerp.addons.decimal_precision as dp +from operator import itemgetter + +class bank_acc_rec_statement(osv.osv): + def check_group(self, cr, uid, ids, context=None): + """Check if following security constraints are implemented for groups: + Bank Statement Preparer– they can create, view and delete any of the Bank Statements provided the Bank Statement is not in the DONE state, + or the Ready for Review state. + Bank Statement Verifier – they can create, view, edit, and delete any of the Bank Statements information at any time. + NOTE: DONE Bank Statements are only allowed to be deleted by a Bank Statement Verifier.""" + model_data_obj = self.pool.get('ir.model.data') + res_groups_obj = self.pool.get('res.groups') + group_verifier_id = model_data_obj._get_id(cr, uid, 'ursa_npg_bank_account_reconciliation', 'group_bank_stmt_verifier') + for statement in self.browse(cr, uid, ids, context=context): + if group_verifier_id: + res_id = model_data_obj.read(cr, uid, [group_verifier_id], ['res_id'])[0]['res_id'] + group_verifier = res_groups_obj.browse(cr, uid, res_id, context=context) + group_user_ids = [user.id for user in group_verifier.users] + if statement.state!='draft' and uid not in group_user_ids: + raise osv.except_osv(_('User Error !'), + _("Only a member of '%s' group may delete/edit bank statements when not in draft state!" %(group_verifier.name))) + return True + + def copy(self, cr, uid, id, default={}, context=None): + default.update({ + 'credit_move_line_ids': [], + 'debit_move_line_ids': [], + 'name': '', + }) + return super(bank_acc_rec_statement, self).copy(cr, uid, id, default=default, context=context) + + def write(self, cr, uid, ids, vals, context=None): + self.check_group(cr, uid, ids, context) # Check if the user is allowed to perform the action + return super(bank_acc_rec_statement, self).write(cr, uid, ids, vals, context=context) + + def unlink(self, cr, uid, ids, context=None): + "Reset the related account.move.line to be re-assigned later to statement." + statement_line_obj = self.pool.get('bank.acc.rec.statement.line') + self.check_group(cr, uid, ids, context) # Check if the user is allowed to perform the action + for statement in self.browse(cr, uid, ids, context=context): + statement_lines = statement.credit_move_line_ids + statement.debit_move_line_ids + statement_line_ids = map(lambda x: x.id, statement_lines) + statement_line_obj.unlink(cr, uid, statement_line_ids, context=context) # call unlink method to reset + return super(bank_acc_rec_statement, self).unlink(cr, uid, ids, context=context) + + def check_difference_balance(self, cr, uid, ids, context=None): + "Check if difference balance is zero or not." + for statement in self.browse(cr, uid, ids, context=context): + + if statement.cleared_balance_cur: + if statement.difference_cur != 0.0: + raise osv.except_osv(_('Warning!'), + _("Prior to reconciling a statement, all differences must be accounted for and the Difference balance must be zero." \ + " Please review and make necessary changes.")) + else: + if statement.difference != 0.0: + raise osv.except_osv(_('Warning!'), + _("Prior to reconciling a statement, all differences must be accounted for and the Difference balance must be zero." \ + " Please review and make necessary changes.")) + return True + + def action_cancel(self, cr, uid, ids, context=None): + "Cancel the the statement." + self.write(cr, uid, ids, {'state': 'cancel'}, context=context) + return True + + def action_review(self, cr, uid, ids, context=None): + "Change the status of statement from 'draft' to 'to_be_reviewed'." + # If difference balance not zero prevent further processing + self.check_difference_balance(cr, uid, ids, context=context) + self.write(cr, uid, ids, {'state': 'to_be_reviewed'}, context=context) + return True + + def action_process(self, cr, uid, ids, context=None): + """Set the account move lines as 'Cleared' and Assign 'Bank Acc Rec Statement ID' + for the statement lines which are marked as 'Cleared'.""" + account_move_line_obj = self.pool.get('account.move.line') + statement_line_obj = self.pool.get('bank.acc.rec.statement.line') + # If difference balance not zero prevent further processing + self.check_difference_balance(cr, uid, ids, context=context) + for statement in self.browse(cr, uid, ids, context=context): + statement_lines = statement.credit_move_line_ids + statement.debit_move_line_ids + for statement_line in statement_lines: + #Mark the move lines as 'Cleared'mand assign the 'Bank Acc Rec Statement ID' + account_move_line_obj.write(cr, uid, [statement_line.move_line_id.id], + {'cleared_bank_account': statement_line.cleared_bank_account, + 'bank_acc_rec_statement_id': statement_line.cleared_bank_account and statement.id or False + }, context=context) + + self.write(cr, uid, [statement.id], {'state': 'done', + 'verified_by_user_id': uid, + 'verified_date': time.strftime('%Y-%m-%d') + }, context=context) + return True + + def action_cancel_draft(self, cr, uid, ids, context=None): + """Reset the statement to draft and perform resetting operations.""" + account_move_line_obj = self.pool.get('account.move.line') + statement_line_obj = self.pool.get('bank.acc.rec.statement.line') + for statement in self.browse(cr, uid, ids, context=context): + statement_lines = statement.credit_move_line_ids + statement.debit_move_line_ids + line_ids = [] + statement_line_ids = [] + for statement_line in statement_lines: + statement_line_ids.append(statement_line.id) + + if statement_line.move_line_id: + line_ids.append(statement_line.move_line_id.id) # Find move lines related to statement lines + + # Reset 'Cleared' and 'Bank Acc Rec Statement ID' to False + account_move_line_obj.write(cr, uid, line_ids, {'cleared_bank_account': False, + 'bank_acc_rec_statement_id': False, + }, context=context) + # Reset 'Cleared' in statement lines + statement_line_obj.write(cr, uid, statement_line_ids, {'cleared_bank_account': False, + 'research_required': False + }, context=context) + # Reset statement + self.write(cr, uid, [statement.id], {'state': 'draft', + 'verified_by_user_id': False, + 'verified_date': False + }, context=context) + + return True + + def action_select_all(self, cr, uid, ids, context=None): + """Mark all the statement lines as 'Cleared'.""" + statement_line_obj = self.pool.get('bank.acc.rec.statement.line') + for statement in self.browse(cr, uid, ids, context=context): + statement_lines = statement.credit_move_line_ids + statement.debit_move_line_ids + statement_line_ids = map(lambda x: x.id, statement_lines) + statement_line_obj.write(cr, uid, statement_line_ids, {'cleared_bank_account': True}, context=context) + return True + + def action_unselect_all(self, cr, uid, ids, context=None): + """Reset 'Cleared' in all the statement lines.""" + statement_line_obj = self.pool.get('bank.acc.rec.statement.line') + for statement in self.browse(cr, uid, ids, context=context): + statement_lines = statement.credit_move_line_ids + statement.debit_move_line_ids + statement_line_ids = map(lambda x: x.id, statement_lines) + statement_line_obj.write(cr, uid, statement_line_ids, {'cleared_bank_account': False}, context=context) + return True + + def _get_balance(self, cr, uid, ids, name, args, context=None): + """Computed as following: + A) Deposits, Credits, and Interest Amount: Total SUM of Amts of lines with Cleared = True + Deposits, Credits, and Interest # of Items: Total of number of lines with Cleared = True + B) Checks, Withdrawals, Debits, and Service Charges Amount: + Checks, Withdrawals, Debits, and Service Charges Amount # of Items: + Cleared Balance (Total Sum of the Deposit Amount Cleared (A) – Total Sum of Checks Amount Cleared (B)) + Difference= (Ending Balance – Beginning Balance) - cleared balance = should be zero. +""" + res = {} + account_precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') + for statement in self.browse(cr, uid, ids, context=context): + res[statement.id] = { + 'sum_of_credits': 0.0, + 'sum_of_debits': 0.0, + 'sum_of_credits_cur': 0.0, + 'sum_of_debits_cur': 0.0, + 'sum_of_ucredits': 0.0, + 'sum_of_udebits': 0.0, + 'sum_of_ucredits_cur': 0.0, + 'sum_of_udebits_cur': 0.0, + 'cleared_balance': 0.0, + 'cleared_balance_cur': 0.0, + 'uncleared_balance': 0.0, + 'uncleared_balance_cur': 0.0, + 'difference': 0.0, + 'difference_cur': 0.0, + 'sum_of_credits_lines': 0.0, + 'sum_of_debits_lines': 0.0, + 'sum_of_ucredits_lines': 0.0, + 'sum_of_udebits_lines': 0.0 + } + for line in statement.credit_move_line_ids: + res[statement.id]['sum_of_credits'] += line.cleared_bank_account and round(line.amount, account_precision) or 0.0 + res[statement.id]['sum_of_credits_cur'] += line.cleared_bank_account and round(line.amountcur, account_precision) or 0.0 + res[statement.id]['sum_of_credits_lines'] += line.cleared_bank_account and 1.0 or 0.0 + res[statement.id]['sum_of_ucredits'] += (not line.cleared_bank_account) and round(line.amount, account_precision) or 0.0 + res[statement.id]['sum_of_ucredits_cur'] += (not line.cleared_bank_account) and round(line.amountcur, account_precision) or 0.0 + res[statement.id]['sum_of_ucredits_lines'] += (not line.cleared_bank_account) and 1.0 or 0.0 + for line in statement.debit_move_line_ids: + res[statement.id]['sum_of_debits'] += line.cleared_bank_account and round(line.amount, account_precision) or 0.0 + res[statement.id]['sum_of_debits_cur'] += line.cleared_bank_account and round(line.amountcur, account_precision) or 0.0 + res[statement.id]['sum_of_debits_lines'] += line.cleared_bank_account and 1.0 or 0.0 + res[statement.id]['sum_of_udebits'] += (not line.cleared_bank_account) and round(line.amount, account_precision) or 0.0 + res[statement.id]['sum_of_udebits_cur'] += (not line.cleared_bank_account) and round(line.amountcur, account_precision) or 0.0 + res[statement.id]['sum_of_udebits_lines'] += (not line.cleared_bank_account) and 1.0 or 0.0 + + res[statement.id]['cleared_balance'] = round(res[statement.id]['sum_of_debits'] - res[statement.id]['sum_of_credits'], account_precision) + res[statement.id]['cleared_balance_cur'] = round(res[statement.id]['sum_of_debits_cur'] - res[statement.id]['sum_of_credits_cur'], account_precision) + res[statement.id]['difference'] = round((statement.ending_balance - statement.starting_balance) - res[statement.id]['cleared_balance'], account_precision) + res[statement.id]['difference_cur'] = round((statement.ending_balance - statement.starting_balance) - res[statement.id]['cleared_balance_cur'], account_precision) + res[statement.id]['uncleared_balance'] = round(res[statement.id]['sum_of_udebits'] - res[statement.id]['sum_of_ucredits'], account_precision) + res[statement.id]['uncleared_balance_cur'] = round(res[statement.id]['sum_of_udebits_cur'] - res[statement.id]['sum_of_ucredits_cur'], account_precision) + return res + + # refresh data + def refresh_record(self, cr, uid, ids, context=None): + + retval = True + refdict = {} + + # get current state of moves in the statement + for statement in self.browse(cr, uid, ids, context=context): + + if statement.state == 'draft': + for cr_item in statement.credit_move_line_ids: + if cr_item.move_line_id and cr_item.cleared_bank_account: + refdict[cr_item.move_line_id.id] = cr_item.cleared_bank_account + + for dr_item in statement.debit_move_line_ids: + if dr_item.move_line_id and dr_item.cleared_bank_account: + refdict[dr_item.move_line_id.id] = dr_item.cleared_bank_account + + # for the statement + for statement in self.browse(cr, uid, ids, context=context): + + # process only if the statement is in draft state + if statement.state == 'draft': + account_id = statement.account_id and statement.account_id.id + ending_date = statement.ending_date + suppress_ending_date_filter = statement.suppress_ending_date_filter + vals = self.onchange_account_id(cr, uid, ids, account_id, ending_date, suppress_ending_date_filter, context=context) + + # list of credit lines + outlist = [] + for cr_item in vals['value']['credit_move_line_ids']: + cr_item['cleared_bank_account'] = refdict and refdict.get(cr_item['move_line_id'], False) or False + cr_item['research_required'] = False + + item = [0, False, cr_item] + outlist.append(item) + + # list of debit lines + inlist = [] + for dr_item in vals['value']['debit_move_line_ids']: + dr_item['cleared_bank_account'] = refdict and refdict.get(dr_item['move_line_id'], False) or False + dr_item['research_required'] = False + + item = [0, False, dr_item] + inlist.append(item) + + # write it to the record so it is visible on the form + retval = self.write(cr, uid, ids, {'last_ending_date':vals['value']['last_ending_date'],'starting_balance': vals['value']['starting_balance'], + 'credit_move_line_ids':outlist, 'debit_move_line_ids': inlist}, context=context) + + return retval + + # get starting balance for the account + def get_starting_balance(self, cr, uid, account_id, ending_date, context=None): + + result = (False,0.0) + reslist=[] + statement_obj = self.pool.get('bank.acc.rec.statement') + domain = [('account_id', '=', account_id), ('state', '=', 'done')] + statement_ids = statement_obj.search(cr, uid, domain, context=context) + + # get all statements for this account in the past + for statement in statement_obj.browse(cr, uid, statement_ids, context=context): + if statement.ending_date < ending_date: + reslist.append((statement.ending_date, statement.ending_balance)) + + # get the latest statement value + if len(reslist): + reslist = sorted(reslist,key=itemgetter(0)) + result = reslist[len(reslist)-1] + + return result + + def onchange_account_id(self, cr, uid, ids, account_id, ending_date, suppress_ending_date_filter, context=None): + account_move_line_obj = self.pool.get('account.move.line') + statement_line_obj = self.pool.get('bank.acc.rec.statement.line') + val = {'value': {'credit_move_line_ids': [], 'debit_move_line_ids': []}} + if account_id: + for statement in self.browse(cr, uid, ids, context=context): + statement_line_ids = statement_line_obj.search(cr, uid, [('statement_id', '=', statement.id)], context=context) + # call unlink method to reset and remove existing statement lines and + # mark reset field values in related move lines + statement_line_obj.unlink(cr, uid, statement_line_ids, context=context) + + # Apply filter on move lines to allow + #1. credit and debit side journal items in posted state of the selected GL account + #2. Journal items which are not cleared in previous bank statements + #3. Date less than or equal to ending date provided the 'Suppress Ending Date Filter' is not checkec + domain = [('account_id', '=', account_id), ('move_id.state', '=', 'posted'), ('cleared_bank_account', '=', False)] + if not suppress_ending_date_filter: + domain += [('date', '<=', ending_date)] + line_ids = account_move_line_obj.search(cr, uid, domain, context=context) + for line in account_move_line_obj.browse(cr, uid, line_ids, context=context): + + if not line.journal_id.centralisation: + amount_currency = (line.amount_currency < 0) and (-1*line.amount_currency) or line.amount_currency + res = { + 'ref': line.ref, + 'date': line.date, + 'partner_id': line.partner_id.id, + 'currency_id': line.currency_id.id, + 'amount': line.credit or line.debit, + 'amountcur': amount_currency, + 'name': line.name, + 'move_line_id': line.id, + 'type': line.credit and 'cr' or 'dr' + } + + if res['type'] == 'cr': + val['value']['credit_move_line_ids'].append(res) + else: + val['value']['debit_move_line_ids'].append(res) + + # look for previous statement for the account to pull ending balance as starting balance + prev_stmt=self.get_starting_balance(cr, uid, account_id, ending_date, context=context) + val['value']['last_ending_date'] = prev_stmt[0] + val['value']['starting_balance'] = prev_stmt[1] + + return val + + _name = "bank.acc.rec.statement" + _columns = { + 'name': fields.char('Name', required=True, size=64, states={'done':[('readonly', True)]}, help="This is a unique name identifying the statement (e.g. Bank X January 2012)."), + 'account_id': fields.many2one('account.account', 'Account', required=True, + states={'done':[('readonly', True)]}, domain="[('company_id', '=', company_id), ('type', '!=', 'view')]", + help="The Bank/Gl Account that is being reconciled."), + 'ending_date': fields.date('Ending Date', required=True, states={'done':[('readonly', True)]}, help="The ending date of your bank statement."), + 'last_ending_date': fields.date('Last Stmt Date', help="The previous statement date of your bank statement."), + 'starting_balance': fields.float('Starting Balance', required=True, digits_compute=dp.get_precision('Account'), help="The Starting Balance on your bank statement.", states={'done':[('readonly', True)]}), + 'ending_balance': fields.float('Ending Balance', required=True, digits_compute=dp.get_precision('Account'), help="The Ending Balance on your bank statement.", states={'done':[('readonly', True)]}), + 'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, + help="The Company for which the deposit ticket is made to"), + 'notes': fields.text('Notes'), + 'verified_date': fields.date('Verified Date', states={'done':[('readonly', True)]}, + help="Date in which Deposit Ticket was verified."), + 'verified_by_user_id': fields.many2one('res.users', 'Verified By', states={'done':[('readonly', True)]}, + help="Entered automatically by the “last user” who saved it. System generated."), + 'credit_move_line_ids': fields.one2many('bank.acc.rec.statement.line', 'statement_id', 'Credits', + domain=[('type','=','cr')], context={'default_type':'cr'}, states={'done':[('readonly', True)]}), + 'debit_move_line_ids': fields.one2many('bank.acc.rec.statement.line', 'statement_id', 'Debits', + domain=[('type','=','dr')], context={'default_type':'dr'}, states={'done':[('readonly', True)]}), + 'cleared_balance': fields.function(_get_balance, method=True, string='Cleared Balance', digits_compute=dp.get_precision('Account'), + type='float', help="Total Sum of the Deposit Amount Cleared – Total Sum of Checks, Withdrawals, Debits, and Service Charges Amount Cleared", + multi="balance"), + 'difference': fields.function(_get_balance, method=True, type='float', string='Difference', digits_compute=dp.get_precision('Account'), + help="(Ending Balance – Beginning Balance) - Cleared Balance.", multi="balance"), + 'cleared_balance_cur': fields.function(_get_balance, method=True, string='Cleared Balance (Cur)', digits_compute=dp.get_precision('Account'), + type='float', help="Total Sum of the Deposit Amount Cleared – Total Sum of Checks, Withdrawals, Debits, and Service Charges Amount Cleared", + multi="balance"), + 'difference_cur': fields.function(_get_balance, method=True, type='float', string='Difference (Cur)', digits_compute=dp.get_precision('Account'), + help="(Ending Balance – Beginning Balance) - Cleared Balance.", multi="balance"), + 'uncleared_balance': fields.function(_get_balance, method=True, string='Uncleared Balance', digits_compute=dp.get_precision('Account'), + type='float', help="Total Sum of the Deposit Amount Uncleared – Total Sum of Checks, Withdrawals, Debits, and Service Charges Amount Uncleared", + multi="balance"), + 'uncleared_balance_cur': fields.function(_get_balance, method=True, string='Unleared Balance (Cur)', digits_compute=dp.get_precision('Account'), + type='float', help="Total Sum of the Deposit Amount Uncleared – Total Sum of Checks, Withdrawals, Debits, and Service Charges Amount Uncleared", + multi="balance"), + 'sum_of_credits': fields.function(_get_balance, method=True, string='Checks, Withdrawals, Debits, and Service Charges Amount', digits_compute=dp.get_precision('Account'), + type='float', help="Total SUM of Amts of lines with Cleared = True", + multi="balance"), + 'sum_of_debits': fields.function(_get_balance, method=True, type='float', string='Deposits, Credits, and Interest Amount', digits_compute=dp.get_precision('Account'), + help="Total SUM of Amts of lines with Cleared = True", multi="balance"), + 'sum_of_credits_cur': fields.function(_get_balance, method=True, string='Checks, Withdrawals, Debits, and Service Charges Amount (Cur)', digits_compute=dp.get_precision('Account'), + type='float', help="Total SUM of Amts of lines with Cleared = True", + multi="balance"), + 'sum_of_debits_cur': fields.function(_get_balance, method=True, type='float', string='Deposits, Credits, and Interest Amount (Cur)', digits_compute=dp.get_precision('Account'), + help="Total SUM of Amts of lines with Cleared = True", multi="balance"), + 'sum_of_credits_lines': fields.function(_get_balance, method=True, string='Checks, Withdrawals, Debits, and Service Charges # of Items', + type='float', help="Total of number of lines with Cleared = True", + multi="balance"), + 'sum_of_debits_lines': fields.function(_get_balance, method=True, type='float', string='Deposits, Credits, and Interest # of Items', + help="Total of number of lines with Cleared = True", multi="balance"), + 'sum_of_ucredits': fields.function(_get_balance, method=True, string='Uncleared - Checks, Withdrawals, Debits, and Service Charges Amount', digits_compute=dp.get_precision('Account'), + type='float', help="Total SUM of Amts of lines with Cleared = False", + multi="balance"), + 'sum_of_udebits': fields.function(_get_balance, method=True, type='float', string='Uncleared - Deposits, Credits, and Interest Amount', digits_compute=dp.get_precision('Account'), + help="Total SUM of Amts of lines with Cleared = False", multi="balance"), + 'sum_of_ucredits_cur': fields.function(_get_balance, method=True, string='Uncleared - Checks, Withdrawals, Debits, and Service Charges Amount (Cur)', digits_compute=dp.get_precision('Account'), + type='float', help="Total SUM of Amts of lines with Cleared = False", + multi="balance"), + 'sum_of_udebits_cur': fields.function(_get_balance, method=True, type='float', string='Uncleared - Deposits, Credits, and Interest Amount (Cur)', digits_compute=dp.get_precision('Account'), + help="Total SUM of Amts of lines with Cleared = False", multi="balance"), + 'sum_of_ucredits_lines': fields.function(_get_balance, method=True, string='Uncleared - Checks, Withdrawals, Debits, and Service Charges # of Items', + type='float', help="Total of number of lines with Cleared = False", + multi="balance"), + 'sum_of_udebits_lines': fields.function(_get_balance, method=True, type='float', string='Uncleared - Deposits, Credits, and Interest # of Items', + help="Total of number of lines with Cleared = False", multi="balance"), + 'suppress_ending_date_filter': fields.boolean('Remove Ending Date Filter', help="If this is checked then the Statement End Date filter on the transactions below will not occur. All transactions would come over."), + 'state': fields.selection([ + ('draft','Draft'), + ('to_be_reviewed','Ready for Review'), + ('done','Done'), + ('cancel', 'Cancel') + ],'State', select=True, readonly=True), + } + _defaults = { + 'state': 'draft', + 'company_id': lambda self, cr, uid, c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id, + 'ending_date': time.strftime('%Y-%m-%d'), + } + _order = "ending_date desc" + _sql_constraints = [ + ('name_company_uniq', 'unique (name, company_id, account_id)', 'The name of the statement must be unique per company and G/L account!') + ] +bank_acc_rec_statement() + +class bank_acc_rec_statement_line(osv.osv): + _name = "bank.acc.rec.statement.line" + _description = "Statement Line" + _columns = { + 'name': fields.char('Name', size=64, help="Derived from the related Journal Item.", required=True), + 'ref': fields.char('Reference', size=64, help="Derived from related Journal Item."), + 'partner_id': fields.many2one('res.partner', string='Partner', help="Derived from related Journal Item."), + 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account'), + help="Derived from the 'debit' amount from related Journal Item."), + 'amountcur': fields.float('Amount in Currency', digits_compute=dp.get_precision('Account'), + help="Derived from the 'amount currency' amount from related Journal Item."), + 'date': fields.date('Date', required=True, help="Derived from related Journal Item."), + 'statement_id': fields.many2one('bank.acc.rec.statement', 'Statement', required=True, ondelete='cascade'), + 'move_line_id': fields.many2one('account.move.line', 'Journal Item', help="Related Journal Item."), + 'cleared_bank_account': fields.boolean('Cleared? ', help='Check if the transaction has cleared from the bank'), + 'research_required': fields.boolean('Research Required? ', help='Check if the transaction should be researched by Accounting personal'), + 'currency_id': fields.many2one('res.currency', 'Currency', help="The optional other currency if it is a multi-currency entry."), + 'type':fields.selection([('dr','Debit'),('cr','Credit')], 'Cr/Dr'), + } + + def create(self, cr, uid, vals, context=None): + account_move_line_obj = self.pool.get('account.move.line') + # Prevent manually adding new statement line. + # This would allow only onchange method to pre-populate statement lines based on the filter rules. + if not vals.get('move_line_id', False): + raise osv.except_osv(_('Processing Error'),_('You cannot add any new bank statement line manually as of this revision!')) + account_move_line_obj.write(cr, uid, [vals['move_line_id']], {'draft_assigned_to_statement': True}, context=context) + return super(bank_acc_rec_statement_line, self).create(cr, uid, vals, context=context) + + def unlink(self, cr, uid, ids, context=None): + account_move_line_obj = self.pool.get('account.move.line') + move_line_ids = [x.move_line_id.id for x in self.browse(cr, uid, ids, context=context) if x.move_line_id] + #map(lambda x: x.move_line_id.id if x.move_line_id, self.browse(cr, uid, ids, context=context)) + # Reset field values in move lines to be added later + account_move_line_obj.write(cr, uid, move_line_ids, {'draft_assigned_to_statement': False, + 'cleared_bank_account': False, + 'bank_acc_rec_statement_id': False, + }, context=context) + return super(bank_acc_rec_statement_line, self).unlink(cr, uid, ids, context=context) + +bank_acc_rec_statement_line() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/account_banking_reconciliation/models/account_move_line.py b/account_banking_reconciliation/models/account_move_line.py new file mode 100644 index 00000000..c6f8dea1 --- /dev/null +++ b/account_banking_reconciliation/models/account_move_line.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011 NovaPoint Group LLC () +# Copyright (C) 2004-2010 OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import fields,osv + +class account_move_line(osv.osv): + _inherit='account.move.line' + + _columns = { + 'cleared_bank_account': fields.boolean('Cleared? ', help='Check if the transaction has cleared from the bank'), + 'bank_acc_rec_statement_id': fields.many2one('bank.acc.rec.statement', 'Bank Acc Rec Statement', help="The Bank Acc Rec Statement linked with the journal item"), + 'draft_assigned_to_statement': fields.boolean('Assigned to Statement? ', help='Check if the move line is assigned to statement lines') + } + + +account_move_line() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/account_banking_reconciliation/report/bank_statement_detail.rml b/account_banking_reconciliation/report/bank_statement_detail.rml new file mode 100644 index 00000000..a4a1619c --- /dev/null +++ b/account_banking_reconciliation/report/bank_statement_detail.rml @@ -0,0 +1,750 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [[ repeatIn(objects, 'stmt') ]] + [[ setLang(stmt.lang) ]] + +
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + + + + + + + + + + + Date + + + Comment + + + Partner + + + Reference + + + Cleared + + + Amount([[ company.currency_id.symbol ]]) + + + Amount([[ stmt.account_id.currency_id.symbol ]]) + + + +
+
+ [[ (stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + + + + + + + + + + + Date + + + Comment + + + Partner + + + Reference + + + Cleared + + + Amount([[ company.currency_id.symbol ]]) + + + Amount([[ stmt.account_id.currency_id.symbol ]]) + + + +
+
+
+ Reconciliation Detail + Period Ending [[ (stmt.ending_date) or '' ]] +
+ + + + + + +
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + + + + Date + + + Comment + + + Partner + + + Reference + + + Cleared + + + Amount([[ company.currency_id.symbol ]]) + + + Amount([[ stmt.account_id.currency_id.symbol ]]) + + + +
+
+ [[ stmt.account_id.currency_id and removeParentNode('section') or '' ]] + + + + + + + Date + + + Comment + + + Partner + + + Reference + + + Cleared + + + Amount([[ company.currency_id.symbol ]]) + + + +
+
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + Initial Balance + + + + [[ stmt.starting_balance ]] + + + + + + Cleared Transactions + + + + + + + + Deposits & Credits-[[ (stmt.sum_of_debits_lines) or '']] items + + + + + +
+
+ [[ stmt.account_id.currency_id and removeParentNode('section') or '' ]] + + + + Initial Balance + + + + [[ stmt.starting_balance ]] + + + + + + Cleared Transactions + + + + + + + + Deposits & Credits-[[ (stmt.sum_of_debits_lines) or '']] items + + + + + +
+
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + [[ repeatIn(stmt.debit_move_line_ids, 'debit') ]] +
[[ (not debit['cleared_bank_account']) and removeParentNode('section') ]] + + + + + + + [[ formatLang(debit['date'],date=True) ]] + + + [[ debit['name'] ]] + + + [[ debit['partner_id'].name or '' ]] + + + [[ debit['ref'] ]] + + + [[ (debit['cleared_bank_account']) and 'X' or '' ]] + + + [[ formatLang((debit['amount'])) ]] + + + [[ formatLang((debit['amountcur'])) ]] + + + +
+
+
+ [[ stmt.account_id.currency_id and removeParentNode('section') or '' ]] + [[ repeatIn(stmt.debit_move_line_ids, 'debit') ]] +
[[ (not debit['cleared_bank_account']) and removeParentNode('section') ]] + + + + + + + [[ formatLang(debit['date'],date=True) ]] + + + [[ debit['name'] ]] + + + [[ debit['partner_id'].name or '' ]] + + + [[ debit['ref'] ]] + + + [[ (debit['cleared_bank_account']) and 'X' or '' ]] + + + [[ formatLang((debit['amount'])) ]] + + + +
+
+
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + Total Deposits & Credits + + + [[ (stmt.sum_of_debits) or '']] + [[ (stmt.sum_of_debits_cur) or '']] + + + + + + + Checks & Payments-[[ (stmt.sum_of_credits_lines) or '']] items + + + + + +
+
+ [[ (stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + Total Deposits & Credits + + + [[ (stmt.sum_of_debits) or '']] + + + + + + + Checks & Payments-[[ (stmt.sum_of_credits_lines) or '']] items + + + + + +
+
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + [[ repeatIn(stmt.credit_move_line_ids, 'credit') ]] + + + + + + + [[ formatLang(credit['date'],date=True) ]] + + + [[ credit['name'] ]] + + + [[ credit['partner_id'].name or '' ]] + + + [[ credit['ref'] ]] + + + [[ (credit['cleared_bank_account']) and 'X' or '' ]] + + + [[ formatLang((credit['amount'])) ]] + + + [[ formatLang((credit['amountcur']))]] + + + +
+
+ [[ (stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + [[ repeatIn(stmt.credit_move_line_ids, 'credit') ]] + + + + + + + [[ formatLang(credit['date'],date=True) ]] + + + [[ credit['name'] ]] + + + [[ credit['partner_id'].name or '' ]] + + + [[ credit['ref'] ]] + + + [[ (credit['cleared_bank_account']) and 'X' or '' ]] + + + [[ formatLang((credit['amount'])) ]] + + + +
+
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + Total Checks & Payments + + + [[ (stmt.sum_of_credits) or '']] + [[ (stmt.sum_of_credits_cur) or '']] + + + + + + Total Cleared Transactions + + + [[ formatLang(stmt.sum_of_debits - stmt.sum_of_credits) or '']] + [[ formatLang(stmt.sum_of_debits_cur - stmt.sum_of_credits_cur) or '']] + + + + Cleared Balance + + + [[ (stmt.cleared_balance) or '']] + [[ (stmt.cleared_balance_cur) or '']] + + + + Ending Balance + + + + [[ (stmt.ending_balance) or '']] + + +
+
+ [[ (stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + + Total Deposits and Credits + + + [[ (stmt.sum_of_credits) or '']] + + + + + + Total Cleared Transactions + + + [[ formatLang(stmt.sum_of_debits - stmt.sum_of_credits) or '']] + + + + Cleared Balance + + + [[ (stmt.cleared_balance) or '']] + + + + Ending Balance + + + [[ (stmt.ending_balance) or '']] + + +
+
+
+
diff --git a/account_banking_reconciliation/report/bank_statement_report.xml b/account_banking_reconciliation/report/bank_statement_report.xml new file mode 100644 index 00000000..cb72d073 --- /dev/null +++ b/account_banking_reconciliation/report/bank_statement_report.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/account_banking_reconciliation/report/bank_statement_summary.rml b/account_banking_reconciliation/report/bank_statement_summary.rml new file mode 100644 index 00000000..55eb3ce0 --- /dev/null +++ b/account_banking_reconciliation/report/bank_statement_summary.rml @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [[ repeatIn(objects, 'stmt') ]] + [[ setLang(stmt.lang) ]] + + +
+ Reconciliation Summary + Period Ending [[ (stmt.ending_date) or '' ]] +
+ + + + + + +
+ [[ (not stmt.account_id.currency_id) and removeParentNode('section') or '' ]] + + + Initial Balance + + [[ stmt.starting_balance ]] + + + + + + + Cleared Transactions + + + + + + + + Deposits & Credits-[[ (stmt.sum_of_debits_lines) or '']] items + [[ (stmt.sum_of_debits) or '']] + [[ (stmt.sum_of_debits_cur) or '']] + + + + + Checks & Payments-[[ (stmt.sum_of_credits_lines) or '']] items + [[ (stmt.sum_of_credits) or '']] + [[ (stmt.sum_of_credits_cur) or '']] + + + + + + + Total Cleared Transactions + [[ formatLang(stmt.sum_of_debits - stmt.sum_of_credits) or '']] + [[ formatLang(stmt.sum_of_debits_cur - stmt.sum_of_credits_cur) or '']] + + + + + + Cleared Balance + [[ (stmt.cleared_balance) or '']] + [[ (stmt.cleared_balance_cur) or '']] + [[ (stmt.cleared_balance_cur) or '']] + + + + + Ending Balance + + [[ (stmt.ending_balance) or '']] + + +
+
+ [[ stmt.account_id.currency_id and removeParentNode('section') or '' ]] + + + Initial Balance + + [[ stmt.starting_balance ]] + + + + + + + Cleared Transactions + + + + + + + + Deposits & Credits-[[ (stmt.sum_of_debits_lines) or '']] items + + [[ (stmt.sum_of_debits) or '']] + + + + + Checks & Payments-[[ (stmt.sum_of_credits_lines) or '']] items + + [[ (stmt.sum_of_credits) or '']] + + + + + + + Total Cleared Transactions + + [[ formatLang(stmt.sum_of_debits - stmt.sum_of_credits) or '']] + + + + + + Cleared Balance + + [[ (stmt.cleared_balance) or '']] + [[ (stmt.cleared_balance) or '']] + + + + + Ending Balance + + [[ (stmt.ending_balance) or '']] + + +
+
+
+
diff --git a/account_banking_reconciliation/security/account_banking_reconciliation.xml b/account_banking_reconciliation/security/account_banking_reconciliation.xml new file mode 100644 index 00000000..eff450eb --- /dev/null +++ b/account_banking_reconciliation/security/account_banking_reconciliation.xml @@ -0,0 +1,25 @@ + + + + + + + + Bank Statement Preparer + + + + Bank Statement Verifier + + + + + + Bank Statements + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + + \ No newline at end of file diff --git a/account_banking_reconciliation/security/ir.model.access.csv b/account_banking_reconciliation/security/ir.model.access.csv new file mode 100644 index 00000000..d630197c --- /dev/null +++ b/account_banking_reconciliation/security/ir.model.access.csv @@ -0,0 +1,5 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_bank_acc_rec_statement_preparer","access.bank.acc.rec.statement.preparer","model_bank_acc_rec_statement","group_bank_stmt_preparer",1,1,1,1 +"access_bank_acc_rec_statement_verifier","access.bank.acc.rec.statement.verifier","model_bank_acc_rec_statement","group_bank_stmt_verifier",1,1,1,1 +"access_bank_acc_rec_statement_line_preparer","access.bank.acc.rec.statement.line.preparer","model_bank_acc_rec_statement_line","group_bank_stmt_preparer",1,1,1,1 +"access_bank_acc_rec_statement_line_verifier","access.bank.acc.rec.statement.line.verifier","model_bank_acc_rec_statement_line","group_bank_stmt_verifier",1,1,1,1 diff --git a/account_banking_reconciliation/static/description/icon.png b/account_banking_reconciliation/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/account_banking_reconciliation/static/description/icon.png differ diff --git a/account_banking_reconciliation/views/account_banking_reconciliation.xml b/account_banking_reconciliation/views/account_banking_reconciliation.xml new file mode 100644 index 00000000..63901753 --- /dev/null +++ b/account_banking_reconciliation/views/account_banking_reconciliation.xml @@ -0,0 +1,230 @@ + + + + + + + + bank.acc.rec.statement.tree + bank.acc.rec.statement + tree + 2 + + + + + + + + + + + + + bank.acc.rec.statement.form + bank.acc.rec.statement + form + +
+
+
+ + + + + + + + + + + + + +