Browse Source

[MIG][12.0] port pos_cash_move_reason

[REF] Don't use ``product.product`` model for Reasons, because Odoo remove
the fields ``expense_pdt`` ``and income_pdt`` from the model.
Use instead a new model ``pos.move.reason`` for this purpose.
[REF] Doesn't inherit from ``cash.box.in`` and ``cash.box.out`` model,
as there are bad designed and doesn't allow clean inheritance.
Instead, use new transient model ``wizard.pos.move.reason``.
[REF] Oca convention. add readme folder.
pull/384/head
Sylvain LE GAL 5 years ago
parent
commit
0e4d86e52b
  1. 133
      pos_cash_move_reason/README.rst
  2. 2
      pos_cash_move_reason/__init__.py
  3. 28
      pos_cash_move_reason/__manifest__.py
  4. 23
      pos_cash_move_reason/__openerp__.py
  5. 21
      pos_cash_move_reason/demo/account_account.xml
  6. 33
      pos_cash_move_reason/demo/pos_move_reason.xml
  7. 21
      pos_cash_move_reason/demo/product_template.xml
  8. 226
      pos_cash_move_reason/i18n/fr.po
  9. 204
      pos_cash_move_reason/i18n/pos_cash_move_reason.pot
  10. 2
      pos_cash_move_reason/models/__init__.py
  11. 57
      pos_cash_move_reason/models/pos_move_reason.py
  12. 39
      pos_cash_move_reason/models/pos_session.py
  13. 17
      pos_cash_move_reason/readme/CONFIGURE.rst
  14. 1
      pos_cash_move_reason/readme/CONTRIBUTORS.rst
  15. 15
      pos_cash_move_reason/readme/DESCRIPTION.rst
  16. 20
      pos_cash_move_reason/readme/HISTORY.rst
  17. 4
      pos_cash_move_reason/readme/ROADMAP.rst
  18. 16
      pos_cash_move_reason/readme/USAGE.rst
  19. 3
      pos_cash_move_reason/security/ir.model.access.csv
  20. 16
      pos_cash_move_reason/security/ir_rule.xml
  21. 13
      pos_cash_move_reason/security/res_groups.xml
  22. BIN
      pos_cash_move_reason/static/description/account_move_form.png
  23. BIN
      pos_cash_move_reason/static/description/pos_cash_move_form.png
  24. BIN
      pos_cash_move_reason/static/description/pos_cash_move_reason_02.png
  25. BIN
      pos_cash_move_reason/static/description/pos_cash_move_tree.png
  26. BIN
      pos_cash_move_reason/static/description/pos_session_form.png
  27. BIN
      pos_cash_move_reason/static/description/wizard_pos_move_reason_form.png
  28. 1
      pos_cash_move_reason/tests/__init__.py
  29. 121
      pos_cash_move_reason/tests/test_pos_cash_move_reason.py
  30. 71
      pos_cash_move_reason/views/view_pos_move_reason.xml
  31. 51
      pos_cash_move_reason/views/view_pos_session.xml
  32. 6
      pos_cash_move_reason/wizard/__init__.py
  33. 75
      pos_cash_move_reason/wizard/pos_box.py
  34. 26
      pos_cash_move_reason/wizard/pos_box.xml
  35. 100
      pos_cash_move_reason/wizard/wizard_pos_move_reason.py
  36. 40
      pos_cash_move_reason/wizard/wizard_pos_move_reason.xml

133
pos_cash_move_reason/README.rst

@ -1,62 +1,137 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
======================
POS cash in-out reason
======================
This module allow to define some products as reason for the functionality of
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! 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-legalsylvain%2Fpos-lightgray.png?logo=github
:target: https://github.com/legalsylvain/pos/tree/12.0-mig-pos_cash_move_reason/pos_cash_move_reason
:alt: legalsylvain/pos
|badge1| |badge2| |badge3|
This module allow to define some reasons for the functionality of
"Put Money In" and "Take Money Out" available in point of sale session.
So, with this module it's possible to impact directly an expense or income
account which is defined on the related product or in its category.
account which is defined on the related reasons and create according
accounting entries.
**Typical Use Case (not exhaustive)**
* You want to track **Bank deposit** moves, using an intermediate
bank account named 'Cash Awaiting Bank Deposit'.
(In France, for instance, "581 - Espèce en attente d'encaissement")
* You want to allow payments from Cash Journal to pay recurring
little expenses. (Gasoline, parking meter, etc.)
**Table of contents**
.. contents::
:local:
Configuration
=============
You need to configure some products that can be used on "Put Money In" and
"Take Money Out". You have to set Point of Sale Cash In or Out and income and
expense account.
* Go to 'Point of Sale' / 'Configuration' / 'Move Reason'
.. figure:: https://raw.githubusercontent.com/legalsylvain/pos/12.0-mig-pos_cash_move_reason/pos_cash_move_reason/static/description/pos_cash_move_tree.png
:alt: PoS Move Reasons List
* Create or update your PoS move Reasons.
* for each reason, you can mention the concerned journal(s), (Generally the
Cash Journal), and if it is a reason to 'put in' and / or to 'take out'
Money.
.. figure:: https://raw.githubusercontent.com/legalsylvain/pos/12.0-mig-pos_cash_move_reason/pos_cash_move_reason/static/description/pos_cash_move_form.png
:alt: PoS Move Reason
**Note**
You should have checked first 'Used in Point of Sale' for the Journals you want
to enable the feature.
Usage
=====
You can use configured products on "Put Money In" and "Take Money Out" wizard available in point of sale session:
* Go to your current session
* Click on the button "Put Money In" or "Take Money Out"
.. figure:: https://raw.githubusercontent.com/legalsylvain/pos/12.0-mig-pos_cash_move_reason/pos_cash_move_reason/static/description/pos_session_form.png
* Select the reason, the journal, the amount, and optionaly an extra
description
.. figure:: https://raw.githubusercontent.com/legalsylvain/pos/12.0-mig-pos_cash_move_reason/pos_cash_move_reason/static/description/wizard_pos_move_reason_form.png
* When closing the session, an account move will be created, with two lines,
one with the default journal account, and one with the expense / income
reason account.
.. figure:: /pos_cash_move_reason/static/description/pos_cash_move_reason_02.png
:alt: Take money out wizard
.. figure:: https://raw.githubusercontent.com/legalsylvain/pos/12.0-mig-pos_cash_move_reason/pos_cash_move_reason/static/description/account_move_form.png
Changelog
=========
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/184/8.0
12.0.3.0.0 (2019-08-13)
~~~~~~~~~~~~~~~~~~~~~~~
* [MIG] Port module to version 12.0.
* [REF] Don't use ``product.product`` model for Reasons, because Odoo remove
the fields ``expense_pdt`` ``and income_pdt`` from the model.
Use instead a new model ``pos.move.reason`` for this purpose.
* [REF] Doesn't inherit from ``cash.box.in`` and ``cash.box.out`` model,
as there are bad designed and doesn't allow clean inheritance.
Instead, use new transient model ``wizard.pos.move.reason``.
8.0.2.0.0 (2018-06-25)
~~~~~~~~~~~~~~~~~~~~~~
* [REF] Minor code refactoring.
8.0.1.0.0 (2017-06-08)
~~~~~~~~~~~~~~~~~~~~~~
* First Version of the module.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/pos/issues>`_.
Bugs are tracked on `GitHub Issues <https://github.com/legalsylvain/pos/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
`here <https://github.com/OCA/pos/issues/new?body=module:%20pos_cash_move_reason%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/legalsylvain/pos/issues/new?body=module:%20pos_cash_move_reason%0Aversion:%2012.0-mig-pos_cash_move_reason%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
=======
Contributors
------------
Authors
~~~~~~~
* Adrien Peiffer <adrien.peiffer@acsone.eu>
* ACSONE SA/NV
* GRAP
Maintainer
----------
Contributors
~~~~~~~~~~~~
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
* Sylvain LE GAL <https://twitter.com/legalsylvain>
This module is maintained by the OCA.
Maintainers
~~~~~~~~~~~
OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.
This module is part of the `legalsylvain/pos <https://github.com/legalsylvain/pos/tree/12.0-mig-pos_cash_move_reason/pos_cash_move_reason>`_ project on GitHub.
To contribute to this module, please visit https://odoo-community.org.
You are welcome to contribute.

2
pos_cash_move_reason/__init__.py

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models
from . import wizard

28
pos_cash_move_reason/__manifest__.py

@ -0,0 +1,28 @@
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': "POS cash in-out reason",
'summary': """""",
'author': 'ACSONE SA/NV,'
'GRAP,'
'Odoo Community Association (OCA)',
'website': "https://www.github.com/OCA/pos",
'category': 'Point Of sale',
'version': '12.0.3.0.0',
'license': 'AGPL-3',
'depends': [
'point_of_sale',
],
'data': [
'security/ir_rule.xml',
'security/res_groups.xml',
'security/ir.model.access.csv',
'views/view_pos_move_reason.xml',
'views/view_pos_session.xml',
'wizard/wizard_pos_move_reason.xml',
],
'demo': [
'demo/account_account.xml',
'demo/pos_move_reason.xml',
],
}

23
pos_cash_move_reason/__openerp__.py

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': "POS cash in-out reason",
'summary': """""",
'author': 'ACSONE SA/NV,'
'GRAP,'
'Odoo Community Association (OCA)',
'website': "http://acsone.eu",
'category': 'POS',
'version': '8.0.2.0.0',
'license': 'AGPL-3',
'depends': [
'point_of_sale',
],
'data': [
'wizard/pos_box.xml',
],
'demo': [
'demo/product_template.xml',
],
}

21
pos_cash_move_reason/demo/account_account.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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).
-->
<odoo>
<record id="bank_deposit_account" model="account.account">
<field name="code">101505</field>
<field name="name">Cash Awaiting Bank Deposit</field>
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
</record>
<record id="gazoline_expense_account" model="account.account">
<field name="code">221500</field>
<field name="name">Gazoline Expense</field>
<field name="user_type_id" ref="account.data_account_type_expenses"/>
</record>
</odoo>

33
pos_cash_move_reason/demo/pos_move_reason.xml

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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).
-->
<odoo>
<record id="bank_out_reason" model="pos.move.reason">
<field name="name">Bank Deposit</field>
<field name="is_income_reason" eval="False" />
<field name="is_expense_reason" eval="True"/>
<field name="expense_account_id" ref="bank_deposit_account"/>
<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>
<record id="gasoline_out_reason" model="pos.move.reason">
<field name="name">Gazoline Expense</field>
<field name="is_income_reason" eval="False" />
<field name="is_expense_reason" eval="True"/>
<field name="expense_account_id" ref="gazoline_expense_account"/>
<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>

21
pos_cash_move_reason/demo/product_template.xml

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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).
-->
<openerp><data>
<record id="income_reason" model="product.template">
<field name="name">Miscellaneous income</field>
<field name="income_pdt" eval="True" />
<field name="property_account_income" ref="account.o_income"/>
</record>
<record id="expense_reason" model="product.template">
<field name="name">Miscellaneous expense</field>
<field name="expense_pdt" eval="True" />
<field name="property_account_expense" ref="account.a_expense"/>
</record>
</data></openerp>

226
pos_cash_move_reason/i18n/fr.po

@ -1,50 +1,228 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_cash_move_reason
# * pos_cash_move_reason
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-15 13:30+0000\n"
"PO-Revision-Date: 2018-02-15 13:30+0000\n"
"POT-Creation-Date: 2019-08-23 15:07+0000\n"
"PO-Revision-Date: 2019-08-23 17:14+0200\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"Language: fr\n"
"X-Generator: Poedit 2.0.6\n"
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:39
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_pos_session_form
msgid ""
"<span class=\"o_stat_text\">Put</span>\n"
" <span class=\"o_stat_text\">Money In</span>"
msgstr ""
"<span class=\"o_stat_text\">Mettre</span>\n"
" <span class=\"o_stat_text\">de l'argent</span>"
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_pos_session_form
msgid ""
"<span class=\"o_stat_text\">Take</span>\n"
" <span class=\"o_stat_text\">Money Out</span>"
msgstr ""
"<span class=\"o_stat_text\">Retirer</span>\n"
" <span class=\"o_stat_text\">de l'argent</span>"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__journal_ids
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__journal_ids
msgid "Accounting Journals"
msgstr "Journaux comptables"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__active
msgid "Active"
msgstr "Actif"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__amount
msgid "Amount"
msgstr "Montant"
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Apply"
msgstr "Appliquer"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__statement_id
msgid "Bank Statement"
msgstr "Relevé bancaire"
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Cancel"
msgstr "Annuler"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__company_id
msgid "Company"
msgstr "Société"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__create_uid
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__create_date
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__create_date
msgid "Created on"
msgstr "Créé le"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__session_id
msgid "Current Session"
msgstr "Session en cours"
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Describe why you take money from the cash register"
msgstr "Veuillez indiquer le motif pour lequel vous retirez de l'argent de la caisse"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_session__display_move_reason_expense
msgid "Display Move Reason Expense"
msgstr "Afficher le motif de sortie d'argent"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_session__display_move_reason_income
msgid "Display Move Reason Income"
msgstr "Afficher le motif d'entrée d'argent"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__display_name
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__expense_account_id
msgid "Expense Account"
msgstr "Compte de dépenses"
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Fill in this form if you put money in the cash register"
msgstr "Remplir ce formulaire si vous mettez de l'argent dans la caisse"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__id
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__id
msgid "ID"
msgstr "ID"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__income_account_id
msgid "Income Account"
msgstr "Compte de revenus"
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/wizard_pos_move_reason.py:67
#, python-format
msgid "Description"
msgstr "Description"
msgid "Invalid Amount"
msgstr "Montant invalide"
#. module: pos_cash_move_reason
#: model:product.template,name:pos_cash_move_reason.expense_reason
msgid "Miscellaneous expense"
msgstr "Dépense diverse"
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__is_expense_reason
msgid "Is Expense Reason"
msgstr "Est un motif de sortie"
#. module: pos_cash_move_reason
#: model:product.template,name:pos_cash_move_reason.income_reason
msgid "Miscellaneous income"
msgstr "Revenu divers"
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__is_income_reason
msgid "Is Income Reason"
msgstr "Est un motif d'entrée"
#. module: pos_cash_move_reason
#: field:cash.box.in,product_id:0 field:cash.box.out,product_id:0
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__journal_id
msgid "Journal"
msgstr "Journal"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason____last_update
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__write_uid
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__write_date
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__move_reason_id
msgid "Move Reason"
msgstr "Motif de mouvement d'argent"
#. module: pos_cash_move_reason
#: model:ir.actions.act_window,name:pos_cash_move_reason.action_pos_move_reason
#: model:ir.actions.act_window,name:pos_cash_move_reason.action_wizard_pos_move_reason
#: model:ir.ui.menu,name:pos_cash_move_reason.menu_pos_move_reason
msgid "Move Reasons"
msgstr "Motifs de mouvement d'argent"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__move_type
msgid "Move type"
msgstr "Type de mouvement"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__name
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_pos_move_reason_form
msgid "Name"
msgstr "Nom"
#. module: pos_cash_move_reason
#: model:ir.model,name:pos_cash_move_reason.model_pos_move_reason
msgid "PoS - Move In / Out Reason"
msgstr "PdV - Motif de mouvement d'rgent"
#. module: pos_cash_move_reason
#: model:ir.model,name:pos_cash_move_reason.model_wizard_pos_move_reason
msgid "PoS Move Reasons Wizard"
msgstr "PdV - Assistant de mouvement d'argent"
#. module: pos_cash_move_reason
#: model:ir.model,name:pos_cash_move_reason.model_pos_session
msgid "Point of Sale Session"
msgstr "Session du point de vente"
#. module: pos_cash_move_reason
#: selection:wizard.pos.move.reason,move_type:0
msgid "Put Money In"
msgstr "Mettre de l'argent"
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__name
msgid "Reason"
msgstr "Motif"
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:62
#, python-format
msgid "You have to define an expense account on the related product %s"
msgstr "Vous devez définir un compte de charge sur le produit lié %s"
#: selection:wizard.pos.move.reason,move_type:0
msgid "Take Money Out"
msgstr "Retirer de l'argent"
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:55
#, python-format
msgid "You have to define an income account on the related product %s"
msgstr "Vous devez définir un compte de produit sur le produit lié %s"
#: model:res.groups,name:pos_cash_move_reason.group_pos_old_actions
msgid "Use Old PoS 'Put or Take Money' Actions"
msgstr "Utiliser la fonctionnalité obsolète du PdV Mettre ou Prendre de l'argent"

204
pos_cash_move_reason/i18n/pos_cash_move_reason.pot

@ -1,11 +1,13 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_cash_move_reason
# * pos_cash_move_reason
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-08-23 15:15+0000\n"
"PO-Revision-Date: 2019-08-23 15:15+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@ -14,36 +16,206 @@ msgstr ""
"Plural-Forms: \n"
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:39
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_pos_session_form
msgid "<span class=\"o_stat_text\">Put</span>\n"
" <span class=\"o_stat_text\">Money In</span>"
msgstr ""
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_pos_session_form
msgid "<span class=\"o_stat_text\">Take</span>\n"
" <span class=\"o_stat_text\">Money Out</span>"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__journal_ids
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__journal_ids
msgid "Accounting Journals"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__active
msgid "Active"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__amount
msgid "Amount"
msgstr ""
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Apply"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__statement_id
msgid "Bank Statement"
msgstr ""
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Cancel"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__company_id
msgid "Company"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__create_uid
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__create_uid
msgid "Created by"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__create_date
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__create_date
msgid "Created on"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__session_id
msgid "Current Session"
msgstr ""
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Describe why you take money from the cash register"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_session__display_move_reason_expense
msgid "Display Move Reason Expense"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_session__display_move_reason_income
msgid "Display Move Reason Income"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__display_name
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__display_name
msgid "Display Name"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__expense_account_id
msgid "Expense Account"
msgstr ""
#. module: pos_cash_move_reason
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_wizard_pos_move_reason_form
msgid "Fill in this form if you put money in the cash register"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__id
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__id
msgid "ID"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__income_account_id
msgid "Income Account"
msgstr ""
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/wizard_pos_move_reason.py:67
#, python-format
msgid "Description"
msgid "Invalid Amount"
msgstr ""
#. module: pos_cash_move_reason
#: model:product.template,name:pos_cash_move_reason.expense_reason
msgid "Miscellaneous expense"
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__is_expense_reason
msgid "Is Expense Reason"
msgstr ""
#. module: pos_cash_move_reason
#: model:product.template,name:pos_cash_move_reason.income_reason
msgid "Miscellaneous income"
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__is_income_reason
msgid "Is Income Reason"
msgstr ""
#. module: pos_cash_move_reason
#: field:cash.box.in,product_id:0
#: field:cash.box.out,product_id:0
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__journal_id
msgid "Journal"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason____last_update
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason____last_update
msgid "Last Modified on"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__write_uid
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__write_uid
msgid "Last Updated by"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__write_date
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__write_date
msgid "Last Updated on"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__move_reason_id
msgid "Move Reason"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.actions.act_window,name:pos_cash_move_reason.action_pos_move_reason
#: model:ir.actions.act_window,name:pos_cash_move_reason.action_wizard_pos_move_reason
#: model:ir.ui.menu,name:pos_cash_move_reason.menu_pos_move_reason
msgid "Move Reasons"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__move_type
msgid "Move type"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_pos_move_reason__name
#: model_terms:ir.ui.view,arch_db:pos_cash_move_reason.view_pos_move_reason_form
msgid "Name"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model,name:pos_cash_move_reason.model_pos_move_reason
msgid "PoS - Move In / Out Reason"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model,name:pos_cash_move_reason.model_wizard_pos_move_reason
msgid "PoS Move Reasons Wizard"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model,name:pos_cash_move_reason.model_pos_session
msgid "Point of Sale Session"
msgstr ""
#. module: pos_cash_move_reason
#: selection:wizard.pos.move.reason,move_type:0
msgid "Put Money In"
msgstr ""
#. module: pos_cash_move_reason
#: model:ir.model.fields,field_description:pos_cash_move_reason.field_wizard_pos_move_reason__name
msgid "Reason"
msgstr ""
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:62
#, python-format
msgid "You have to define an expense account on the related product %s"
#: selection:wizard.pos.move.reason,move_type:0
msgid "Take Money Out"
msgstr ""
#. module: pos_cash_move_reason
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:55
#, python-format
msgid "You have to define an income account on the related product %s"
#: model:res.groups,name:pos_cash_move_reason.group_pos_old_actions
msgid "Use Old PoS 'Put or Take Money' Actions"
msgstr ""

2
pos_cash_move_reason/models/__init__.py

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

57
pos_cash_move_reason/models/pos_move_reason.py

@ -0,0 +1,57 @@
# Copyright (C) 2019-Today: GTRAP (<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 PosMoveReason(models.Model):
_name = 'pos.move.reason'
_description = 'PoS - Move In / Out Reason'
@api.model
def _default_journal_ids(self):
AccountJournal = self.env['account.journal']
journals = AccountJournal.search([
('journal_user', '=', True),
('type', '=', 'cash')])
return journals.ids
@api.model
def _default_company_id(self):
return self.env.user.company_id
name = fields.Char(string='Name', required=True)
active = fields.Boolean(string='Active', default=True)
journal_ids = fields.Many2many(
comodel_name='account.journal', string='Accounting Journals',
domain="[('journal_user', '=', True)]",
default=_default_journal_ids)
is_income_reason = fields.Boolean(
string='Is Income Reason', default=True)
is_expense_reason = fields.Boolean(
string='Is Expense Reason', default=True)
income_account_id = fields.Many2one(
string='Income Account', comodel_name='account.account')
expense_account_id = fields.Many2one(
string='Expense Account', comodel_name='account.account')
company_id = fields.Many2one(
string='Company', comodel_name='res.company',
default=_default_company_id, required=True)
@api.onchange('is_income_reason')
def _onchange_is_income_reason(self):
if not self.is_income_reason:
self.income_account_id = False
@api.onchange('is_expense_reason')
def _onchange_is_expense_reason(self):
if not self.is_expense_reason:
self.expense_account_id = False

39
pos_cash_move_reason/models/pos_session.py

@ -0,0 +1,39 @@
# Copyright (C) 2019-Today: GTRAP (<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 PosSession(models.Model):
_inherit = 'pos.session'
display_move_reason_income = fields.Boolean(
compute='_compute_display_move_reason')
display_move_reason_expense = fields.Boolean(
compute='_compute_display_move_reason')
@api.multi
def _compute_display_move_reason(self):
MoveReason = self.env['pos.move.reason']
for session in self:
# Get all reasons
reasons = MoveReason.search([
('company_id', '=', session.config_id.company_id.id)])
session.display_move_reason_income = len(
reasons.filtered(lambda x: x.is_income_reason))
session.display_move_reason_expense = len(
reasons.filtered(lambda x: x.is_expense_reason))
def button_move_income(self):
return self._button_move_reason('income')
def button_move_expense(self):
return self._button_move_reason('expense')
def _button_move_reason(self, move_type):
action = self.env.ref(
'pos_cash_move_reason.action_wizard_pos_move_reason').read()[0]
action['context'] = {'default_move_type': move_type}
return action

17
pos_cash_move_reason/readme/CONFIGURE.rst

@ -0,0 +1,17 @@
* Go to 'Point of Sale' / 'Configuration' / 'Move Reason'
.. figure:: ../static/description/pos_cash_move_tree.png
:alt: PoS Move Reasons List
* Create or update your PoS move Reasons.
* for each reason, you can mention the concerned journal(s), (Generally the
Cash Journal), and if it is a reason to 'put in' and / or to 'take out'
Money.
.. figure:: ../static/description/pos_cash_move_form.png
:alt: PoS Move Reason
**Note**
You should have checked first 'Used in Point of Sale' for the Journals you want
to enable the feature.

1
pos_cash_move_reason/readme/CONTRIBUTORS.rst

@ -0,0 +1 @@
* Sylvain LE GAL <https://twitter.com/legalsylvain>

15
pos_cash_move_reason/readme/DESCRIPTION.rst

@ -0,0 +1,15 @@
This module allow to define some reasons for the functionality of
"Put Money In" and "Take Money Out" available in point of sale session.
So, with this module it's possible to impact directly an expense or income
account which is defined on the related reasons and create according
accounting entries.
**Typical Use Case (not exhaustive)**
* You want to track **Bank deposit** moves, using an intermediate
bank account named 'Cash Awaiting Bank Deposit'.
(In France, for instance, "581 - Espèce en attente d'encaissement")
* You want to allow payments from Cash Journal to pay recurring
little expenses. (Gasoline, parking meter, etc.)

20
pos_cash_move_reason/readme/HISTORY.rst

@ -0,0 +1,20 @@
12.0.3.0.0 (2019-08-13)
~~~~~~~~~~~~~~~~~~~~~~~
* [MIG] Port module to version 12.0.
* [REF] Don't use ``product.product`` model for Reasons, because Odoo remove
the fields ``expense_pdt`` ``and income_pdt`` from the model.
Use instead a new model ``pos.move.reason`` for this purpose.
* [REF] Doesn't inherit from ``cash.box.in`` and ``cash.box.out`` model,
as there are bad designed and doesn't allow clean inheritance.
Instead, use new transient model ``wizard.pos.move.reason``.
8.0.2.0.0 (2018-06-25)
~~~~~~~~~~~~~~~~~~~~~~
* [REF] Minor code refactoring.
8.0.1.0.0 (2017-06-08)
~~~~~~~~~~~~~~~~~~~~~~
* First Version of the module.

4
pos_cash_move_reason/readme/ROADMAP.rst

@ -0,0 +1,4 @@
As it is not possible to disable actions on Odoo, a new technical group is
added by this module, named 'Use Old PoS 'Put or Take Money' Actions', to
hide native obsolete actions available on the model ``pos.session``
(the two buttons "Take Money Out" and "Put Money In")

16
pos_cash_move_reason/readme/USAGE.rst

@ -0,0 +1,16 @@
* Go to your current session
* Click on the button "Put Money In" or "Take Money Out"
.. figure:: ../static/description/pos_session_form.png
* Select the reason, the journal, the amount, and optionaly an extra
description
.. figure:: ../static/description/wizard_pos_move_reason_form.png
* When closing the session, an account move will be created, with two lines,
one with the default journal account, and one with the expense / income
reason account.
.. figure:: ../static/description/account_move_form.png

3
pos_cash_move_reason/security/ir.model.access.csv

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_pos_move_reason_reader,PoS Move Reason Reader,model_pos_move_reason,point_of_sale.group_pos_user,1,0,0,0
access_pos_move_reason_manager,PoS Move Reason Manager,model_pos_move_reason,account.group_account_manager,1,1,1,1

16
pos_cash_move_reason/security/ir_rule.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019-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="ir_rule_pos_move_reason" model="ir.rule">
<field name="name">PoS Move Reasons</field>
<field name="model_id" ref="model_pos_move_reason"/>
<field name="global" eval="True" />
<field name="domain_force">['|', ('company_id', '=', user.company_id.id), ('company_id', '=', False)]</field>
</record>
</odoo>

13
pos_cash_move_reason/security/res_groups.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019-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="group_pos_old_actions" model="res.groups">
<field name="name">Use Old PoS 'Put or Take Money' Actions</field>
</record>
</odoo>

BIN
pos_cash_move_reason/static/description/account_move_form.png

After

Width: 977  |  Height: 522  |  Size: 44 KiB

BIN
pos_cash_move_reason/static/description/pos_cash_move_form.png

After

Width: 1142  |  Height: 307  |  Size: 26 KiB

BIN
pos_cash_move_reason/static/description/pos_cash_move_reason_02.png

Before

Width: 903  |  Height: 275  |  Size: 24 KiB

BIN
pos_cash_move_reason/static/description/pos_cash_move_tree.png

After

Width: 1020  |  Height: 203  |  Size: 25 KiB

BIN
pos_cash_move_reason/static/description/pos_session_form.png

After

Width: 1063  |  Height: 407  |  Size: 44 KiB

BIN
pos_cash_move_reason/static/description/wizard_pos_move_reason_form.png

After

Width: 809  |  Height: 418  |  Size: 34 KiB

1
pos_cash_move_reason/tests/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

121
pos_cash_move_reason/tests/test_pos_cash_move_reason.py

@ -1,99 +1,54 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.tests import common
from odoo.tests import common
class TestPosCashMoveReason(common.TransactionCase):
def setUp(self):
super(TestPosCashMoveReason, self).setUp()
self.pos_session_obj = self.env['pos.session']
self.aml_obj = self.env['account.move.line']
self.cash_in_obj = self.env['cash.box.in']
self.cash_out_obj = self.env['cash.box.out']
self.cash_move_reason_obj = self.env['product.template']
self.main_config = self.env.ref('point_of_sale.pos_config_main')
self.cash_journal = self.env.ref('account.cash_journal')
self.income_account = self.env.ref('account.o_income')
self.expense_account = self.env.ref('account.a_expense')
self.income_reason = self.env.ref('pos_cash_move_reason.income_reason')
self.expense_reason = self.env.ref(
'pos_cash_move_reason.expense_reason')
self.PosSession = self.env['pos.session']
self.WizardReason = self.env['wizard.pos.move.reason']
self.AccountMoveLine = self.env['account.move.line']
def test01(self):
# I set cash control on cash journal
self.cash_journal.cash_control = True
# I create and open a new session
self.session_01 = self.pos_session_obj.create(
{'config_id': self.main_config.id})
ctx = self.env.context.copy()
# context is updated in open_cb
# -> Need to call with old api to give unfrozen context
self.registry['pos.session'].open_cb(
self.cr, self.uid, [self.session_01.id], context=ctx)
ctx['active_ids'] = self.session_01.id
ctx['active_model'] = self.session_01._name
# I put the session in validation control
self.session_01.signal_workflow('cashbox_control')
ctx['active_ids'] = self.session_01.id
ctx['active_model'] = self.session_01._name
# I create a cash in
cash_in = self.cash_in_obj.with_context(ctx).create(
{'name': 'Initialization',
'product_id': self.income_reason.id,
'amount': 500.0})
cash_in.with_context(ctx).run()
# I close the session
self.session_01.signal_workflow('close')
# I get the statement from the session
statement = self.env['account.bank.statement'].search(
[('pos_session_id', '=', self.session_01.id),
('journal_id', '=', self.cash_journal.id)])
# I get all move lines of this statement
move_line_ids = statement.move_line_ids.ids
move_line = self.env['account.move.line'].search(
[('account_id', '=', self.income_account.id),
('credit', '=', 500.0),
('id', 'in', move_line_ids)])
# I check the created move line from the cash in
self.assertEquals(len(move_line.ids), 1)
self.config = self.env.ref('point_of_sale.pos_config_main').copy()
self.cash_journal = self.env['account.journal'].search([
('type', '=', 'cash'),
('company_id', '=', self.env.ref('base.main_company').id),
])[0]
self.deposit_reason = self.env.ref(
'pos_cash_move_reason.bank_out_reason')
def test_take_money(self):
# Open New Session
self.config.open_session_cb()
session = self.PosSession.search([
('state', '=', 'opened'),
('config_id', '=', self.config.id),
])
# Get Cash Statement
statement = session.statement_ids.filtered(
lambda x: x.journal_id == self.cash_journal)
# Take money to put in Bank
wizard = self.WizardReason.with_context(
active_id=session.id,
default_move_type='expense').create({
'move_reason_id': self.deposit_reason.id,
'journal_id': self.cash_journal.id,
'statement_id': statement.id,
'amount': 500,
'name': 'Test Bank Deposit',
})
wizard.apply()
session.action_pos_session_closing_control()
def test02(self):
# I set cash control on cash journal
self.cash_journal.cash_control = True
# I create and open a new session
self.session_01 = self.pos_session_obj.create(
{'config_id': self.main_config.id})
ctx = self.env.context.copy()
# context is updated in open_cb
# -> Need to call with old api to give unfrozen context
self.registry['pos.session'].open_cb(
self.cr, self.uid, [self.session_01.id], context=ctx)
ctx['active_ids'] = self.session_01.id
ctx['active_model'] = self.session_01._name
# I put the session in validation control
self.session_01.signal_workflow('cashbox_control')
ctx['active_ids'] = self.session_01.id
ctx['active_model'] = self.session_01._name
# I create a cash out
cash_out = self.cash_out_obj.with_context(ctx).create(
{'name': 'Miscellaneous expense',
'product_id': self.expense_reason.id,
'amount': 500.0})
cash_out.with_context(ctx).run()
# I close the session
self.session_01.signal_workflow('close')
# I get the statement from the session
statement = self.env['account.bank.statement'].search(
[('pos_session_id', '=', self.session_01.id),
('journal_id', '=', self.cash_journal.id)])
# I get all move lines of this statement
move_line_ids = statement.move_line_ids.ids
move_line = self.env['account.move.line'].search(
[('account_id', '=', self.expense_account.id),
[('account_id', '=', self.deposit_reason.expense_account_id.id),
('debit', '=', 500.0),
('id', 'in', move_line_ids)])
('id', 'in', statement.move_line_ids.ids)])
# I check the created move line from the cash in
self.assertEquals(len(move_line.ids), 1)

71
pos_cash_move_reason/views/view_pos_move_reason.xml

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019-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_pos_move_reason_tree" model="ir.ui.view">
<field name="model">pos.move.reason</field>
<field name="arch" type="xml">
<tree colors="gray:active == False;">
<field name="name"/>
<field name="journal_ids" widget="many2many_tags"/>
<field name="income_account_id"/>
<field name="expense_account_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<record id="view_pos_move_reason_form" model="ir.ui.view">
<field name="model">pos.move.reason</field>
<field name="arch" type="xml">
<form>
<sheet>
<div class="oe_title oe_left">
<div class="oe_edit_only">
<label for="name"/>
</div>
<h1>
<field name="name" default_focus="1" placeholder="Name"/>
</h1>
</div>
<div class="oe_right oe_button_box" name="buttons" />
<group col="4" name="description">
<field name="company_id" groups="base.group_multi_company"/>
<field name="active"/>
<field name="journal_ids" widget="many2many_tags"/>
</group>
<group col="4">
<field name="is_income_reason"/>
<field name="income_account_id" attrs="{
'required': [('is_income_reason', '=', True)],
'invisible': [('is_income_reason', '=', False)]}"/>
<field name="is_expense_reason"/>
<field name="expense_account_id" attrs="{
'required': [('is_expense_reason', '=', True)],
'invisible': [('is_expense_reason', '=', False)]}"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_pos_move_reason" model="ir.actions.act_window">
<field name="name">Move Reasons</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.move.reason</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_pos_move_reason"
parent="point_of_sale.menu_point_config_product"
action="action_pos_move_reason"
sequence="50"/>
</odoo>

51
pos_cash_move_reason/views/view_pos_session.xml

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- Add new buttons Buttons -->
<xpath expr="//sheet/div[@name='button_box']" position="inside">
<button class="oe_stat_button" name="button_move_income"
type="object" icon="fa-level-down"
attrs="{'invisible': ['|',
('display_move_reason_income', '=', False),
('state', 'not in', ['opened', 'closing_control'])]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Put</span>
<span class="o_stat_text">Money In</span>
<field name="display_move_reason_income" invisible="1"/>
</div>
</button>
<button class="oe_stat_button" name="button_move_expense"
type="object" icon="fa-level-up"
attrs="{'invisible': ['|',
('display_move_reason_expense', '=', False),
('state', 'not in', ['opened', 'closing_control'])]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Take</span>
<span class="o_stat_text">Money Out</span>
<field name="display_move_reason_expense" invisible="1"/>
</div>
</button>
</xpath>
<!-- Hide obsolete Buttons -->
<xpath expr="//button[@name='%(point_of_sale.action_pos_box_in)d']" position="attributes">
<attribute name="groups">pos_cash_move_reason.group_pos_old_actions</attribute>
</xpath>
<xpath expr="//button[@name='%(point_of_sale.action_pos_box_out)d']" position="attributes">
<attribute name="groups">pos_cash_move_reason.group_pos_old_actions</attribute>
</xpath>
</field>
</record>
<record id="point_of_sale.action_pos_box_in" model="ir.actions.act_window">
<field name="groups_id" eval="[(4, ref('pos_cash_move_reason.group_pos_old_actions'))]"/>
</record>
<record id="point_of_sale.action_pos_box_out" model="ir.actions.act_window">
<field name="groups_id" eval="[(4, ref('pos_cash_move_reason.group_pos_old_actions'))]"/>
</record>
</odoo>

6
pos_cash_move_reason/wizard/__init__.py

@ -1,5 +1 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import pos_box
from . import wizard_pos_move_reason

75
pos_cash_move_reason/wizard/pos_box.py

@ -1,75 +0,0 @@
# -*- coding: utf-8 -*-
# © 2015 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import api, exceptions, fields, _
from openerp.addons.point_of_sale.wizard.pos_box import PosBox
from lxml import etree
import simplejson
class PosBoxCashMoveReason(PosBox):
_register = False
product_id = fields.Many2one(
comodel_name='product.template', string='Reason')
@api.onchange('product_id')
def onchange_reason(self):
for record in self:
if record.product_id.id:
record.name = record.product_id.name
@api.model
def fields_view_get(self, view_id=None, view_type='form',
toolbar=False, submenu=False):
res = super(PosBoxCashMoveReason, self).fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=submenu)
doc = etree.XML(res['arch'])
if self.env.context.get('active_model', '') != 'pos.session':
for node in doc.xpath("//field[@name='product_id']"):
modifiers = {'invisible': True, 'required': False}
node.set('invisible', '1')
node.set('required', '0')
node.set('modifiers', simplejson.dumps(modifiers))
else:
for node in doc.xpath("//field[@name='name']"):
node.set('string', _('Description'))
res['arch'] = etree.tostring(doc)
return res
@api.model
def _compute_values_for_statement_line(self, box, record):
values = super(
PosBoxCashMoveReason, self)._compute_values_for_statement_line(
box, record)
if self.env.context.get('active_model', '') == 'pos.session':
product = box.product_id
account_id = False
if self._name == 'cash.box.in':
account_id = product.property_account_income.id or\
product.categ_id.property_account_income_categ.id
if not account_id:
raise exceptions.Warning(_(
"You have to define an income account on the related"
" product %s") % (product.name))
elif self._name == 'cash.box.out':
account_id = product.property_account_expense.id or\
product.categ_id.property_account_expense_categ.id
if not account_id:
raise exceptions.Warning(_(
"You have to define an expense account on the related"
" product %s") % (product.name))
values['account_id'] = account_id
return values
# the following lines are required for correct inheritance mechanism
class PosBoxIn(PosBoxCashMoveReason):
_inherit = 'cash.box.in'
class PosBoxOut(PosBoxCashMoveReason):
_inherit = 'cash.box.out'

26
pos_cash_move_reason/wizard/pos_box.xml

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp><data>
<record model="ir.ui.view" id="cash_box_in_form">
<field name="model">cash.box.in</field>
<field name="inherit_id" ref="account.cash_box_in_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<field name="product_id" required="1" class="oe_inline"
domain="[('income_pdt', '=', True)]"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="cash_box_out_form">
<field name="model">cash.box.out</field>
<field name="inherit_id" ref="account.cash_box_out_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<field name="product_id" required="1" class="oe_inline"
domain="[('expense_pdt', '=', True)]"/>
</xpath>
</field>
</record>
</data></openerp>

100
pos_cash_move_reason/wizard/wizard_pos_move_reason.py

@ -0,0 +1,100 @@
# © 2015 ACSONE SA/NV (<http://acsone.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class WizardPosMoveReason(models.TransientModel):
_name = 'wizard.pos.move.reason'
_description = 'PoS Move Reasons Wizard'
def _default_move_type(self):
return self.env.context.get('default_move_type', 'expense')
def _default_session_id(self):
return self.env.context.get('active_id', False)
_MOVE_TYPE_SELECTION = [
('income', 'Put Money In'),
('expense', 'Take Money Out'),
]
move_type = fields.Selection(
selection=_MOVE_TYPE_SELECTION, string='Move type',
default=_default_move_type)
move_reason_id = fields.Many2one(
comodel_name='pos.move.reason', string='Move Reason', required=True)
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)
statement_id = fields.Many2one(
comodel_name='account.bank.statement', string='Bank Statement',
compute='_compute_statement_id')
journal_ids = fields.Many2many(
comodel_name='account.journal', related='move_reason_id.journal_ids')
name = fields.Char(string='Reason', required=True)
amount = fields.Float(string='Amount', required=True)
@api.onchange('move_type')
def onchange_move_type(self):
if self.move_type == 'income':
return {'domain': {
'move_reason_id': [('is_income_reason', '=', True)]}}
else:
return {'domain': {
'move_reason_id': [('is_expense_reason', '=', True)]}}
@api.onchange('move_reason_id')
def onchange_reason(self):
if len(self.journal_ids) == 1:
self.journal_id = self.journal_ids[0].id
self.name = self.move_reason_id.name
@api.constrains('amount')
def _check_amount(self):
for wizard in self.filtered(lambda x: x.amount <= 0):
raise UserError(_("Invalid Amount"))
@api.depends('journal_id', 'session_id')
def _compute_statement_id(self):
for wizard in self:
if wizard.session_id and wizard.journal_id:
statements = wizard.session_id.statement_ids.filtered(
lambda x: x.journal_id == wizard.journal_id)
wizard.statement_id = statements and statements[0]
@api.multi
def apply(self):
self.ensure_one()
AccountBankStatementLine = self.env['account.bank.statement.line']
AccountBankStatementLine.create(self._prepare_statement_line())
@api.multi
def _prepare_statement_line(self):
self.ensure_one()
if self.move_type == 'income':
account = self.move_reason_id.income_account_id
amount = self.amount
else:
account = self.move_reason_id.expense_account_id
amount = - self.amount
return {
'date': fields.Datetime.now(),
'statement_id': self.statement_id.id,
'journal_id': self.journal_id.id,
'amount': amount,
'account_id': account.id,
'name': self.name,
'ref': self.session_id.name,
}

40
pos_cash_move_reason/wizard/wizard_pos_move_reason.xml

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_wizard_pos_move_reason_form" model="ir.ui.view">
<field name="model">wizard.pos.move.reason</field>
<field name="arch" type="xml">
<form>
<separator string="Fill in this form if you put money in the cash register"
attrs="{'invisible': [('move_type', '=', 'expense')]}"/>
<separator string="Describe why you take money from the cash register"
attrs="{'invisible': [('move_type', '=', 'income')]}"/>
<group>
<field name="move_type" invisible="1"/>
<field name="session_id"/>
<field name="move_reason_id" />
<field name="journal_id" attrs="{'invisible': [('move_reason_id', '=', False)]}" />
<field name="statement_id" invisible="1"/>
<field name="journal_ids" invisible="1"/>
<field name="name"/>
<field name="amount"/>
</group>
<footer>
<button name="apply" string="Apply" type="object" class="btn-primary"/>
<button class="btn-secondary" special="cancel" string="Cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_wizard_pos_move_reason" model="ir.actions.act_window">
<field name="name">Move Reasons</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">wizard.pos.move.reason</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>
Loading…
Cancel
Save