1st version wth redudancy

This commit is contained in:
makayabou 2024-07-07 00:01:45 +02:00
parent 9dedfed123
commit 9f06e88b88
11 changed files with 559 additions and 0 deletions

3
gn_cash/__init__.py Normal file
View File

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

20
gn_cash/__manifest__.py Normal file
View File

@ -0,0 +1,20 @@
{
'name': "Gn Cash",
'version': '16.0.0.0.1',
'author': 'Garage Numérique',
'category': 'Accounting',
'description': """
This module revivals cash statements from odoo 15.
""",
'depends': ['account_reconcile_oca', 'account_statement_import_sheet_file'],
'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,
'installable': True,
}

View File

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

View File

@ -0,0 +1,90 @@
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

View File

@ -0,0 +1,174 @@
# -*- coding: utf-8 -*-
import math
from odoo import api, fields, models, _
from odoo.tools import float_is_zero
from odoo.tools.misc import formatLang, format_date, str2bool
from odoo.exceptions import UserError, ValidationError
class AccountCashboxLine(models.Model):
""" Cash Box Details """
_name = 'gn_cash.account.cashbox.line'
_description = 'CashBox Line'
_rec_name = 'coin_value'
_order = 'coin_value'
@api.depends('coin_value', 'number')
def _sub_total(self):
""" Calculates Sub total"""
for cashbox_line in self:
cashbox_line.subtotal = cashbox_line.coin_value * cashbox_line.number
coin_value = fields.Float(string='Coin/Bill Value', required=True, digits=0)
number = fields.Integer(string='#Coins/Bills', help='Opening Unit Numbers')
subtotal = fields.Float(compute='_sub_total', string='Subtotal', digits=0, readonly=True)
cashbox_id = fields.Many2one('gn_cash.account.bank.statement.cashbox', string="Cashbox")
currency_id = fields.Many2one('res.currency', related='cashbox_id.currency_id')
class AccountBankStmtCashWizard(models.Model):
"""
Account Bank Statement popup that allows entering cash details.
"""
_name = 'gn_cash.account.bank.statement.cashbox'
_description = 'Bank Statement Cashbox'
_rec_name = 'id'
cashbox_lines_ids = fields.One2many('gn_cash.account.cashbox.line', 'cashbox_id', string='Cashbox Lines')
start_bank_stmt_ids = fields.One2many('account.bank.statement', 'cashbox_start_id')
end_bank_stmt_ids = fields.One2many('account.bank.statement', 'cashbox_end_id')
total = fields.Float(compute='_compute_total')
currency_id = fields.Many2one('res.currency', compute='_compute_currency')
@api.depends('start_bank_stmt_ids', 'end_bank_stmt_ids')
def _compute_currency(self):
for cashbox in self:
cashbox.currency_id = False
if cashbox.end_bank_stmt_ids:
cashbox.currency_id = cashbox.end_bank_stmt_ids[0].currency_id
if cashbox.start_bank_stmt_ids:
cashbox.currency_id = cashbox.start_bank_stmt_ids[0].currency_id
@api.depends('cashbox_lines_ids', 'cashbox_lines_ids.coin_value', 'cashbox_lines_ids.number')
def _compute_total(self):
for cashbox in self:
cashbox.total = sum([line.subtotal for line in cashbox.cashbox_lines_ids])
@api.model
def default_get(self, fields):
vals = super(AccountBankStmtCashWizard, self).default_get(fields)
balance = self.env.context.get('balance')
statement_id = self.env.context.get('statement_id')
if 'start_bank_stmt_ids' in fields and not vals.get('start_bank_stmt_ids') and statement_id and balance == 'start':
vals['start_bank_stmt_ids'] = [(6, 0, [statement_id])]
if 'end_bank_stmt_ids' in fields and not vals.get('end_bank_stmt_ids') and statement_id and balance == 'close':
vals['end_bank_stmt_ids'] = [(6, 0, [statement_id])]
return vals
def name_get(self):
result = []
for cashbox in self:
result.append((cashbox.id, str(cashbox.total)))
return result
@api.model_create_multi
def create(self, vals):
cashboxes = super(AccountBankStmtCashWizard, self).create(vals)
cashboxes._validate_cashbox()
return cashboxes
def write(self, vals):
res = super(AccountBankStmtCashWizard, self).write(vals)
self._validate_cashbox()
return res
def _validate_cashbox(self):
for cashbox in self:
if cashbox.start_bank_stmt_ids:
cashbox.start_bank_stmt_ids.write({'balance_start': cashbox.total})
if cashbox.end_bank_stmt_ids:
cashbox.end_bank_stmt_ids.write({'balance_end_real': cashbox.total})
class AccountBankStmtCloseCheck(models.TransientModel):
"""
Account Bank Statement wizard that check that closing balance is correct.
"""
_name = 'account.bank.statement.closebalance'
_description = 'Bank Statement Closing Balance'
def validate(self):
bnk_stmt_id = self.env.context.get('active_id', False)
if bnk_stmt_id:
self.env['account.bank.statement'].browse(bnk_stmt_id).button_validate()
return {'type': 'ir.actions.act_window_close'}
class BankStatement(models.Model):
_inherit = 'account.bank.statement'
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")
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.
"""
for statement in self.filtered(lambda stmt: stmt.journal_type == 'cash'):
if not statement.currency_id.is_zero(statement.difference):
st_line_vals = {
'statement_id': statement.id,
'journal_id': statement.journal_id.id,
'amount': statement.difference,
'date': statement.date,
}
if statement.currency_id.compare_amounts(statement.difference, 0.0) < 0.0:
if not statement.journal_id.loss_account_id:
raise UserError(_(
"Please go on the %s journal and define a Loss Account. "
"This account will be used to record cash difference.",
statement.journal_id.name
))
st_line_vals['payment_ref'] = _("Cash difference observed during the counting (Loss)")
st_line_vals['counterpart_account_id'] = statement.journal_id.loss_account_id.id
else:
# statement.difference > 0.0
if not statement.journal_id.profit_account_id:
raise UserError(_(
"Please go on the %s journal and define a Profit Account. "
"This account will be used to record cash difference.",
statement.journal_id.name
))
st_line_vals['payment_ref'] = _("Cash difference observed during the counting (Profit)")
st_line_vals['counterpart_account_id'] = statement.journal_id.profit_account_id.id
self.env['account.bank.statement.line'].create(st_line_vals)
return True
def open_cashbox_id(self):
self.ensure_one()
context = dict(self.env.context or {})
if context.get('balance'):
context['statement_id'] = self.id
if context['balance'] == 'start':
cashbox_id = self.cashbox_start_id.id
elif context['balance'] == 'close':
cashbox_id = self.cashbox_end_id.id
else:
cashbox_id = False
action = {
'name': _('Cash Control'),
'view_mode': 'form',
'res_model': 'gn_cash.account.bank.statement.cashbox',
'view_id': self.env.ref('gn_cash.view_account_bnk_stmt_cashbox_footer').id,
'type': 'ir.actions.act_window',
'res_id': cashbox_id,
'context': context,
'target': 'new'
}
return action

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_account_cashbox,account.bank.statement.cashbox,model_gn_cash_account_bank_statement_cashbox,account.group_account_user,1,1,1,1
access_account_cashbox_line,account.bank.statement.cashbox.line,model_gn_cash_account_cashbox_line,account.group_account_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_account_cashbox account.bank.statement.cashbox model_gn_cash_account_bank_statement_cashbox account.group_account_user 1 1 1 1
3 access_account_cashbox_line account.bank.statement.cashbox.line model_gn_cash_account_cashbox_line account.group_account_user 1 1 1 1

View File

@ -0,0 +1,124 @@
<?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">
<field name="name">Cash Logs</field>
<field name="res_model">account.bank.statement</field>
<field name="view_mode">tree,form,pivot,graph</field>
<field name="domain">['|', ('journal_id', '=', False), ('journal_id.type', '=', 'cash')]</field>
<field name="context">{'journal_type':'cash'}</field>
<field name="search_view_id" ref="account.view_bank_statement_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new cash log
</p><p>
A Cash Register allows you to manage cash entries in your cash
journals. This feature provides an easy way to follow up cash
payments on a daily basis.
</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>
</data>
</odoo>

View File

@ -0,0 +1,43 @@
<?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>

View File

@ -0,0 +1,18 @@
<?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>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="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">
<form>
<sheet>
<field name="start_bank_stmt_ids" invisible="1"/>
<field name="end_bank_stmt_ids" invisible="1"/>
<field name="currency_id" invisible="1"/>
<field name="cashbox_lines_ids" nolabel="1" context="{'default_currency_id': currency_id}">
<tree editable="bottom">
<field name="currency_id" invisible="1"/>
<field name="number"/>
<field name="coin_value" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="subtotal" widget="monetary" options="{'currency_field': 'currency_id'}"/>
</tree>
</field>
<div>
<group>
<group class="oe_subtotal_footer oe_right" cols="6">
<field name="currency_id" invisible="1" />
<div class="o_td_label"></div>
<field name="total" widget="monetary" options="{'currency_field': 'currency_id'}"/>
</group>
</group>
</div>
</sheet>
</form>
</field>
</record>
<record id="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="arch" type="xml">
<xpath expr="//sheet" position="after">
<footer>
<button string="Confirm" class="btn-primary" special="save" data-hotkey="v"/>
<button string="Cancel" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</xpath>
</field>
</record>
<record id="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="arch" type="xml">
<form>
<div>
<p>The closing balance is different than the computed one!</p>
<p>Confirming this will create automatically a journal entry with the difference in the profit/loss account set on the cash journal.</p>
<footer>
<button string="Confirm" name="validate" type="object" class="btn-primary" data-hotkey="q"/>
<button string="Cancel" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</div>
</form>
</field>
</record>
<record id="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="view_mode">tree,form</field>
<field name="view_id" ref="view_account_bnk_stmt_check"/>
<field name="target">new</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<delete model="ir.ui.view" id="gn_cash.account_journal_dashboard_kanban_view"/>
<delete model="ir.ui.view" id="gn_cash.view_account_journal_form"/>
</data>
</odoo>