Adrien Peiffer (ACSONE)
9 years ago
committed by
Sylvain LE GAL
12 changed files with 402 additions and 0 deletions
-
62pos_cash_move_reason/README.rst
-
5pos_cash_move_reason/__init__.py
-
19pos_cash_move_reason/__openerp__.py
-
45pos_cash_move_reason/i18n/fr.po
-
43pos_cash_move_reason/i18n/pos_cash_move_reason.pot
-
BINpos_cash_move_reason/static/description/icon.png
-
BINpos_cash_move_reason/static/description/pos_cash_move_reason_02.png
-
5pos_cash_move_reason/tests/__init__.py
-
106pos_cash_move_reason/tests/test_pos_cash_move_reason.py
-
5pos_cash_move_reason/wizard/__init__.py
-
86pos_cash_move_reason/wizard/pos_box.py
-
26pos_cash_move_reason/wizard/pos_box.xml
@ -0,0 +1,62 @@ |
|||||
|
.. 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 |
||||
|
"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. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
Usage |
||||
|
===== |
||||
|
|
||||
|
You can use configured products on "Put Money In" and "Take Money Out" wizard available in point of sale session: |
||||
|
|
||||
|
.. figure:: static/description/pos_cash_move_reason_02.png |
||||
|
:alt: Take money out wizard |
||||
|
|
||||
|
|
||||
|
.. 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 |
||||
|
|
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/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**>`_. |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
* Adrien Peiffer <adrien.peiffer@acsone.eu> |
||||
|
|
||||
|
Maintainer |
||||
|
---------- |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +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 wizard |
@ -0,0 +1,19 @@ |
|||||
|
# -*- 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,' |
||||
|
'Odoo Community Association (OCA)', |
||||
|
'website': "http://acsone.eu", |
||||
|
'category': 'POS', |
||||
|
'version': '8.0.1.0.0', |
||||
|
'license': 'AGPL-3', |
||||
|
'depends': [ |
||||
|
'point_of_sale', |
||||
|
], |
||||
|
'data': [ |
||||
|
'wizard/pos_box.xml', |
||||
|
], |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * pos_cash_move_reason |
||||
|
# |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 8.0\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"POT-Creation-Date: 2016-04-12 11:10+0000\n" |
||||
|
"PO-Revision-Date: 2016-04-12 11:10+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_cash_move_reason |
||||
|
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:36 |
||||
|
#, python-format |
||||
|
msgid "Description" |
||||
|
msgstr "Description" |
||||
|
|
||||
|
#. module: pos_cash_move_reason |
||||
|
#: field:cash.box.in,product_id:0 |
||||
|
#: field:cash.box.out,product_id:0 |
||||
|
msgid "Reason" |
||||
|
msgstr "Motif" |
||||
|
|
||||
|
#. module: pos_cash_move_reason |
||||
|
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:84 |
||||
|
#, python-format |
||||
|
msgid "You have to define an\n" |
||||
|
" expense account on the related product" |
||||
|
msgstr "Vous devez définir un\n" |
||||
|
" compte de charge sur le produit lié" |
||||
|
|
||||
|
#. module: pos_cash_move_reason |
||||
|
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:60 |
||||
|
#, python-format |
||||
|
msgid "You have to define an\n" |
||||
|
" income account on the related product" |
||||
|
msgstr "Vous devez définir un\n" |
||||
|
" compte de produit sur le produit lié" |
||||
|
|
@ -0,0 +1,43 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * pos_cash_move_reason |
||||
|
# |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 8.0\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"POT-Creation-Date: 2016-04-12 11:09+0000\n" |
||||
|
"PO-Revision-Date: 2016-04-12 11:09+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_cash_move_reason |
||||
|
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:36 |
||||
|
#, python-format |
||||
|
msgid "Description" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: pos_cash_move_reason |
||||
|
#: field:cash.box.in,product_id:0 |
||||
|
#: field:cash.box.out,product_id:0 |
||||
|
msgid "Reason" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: pos_cash_move_reason |
||||
|
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:84 |
||||
|
#, python-format |
||||
|
msgid "You have to define an\n" |
||||
|
" expense account on the related product" |
||||
|
msgstr "" |
||||
|
|
||||
|
#. module: pos_cash_move_reason |
||||
|
#: code:addons/pos_cash_move_reason/wizard/pos_box.py:60 |
||||
|
#, python-format |
||||
|
msgid "You have to define an\n" |
||||
|
" income account on the related product" |
||||
|
msgstr "" |
||||
|
|
After Width: 128 | Height: 128 | Size: 9.2 KiB |
After Width: 903 | Height: 275 | Size: 24 KiB |
@ -0,0 +1,5 @@ |
|||||
|
# -*- 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 test_pos_cash_move_reason |
@ -0,0 +1,106 @@ |
|||||
|
# -*- 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 |
||||
|
|
||||
|
|
||||
|
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') |
||||
|
|
||||
|
def test01(self): |
||||
|
# I create one move reason |
||||
|
vals = {'name': 'Miscellaneous income', |
||||
|
'property_account_income': self.income_account.id, |
||||
|
'income_pdt': True} |
||||
|
move_reason = self.cash_move_reason_obj.create(vals) |
||||
|
# 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': move_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) |
||||
|
|
||||
|
def test02(self): |
||||
|
# I create one move reason |
||||
|
vals = {'name': 'Miscellaneous expense', |
||||
|
'property_account_expense': self.expense_account.id, |
||||
|
'expense_pdt': True} |
||||
|
move_reason = self.cash_move_reason_obj.create(vals) |
||||
|
# 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': move_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), |
||||
|
('debit', '=', 500.0), |
||||
|
('id', 'in', move_line_ids)]) |
||||
|
# I check the created move line from the cash in |
||||
|
self.assertEquals(len(move_line.ids), 1) |
@ -0,0 +1,5 @@ |
|||||
|
# -*- 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 |
@ -0,0 +1,86 @@ |
|||||
|
# -*- 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 |
||||
|
|
||||
|
@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 |
||||
|
|
||||
|
|
||||
|
class PosBoxIn(PosBoxCashMoveReason): |
||||
|
_inherit = 'cash.box.in' |
||||
|
|
||||
|
product_id = fields.Many2one( |
||||
|
comodel_name='product.template', string='Reason', |
||||
|
domain="[('income_pdt', '=', True)]") |
||||
|
|
||||
|
@api.model |
||||
|
def _compute_values_for_statement_line(self, box, record): |
||||
|
values = super(PosBoxIn, self)._compute_values_for_statement_line( |
||||
|
box, record) |
||||
|
if self.env.context.get('active_model', '') == 'pos.session': |
||||
|
if box.product_id.id: |
||||
|
product = box.product_id |
||||
|
account_id = product.property_account_income.id or\ |
||||
|
product.categ_id.property_account_income_categ.id |
||||
|
if account_id: |
||||
|
values['account_id'] = account_id |
||||
|
else: |
||||
|
raise exceptions.Warning(_("""You have to define an |
||||
|
income account on the related product""")) |
||||
|
return values |
||||
|
|
||||
|
|
||||
|
class PosBoxOut(PosBoxCashMoveReason): |
||||
|
_inherit = 'cash.box.out' |
||||
|
|
||||
|
product_id = fields.Many2one( |
||||
|
comodel_name='product.template', string='Reason', |
||||
|
domain="[('expense_pdt', '=', True)]") |
||||
|
|
||||
|
@api.model |
||||
|
def _compute_values_for_statement_line(self, box, record): |
||||
|
values = super(PosBoxOut, self)._compute_values_for_statement_line( |
||||
|
box, record) |
||||
|
if self.env.context.get('active_model', '') == 'pos.session': |
||||
|
if box.product_id.id: |
||||
|
product = box.product_id |
||||
|
account_id = product.property_account_expense.id or\ |
||||
|
product.categ_id.property_account_expense_categ.id |
||||
|
if account_id: |
||||
|
values['account_id'] = account_id |
||||
|
else: |
||||
|
raise exceptions.Warning(_("""You have to define an |
||||
|
expense account on the related product""")) |
||||
|
return values |
@ -0,0 +1,26 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<openerp> |
||||
|
<data> |
||||
|
<record model="ir.ui.view" id="cash_box_in_form"> |
||||
|
<field name="name">cash.box.in.form</field> |
||||
|
<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" /> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="cash_box_out_form"> |
||||
|
<field name="name">cash.box.out.form</field> |
||||
|
<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"/> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue