-
114pos_multiple_control/README.rst
-
2pos_multiple_control/__init__.py
-
33pos_multiple_control/__manifest__.py
-
21pos_multiple_control/demo/account_account.xml
-
26pos_multiple_control/demo/account_journal.xml
-
22pos_multiple_control/demo/pos_config.xml
-
23pos_multiple_control/demo/pos_move_reason.xml
-
20pos_multiple_control/demo/res_groups.xml
-
497pos_multiple_control/i18n/fr.po
-
4pos_multiple_control/models/__init__.py
-
144pos_multiple_control/models/account_bank_statement.py
-
24pos_multiple_control/models/account_journal.py
-
49pos_multiple_control/models/pos_config.py
-
168pos_multiple_control/models/pos_session.py
-
25pos_multiple_control/readme/CONFIGURE.rst
-
3pos_multiple_control/readme/CONTRIBUTORS.rst
-
27pos_multiple_control/readme/DESCRIPTION.rst
-
BINpos_multiple_control/static/description/account_journal_config.png
-
BINpos_multiple_control/static/description/change_starting_balance.gif
-
BINpos_multiple_control/static/description/end_session_balance_automatic_solve.gif
-
BINpos_multiple_control/static/description/icon.png
-
469pos_multiple_control/static/description/index.html
-
BINpos_multiple_control/static/description/open_new_session.png
-
BINpos_multiple_control/static/description/pos_session.png
-
BINpos_multiple_control/static/description/pos_session_config.png
-
1pos_multiple_control/tests/__init__.py
-
170pos_multiple_control/tests/test_pos_multiple_control.py
-
31pos_multiple_control/views/view_account_journal.xml
-
45pos_multiple_control/views/view_pos_config.xml
-
135pos_multiple_control/views/view_pos_session.xml
-
1pos_multiple_control/wizard/__init__.py
-
153pos_multiple_control/wizard/wizard_pos_update_statement_balance.py
-
38pos_multiple_control/wizard/wizard_pos_update_statement_balance.xml
@ -0,0 +1,114 @@ |
|||
===================================== |
|||
Point Of Sale - Multiple Cash Control |
|||
===================================== |
|||
|
|||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|||
!! This file is generated by oca-gen-addon-readme !! |
|||
!! changes will be overwritten. !! |
|||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|||
|
|||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png |
|||
:target: https://odoo-community.org/page/development-status |
|||
:alt: Beta |
|||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
.. |badge3| image:: https://img.shields.io/badge/github-quentinDupont%2Fgrap--odoo--incubator-lightgray.png?logo=github |
|||
:target: https://github.com/quentinDupont/grap-odoo-incubator/tree/12.0_pos_multiple_control/pos_multiple_control |
|||
:alt: quentinDupont/grap-odoo-incubator |
|||
|
|||
|badge1| |badge2| |badge3| |
|||
|
|||
This module extends the functionality of the point of sale by allowing a |
|||
better control at the closing of the session. |
|||
|
|||
* Show differences for all statements chosen (see config part) |
|||
|
|||
* Allow user to control each statement. (not only the cash statement, by |
|||
default) and change his starting and ending balance |
|||
|
|||
.. figure:: https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/change_starting_balance.gif |
|||
|
|||
* Quickly solve differences (we can set an absolute limit), |
|||
thanks to pos_move_reason |
|||
|
|||
See this gif where where we set ending balance with difference, solve it and |
|||
close session : |
|||
|
|||
.. figure:: https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/end_session_balance_automatic_solve.gif |
|||
|
|||
As the verification is more complete, allow the user to reopen a new session, |
|||
if the first one is in a closed state. |
|||
|
|||
.. figure:: https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/open_new_session.png |
|||
|
|||
Extra checks are done, to prevent user errors: |
|||
|
|||
* It is not possible to click on the button 'Close Session' if there are some |
|||
draft orders. |
|||
|
|||
**Table of contents** |
|||
|
|||
.. contents:: |
|||
:local: |
|||
|
|||
Configuration |
|||
============= |
|||
|
|||
To configure this module, you need to: |
|||
|
|||
**Configure the journals** you want to control in your point of sale (POS) |
|||
|
|||
* Go to Invoicing / Configuration / Journals / Journals |
|||
|
|||
* Check the box 'POS Journal Control' if you want to enable this feature for this journal |
|||
|
|||
* Unchecked journal will be in grey |
|||
|
|||
.. figure:: https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/account_journal_config.png |
|||
|
|||
**Configure your POS configuration** |
|||
|
|||
* Go to Point of Sale / Configuration / Point of Sale / <your pos> |
|||
|
|||
* Choose your Payments methods (1) |
|||
|
|||
* Check Cash Control (2) |
|||
|
|||
* (optional) Choose a "pos move reason" to ausolve difference (3) (see pos_move_reason module for more details) |
|||
|
|||
* (optional) Choose a limit to allow or not the user to autosolve control difference in pos - Set 0 if you don't want any limit. (4) |
|||
|
|||
.. figure:: https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/pos_session_config.png |
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues <https://github.com/quentinDupont/grap-odoo-incubator/issues>`_. |
|||
In case of trouble, please check there if your issue has already been reported. |
|||
If you spotted it first, help us smashing it by providing a detailed and welcomed |
|||
`feedback <https://github.com/quentinDupont/grap-odoo-incubator/issues/new?body=module:%20pos_multiple_control%0Aversion:%2012.0_pos_multiple_control%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
|||
|
|||
Do not contact contributors directly about support or help with technical issues. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Authors |
|||
~~~~~~~ |
|||
|
|||
* GRAP |
|||
|
|||
Contributors |
|||
~~~~~~~~~~~~ |
|||
|
|||
* Sylvain LE GAL <https://twitter.com/legalsylvain> |
|||
* Julien WESTE |
|||
* Quentin DUPONT <https://twitter.com/pondupont> |
|||
|
|||
Maintainers |
|||
~~~~~~~~~~~ |
|||
|
|||
This module is part of the `quentinDupont/grap-odoo-incubator <https://github.com/quentinDupont/grap-odoo-incubator/tree/12.0_pos_multiple_control/pos_multiple_control>`_ project on GitHub. |
|||
|
|||
You are welcome to contribute. |
@ -0,0 +1,2 @@ |
|||
from . import wizard |
|||
from . import models |
@ -0,0 +1,33 @@ |
|||
# Copyright (C) 2013 - Today: GRAP (http://www.grap.coop) |
|||
# @author Julien WESTE |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# @author: Quentin DUPONT (https://twitter.com/pondupont) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
{ |
|||
"name": "Point Of Sale - Multiple Cash Control", |
|||
"summary": "Allow user to control each statement and add extra checks", |
|||
"version": "12.0.1.0.0", |
|||
"category": "Point of Sale", |
|||
"author": "GRAP, Odoo Community Association (OCA)", |
|||
"website": "http://www.grap.coop", |
|||
"license": "AGPL-3", |
|||
"depends": [ |
|||
"point_of_sale", |
|||
"pos_cash_move_reason" |
|||
], |
|||
"data": [ |
|||
"views/view_account_journal.xml", |
|||
"views/view_pos_config.xml", |
|||
"views/view_pos_session.xml", |
|||
"wizard/wizard_pos_update_statement_balance.xml" |
|||
], |
|||
'demo': [ |
|||
'demo/res_groups.xml', |
|||
'demo/account_account.xml', |
|||
'demo/account_journal.xml', |
|||
'demo/pos_move_reason.xml', |
|||
'demo/pos_config.xml', |
|||
], |
|||
"installable": True, |
|||
} |
@ -0,0 +1,21 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) |
|||
@author: Quentin DUPONT (https://twitter.com/pondupont) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
<odoo> |
|||
|
|||
<record id="register_error_income" model="account.account"> |
|||
<field name="code">7582</field> |
|||
<field name="name">Cash Register Error Income</field> |
|||
<field name="user_type_id" ref="account.data_account_type_revenue"/> |
|||
</record> |
|||
|
|||
<record id="register_error_expense" model="account.account"> |
|||
<field name="code">6582</field> |
|||
<field name="name">Cash Register Error Expense</field> |
|||
<field name="user_type_id" ref="account.data_account_type_expenses"/> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="check_journal" model="account.journal"> |
|||
<field name="code">CHK-C</field> |
|||
<field name="type">bank</field> |
|||
<field name="name">Check Journal (With Control)</field> |
|||
<field name="journal_user" eval="True" /> |
|||
<field name="pos_control" eval="True" /> |
|||
</record> |
|||
|
|||
<record id="cash_journal" model="account.journal"> |
|||
<field name="code">CSH-C</field> |
|||
<field name="type">cash</field> |
|||
<field name="name">Cash Journal (With Control)</field> |
|||
<field name="journal_user" eval="True" /> |
|||
<field name="pos_control" eval="True" /> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,22 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
@author Quentin DUPONT (https://twitter.com/pondupont) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="pos_config_control" model="pos.config"> |
|||
<field name="name">Point Of Sale (With Mutiple Controls)</field> |
|||
<field name="picking_type_id" ref="point_of_sale.picking_type_posout" /> |
|||
<field name="journal_ids" eval="[ |
|||
(4, ref('check_journal')), |
|||
(4, ref('cash_journal'))]" /> |
|||
<field name="cash_control" eval="True" /> |
|||
<field name="autosolve_pos_move_reason" eval="cash_register_error" /> |
|||
|
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,23 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
@author Quentin DUPONT (https://twitter.com/pondupont) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record model="pos.move.reason" id="cash_register_error"> |
|||
<field name="name">Cash register error</field> |
|||
<field name="is_income_reason" eval="True" /> |
|||
<field name="is_expense_reason" eval="True"/> |
|||
<field name="income_account_id" ref="register_error_income"/> |
|||
<field name="expense_account_id" ref="register_error_expense"/> |
|||
<field name="journal_ids" model="account.journal" search="[ |
|||
('type', '=', 'cash'), |
|||
('company_id', '=', obj().env.ref('base.main_company').id), |
|||
]"/> |
|||
<field name="company_id" ref="base.main_company"/> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="account.group_account_manager" model="res.groups"> |
|||
<field name="users" eval="[ |
|||
(4, ref('base.user_root'))]" /> |
|||
</record> |
|||
|
|||
<record id="point_of_sale.group_pos_user" model="res.groups"> |
|||
<field name="users" eval="[ |
|||
(4, ref('base.user_demo'))]" /> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,497 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * pos_multiple_control |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 12.0\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2020-04-09 15:56+0000\n" |
|||
"PO-Revision-Date: 2020-04-09 15:56+0000\n" |
|||
"Last-Translator: <>\n" |
|||
"Language-Team: \n" |
|||
"MIME-Version: 1.0\n" |
|||
"Content-Type: text/plain; charset=UTF-8\n" |
|||
"Content-Transfer-Encoding: \n" |
|||
"Plural-Forms: \n" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "$ 3.12" |
|||
msgstr "3,12 $" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "$ 4.40" |
|||
msgstr "4,40 $" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "$ 4.50" |
|||
msgstr "4,50 $" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "$ 8.50" |
|||
msgstr "8,50 $" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "+ Transactions" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "<span class=\"o_stat_text\">Set Opening Balance</span>" |
|||
msgstr "<span class=\"o_stat_text\">Réglez le solde d'ouverture</span>" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "<span class=\"pos-change_amount\">$ 0.86</span>" |
|||
msgstr "<span class=\"pos-change_amount\"/>" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "<span class=\"pos-change_title\">Change</span>" |
|||
msgstr "<span class=\"pos-change_title\"/>" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "<span class=\"total-amount-formatting\">TOTAL</span>" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "<span id=\"total-amount\" class=\"pos_total-amount\">$ 469.14</span>" |
|||
msgstr "<span class=\"pos_total-amount\" id=\"total-amount\"/>" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "<span>$ 470.00</span>" |
|||
msgstr "<span/>" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "<span>Cash (USD):</span>" |
|||
msgstr "<span/>" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_wizard_pos_update_bank_statement_balance_form |
|||
msgid "Apply" |
|||
msgstr "Appliquer" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_config__autosolve_limit |
|||
msgid "Autosolve limit" |
|||
msgstr "Limite de résolution automatique" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_config__autosolve_pos_move_reason |
|||
msgid "Autosolve pos move reason" |
|||
msgstr "Raison de résolution automatique" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__balance_end_real |
|||
msgid "Balance End Real" |
|||
msgstr "Solde réel de fermeture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__balance_start_real |
|||
msgid "Balance Start Real" |
|||
msgstr "Solde réel d'ouverture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__balance_moment |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__balance_moment |
|||
msgid "Balance moment" |
|||
msgstr "Moment de balance" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_account_bank_statement |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__statement_ids |
|||
msgid "Bank Statement" |
|||
msgstr "Relevé bancaire" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_wizard_pos_update_bank_statement_balance_form |
|||
msgid "Cancel" |
|||
msgstr "Annuler" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_cash_box_in |
|||
msgid "Cash Box In" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_cash_box_out |
|||
msgid "Cash Box Out" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__balance_end |
|||
msgid "Computed Balance" |
|||
msgstr "Solde calculé" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_account_bank_statement__control_difference |
|||
msgid "Control Difference" |
|||
msgstr "Différence" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__control_statement_ids |
|||
msgid "Control statements" |
|||
msgstr "Déclarations de contrôle" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_account_bank_statement__control_balance |
|||
msgid "Controled Balance" |
|||
msgstr "Solde contrôlé" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__create_uid |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__create_uid |
|||
msgid "Created by" |
|||
msgstr "Créé par" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__create_date |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__create_date |
|||
msgid "Created on" |
|||
msgstr "Créé le" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__currency_id |
|||
msgid "Currency" |
|||
msgstr "Devise" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__session_id |
|||
msgid "Current Session" |
|||
msgstr "Session en cours" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: selection:wizard.pos.update.bank.statement.balance,balance_moment:0 |
|||
msgid "Default" |
|||
msgstr "Par défaut" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:product.template,name:pos_multiple_control.demo_product_cash_box |
|||
msgid "Demo Product Cash box product" |
|||
msgstr "Produit de démonstration Produit de caisse" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:product.template,name:pos_multiple_control.demo_product_not_cash_box |
|||
msgid "Demo Product Not Cash box product" |
|||
msgstr "Produit de démonstration Pas un produit de caisse" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Desk Organizer" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__display_name |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__display_name |
|||
msgid "Display Name" |
|||
msgstr "Nom affiché" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_account_bank_statement__display_autosolve |
|||
msgid "Display autosolve" |
|||
msgstr "Afficher résolution automatique" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Do you really want to solve this difference automatically ?" |
|||
msgstr "Voulez-vous vraiment solder cette différence automatiquement ?" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: selection:wizard.pos.update.bank.statement.balance,balance_moment:0 |
|||
msgid "Ending balance" |
|||
msgstr "Solde de fermeture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_wizard_pos_update_bank_statement_balance_form |
|||
msgid "Here you can change the" |
|||
msgstr "Ici vous pouvez changer le" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__id |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__id |
|||
msgid "ID" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,help:pos_multiple_control.field_account_journal__pos_control |
|||
msgid "If you want this journal to be controled at closing of point of sale, check this option" |
|||
msgstr "Si vous souhaitez que ce journal soit contrôlé à la fermeture du point de vente, cochez cette option" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__item_ids |
|||
msgid "Items" |
|||
msgstr "Articles" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_account_journal |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__journal_id |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__journal_id |
|||
msgid "Journal" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance____last_update |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line____last_update |
|||
msgid "Last Modified on" |
|||
msgstr "Dernière modification le" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__write_uid |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__write_uid |
|||
msgid "Last Updated by" |
|||
msgstr "Dernière mise à jour par" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance__write_date |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__write_date |
|||
msgid "Last Updated on" |
|||
msgstr "Dernière mise à jour le" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Led Lamp" |
|||
msgstr "Lampe Led" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_config_form |
|||
msgid "Limit to display autosolve button" |
|||
msgstr "Limite d'affichage du bouton de résolution automatique" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Monitor Stand" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_config_kanban |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "New Session" |
|||
msgstr "Nouvelle session" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Odoo Logo" |
|||
msgstr "Logo Odoo" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__control_register_balance_start |
|||
msgid "Opening Balances" |
|||
msgstr "Solde d'ouverture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: code:addons/pos_multiple_control/wizard/wizard_pos_update_statement_balance.py:85 |
|||
#, python-format |
|||
msgid "Out" |
|||
msgstr "Sortie" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_account_journal__pos_control |
|||
msgid "POS Journal Control" |
|||
msgstr "Journal de contrôle du point de vente" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_wizard_pos_update_bank_statement_balance |
|||
msgid "POS Update Bank Statement Balance" |
|||
msgstr "Mise à jour du solde de relevé de banque" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_wizard_pos_update_bank_statement_balance_line |
|||
msgid "POS Update Bank Statement Balance Line" |
|||
msgstr "Mise à jour des lignes de solde de relevé de banque" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_pos_config |
|||
msgid "Point of Sale Configuration" |
|||
msgstr "Paramétrage du point de vente" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model,name:pos_multiple_control.model_pos_session |
|||
msgid "Point of Sale Session" |
|||
msgstr "Session du point de vente" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_account_bank_statement__is_pos_control |
|||
msgid "Pos control Bank statement" |
|||
msgstr "Contrôle des point de vente Relevé bancaire" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_account_bank_statement__pos_session_state |
|||
msgid "Pos session state" |
|||
msgstr "État de la session de vente" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Price" |
|||
msgstr "Prix" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Quantity" |
|||
msgstr "Quantité" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Real Closing Balance" |
|||
msgstr "Solde de clôture réel" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__control_register_balance |
|||
msgid "Real Closing Balances" |
|||
msgstr "Réel solde de clôture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_cash_box_out__ref |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__name |
|||
msgid "Reference" |
|||
msgstr "Référence" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Set your ending balance" |
|||
msgstr "Définissez votre solde de clôture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Set your starting balance" |
|||
msgstr "Définissez votre solde d'ouverture" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Solve difference automatically with a product choosen in pos config" |
|||
msgstr "Résoudre la différence automatiquement avec un produit choisi dans la configuration du point de vente" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__balance_start |
|||
msgid "Starting Balance" |
|||
msgstr "Solde initial" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: selection:wizard.pos.update.bank.statement.balance,balance_moment:0 |
|||
msgid "Starting balance" |
|||
msgstr "Solde initial" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__statement_id |
|||
msgid "Statement" |
|||
msgstr "Relevé" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_wizard_pos_update_bank_statement_balance_form |
|||
msgid "Statements" |
|||
msgstr "Relevés" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__summary_statement_ids |
|||
msgid "Summary statements" |
|||
msgstr "Résumé de relevés" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__control_register_balance_end |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Theoretical Closing Balances" |
|||
msgstr "Solde de fermeture théorique" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Total" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__control_register_difference |
|||
msgid "Total difference" |
|||
msgstr "Différence total" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,help:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__total_entry_encoding |
|||
msgid "Total of transaction lines." |
|||
msgstr "Total des lignes de transaction. " |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_pos_session__control_register_total_entry_encoding |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_pos_session_form |
|||
msgid "Transactions" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__total_entry_encoding |
|||
msgid "Transactions Subtotal" |
|||
msgstr "Sous-total des transactions" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:product.template,uom_name:pos_multiple_control.demo_product_cash_box |
|||
#: model:product.template,uom_name:pos_multiple_control.demo_product_not_cash_box |
|||
msgid "Unit(s)" |
|||
msgstr "Unité(s)" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:ir.ui.view,arch_db:pos_multiple_control.view_wizard_pos_update_bank_statement_balance_form |
|||
msgid "Update Balance" |
|||
msgstr "Mettre à jour le solde" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.actions.act_window,name:pos_multiple_control.action_wizard_pos_update_bank_statement_balance |
|||
msgid "Update Balances" |
|||
msgstr "Mettre à jour les soldes" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: code:addons/pos_multiple_control/models/account_bank_statement.py:123 |
|||
#, python-format |
|||
msgid "We can't autosolve this difference. \n" |
|||
"You need to configure the Point Of Sale config and choose a pos move reason for autosolving this difference." |
|||
msgstr "On ne peut pas résoudre automatiquement cette différence. \n" |
|||
"Vous devez paramétrer la configuration de caisse et choisir un article spécial pour résoudre automatiquement cette différence." |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model_terms:pos.config,customer_facing_display_html:pos_multiple_control.pos_config_control |
|||
msgid "Whiteboard Pen" |
|||
msgstr "Marqueur pour Tableau Blanc" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:ir.model.fields,field_description:pos_multiple_control.field_wizard_pos_update_bank_statement_balance_line__wiz_id |
|||
msgid "Wiz" |
|||
msgstr "" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: code:addons/pos_multiple_control/models/pos_session.py:125 |
|||
#, python-format |
|||
msgid "You can not close this session because the journal %s (from %s) has a not null difference: %s%s \n" |
|||
" You have to change his starting or ending balance" |
|||
msgstr "Vous ne pouvez pas fermer cette session car le relevé %s (de %s) a une différence non nulle : %s%s \n" |
|||
"Vous devez modifier son solde de départ ou de fin." |
|||
|
|||
#. module: pos_multiple_control |
|||
#: code:addons/pos_multiple_control/models/pos_session.py:110 |
|||
#, python-format |
|||
msgid "You can not end this session because there are some draft orders: \n" |
|||
"\n" |
|||
"- %s" |
|||
msgstr "Vous ne pouvez pas fermer cette session car le relevé %s a une différence non nulle : \n" |
|||
"\n" |
|||
"- %s" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: code:addons/pos_multiple_control/models/pos_box.py:55 |
|||
#, python-format |
|||
msgid "You cannot put/take money in/out for the statement %s which is closed" |
|||
msgstr "Vous ne pouvez pas prendre ou retirer de l'argent sur le relevé %s car celui ci est fermé" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: code:addons/pos_multiple_control/wizard/wizard_pos_update_statement_balance.py:67 |
|||
#, python-format |
|||
msgid "You cannot start the closing balance for multiple POS sessions" |
|||
msgstr "Vous ne pouvez changer en même temps le solde de plusieurs sessions de vente" |
|||
|
|||
#. module: pos_multiple_control |
|||
#: model:product.template,weight_uom_name:pos_multiple_control.demo_product_cash_box |
|||
#: model:product.template,weight_uom_name:pos_multiple_control.demo_product_not_cash_box |
|||
msgid "kg" |
|||
msgstr "" |
@ -0,0 +1,4 @@ |
|||
from . import account_bank_statement |
|||
from . import account_journal |
|||
from . import pos_session |
|||
from . import pos_config |
@ -0,0 +1,144 @@ |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# @author Quentin DUPONT (quentin.dupont@grap.coop) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import _, api, fields, models |
|||
from odoo.exceptions import Warning as UserError |
|||
import odoo.addons.decimal_precision as dp |
|||
|
|||
|
|||
class AccountBankStatement(models.Model): |
|||
_inherit = "account.bank.statement" |
|||
|
|||
# Columns Section |
|||
control_balance = fields.Float( |
|||
string="Controled Balance", |
|||
compute="_compute_control_balance", |
|||
digits_compute=dp.get_precision("Account"), |
|||
) |
|||
|
|||
control_difference = fields.Float( |
|||
string="Control Difference", |
|||
compute="_compute_control_difference", |
|||
digits_compute=dp.get_precision("Account"), |
|||
) |
|||
|
|||
is_pos_control = fields.Boolean( |
|||
string="Pos control Bank statement", |
|||
compute="_compute_is_pos_control", store=True, |
|||
) |
|||
|
|||
pos_session_state = fields.Char( |
|||
string="Pos session state", compute="_compute_pos_session_state" |
|||
) |
|||
|
|||
display_autosolve = fields.Boolean( |
|||
string="Display autosolve", compute="_compute_display_autosolve" |
|||
) |
|||
|
|||
# Compute Section |
|||
@api.multi |
|||
@api.depends("line_ids") |
|||
def _compute_control_balance(self): |
|||
for statement in self: |
|||
statement.control_balance = sum( |
|||
statement.mapped("balance_end_real") |
|||
) |
|||
|
|||
@api.multi |
|||
@api.depends("control_balance", "total_entry_encoding", "balance_end_real") |
|||
def _compute_control_difference(self): |
|||
for statement in self: |
|||
statement.control_difference = ( |
|||
+ statement.balance_end_real |
|||
- statement.balance_start |
|||
- statement.total_entry_encoding |
|||
) |
|||
|
|||
@api.multi |
|||
@api.depends("journal_id.pos_control", "pos_session_state", |
|||
"balance_start") |
|||
def _compute_is_pos_control(self): |
|||
for statement in self: |
|||
journal = statement.journal_id |
|||
statement.is_pos_control = journal.pos_control |
|||
|
|||
@api.multi |
|||
@api.depends("pos_session_id.state") |
|||
def _compute_pos_session_state(self): |
|||
for statement in self: |
|||
statement.pos_session_state = statement.pos_session_id.state |
|||
|
|||
# Display button autosolve with some conditions |
|||
@api.multi |
|||
def _compute_display_autosolve(self): |
|||
for statement in self: |
|||
if not statement.journal_id.pos_control: |
|||
statement.display_autosolve = False |
|||
else: |
|||
if statement.pos_session_id.config_id.autosolve_limit: |
|||
difference_with_limit = ( |
|||
abs(statement.control_difference) |
|||
- statement.pos_session_id.config_id.autosolve_limit |
|||
) |
|||
else: |
|||
difference_with_limit = -1 |
|||
statement.display_autosolve = ( |
|||
statement.pos_session_state not in |
|||
["closed"] |
|||
and difference_with_limit < 0 |
|||
and abs(round(statement.control_difference, 3)) != 0 |
|||
) |
|||
|
|||
@api.multi |
|||
@api.depends("pos_session_state") |
|||
def automatic_solve(self): |
|||
self.WizardReason = self.env['wizard.pos.move.reason'] |
|||
for statement in self: |
|||
pos_move_reason = statement.\ |
|||
pos_session_id.config_id.autosolve_pos_move_reason |
|||
if pos_move_reason: |
|||
cb_pos_move_reason_id = pos_move_reason.id |
|||
cb_difference = statement.control_difference |
|||
cb_journal_id = statement.journal_id.id |
|||
if cb_difference < 0: |
|||
default_move_type = "expense" |
|||
else: |
|||
default_move_type = "income" |
|||
|
|||
wizard = self.WizardReason.with_context( |
|||
active_id=statement.pos_session_id.id, |
|||
default_move_type=default_move_type).create({ |
|||
'move_reason_id': cb_pos_move_reason_id, |
|||
'journal_id': cb_journal_id, |
|||
'statement_id': statement.id, |
|||
'amount': abs(cb_difference), |
|||
'name': 'Automatic solve', |
|||
}) |
|||
wizard.apply() |
|||
|
|||
else: |
|||
raise UserError( |
|||
_( |
|||
"We can't autosolve this difference. \nYou need to " |
|||
"configure the Point Of Sale config and choose a " |
|||
"pos move reason for autosolving this difference." |
|||
) |
|||
) |
|||
|
|||
def open_cashbox_starting_balance(self): |
|||
return self.open_cashbox_balance('starting') |
|||
|
|||
def open_cashbox_ending_balance(self): |
|||
return self.open_cashbox_balance('ending') |
|||
|
|||
def open_cashbox_balance(self, balance_moment): |
|||
action = self.env.ref( |
|||
"pos_multiple_control." |
|||
"action_wizard_pos_update_bank_statement_balance").read()[0] |
|||
action['context'] = {'balance_moment': balance_moment, |
|||
'active_id': [self.id], |
|||
'active_pos_id': [self.pos_session_id.id], |
|||
'active_model': 'pos.session'} |
|||
return action |
@ -0,0 +1,24 @@ |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class AccountJournal(models.Model): |
|||
_inherit = "account.journal" |
|||
|
|||
pos_control = fields.Boolean( |
|||
string="POS Journal Control", |
|||
help="If you want this journal" |
|||
" to be controled at closing of point of sale, check this option", |
|||
default=False |
|||
) |
|||
|
|||
@api.onchange("type") |
|||
def onchange_type(self): |
|||
for journal in self: |
|||
if journal.type in ["bank", "cash"]: |
|||
journal.pos_control = True |
|||
else: |
|||
journal.pos_control = False |
@ -0,0 +1,49 @@ |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author Quentin DUPONT (quentin.dupont@grap.coop) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
|
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class PosConfig(models.Model): |
|||
_inherit = "pos.config" |
|||
|
|||
# Columns Section |
|||
autosolve_pos_move_reason = fields.Many2one( |
|||
string="Autosolve pos move reason", |
|||
description="Product used to autosolve control difference", |
|||
comodel_name="pos.move.reason", |
|||
domain="['|', \ |
|||
('is_income_reason', '=', True), ('is_expense_reason', '=', True)]", |
|||
default="", |
|||
) |
|||
|
|||
autosolve_limit = fields.Float( |
|||
string="Autosolve limit", |
|||
description="Limit for autosolving bank statement", default=20 |
|||
) |
|||
|
|||
@api.multi |
|||
def open_new_session(self, openui): |
|||
self.ensure_one() |
|||
# Check if some opening / opened session exists |
|||
session_obj = self.env['pos.session'] |
|||
sessions = session_obj.search([ |
|||
('user_id', '=', self.env.uid), |
|||
('config_id', '=', self.id), |
|||
('state', 'in', ['opened', 'opening_control']), |
|||
], limit=1) |
|||
if sessions: |
|||
# An opening / opened session exists |
|||
session = sessions[0] |
|||
else: |
|||
# Create a session |
|||
session = session_obj.create({ |
|||
'user_id': self.env.uid, |
|||
'config_id': self.id, |
|||
}) |
|||
|
|||
if session.state == 'opening_control' or openui is False: |
|||
return self._open_session(session.id) |
|||
return self.open_ui() |
@ -0,0 +1,168 @@ |
|||
# Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo import _, api, fields, models |
|||
from odoo.exceptions import ValidationError |
|||
from odoo.exceptions import Warning as UserError |
|||
|
|||
|
|||
class PosSession(models.Model): |
|||
_inherit = "pos.session" |
|||
|
|||
# Columns Section |
|||
statement_ids = fields.One2many(readonly=False) |
|||
|
|||
control_statement_ids = fields.One2many( |
|||
string="Control statements", |
|||
comodel_name="account.bank.statement", |
|||
related="statement_ids", |
|||
) |
|||
|
|||
summary_statement_ids = fields.One2many( |
|||
string="Summary statements", |
|||
comodel_name="account.bank.statement", |
|||
related="statement_ids", |
|||
) |
|||
|
|||
control_register_balance_start = fields.Float( |
|||
compute='_compute_control_register_balance_start', |
|||
string='Opening Balances') |
|||
|
|||
control_register_total_entry_encoding = fields.Float( |
|||
compute='_compute_control_register_total_entry_encoding', |
|||
string='Transactions') |
|||
|
|||
control_register_balance_end = fields.Float( |
|||
compute='_compute_control_register_balance_end', |
|||
string='Theoretical Closing Balances') |
|||
|
|||
control_register_balance = fields.Float( |
|||
compute='_compute_control_register_balance', |
|||
string='Real Closing Balances') |
|||
|
|||
control_register_difference = fields.Float( |
|||
compute='_compute_control_register_difference', |
|||
string='Total difference') |
|||
|
|||
# Compute Section |
|||
@api.multi |
|||
@api.depends('statement_ids.is_pos_control', 'statement_ids.balance_start') |
|||
def _compute_control_register_balance_start(self): |
|||
for session in self: |
|||
session.control_register_balance_start = sum( |
|||
session.statement_ids.filtered( |
|||
lambda x: x.is_pos_control).mapped('balance_start')) |
|||
|
|||
@api.multi |
|||
@api.depends( |
|||
'statement_ids.is_pos_control', 'statement_ids.total_entry_encoding') |
|||
def _compute_control_register_total_entry_encoding(self): |
|||
for session in self: |
|||
session.control_register_total_entry_encoding = sum( |
|||
session.statement_ids.filtered( |
|||
lambda x: x.is_pos_control).mapped('total_entry_encoding')) |
|||
|
|||
@api.multi |
|||
@api.depends( |
|||
'statement_ids.is_pos_control', 'statement_ids.balance_end_real') |
|||
def _compute_control_register_balance_end(self): |
|||
for session in self: |
|||
session.control_register_balance_end = sum( |
|||
session.statement_ids.filtered( |
|||
lambda x: x.is_pos_control).mapped('balance_end')) |
|||
|
|||
@api.multi |
|||
@api.depends( |
|||
'statement_ids.is_pos_control', 'statement_ids.control_balance') |
|||
def _compute_control_register_balance(self): |
|||
for session in self: |
|||
session.control_register_balance = sum( |
|||
session.statement_ids.filtered( |
|||
lambda x: x.is_pos_control).mapped('control_balance')) |
|||
|
|||
@api.multi |
|||
@api.depends( |
|||
'statement_ids.is_pos_control', 'statement_ids.control_difference') |
|||
def _compute_control_register_difference(self): |
|||
for session in self: |
|||
session.control_register_difference = sum( |
|||
session.statement_ids.filtered( |
|||
lambda x: x.is_pos_control).mapped('control_difference')) |
|||
|
|||
# Model |
|||
@api.multi |
|||
def open_cashbox_opening(self): |
|||
return super(PosSession, self).open_cashbox() |
|||
|
|||
@api.multi |
|||
def action_pos_session_new_session(self): |
|||
return self.config_id.open_new_session(False) |
|||
|
|||
@api.multi |
|||
def wkf_action_closing_control(self): |
|||
for session in self: |
|||
draft_orders = session.order_ids.filtered( |
|||
lambda x: x.state == "draft" |
|||
) |
|||
if len(draft_orders): |
|||
raise UserError( |
|||
_( |
|||
"You can not end this session because there are some" |
|||
" draft orders: \n\n- %s" |
|||
) |
|||
% ("\n- ".join([x.name for x in draft_orders])) |
|||
) |
|||
return super(PosSession, self).wkf_action_closing_control() |
|||
|
|||
@api.multi |
|||
def action_pos_session_validate(self): |
|||
for session in self: |
|||
for statement in session.statement_ids: |
|||
if statement.journal_id.pos_control is True: |
|||
if abs(statement.control_difference) > 0.001: |
|||
raise UserError( |
|||
_( |
|||
"You can not close this session because the " |
|||
"journal %s (from %s) has a not null " |
|||
"difference: %s%s \n You have to change his " |
|||
"starting or ending balance" |
|||
) |
|||
% (statement.journal_id.name, statement.name, |
|||
str(round(statement.control_difference, 3)), |
|||
statement.currency_id.symbol) |
|||
) |
|||
return super(PosSession, self).action_pos_session_validate() |
|||
|
|||
# Constraints |
|||
@api.multi |
|||
@api.constrains('user_id', 'state') |
|||
def _check_unicity(self): |
|||
for session in self: |
|||
domain = [ |
|||
("state", "in", ["opening_control", "opened"]), |
|||
("user_id", "=", session.user_id.id), |
|||
] |
|||
if self.search_count(domain) > 1: |
|||
raise ValidationError( |
|||
_( |
|||
"You cannot create two active sessions " |
|||
"with the same responsible!" |
|||
) |
|||
) |
|||
|
|||
@api.multi |
|||
@api.constrains('config_id', 'state') |
|||
def _check_pos_config(self): |
|||
for session in self: |
|||
domain = [ |
|||
("state", "in", ["opening_control", "opened"]), |
|||
("config_id", "=", session.config_id.id), |
|||
] |
|||
if self.search_count(domain) > 1: |
|||
raise ValidationError( |
|||
_( |
|||
"You cannot create two active sessions related" |
|||
" to the same point of sale!" |
|||
) |
|||
) |
@ -0,0 +1,25 @@ |
|||
To configure this module, you need to: |
|||
|
|||
**Configure the journals** you want to control in your point of sale (POS) |
|||
|
|||
* Go to Invoicing / Configuration / Journals / Journals |
|||
|
|||
* Check the box 'POS Journal Control' if you want to enable this feature for this journal |
|||
|
|||
* Unchecked journal will be in grey |
|||
|
|||
.. figure:: ../static/description/account_journal_config.png |
|||
|
|||
**Configure your POS configuration** |
|||
|
|||
* Go to Point of Sale / Configuration / Point of Sale / <your pos> |
|||
|
|||
* Choose your Payments methods (1) |
|||
|
|||
* Check Cash Control (2) |
|||
|
|||
* (optional) Choose a "pos move reason" to ausolve difference (3) (see pos_move_reason module for more details) |
|||
|
|||
* (optional) Choose a limit to allow or not the user to autosolve control difference in pos - Set 0 if you don't want any limit. (4) |
|||
|
|||
.. figure:: ../static/description/pos_session_config.png |
@ -0,0 +1,3 @@ |
|||
* Sylvain LE GAL <https://twitter.com/legalsylvain> |
|||
* Julien WESTE |
|||
* Quentin DUPONT <https://twitter.com/pondupont> |
@ -0,0 +1,27 @@ |
|||
This module extends the functionality of the point of sale by allowing a |
|||
better control at the closing of the session. |
|||
|
|||
* Show differences for all statements chosen (see config part) |
|||
|
|||
* Allow user to control each statement. (not only the cash statement, by |
|||
default) and change his starting and ending balance |
|||
|
|||
.. figure:: ../static/description/change_starting_balance.gif |
|||
|
|||
* Quickly solve differences (we can set an absolute limit), |
|||
thanks to pos_move_reason |
|||
|
|||
See this gif where where we set ending balance with difference, solve it and |
|||
close session : |
|||
|
|||
.. figure:: ../static/description/end_session_balance_automatic_solve.gif |
|||
|
|||
As the verification is more complete, allow the user to reopen a new session, |
|||
if the first one is in a closed state. |
|||
|
|||
.. figure:: ../static/description/open_new_session.png |
|||
|
|||
Extra checks are done, to prevent user errors: |
|||
|
|||
* It is not possible to click on the button 'Close Session' if there are some |
|||
draft orders. |
After Width: 425 | Height: 369 | Size: 17 KiB |
After Width: 1129 | Height: 610 | Size: 317 KiB |
After Width: 1174 | Height: 624 | Size: 1.1 MiB |
After Width: 164 | Height: 164 | Size: 12 KiB |
@ -0,0 +1,469 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
|||
<head> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
|||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" /> |
|||
<title>Point Of Sale - Multiple Cash Control</title> |
|||
<style type="text/css"> |
|||
|
|||
/* |
|||
:Author: David Goodger (goodger@python.org) |
|||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $ |
|||
:Copyright: This stylesheet has been placed in the public domain. |
|||
|
|||
Default cascading style sheet for the HTML output of Docutils. |
|||
|
|||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to |
|||
customize this style sheet. |
|||
*/ |
|||
|
|||
/* used to remove borders from tables and images */ |
|||
.borderless, table.borderless td, table.borderless th { |
|||
border: 0 } |
|||
|
|||
table.borderless td, table.borderless th { |
|||
/* Override padding for "table.docutils td" with "! important". |
|||
The right padding separates the table cells. */ |
|||
padding: 0 0.5em 0 0 ! important } |
|||
|
|||
.first { |
|||
/* Override more specific margin styles with "! important". */ |
|||
margin-top: 0 ! important } |
|||
|
|||
.last, .with-subtitle { |
|||
margin-bottom: 0 ! important } |
|||
|
|||
.hidden { |
|||
display: none } |
|||
|
|||
.subscript { |
|||
vertical-align: sub; |
|||
font-size: smaller } |
|||
|
|||
.superscript { |
|||
vertical-align: super; |
|||
font-size: smaller } |
|||
|
|||
a.toc-backref { |
|||
text-decoration: none ; |
|||
color: black } |
|||
|
|||
blockquote.epigraph { |
|||
margin: 2em 5em ; } |
|||
|
|||
dl.docutils dd { |
|||
margin-bottom: 0.5em } |
|||
|
|||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { |
|||
overflow: hidden; |
|||
} |
|||
|
|||
/* Uncomment (and remove this text!) to get bold-faced definition list terms |
|||
dl.docutils dt { |
|||
font-weight: bold } |
|||
*/ |
|||
|
|||
div.abstract { |
|||
margin: 2em 5em } |
|||
|
|||
div.abstract p.topic-title { |
|||
font-weight: bold ; |
|||
text-align: center } |
|||
|
|||
div.admonition, div.attention, div.caution, div.danger, div.error, |
|||
div.hint, div.important, div.note, div.tip, div.warning { |
|||
margin: 2em ; |
|||
border: medium outset ; |
|||
padding: 1em } |
|||
|
|||
div.admonition p.admonition-title, div.hint p.admonition-title, |
|||
div.important p.admonition-title, div.note p.admonition-title, |
|||
div.tip p.admonition-title { |
|||
font-weight: bold ; |
|||
font-family: sans-serif } |
|||
|
|||
div.attention p.admonition-title, div.caution p.admonition-title, |
|||
div.danger p.admonition-title, div.error p.admonition-title, |
|||
div.warning p.admonition-title, .code .error { |
|||
color: red ; |
|||
font-weight: bold ; |
|||
font-family: sans-serif } |
|||
|
|||
/* Uncomment (and remove this text!) to get reduced vertical space in |
|||
compound paragraphs. |
|||
div.compound .compound-first, div.compound .compound-middle { |
|||
margin-bottom: 0.5em } |
|||
|
|||
div.compound .compound-last, div.compound .compound-middle { |
|||
margin-top: 0.5em } |
|||
*/ |
|||
|
|||
div.dedication { |
|||
margin: 2em 5em ; |
|||
text-align: center ; |
|||
font-style: italic } |
|||
|
|||
div.dedication p.topic-title { |
|||
font-weight: bold ; |
|||
font-style: normal } |
|||
|
|||
div.figure { |
|||
margin-left: 2em ; |
|||
margin-right: 2em } |
|||
|
|||
div.footer, div.header { |
|||
clear: both; |
|||
font-size: smaller } |
|||
|
|||
div.line-block { |
|||
display: block ; |
|||
margin-top: 1em ; |
|||
margin-bottom: 1em } |
|||
|
|||
div.line-block div.line-block { |
|||
margin-top: 0 ; |
|||
margin-bottom: 0 ; |
|||
margin-left: 1.5em } |
|||
|
|||
div.sidebar { |
|||
margin: 0 0 0.5em 1em ; |
|||
border: medium outset ; |
|||
padding: 1em ; |
|||
background-color: #ffffee ; |
|||
width: 40% ; |
|||
float: right ; |
|||
clear: right } |
|||
|
|||
div.sidebar p.rubric { |
|||
font-family: sans-serif ; |
|||
font-size: medium } |
|||
|
|||
div.system-messages { |
|||
margin: 5em } |
|||
|
|||
div.system-messages h1 { |
|||
color: red } |
|||
|
|||
div.system-message { |
|||
border: medium outset ; |
|||
padding: 1em } |
|||
|
|||
div.system-message p.system-message-title { |
|||
color: red ; |
|||
font-weight: bold } |
|||
|
|||
div.topic { |
|||
margin: 2em } |
|||
|
|||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, |
|||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { |
|||
margin-top: 0.4em } |
|||
|
|||
h1.title { |
|||
text-align: center } |
|||
|
|||
h2.subtitle { |
|||
text-align: center } |
|||
|
|||
hr.docutils { |
|||
width: 75% } |
|||
|
|||
img.align-left, .figure.align-left, object.align-left, table.align-left { |
|||
clear: left ; |
|||
float: left ; |
|||
margin-right: 1em } |
|||
|
|||
img.align-right, .figure.align-right, object.align-right, table.align-right { |
|||
clear: right ; |
|||
float: right ; |
|||
margin-left: 1em } |
|||
|
|||
img.align-center, .figure.align-center, object.align-center { |
|||
display: block; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
} |
|||
|
|||
table.align-center { |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
} |
|||
|
|||
.align-left { |
|||
text-align: left } |
|||
|
|||
.align-center { |
|||
clear: both ; |
|||
text-align: center } |
|||
|
|||
.align-right { |
|||
text-align: right } |
|||
|
|||
/* reset inner alignment in figures */ |
|||
div.align-right { |
|||
text-align: inherit } |
|||
|
|||
/* div.align-center * { */ |
|||
/* text-align: left } */ |
|||
|
|||
.align-top { |
|||
vertical-align: top } |
|||
|
|||
.align-middle { |
|||
vertical-align: middle } |
|||
|
|||
.align-bottom { |
|||
vertical-align: bottom } |
|||
|
|||
ol.simple, ul.simple { |
|||
margin-bottom: 1em } |
|||
|
|||
ol.arabic { |
|||
list-style: decimal } |
|||
|
|||
ol.loweralpha { |
|||
list-style: lower-alpha } |
|||
|
|||
ol.upperalpha { |
|||
list-style: upper-alpha } |
|||
|
|||
ol.lowerroman { |
|||
list-style: lower-roman } |
|||
|
|||
ol.upperroman { |
|||
list-style: upper-roman } |
|||
|
|||
p.attribution { |
|||
text-align: right ; |
|||
margin-left: 50% } |
|||
|
|||
p.caption { |
|||
font-style: italic } |
|||
|
|||
p.credits { |
|||
font-style: italic ; |
|||
font-size: smaller } |
|||
|
|||
p.label { |
|||
white-space: nowrap } |
|||
|
|||
p.rubric { |
|||
font-weight: bold ; |
|||
font-size: larger ; |
|||
color: maroon ; |
|||
text-align: center } |
|||
|
|||
p.sidebar-title { |
|||
font-family: sans-serif ; |
|||
font-weight: bold ; |
|||
font-size: larger } |
|||
|
|||
p.sidebar-subtitle { |
|||
font-family: sans-serif ; |
|||
font-weight: bold } |
|||
|
|||
p.topic-title { |
|||
font-weight: bold } |
|||
|
|||
pre.address { |
|||
margin-bottom: 0 ; |
|||
margin-top: 0 ; |
|||
font: inherit } |
|||
|
|||
pre.literal-block, pre.doctest-block, pre.math, pre.code { |
|||
margin-left: 2em ; |
|||
margin-right: 2em } |
|||
|
|||
pre.code .ln { color: grey; } /* line numbers */ |
|||
pre.code, code { background-color: #eeeeee } |
|||
pre.code .comment, code .comment { color: #5C6576 } |
|||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } |
|||
pre.code .literal.string, code .literal.string { color: #0C5404 } |
|||
pre.code .name.builtin, code .name.builtin { color: #352B84 } |
|||
pre.code .deleted, code .deleted { background-color: #DEB0A1} |
|||
pre.code .inserted, code .inserted { background-color: #A3D289} |
|||
|
|||
span.classifier { |
|||
font-family: sans-serif ; |
|||
font-style: oblique } |
|||
|
|||
span.classifier-delimiter { |
|||
font-family: sans-serif ; |
|||
font-weight: bold } |
|||
|
|||
span.interpreted { |
|||
font-family: sans-serif } |
|||
|
|||
span.option { |
|||
white-space: nowrap } |
|||
|
|||
span.pre { |
|||
white-space: pre } |
|||
|
|||
span.problematic { |
|||
color: red } |
|||
|
|||
span.section-subtitle { |
|||
/* font-size relative to parent (h1..h6 element) */ |
|||
font-size: 80% } |
|||
|
|||
table.citation { |
|||
border-left: solid 1px gray; |
|||
margin-left: 1px } |
|||
|
|||
table.docinfo { |
|||
margin: 2em 4em } |
|||
|
|||
table.docutils { |
|||
margin-top: 0.5em ; |
|||
margin-bottom: 0.5em } |
|||
|
|||
table.footnote { |
|||
border-left: solid 1px black; |
|||
margin-left: 1px } |
|||
|
|||
table.docutils td, table.docutils th, |
|||
table.docinfo td, table.docinfo th { |
|||
padding-left: 0.5em ; |
|||
padding-right: 0.5em ; |
|||
vertical-align: top } |
|||
|
|||
table.docutils th.field-name, table.docinfo th.docinfo-name { |
|||
font-weight: bold ; |
|||
text-align: left ; |
|||
white-space: nowrap ; |
|||
padding-left: 0 } |
|||
|
|||
/* "booktabs" style (no vertical lines) */ |
|||
table.docutils.booktabs { |
|||
border: 0px; |
|||
border-top: 2px solid; |
|||
border-bottom: 2px solid; |
|||
border-collapse: collapse; |
|||
} |
|||
table.docutils.booktabs * { |
|||
border: 0px; |
|||
} |
|||
table.docutils.booktabs th { |
|||
border-bottom: thin solid; |
|||
text-align: left; |
|||
} |
|||
|
|||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, |
|||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { |
|||
font-size: 100% } |
|||
|
|||
ul.auto-toc { |
|||
list-style-type: none } |
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
<div class="document" id="point-of-sale-multiple-cash-control"> |
|||
<h1 class="title">Point Of Sale - Multiple Cash Control</h1> |
|||
|
|||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
|||
!! This file is generated by oca-gen-addon-readme !! |
|||
!! changes will be overwritten. !! |
|||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> |
|||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/quentinDupont/grap-odoo-incubator/tree/12.0_pos_multiple_control/pos_multiple_control"><img alt="quentinDupont/grap-odoo-incubator" src="https://img.shields.io/badge/github-quentinDupont%2Fgrap--odoo--incubator-lightgray.png?logo=github" /></a></p> |
|||
<p>This module extends the functionality of the point of sale by allowing a |
|||
better control at the closing of the session.</p> |
|||
<ul class="simple"> |
|||
<li>Show differences for all statements chosen (see config part)</li> |
|||
<li>Allow user to control each statement. (not only the cash statement, by |
|||
default) and change his starting and ending balance</li> |
|||
</ul> |
|||
<div class="figure"> |
|||
<img alt="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/change_starting_balance.gif" src="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/change_starting_balance.gif" /> |
|||
</div> |
|||
<ul class="simple"> |
|||
<li>Quickly solve differences (we can set an absolute limit), |
|||
thanks to pos_move_reason</li> |
|||
</ul> |
|||
<p>See this gif where where we set ending balance with difference, solve it and |
|||
close session :</p> |
|||
<div class="figure"> |
|||
<img alt="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/end_session_balance_automatic_solve.gif" src="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/end_session_balance_automatic_solve.gif" /> |
|||
</div> |
|||
<p>As the verification is more complete, allow the user to reopen a new session, |
|||
if the first one is in a closed state.</p> |
|||
<div class="figure"> |
|||
<img alt="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/open_new_session.png" src="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/open_new_session.png" /> |
|||
</div> |
|||
<p>Extra checks are done, to prevent user errors:</p> |
|||
<ul class="simple"> |
|||
<li>It is not possible to click on the button ‘Close Session’ if there are some |
|||
draft orders.</li> |
|||
</ul> |
|||
<p><strong>Table of contents</strong></p> |
|||
<div class="contents local topic" id="contents"> |
|||
<ul class="simple"> |
|||
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a></li> |
|||
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li> |
|||
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul> |
|||
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li> |
|||
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li> |
|||
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="section" id="configuration"> |
|||
<h1><a class="toc-backref" href="#id1">Configuration</a></h1> |
|||
<p>To configure this module, you need to:</p> |
|||
<p><strong>Configure the journals</strong> you want to control in your point of sale (POS)</p> |
|||
<ul class="simple"> |
|||
<li>Go to Invoicing / Configuration / Journals / Journals</li> |
|||
<li>Check the box ‘POS Journal Control’ if you want to enable this feature for this journal</li> |
|||
<li>Unchecked journal will be in grey</li> |
|||
</ul> |
|||
<div class="figure"> |
|||
<img alt="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/account_journal_config.png" src="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/account_journal_config.png" /> |
|||
</div> |
|||
<p><strong>Configure your POS configuration</strong></p> |
|||
<ul class="simple"> |
|||
<li>Go to Point of Sale / Configuration / Point of Sale / <your pos></li> |
|||
<li>Choose your Payments methods (1)</li> |
|||
<li>Check Cash Control (2)</li> |
|||
<li>(optional) Choose a “pos move reason” to ausolve difference (3) (see pos_move_reason module for more details)</li> |
|||
<li>(optional) Choose a limit to allow or not the user to autosolve control difference in pos - Set 0 if you don’t want any limit. (4)</li> |
|||
</ul> |
|||
<div class="figure"> |
|||
<img alt="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/pos_session_config.png" src="https://raw.githubusercontent.com/quentinDupont/grap-odoo-incubator/12.0_pos_multiple_control/pos_multiple_control/static/description/pos_session_config.png" /> |
|||
</div> |
|||
</div> |
|||
<div class="section" id="bug-tracker"> |
|||
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1> |
|||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/quentinDupont/grap-odoo-incubator/issues">GitHub Issues</a>. |
|||
In case of trouble, please check there if your issue has already been reported. |
|||
If you spotted it first, help us smashing it by providing a detailed and welcomed |
|||
<a class="reference external" href="https://github.com/quentinDupont/grap-odoo-incubator/issues/new?body=module:%20pos_multiple_control%0Aversion:%2012.0_pos_multiple_control%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> |
|||
<p>Do not contact contributors directly about support or help with technical issues.</p> |
|||
</div> |
|||
<div class="section" id="credits"> |
|||
<h1><a class="toc-backref" href="#id3">Credits</a></h1> |
|||
<div class="section" id="authors"> |
|||
<h2><a class="toc-backref" href="#id4">Authors</a></h2> |
|||
<ul class="simple"> |
|||
<li>GRAP</li> |
|||
</ul> |
|||
</div> |
|||
<div class="section" id="contributors"> |
|||
<h2><a class="toc-backref" href="#id5">Contributors</a></h2> |
|||
<ul class="simple"> |
|||
<li>Sylvain LE GAL <<a class="reference external" href="https://twitter.com/legalsylvain">https://twitter.com/legalsylvain</a>></li> |
|||
<li>Julien WESTE</li> |
|||
<li>Quentin DUPONT <<a class="reference external" href="https://twitter.com/pondupont">https://twitter.com/pondupont</a>></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section" id="maintainers"> |
|||
<h2><a class="toc-backref" href="#id6">Maintainers</a></h2> |
|||
<p>This module is part of the <a class="reference external" href="https://github.com/quentinDupont/grap-odoo-incubator/tree/12.0_pos_multiple_control/pos_multiple_control">quentinDupont/grap-odoo-incubator</a> project on GitHub.</p> |
|||
<p>You are welcome to contribute.</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</body> |
|||
</html> |
After Width: 584 | Height: 222 | Size: 13 KiB |
After Width: 1132 | Height: 515 | Size: 78 KiB |
After Width: 1082 | Height: 375 | Size: 39 KiB |
@ -0,0 +1 @@ |
|||
from . import test_pos_multiple_control |
@ -0,0 +1,170 @@ |
|||
# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) |
|||
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from odoo.tests.common import TransactionCase |
|||
from odoo.exceptions import ValidationError |
|||
from odoo.exceptions import Warning as UserError |
|||
|
|||
|
|||
class TestMultipleControl(TransactionCase): |
|||
"""Tests for 'Point of Sale - Multiple Control' Module""" |
|||
|
|||
def setUp(self): |
|||
super(TestMultipleControl, self).setUp() |
|||
self.session_obj = self.env["pos.session"] |
|||
self.order_obj = self.env["pos.order"] |
|||
self.payment_obj = self.env["pos.make.payment"] |
|||
self.partner = self.env.ref("base.partner_demo_portal") |
|||
self.product = self.env.ref("product.product_product_3") |
|||
self.pos_move_reason = self.env.ref( |
|||
"pos_multiple_control.cash_register_error" |
|||
) |
|||
self.pos_config = self.env.ref( |
|||
"pos_multiple_control.pos_config_control" |
|||
) |
|||
self.check_journal = self.env.ref("pos_multiple_control.check_journal") |
|||
self.cash_journal = self.env.ref("pos_multiple_control.cash_journal") |
|||
|
|||
def _order(self, session, price, journal): |
|||
# I create a new PoS order with 2 lines |
|||
order = self.order_obj.create({ |
|||
'session_id': session.id, |
|||
'partner_id': self.partner.id, |
|||
'pricelist_id': self.partner.property_product_pricelist.id, |
|||
'lines': [(0, 0, { |
|||
'name': "OL/0001", |
|||
'product_id': self.product.id, |
|||
'price_unit': price, |
|||
'qty': 1.0, |
|||
# 'tax_ids': [(6, 0, self.product.taxes_id.ids)], |
|||
'price_subtotal': price, |
|||
'price_subtotal_incl': price, |
|||
})], |
|||
'amount_total': price, |
|||
'amount_tax': 0.0, |
|||
'amount_paid': 0.0, |
|||
'amount_return': 0.0, |
|||
}) |
|||
return order |
|||
|
|||
def _order_and_pay(self, session, price, journal): |
|||
order = self._order(session, price, journal) |
|||
|
|||
context_make_payment = { |
|||
"active_ids": [order.id], |
|||
"active_id": order.id |
|||
} |
|||
self.pos_make_payment = self.payment_obj.with_context( |
|||
context_make_payment).create({'amount': price}) |
|||
|
|||
# I click on the validate button to register the payment. |
|||
context_payment = {'active_id': order.id} |
|||
self.pos_make_payment.with_context(context_payment).check() |
|||
|
|||
return order |
|||
|
|||
# Test Section |
|||
def test_01_two_opening_session(self): |
|||
# I create new session |
|||
self.session_obj.create({"config_id": self.pos_config.id}) |
|||
|
|||
# I Try to create a new session |
|||
with self.assertRaises(ValidationError): |
|||
self.session_obj.create({"config_id": self.pos_config.id}) |
|||
|
|||
def test_02_opening_and_opened_session(self): |
|||
# I create new session and open it |
|||
session = self.session_obj.create({"config_id": self.pos_config.id}) |
|||
self.pos_config.open_session_cb() |
|||
self.pos_config._open_session(session.id) |
|||
|
|||
# I Try to create a new session |
|||
with self.assertRaises(ValidationError): |
|||
self.session_obj.create({"config_id": self.pos_config.id}) |
|||
|
|||
def test_03_check_close_session_with_draft_order(self): |
|||
# I create new session and open it |
|||
session = self.session_obj.create({"config_id": self.pos_config.id}) |
|||
self.pos_config.open_session_cb() |
|||
self.pos_config._open_session(session.id) |
|||
|
|||
# Create a Draft order, and try to close the session |
|||
self._order(session, 1, self.check_journal) |
|||
|
|||
with self.assertRaises(UserError): |
|||
session.wkf_action_closing_control() |
|||
|
|||
def test_04_check_bank_statement_control(self): |
|||
# I create new session and open it |
|||
session = self.session_obj.create({"config_id": self.pos_config.id}) |
|||
|
|||
# Make 2 Sales of 1100 and check transactions and theoritical balance |
|||
self.pos_config.open_session_cb() |
|||
self.pos_config._open_session(session.id) |
|||
self._order_and_pay(session, 100, self.check_journal) |
|||
self._order_and_pay(session, 1000, self.check_journal) |
|||
self.assertEqual( |
|||
session.control_register_total_entry_encoding, |
|||
1100, |
|||
"Incorrect transactions total", |
|||
) |
|||
self.assertEqual( |
|||
session.control_register_balance_end, |
|||
session.control_register_balance_start + 1100, |
|||
"Incorrect theoritical ending balance", |
|||
) |
|||
|
|||
with self.assertRaises(UserError): |
|||
session.action_pos_session_validate() |
|||
|
|||
def test_05_check_autosolve(self): |
|||
# I create new session and open it |
|||
self.pos_config.write( |
|||
{ |
|||
"autosolve_pos_move_reason": self.pos_move_reason.id, |
|||
"autosolve_limit": 20, |
|||
} |
|||
) |
|||
session = self.session_obj.create({"config_id": self.pos_config.id}) |
|||
|
|||
# Make sales and autosolve |
|||
self.pos_config.open_session_cb() |
|||
self.pos_config._open_session(session.id) |
|||
sale = self._order_and_pay(session, 18, self.check_journal) |
|||
sale.statement_ids[0].statement_id.automatic_solve() |
|||
self.assertEqual( |
|||
session.summary_statement_ids[1].control_difference, |
|||
0, |
|||
"Incorrect transactions total", |
|||
) |
|||
|
|||
def test_06_check_display_button(self): |
|||
# I create new session and open it |
|||
self.pos_config.write( |
|||
{ |
|||
"autosolve_pos_move_reason": self.pos_move_reason.id, |
|||
"autosolve_limit": 30, |
|||
} |
|||
) |
|||
session = self.session_obj.create({"config_id": self.pos_config.id}) |
|||
|
|||
# Make sales too important |
|||
self.pos_config.open_session_cb() |
|||
self.pos_config._open_session(session.id) |
|||
sale = self._order_and_pay(session, 31, self.check_journal) |
|||
self.assertEqual( |
|||
sale.statement_ids[0].statement_id.display_autosolve, |
|||
False, |
|||
"Autosolve button should be hidden", |
|||
) |
|||
|
|||
# Autosolve and second sales |
|||
sale.statement_ids[0].statement_id.automatic_solve() |
|||
sale2 = self._order_and_pay(session, 29, self.check_journal) |
|||
sale2.statement_ids[0].statement_id._compute_display_autosolve() |
|||
self.assertEqual( |
|||
sale2.statement_ids[0].statement_id.display_autosolve, |
|||
True, |
|||
"Autosolve button should not be hidden", |
|||
) |
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="view_account_journal_form" model="ir.ui.view"> |
|||
<field name="model">account.journal</field> |
|||
<field name="inherit_id" ref="account.view_account_journal_form"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="journal_user" position="after"> |
|||
<field name="pos_control" attrs="{'invisible': [('type', 'not in', ['bank', 'cash'])]}"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_account_journal_tree" model="ir.ui.view"> |
|||
<field name="model">account.journal</field> |
|||
<field name="inherit_id" ref="account.view_account_journal_tree"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="company_id" position="before"> |
|||
<field name="journal_user"/> |
|||
<field name="pos_control"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,45 @@ |
|||
<?xml version="1.0"?> |
|||
<!-- |
|||
Copyright (C) 2019 - Today: GRAP (http://www.grap.coop) |
|||
@author Quentin DUPONT (quentin.dupont@grap.coop) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="view_pos_config_form" model="ir.ui.view"> |
|||
<field name="model">pos.config</field> |
|||
<field name="inherit_id" ref="point_of_sale.pos_config_view_form"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='iface_precompute_cash']/../.." position="after"> |
|||
<div class="col-12 col-lg-6 o_setting_box"> |
|||
<div class="o_setting_right_pane"> |
|||
<label for="autosolve_pos_move_reason"/> |
|||
<field name="autosolve_pos_move_reason"/> |
|||
</div> |
|||
</div> |
|||
<div class="col-12 col-lg-6 o_setting_box"> |
|||
<div class="o_setting_right_pane"> |
|||
<label for="autosolve_limit"/> |
|||
<div class="text-muted"> |
|||
Limit to display autosolve button |
|||
</div> |
|||
<field name="autosolve_limit"/> |
|||
</div> |
|||
</div> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_pos_config_kanban" model="ir.ui.view"> |
|||
<field name="model">pos.config</field> |
|||
<field name="inherit_id" ref="point_of_sale.view_pos_config_kanban"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//button[@name='open_existing_session_cb']" position="after"> |
|||
<button t-if="_.contains(['closing_control'], record.current_session_state.raw_value)" class="btn btn-primary" name="open_new_session" type="object">New Session</button> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
|
|||
</odoo> |
@ -0,0 +1,135 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
@author Quentin DUPONT (https://twitter.com/pondupont) |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
|
|||
<record id="view_pos_session_form" model="ir.ui.view"> |
|||
<field name="model">pos.session</field> |
|||
<field name="inherit_id" ref="point_of_sale.view_pos_session_form"/> |
|||
<field name="arch" type="xml"> |
|||
<!-- Improve views --> |
|||
<field name="config_id" position="attributes"> |
|||
<attribute name="readonly">1</attribute> |
|||
</field> |
|||
|
|||
<!-- Hide obsolete Buttons --> |
|||
<!-- Same name button for opening and closing.. --> |
|||
<xpath expr="//button[@name='open_cashbox']" position="replace"> |
|||
<button name="open_cashbox_opening" |
|||
class="oe_stat_button" |
|||
attrs="{'invisible':['|', ('cash_control', '=', False), ('state', '!=', 'opening_control')]}" |
|||
icon="fa-money" |
|||
type="object" context="{'balance': 'start'}"> |
|||
<span class="o_stat_text">Set Opening Balance</span> |
|||
</button> |
|||
</xpath> |
|||
<!-- Hide closing button --> |
|||
<xpath expr="//button[@name='open_cashbox']" position="replace"> |
|||
</xpath> |
|||
|
|||
<!-- Add new session button on closing--> |
|||
<xpath expr="//header" position="inside"> |
|||
<button name="action_pos_session_new_session" type="object" |
|||
string="New Session" class="oe_highlight" |
|||
attrs="{'invisible' : [('state', '!=', 'closed')]}"/> |
|||
</xpath> |
|||
|
|||
<!-- Theoritical Summary --> |
|||
<xpath expr="//field[@name='cash_register_balance_start']/.." position="attributes"> |
|||
<attribute name="invisible">1</attribute> |
|||
</xpath> |
|||
<xpath expr="//field[@name='cash_register_balance_start']/.." position="after"> |
|||
<group class="oe_subtotal_footer oe_right"> |
|||
<field name="control_register_balance_start" readonly="1" class="oe_subtotal_footer_separator" widget="monetary" options="{'currency_field': 'currency_id'}"/> |
|||
<label for="control_register_total_entry_encoding" attrs="{'invisible' : [('state', '=', 'opening_control')]}" string="+ Transactions" class="oe_opening_total"/> |
|||
<field name="control_register_total_entry_encoding" nolabel="1" attrs="{'invisible' : [('state', '=', 'opening_control')]}" class="oe_pos_total" widget="monetary" options="{'currency_field': 'currency_id'}"/> |
|||
<label for="control_register_balance_end" attrs="{'invisible' : [('state', '=', 'opening_control')]}" string="Theoretical Closing Balances" class="oe_opening_total"/> |
|||
<field name="control_register_balance_end" nolabel="1" attrs="{'invisible' : [('state', '=', 'opening_control')]}" class="oe_subtotal_footer_separator" widget="monetary" options="{'currency_field': 'currency_id'}"/> |
|||
</group> |
|||
</xpath> |
|||
|
|||
|
|||
<!-- Real Summary and Differences --> |
|||
<xpath expr="//field[@name='cash_register_balance_end_real']/../.." position="replace"> |
|||
<div> |
|||
<group/> |
|||
<group class="oe_subtotal_footer oe_right" attrs="{'invisible': ['|', ('cash_control', '=', False), ('state', '=', 'opening_control')]}"> |
|||
<field name="control_register_balance" string="Real Closing Balance" class="oe_subtotal_footer_separator" widget="monetary" options="{'currency_field': 'currency_id'}"/> |
|||
<field name="control_register_difference" class="oe_subtotal_footer_separator oe_right oe_pos_total oe_pos_difference" widget="monetary" options="{'currency_field': 'currency_id'}"/> |
|||
</group> |
|||
</div> |
|||
</xpath> |
|||
|
|||
<!-- Summary by Payment Methods --> |
|||
<field name="statement_ids" position="attributes"> |
|||
<attribute name="invisible">1</attribute> |
|||
</field> |
|||
<field name="statement_ids" position="after"> |
|||
<field name="summary_statement_ids" nolabel="1" colspan="4" |
|||
attrs="{'invisible': [('state', 'in', ['opening_control'])], 'readonly': 1}"> |
|||
<tree decoration-muted="is_pos_control == False and state != 'closed'" decoration-danger="is_pos_control == True and control_difference != 0"> |
|||
<field name="is_pos_control" invisible="1"/> |
|||
<field name="name" /> |
|||
<field name="journal_id" /> |
|||
<field name="balance_start"/> |
|||
<button name="open_cashbox_starting_balance" |
|||
help="Set your starting balance" |
|||
type="object" |
|||
class="oe_stat_button" icon="fa-money" |
|||
attrs="{'invisible' : ['|', ('is_pos_control','!=', True), ('state', 'in', ['opening_control','closed'])]}"> |
|||
</button> |
|||
<field name="total_entry_encoding" /> |
|||
<field name="balance_end_real"/> |
|||
<button name="open_cashbox_ending_balance" |
|||
help="Set your ending balance" |
|||
type="object" |
|||
class="oe_stat_button" icon="fa-money" |
|||
attrs="{'invisible' : ['|', ('is_pos_control','!=', True), ('state', 'in', ['opening_control', 'closed'])]}"> |
|||
</button> |
|||
<field name="control_difference"/> |
|||
<field name="currency_id" groups="base.group_multi_currency" /> |
|||
<field name="state" invisible="1"/> |
|||
</tree> |
|||
<form> |
|||
<group> |
|||
<field name="name" /> |
|||
<field name="journal_id" /> |
|||
<field name="state" invisible="1" /> |
|||
</group> |
|||
<field name="line_ids" colspan="2"> |
|||
<tree string="Transactions"> |
|||
<field name="date"/> |
|||
<field name="ref"/> |
|||
<field name="name"/> |
|||
<field name="partner_id" /> |
|||
<field name="amount" sum="Total"/> |
|||
</tree> |
|||
</field> |
|||
</form> |
|||
</field> |
|||
</field> |
|||
|
|||
<!-- Automatic solve --> |
|||
<field name="control_difference" position="after"> |
|||
<field name="pos_session_state" invisible="1"/> |
|||
<field name="display_autosolve" invisible="1"/> |
|||
</field> |
|||
<field name="control_difference" position="after"> |
|||
<button name="automatic_solve" |
|||
help="Solve difference automatically with a product choosen in pos config" |
|||
type="object" |
|||
class="oe_stat_button" icon="fa-cogs" |
|||
confirm="Do you really want to solve this difference automatically ?" |
|||
attrs="{'invisible':[ |
|||
('display_autosolve', '!=', True)]}"> |
|||
</button> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1 @@ |
|||
from . import wizard_pos_update_statement_balance |
@ -0,0 +1,153 @@ |
|||
# 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 WizardPOSBankStatementUpdateBalance(models.TransientModel): |
|||
_name = "wizard.pos.update.bank.statement.balance" |
|||
_description = 'POS Update Bank Statement Balance' |
|||
|
|||
def _default_session_id(self): |
|||
return self.env.context.get('active_pos_id', False) |
|||
|
|||
_BALANCE_MOMENT_SELECTION = [ |
|||
('bydefault', 'Default'), |
|||
('starting', 'Starting balance'), |
|||
('ending', 'Ending balance'), |
|||
] |
|||
|
|||
item_ids = fields.One2many( |
|||
comodel_name="wizard.pos.update.bank.statement.balance.line", |
|||
inverse_name="wiz_id", |
|||
string="Items", |
|||
) |
|||
|
|||
balance_moment = fields.Selection( |
|||
selection=_BALANCE_MOMENT_SELECTION, string='Balance moment', |
|||
default='bydefault') |
|||
|
|||
journal_id = fields.Many2one( |
|||
comodel_name='account.journal', string="Journal", |
|||
domain="[('id', 'in', journal_ids)]", required=True) |
|||
|
|||
session_id = fields.Many2one( |
|||
comodel_name='pos.session', string="Current Session", |
|||
default=_default_session_id, required=True, readonly=True) |
|||
|
|||
@api.model |
|||
def _prepare_item(self, statement): |
|||
return { |
|||
"statement_id": statement.id, |
|||
"name": statement.name, |
|||
"journal_id": statement.journal_id.id, |
|||
"balance_start": statement.balance_start, |
|||
"balance_end": statement.balance_end, |
|||
"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) |
|||
# Load objects |
|||
session_obj = self.env["pos.session"] |
|||
bank_statement_obj = self.env["account.bank.statement"] |
|||
# Load context |
|||
active_ids = self.env.context["active_id"] or [] |
|||
active_pos_id = self.env.context["active_pos_id"] or [] |
|||
active_model = self.env.context["active_model"] or [] |
|||
balance_moment = self.env.context["balance_moment"] or [] |
|||
# Check propagation |
|||
if not active_pos_id: |
|||
return res |
|||
assert active_model == "pos.session", \ |
|||
"Bad context propagation" |
|||
if len(active_pos_id) > 1: |
|||
raise UserError(_('You cannot start the closing ' |
|||
'balance for multiple POS sessions')) |
|||
# Add bank statement lines |
|||
session = session_obj.browse(active_pos_id[0]) |
|||
bank_statement = bank_statement_obj.browse(active_ids[0]) |
|||
items = [] |
|||
items.append([0, 0, self._prepare_item(bank_statement)]) |
|||
# Give values for wizard |
|||
res["session_id"] = session.id |
|||
res["item_ids"] = items |
|||
res["balance_moment"] = balance_moment |
|||
res["journal_id"] = bank_statement.journal_id.id |
|||
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() |
|||
# record new values from wizard |
|||
for item in self.item_ids: |
|||
if item.balance_moment == 'starting': |
|||
item.statement_id.balance_start = item.balance_start_real |
|||
elif item.balance_moment == 'ending': |
|||
item.statement_id.balance_end_real = item.balance_end_real |
|||
# item.statement_id.balance_end = item.balance_end_real |
|||
return True |
|||
|
|||
|
|||
class WizardPOSBankStatementUpdateBalanceLine(models.TransientModel): |
|||
_name = "wizard.pos.update.bank.statement.balance.line" |
|||
_description = 'POS Update Bank Statement Balance Line' |
|||
|
|||
wiz_id = fields.Many2one( |
|||
comodel_name='wizard.pos.update.bank.statement.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( |
|||
string="Starting Balance", |
|||
default=0.0, |
|||
compute='_compute_balance_start' |
|||
) |
|||
balance_start_real = fields.Monetary( |
|||
default=0.0 |
|||
) |
|||
total_entry_encoding = fields.Monetary( |
|||
related='statement_id.total_entry_encoding', |
|||
) |
|||
balance_end = fields.Monetary( |
|||
string="Computed Balance", |
|||
default=0.0, |
|||
compute='_compute_balance_end' |
|||
) |
|||
balance_end_real = fields.Monetary( |
|||
default=0.0 |
|||
) |
|||
currency_id = fields.Many2one( |
|||
comodel_name='res.currency', |
|||
related='statement_id.currency_id' |
|||
) |
|||
balance_moment = fields.Selection( |
|||
related='wiz_id.balance_moment', |
|||
default='bydefault') |
|||
|
|||
def _compute_balance_start(self): |
|||
for rec in self: |
|||
rec.balance_start = rec.statement_id.balance_start |
|||
|
|||
def _compute_balance_end(self): |
|||
for rec in self: |
|||
rec.balance_end = rec.statement_id.balance_end |
@ -0,0 +1,38 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
|
|||
<record id="view_wizard_pos_update_bank_statement_balance_form" model="ir.ui.view"> |
|||
<field name="model">wizard.pos.update.bank.statement.balance</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Update Balance"> |
|||
Here you can change the <b><field name="balance_moment" readonly="1"/></b> |
|||
<field name="item_ids" nolabel="1"> |
|||
<tree string="Statements" create="0" editable="top" limit="1"> |
|||
<field name="journal_id"/> |
|||
<field name="balance_moment" invisible="1"/> |
|||
<field name="balance_start"/> |
|||
<field name="balance_start_real" invisible="context.get('balance_moment') != 'starting'"/> |
|||
<field name="total_entry_encoding" invisible="context.get('balance_moment') != 'ending'"/> |
|||
<field name="balance_end" invisible="context.get('balance_moment') != 'ending'"/> |
|||
<field name="balance_end_real" invisible="context.get('balance_moment') != 'ending'"/> |
|||
<field name="currency_id" groups="base.group_multi_currency"/> |
|||
</tree> |
|||
</field> |
|||
<footer> |
|||
<button name="action_confirm" string="Apply" type="object" class="btn-primary"/> |
|||
<button class="btn-secondary" special="cancel" string="Cancel"/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_wizard_pos_update_bank_statement_balance" model="ir.actions.act_window"> |
|||
<field name="name">Update Balances</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">wizard.pos.update.bank.statement.balance</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
</odoo> |