Browse Source

add pos_statement_closing_balance

pull/449/head
Jordi Ballester Alomar 5 years ago
committed by Adrià Gil Sorribes
parent
commit
88519236f3
  1. 2
      pos_statement_closing_balance/__init__.py
  2. 22
      pos_statement_closing_balance/__manifest__.py
  3. 2
      pos_statement_closing_balance/models/__init__.py
  4. 10
      pos_statement_closing_balance/models/account_journal.py
  5. 48
      pos_statement_closing_balance/models/pos_session.py
  6. 3
      pos_statement_closing_balance/readme/CONFIGURATION.rst
  7. 3
      pos_statement_closing_balance/readme/CONTRIBUTORS.rst
  8. 8
      pos_statement_closing_balance/readme/DESCRIPTION.rst
  9. 7
      pos_statement_closing_balance/readme/USAGE.rst
  10. 1
      pos_statement_closing_balance/tests/__init__.py
  11. 65
      pos_statement_closing_balance/tests/test_pos_statement_closing_balance.py
  12. 13
      pos_statement_closing_balance/views/account_journal_views.xml
  13. 19
      pos_statement_closing_balance/views/pos_session_views.xml
  14. 1
      pos_statement_closing_balance/wizards/__init__.py
  15. 121
      pos_statement_closing_balance/wizards/pos_update_statement_closing_balance.py
  16. 33
      pos_statement_closing_balance/wizards/pos_update_statement_closing_balance.xml

2
pos_statement_closing_balance/__init__.py

@ -0,0 +1,2 @@
from . import wizards
from . import models

22
pos_statement_closing_balance/__manifest__.py

@ -0,0 +1,22 @@
# Copyright 2020 ForgeFlow, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
'name': 'POS Statement Closing Balance',
'version': '12.0.1.0.1',
'category': 'Point Of Sale',
'summary': 'Allows to set a closing balance in your statements and '
'auto-post the difference between theoretical and actual.',
'author': 'ForgeFlow, Odoo Community Association (OCA)',
'website': 'http://www.github.com/OCA/pos',
'license': 'AGPL-3',
'depends': [
'pos_cash_box_journal',
],
'data': [
'wizards/pos_update_statement_closing_balance.xml',
'views/pos_session_views.xml',
'views/account_journal_views.xml',
],
'installable': True,
}

2
pos_statement_closing_balance/models/__init__.py

@ -0,0 +1,2 @@
from . import pos_session
from . import account_journal

10
pos_statement_closing_balance/models/account_journal.py

@ -0,0 +1,10 @@
# Copyright 2020 ForgeFlow, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class AccountJournal(models.Model):
_inherit = 'account.journal'
pos_control_ending_balance = fields.Boolean(
'Control ending balance in POS')

48
pos_statement_closing_balance/models/pos_session.py

@ -0,0 +1,48 @@
# Copyright 2020 ForgeFlow, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class PosSession(models.Model):
_inherit = "pos.session"
ending_balances_to_update = fields.Boolean(
compute='_compute_ending_balances_to_update')
@api.multi
def _compute_ending_balances_to_update(self):
for rec in self:
rec.ending_balances_to_update = False
for statement in rec.statement_ids:
journal = statement.journal_id
if journal.pos_control_ending_balance and \
journal.type != 'cash' or (journal.type == 'cash' and
not rec.cash_control):
rec.ending_balances_to_update = True
@api.multi
def button_update_statement_ending_balance(self):
self.ensure_one()
action = self.env.ref(
"pos_statement_closing_balance."
"action_pos_update_bank_statement_closing_balance")
result = action.read()[0]
return result
@api.multi
def _check_pos_session_bank_balance(self):
for session in self:
for statement in session.statement_ids:
if statement.journal_id.pos_control_ending_balance and \
(statement != session.cash_register_id) and (
statement.balance_end != statement.balance_end_real):
raise ValidationError(_(
'Mismatch in the closing balance '
'for a non-cash statement.'))
return True
@api.multi
def action_pos_session_closing_control(self):
self._check_pos_session_bank_balance()
return super(PosSession, self).action_pos_session_closing_control()

3
pos_statement_closing_balance/readme/CONFIGURATION.rst

@ -0,0 +1,3 @@
* Go to *Invoicing > Configuration > Journals* and set, for each Journal
that will be used in the POS, the flag 'Control ending balance in POS' if
you expect users to enter the ending balance.

3
pos_statement_closing_balance/readme/CONTRIBUTORS.rst

@ -0,0 +1,3 @@
* ForgeFlow
* Jordi Ballester Alomar <jordi.ballester@forgeflow.com>

8
pos_statement_closing_balance/readme/DESCRIPTION.rst

@ -0,0 +1,8 @@
This module extends the functionality of point of sale to allow users to input
the ending balances of the payment methods when they close a POS Session.
The system will then post the difference to the 'Liquidity Transfers' account.
Currently it's only possible to define the ending balance for the cash
if you configure "Cash Control" in the POS Configuration. But that setting
will not allow users to enter the ending balances for credit card transactions
, for example.

7
pos_statement_closing_balance/readme/USAGE.rst

@ -0,0 +1,7 @@
* Go to *Point of Sale*, then to a session and go to *Settings*.
* Define the payment methods that you want to use.
* Start the Session and create some POS orders.
* Go back to the POS Session and press "Close".
* Press the button "Update Ending Balances" in the POS Session, and enter
the final balance in the column "Balance End Real".

1
pos_statement_closing_balance/tests/__init__.py

@ -0,0 +1 @@
from . import test_pos_statement_closing_balance

65
pos_statement_closing_balance/tests/test_pos_statement_closing_balance.py

@ -0,0 +1,65 @@
# Copyright 2020 ForgeFlow, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
class TestPosStatementClosingBalance(TransactionCase):
def setUp(self):
super(TestPosStatementClosingBalance, self).setUp()
self.pos_config = self.env["pos.config"].create({"name": "PoS config"})
bank_journal = self.env["account.journal"].create({
"name": "Test bank",
"code": "TB1",
"type": "bank",
"pos_control_ending_balance": True,
})
self.pos_config.journal_ids += bank_journal
self.pos_config.open_session_cb()
self.session = self.pos_config.current_session_id
self.session.action_pos_session_open()
def test_wizard(self):
journal = self.session.journal_ids.filtered(lambda j: j.code == 'TB1')
wizard = (
self.env["cash.box.journal.in"]
.with_context(
active_model="pos.session", active_ids=self.session.ids
)
.create({"amount": 10, "name": "Out"})
)
wizard.journal_id = journal
wizard.run()
self.assertEqual(
self.session.statement_ids.filtered(
lambda r: r.journal_id.id == journal.id
).difference,
-10.0,
)
with self.assertRaises(ValidationError):
self.session.action_pos_session_closing_control()
wizard = (
self.env["pos.update.bank.statement.closing.balance"]
.with_context(
active_model="pos.session", active_ids=self.session.ids
)
.create({})
)
for item in wizard.item_ids:
item.balance_end_real = 2.0
wizard.action_confirm()
self.assertEqual(
self.session.statement_ids.filtered(
lambda r: r.journal_id.id == journal.id
).balance_end,
2.0,
)
self.assertEqual(
self.session.statement_ids.filtered(
lambda r: r.journal_id.id == journal.id
).difference,
0,
)
self.session.action_pos_session_closing_control()
self.assertEqual(self.session.state, 'closed')

13
pos_statement_closing_balance/views/account_journal_views.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_journal_form" model="ir.ui.view">
<field name="name">account.journal.form</field>
<field name="model">account.journal</field>
<field name="inherit_id" ref="account.view_account_journal_form"/>
<field name="arch" type="xml">
<field name="type" position="after">
<field name="pos_control_ending_balance"/>
</field>
</field>
</record>
</odoo>

19
pos_statement_closing_balance/views/pos_session_views.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_pos_session_form" model="ir.ui.view">
<field name="name">pos.session.form.view</field>
<field name="model">pos.session</field>
<field name="inherit_id" ref="point_of_sale.view_pos_session_form"/>
<field name="arch" type="xml">
<button name="open_cashbox" position="after">
<button name="button_update_statement_ending_balance"
class="oe_stat_button"
attrs="{'invisible':[('state', '=', 'closed')]}"
icon="fa-money"
type="object" context="{'balance': 'end'}">
<span class="o_stat_text">Update Ending Balances</span>
</button>
</button>
</field>
</record>
</odoo>

1
pos_statement_closing_balance/wizards/__init__.py

@ -0,0 +1 @@
from . import pos_update_statement_closing_balance

121
pos_statement_closing_balance/wizards/pos_update_statement_closing_balance.py

@ -0,0 +1,121 @@
# Copyright 2020 ForgeFlow, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class POSBankStatementUpdateClosingBalance(models.TransientModel):
_name = "pos.update.bank.statement.closing.balance"
_description = 'POS Update Bank Statement Closing Balance'
session_id = fields.Many2one(
comodel_name='pos.session',
)
item_ids = fields.One2many(
comodel_name="pos.update.bank.statement.closing.balance.line",
inverse_name="wiz_id",
string="Items",
)
@api.model
def _prepare_item(self, session, statement):
return {
"statement_id": statement.id,
"name": statement.name,
"journal_id": statement.journal_id.id,
"balance_start": statement.balance_start,
"total_entry_encoding": statement.total_entry_encoding,
"currency_id": statement.currency_id.id,
}
@api.model
def default_get(self, flds):
res = super().default_get(flds)
session_obj = self.env["pos.session"]
active_ids = self.env.context["active_ids"] or []
active_model = self.env.context["active_model"]
if not active_ids:
return res
assert active_model == "pos.session", \
"Bad context propagation"
items = []
if len(active_ids) > 1:
raise UserError(_('You cannot start the closing '
'balance for multiple POS sessions'))
session = session_obj.browse(active_ids[0])
for statement in session.statement_ids:
if statement.journal_id.type != 'cash' or \
(statement.journal_id.type == 'cash' and
not session.cash_control):
items.append([0, 0, self._prepare_item(session, statement)])
res["session_id"] = session.id
res["item_ids"] = items
return res
@api.model
def _prepare_cash_box_journal(self, item):
return {
'amount': abs(item.difference),
'name': _('Out'),
"journal_id": item.journal_id.id,
}
@api.multi
def action_confirm(self):
self.ensure_one()
for item in self.item_ids:
if item.difference:
if item.difference > 0.0:
model = "cash.box.journal.in"
else:
model = "cash.box.journal.out"
wizard = (
self.env[model]
.with_context(
active_model="pos.session",
active_ids=self.session_id.ids
).create(self._prepare_cash_box_journal(item))
)
wizard.run()
item.statement_id.balance_end_real = item.balance_end_real
return True
class BankStatementLineUpdateEndingBalanceLine(models.TransientModel):
_name = "pos.update.bank.statement.closing.balance.line"
_description = 'POS Update Bank Statement Closing Balance Line'
wiz_id = fields.Many2one(
comodel_name='pos.update.bank.statement.closing.balance',
required=True,
)
statement_id = fields.Many2one(
comodel_name='account.bank.statement',
)
name = fields.Char(
related='statement_id.name'
)
journal_id = fields.Many2one(
comodel_name='account.journal',
related='statement_id.journal_id',
)
balance_start = fields.Monetary(
related='statement_id.balance_start',
)
total_entry_encoding = fields.Monetary(
related='statement_id.total_entry_encoding',
)
balance_end = fields.Monetary(compute='_compute_balance_end')
balance_end_real = fields.Monetary(default=0.0)
difference = fields.Monetary(compute='_compute_balance_end')
currency_id = fields.Many2one(
comodel_name='res.currency',
related='statement_id.currency_id'
)
def _compute_balance_end(self):
for rec in self:
rec.balance_end = rec.balance_start + rec.total_entry_encoding
rec.difference = rec.balance_end_real - rec.balance_end

33
pos_statement_closing_balance/wizards/pos_update_statement_closing_balance.xml

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="pos_update_bank_statement_closing_balance_form" model="ir.ui.view">
<field name="name">pos.update.bank.statement.closing.balance.form</field>
<field name="model">pos.update.bank.statement.closing.balance</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Update Ending Balance">
<field name="item_ids" nolabel="1">
<tree string="Statements" create="0" editable="top">
<field name="name"/>
<field name="journal_id"/>
<field name="balance_start"/>
<field name="total_entry_encoding"/>
<field name="balance_end_real"/>
<field name="currency_id" groups="base.group_multi_currency"/>
</tree>
</field>
<footer>
<button name="action_confirm" string="Confirm" type="object" class="btn-primary"/>
<button special="cancel" string="Cancel" class="btn-default"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="action_pos_update_bank_statement_closing_balance">
<field name="name">Update Ending Balances</field>
<field name="res_model">pos.update.bank.statement.closing.balance</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>
Loading…
Cancel
Save