cash statement form with cashbox

16-gn-cash
Florian Roger 2 months ago
parent 9f06e88b88
commit 12572120e3

@ -0,0 +1,23 @@
# GN-CASH
This modules revivals cash statements from Odoo 15.
It adds a wizard for cashbox counting after balance_start an balance_end_real fields of bank.statement form view.
It is based on modules:
- (account_statement_base from OCA)[https://github.com/OCA/account-reconcile]
## How do we work with it:
1. Each day, users create operations they assume (like receive donation, etc.)
2. If time is short, they can also declare it on a simple solo statement line
3. At the end of the week, Odoo generates a statement with missing lines (i.e. lines with payment suspense accounts)
4. the accountant verifies cashbox balance and validate loss/profit
## Whats Needs to Be Done:
- add validate cashbox and entry lines creation
- allow user to add statement lines 'on-the-fly'
- allow user to create Donation / Expense / Cash-In / Cash-Out operations
- create an action triggered by a button leading to a wizard that auto-generates cash statement from lines with payment suspense account.

@ -6,13 +6,10 @@
'description': """
This module revivals cash statements from odoo 15.
""",
'depends': ['account_reconcile_oca', 'account_statement_import_sheet_file'],
'depends': ['account_statement_base'],
'data': [
'security/ir.model.access.csv',
'views/delete_views.xml',
'views/account_journal_views.xml',
'views/account_cash_statement_views.xml',
'views/account_journal_dashboard_view.xml',
'views/cash_statement_views.xml',
],
'translate': True,

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
from . import cash_statement
#, account_journal_dashboard
#account_journal_dashboard

@ -1,90 +0,0 @@
from odoo import models, api, _, fields
from odoo.exceptions import UserError
import ast
class account_journal(models.Model):
_inherit = "account.journal"
def _select_action_to_open(self):
self.ensure_one()
if self._context.get('action_name'):
return self._context.get('action_name')
elif self.type == 'bank':
return 'account.action_bank_statement_tree'
elif self.type == 'cash':
#return 'gn_cash.action_cash_statement_tree'
return 'account.action_view_bank_statement_tree'
elif self.type == 'sale':
return 'account.action_move_out_invoice_type'
elif self.type == 'purchase':
return 'account.action_move_in_invoice_type'
else:
return 'account.action_move_journal_line'
def create_cash_statement(self):
"""return action to create a cash statements."""
action = self.env["ir.actions.actions"]._for_xml_id("gn_cash.action_cash_statement_tree")
action.update({
'views': [(self.env.ref('gn_cash.view_cash_statement_form').id, 'form')],
'context': {
'default_journal_id': str(self.id),
'journal_type': str(self.type),
}
})
return action
def open_action(self):
"""return action based on type for related journals"""
self.ensure_one()
action_name = self._select_action_to_open()
# Set 'account.' prefix if missing.
#if not action_name.startswith("account."):
# action_name = 'account.%s' % action_name
action = self.env["ir.actions.act_window"]._for_xml_id(action_name)
context = self._context.copy()
if 'context' in action and isinstance(action['context'], str):
context.update(ast.literal_eval(action['context']))
else:
context.update(action.get('context', {}))
action['context'] = context
action['context'].update({
'default_journal_id': self.id,
})
domain_type_field = action['res_model'] == 'account.move.line' and 'move_id.move_type' or 'move_type' # The model can be either account.move or account.move.line
# Override the domain only if the action was not explicitly specified in order to keep the
# original action domain.
if action.get('domain') and isinstance(action['domain'], str):
action['domain'] = ast.literal_eval(action['domain'] or '[]')
if not self._context.get('action_name'):
if self.type == 'sale':
action['domain'] = [(domain_type_field, 'in', ('out_invoice', 'out_refund', 'out_receipt'))]
elif self.type == 'purchase':
action['domain'] = [(domain_type_field, 'in', ('in_invoice', 'in_refund', 'in_receipt', 'entry'))]
action['domain'] = (action['domain'] or []) + [('journal_id', '=', self.id)]
return action
def open_action_with_context(self):
action_name = self.env.context.get('action_name', False)
if not action_name:
return False
ctx = dict(self.env.context, default_journal_id=self.id)
if ctx.get('search_default_journal', False):
ctx.update(search_default_journal_id=self.id)
ctx['search_default_journal'] = False # otherwise it will do a useless groupby in bank statements
ctx.pop('group_by', None)
action = self.env['ir.actions.act_window']._for_xml_id(action_name)
action['context'] = ctx
if ctx.get('use_domain', False):
action['domain'] = isinstance(ctx['use_domain'], list) and ctx['use_domain'] or ['|', ('journal_id', '=', self.id), ('journal_id', '=', False)]
action['name'] = _(
"%(action)s for journal %(journal)s",
action=action["name"],
journal=self.name,
)
return action

@ -95,9 +95,14 @@ class AccountBankStmtCloseCheck(models.TransientModel):
"""
Account Bank Statement wizard that check that closing balance is correct.
"""
_name = 'account.bank.statement.closebalance'
_name = 'gn_cash.account.bank.statement.closebalance'
_description = 'Bank Statement Closing Balance'
"""
Warning!! This method is not linked to effective operations.
We need to figure out what to do with difference found beetween calculated total and wizard total
i.e. which moves need to be created
"""
def validate(self):
bnk_stmt_id = self.env.context.get('active_id', False)
if bnk_stmt_id:
@ -110,6 +115,9 @@ class BankStatement(models.Model):
cashbox_start_id = fields.Many2one('gn_cash.account.bank.statement.cashbox', string="Starting Cashbox")
cashbox_end_id = fields.Many2one('gn_cash.account.bank.statement.cashbox', string="Ending Cashbox")
#This is the function we need to verify in order to have a functionnal validate on wizard
def _check_cash_balance_end_real_same_as_computed(self):
""" Check the balance_end_real (encoded manually by the user) is equals to the balance_end (computed by odoo).
For a cash statement, if there is a difference, the different is set automatically to a profit/loss account.

@ -1,85 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_cash_statement_form" model="ir.ui.view">
<field name="name">gn_cash.account.cash.statement.form</field>
<field name="model">account.bank.statement</field>
<field name="priority">1</field>
<field name="arch" type="xml">
<form string="Cash registry">
<div
class="alert alert-warning"
role="alert"
attrs="{'invisible': [('problem_description', '=', False)]}"
>
<field name="problem_description" />
</div>
<sheet>
<div name="button_box" position="inside">
<button
class="oe_stat_button"
type="action"
name="%(account_statement_base.account_bank_statement_line_action)d"
icon="fa-bars"
context="{'search_default_statement_id': id}"
string="Transactions for cashbox"
/>
</div>
<div class="oe_title oe_inline">
<label for="name" />
<h1><field
name="name"
placeholder="e.g. BNK/2021/0001"
/></h1>
</div>
<group>
<group>
<field name="date" />
<field
name='company_id'
options="{'no_create': True}"
groups="base.group_multi_company"
/>
<field name="currency_id" invisible="1" />
<field name="journal_id" invisible="1" />
<field name="cashbox_start_id" invisible="1"/>
<field name="cashbox_end_id" invisible="1"/>
</group>
<group>
<label for="balance_start" />
<div>
<field name="balance_start" class="oe_inline" />
<button name="open_cashbox_id" string="&#8594; Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'start'}"/>
</div>
<label for="balance_end_real" />
<div>
<field name="balance_end_real" class="oe_inline" />
<button name="open_cashbox_id" string="&#8594; Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'close'}"/>
</div>
</group>
</group>
<field
name="line_ids"
context="{'default_journal_id': journal_id}"
/>
<group
class="oe_subtotal_footer oe_right"
name="sale_total"
col="1"
>
<field
name="balance_end"
class="oe_subtotal_footer_separator"
/>
</group>
<field name="attachment_ids" widget="many2many_binary" />
<div class="oe_clear" />
</sheet>
</form>
</field>
</record>
<record id="action_cash_statement_tree" model="ir.actions.act_window">
<record id="gn_cash.action_cash_statement_tree" model="ir.actions.act_window">
<field name="name">Cash Logs</field>
<field name="res_model">account.bank.statement</field>
<field name="view_mode">tree,form,pivot,graph</field>
@ -96,29 +18,19 @@
</p>
</field>
</record>
<record model="ir.actions.act_window.view" id="action_cash_statement_tree_cash">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="account.view_bank_statement_tree"/>
<field name="act_window_id" ref="action_cash_statement_tree"/>
</record>
<record model="ir.actions.act_window.view" id="action_cash_statement_form_cash">
<field name="sequence" eval="1"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_cash_statement_form"/>
<field name="act_window_id" ref="action_cash_statement_tree"/>
</record>
<record model="ir.actions.act_window.view" id="action_cash_statement_tree_cash">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="account.view_bank_statement_tree"/>
<field name="act_window_id" ref="account.action_view_bank_statement_tree"/>
</record>
<record model="ir.actions.act_window.view" id="action_cash_statement_form_cash">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_cash_statement_form"/>
<field name="act_window_id" ref="account.action_view_bank_statement_tree"/>
</record>
<record id="gn_cash.view_cash_statement_form" model="ir.ui.view">
<field name="name">gn_cash.account.cash.statement.form</field>
<field name="model">account.bank.statement</field>
<field name="inherit_id" ref="account_statement_base.view_bank_statement_form"/>
<field name="priority">100</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='balance_start']" position="after" >
<button name="open_cashbox_id" invisible ="context.get('journal_type', False) != 'cash'" string="&#8594; Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'start'}"/>
</xpath>
<xpath expr="//field[@name='balance_end_real']" position="after">
<button name="open_cashbox_id" invisible ="context.get('journal_type', False) != 'cash'" string="&#8594; Count" type="object" class="oe_edit_only oe_link oe_inline" context="{'balance':'close'}"/>
</xpath>
</field>
</record>
</data>
</odoo>

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="account_journal_dashboard_kanban_view" model="ir.ui.view">
<field name="name">gn_cash.journal.dashboard.kanban</field>
<field name="model">account.journal</field>
<field name="inherit_id" ref="account.account_journal_dashboard_kanban_view"/>
<field name="arch" type="xml">
<xpath
expr='//a[@name="create_cash_statement"]/..'
position='replace'
>
<t t-if="dashboard.bank_statements_source == 'file_import_oca'">
<t t-if="journal_type == 'cash'">
<button
name="import_account_statement"
type="object"
class="btn btn-primary"
groups="account.group_account_user"
>
<span>Import Cash Log</span>
</button>
</t>
</t>
</xpath>
<xpath expr='//div[@name="bank_customer_payment"]' position="before">
<div t-if="journal_type == 'cash'" groups="account.group_account_user">
<a
type="object"
name="import_account_statement"
>Import Cash Statement (OCA)</a>
<a
type="object"
name="action_view_bank_statement_tree"
groups="account.group_account_invoice"
>New manual Cash Statement</a>
</div>
</xpath>
</field>
</record>
</data>
</odoo>

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="gn_cash.view_account_journal_form" model="ir.ui.view">
<field name="name">gn_cash.account.journal.form</field>
<field name="model">account.journal</field>
<field name="inherit_id" ref="account_statement_import_sheet_file.view_account_journal_form_n43"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='advanced_settings']/group/group/field[@name='default_sheet_mapping_id']/.." position="after">
<group string="Statement Import Map for Cash and Bank" attrs="{'invisible': [('type','!=', 'cash')]}">
<field name="bank_statements_source" attrs="{'required': [('type', '=', 'cash')]}" widget="radio" groups="account.group_account_readonly"/>
<field name="default_sheet_mapping_id" />
</group>
</xpath>
</field>
</record>
</data>
</odoo>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_account_bnk_stmt_cashbox" model="ir.ui.view">
<record id="gn_cash.view_account_bnk_stmt_cashbox" model="ir.ui.view">
<field name="name">gn_cash.account.bnk_stmt_cashbox.form</field>
<field name="model">gn_cash.account.bank.statement.cashbox</field>
<field name="arch" type="xml">
@ -31,12 +31,12 @@
</form>
</field>
</record>
<record id="view_account_bnk_stmt_cashbox_footer" model="ir.ui.view">
<record id="gn_cash.view_account_bnk_stmt_cashbox_footer" model="ir.ui.view">
<field name="name">gn_cash.account.bnk_stmt_cashbox.form</field>
<field name="model">gn_cash.account.bank.statement.cashbox</field>
<field name="priority">1000</field>
<field name="mode">primary</field>
<field name="inherit_id" ref="view_account_bnk_stmt_cashbox"/>
<field name="inherit_id" ref="gn_cash.view_account_bnk_stmt_cashbox"/>
<field name="arch" type="xml">
<xpath expr="//sheet" position="after">
<footer>
@ -46,9 +46,9 @@
</xpath>
</field>
</record>
<record id="view_account_bnk_stmt_check" model="ir.ui.view">
<record id="gn_cash.view_account_bnk_stmt_check" model="ir.ui.view">
<field name="name">gn_cash.account.bnk_stmt_check.form</field>
<field name="model">account.bank.statement.closebalance</field>
<field name="model">gn_cash.account.bank.statement.closebalance</field>
<field name="arch" type="xml">
<form>
<div>
@ -62,9 +62,9 @@
</form>
</field>
</record>
<record id="action_view_account_bnk_stmt_check" model="ir.actions.act_window">
<record id="gn_cash.action_view_account_bnk_stmt_check" model="ir.actions.act_window">
<field name="name">Check Closing Balance</field>
<field name="res_model">account.bank.statement.closebalance</field>
<field name="res_model">gn_cash.account.bank.statement.closebalance</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_account_bnk_stmt_check"/>
<field name="target">new</field>

Loading…
Cancel
Save