Browse Source

[ADD] new module pos_store_draft_order (#49)

* [ADD] new module pos_slate;

* [REF] change file headers according to the new name of the module;

* [FIX] bad terminology;

* [REF] Oca convention;

* [REF] remove useless headers in init files, to reduce the size of the cloud;

* [REF] use new API;
[REF] move documentation from openerp manifest file to readme rst file;
[ADD] screenshot images and some sentences to describe the module;

* [FIX] bad folder for images;

* [FIX] readme file;

* [REF] improve description;

* [FIX] description;

* [REF] rename module and improve tests;

* [FIX] flake8
pull/183/head
Sylvain LE GAL 7 years ago
committed by Rafael Blasco
parent
commit
8a32f9af08
  1. 109
      pos_store_draft_order/README.rst
  2. 2
      pos_store_draft_order/__init__.py
  3. 41
      pos_store_draft_order/__openerp__.py
  4. 24
      pos_store_draft_order/demo/pos_config.yml
  5. 48
      pos_store_draft_order/i18n/fr.po
  6. 51
      pos_store_draft_order/i18n/pos_store_draft_order.pot
  7. 4
      pos_store_draft_order/model/__init__.py
  8. 36
      pos_store_draft_order/model/pos_config.py
  9. 40
      pos_store_draft_order/model/pos_order.py
  10. 67
      pos_store_draft_order/model/pos_session.py
  11. BIN
      pos_store_draft_order/static/description/1_before_closing.png
  12. BIN
      pos_store_draft_order/static/description/2_after_closing.png
  13. BIN
      pos_store_draft_order/static/description/3_after_opening.png
  14. BIN
      pos_store_draft_order/static/description/icon.png
  15. BIN
      pos_store_draft_order/static/description/pos_order_states.png
  16. 2
      pos_store_draft_order/tests/__init__.py
  17. 95
      pos_store_draft_order/tests/test_pos_store_draft_order.py
  18. 49
      pos_store_draft_order/view/view.xml

109
pos_store_draft_order/README.rst

@ -0,0 +1,109 @@
.. 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
==================================
Point Of Sale - Store Draft Orders
==================================
Allow to close a Session even if there are some PoS Orders in draft state.
By default, in Odoo, All PoS Orders must be in 'paid' or 'invoiced' state to
allow user to close the session.
This module can be usefull to let Orders in draft 'state' for some customers.
Feature
-------
1. New computed field 'is_partial_paid' on PoS Order
* This field is True, if the PoS order is in a draft state with some
payments;
* Forbid to close a session if there is a partial paid Order, to avoid to have
Account Move Lines that can not be reconciled;
* In the tree view, the partial_paid orders are displayed in red colors;
.. image:: ./static/description/pos_order_states.png
:alt: Blue, red and black orders depending of payments.
2. Possibility to close session
* if a PoS order is in a 'draft' state (without any payment), the PoS Order
will be unassociated to the current session, when closing the session;
* When opening a new session, the PoS Orders in 'draft' state will be
associated to the new session, based on the user_id;
**Workflow**
* The PoS order 'Main/0004' is in draft state, before closing the session
.. image:: ./static/description/1_before_closing.png
* The PoS order is unassociated of the closed session 'POS/2015/09/05/01'
.. image:: ./static/description/2_after_closing.png
* The PoS order is associated to the new opened session 'POS/2015/09/05/02'
.. image:: ./static/description/3_after_opening.png
Installation
============
This module will allow users to let orders in a draft state, only for orders
created in back-office.
If you want the same feature for the front-office PoS, please install both
modules : 'pos_store_draft_order' and 'pos_order_load'.
Configuration
=============
* A new field 'allow_store_draft_order' is available in PoS Config Model, to
allow or block the cashier to let Orders in a draft state when closing
session;
Usage
=====
To use this module, you need to:
* go to ...
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/xxxx/8.0
For further information, please visit:
* https://www.odoo.com/forum/help-1
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_store_draft_order%0Aversion:%208.0.1.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Sylvain LE GAL (https://twitter.com/legalsylvain)
* Julien WESTE
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 http://odoo-community.org.

2
pos_store_draft_order/__init__.py

@ -0,0 +1,2 @@
# -*- encoding: utf-8 -*-
from . import model

41
pos_store_draft_order/__openerp__.py

@ -0,0 +1,41 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Point Of Sale - Store Draft Orders Module for Odoo
# Copyright (C) 2013-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Point Of Sale - Store Draft Orders',
'version': '8.0.1.0.0',
'category': 'Point of Sale',
'summary': "Allow users to close session with Draft Orders",
'author': 'GRAP,Odoo Community Association (OCA)',
'website': 'http://www.odoo-community.org',
'license': 'AGPL-3',
'depends': [
'point_of_sale',
],
'data': [
'view/view.xml',
],
'demo': [
'demo/pos_config.yml',
],
}

24
pos_store_draft_order/demo/pos_config.yml

@ -0,0 +1,24 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Point Of Sale - Store Draft Orders Module for Odoo
# Copyright (C) 2015-Today GRAP (http://www.grap.coop)
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
- !record {model: pos.config, id: point_of_sale.pos_config_main}:
allow_store_draft_order: True

48
pos_store_draft_order/i18n/fr.po

@ -0,0 +1,48 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_store_draft_order
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-19 11:47+0000\n"
"PO-Revision-Date: 2015-10-19 11:47+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_store_draft_order
#: field:pos.config,allow_store_draft_order:0
msgid "Allow to Store Draft Orders"
msgstr "Autoriser les ardoises"
#. module: pos_store_draft_order
#: help:pos.config,allow_store_draft_order:0
msgid "If you check this field, users will have the possibility to let some PoS orders in a draft state, and allow the customer to paid later.\n"
"Order in a draft state will not generate entries during the close of the session."
msgstr "Si vous cochez cette case, les utilisateurs auront la possibilité de laisser certaines ventes à l'état de brouillon, et autorisera le client à payer plus tard.\n"
"Ces ventes à l'état de brouillon ne génèrent pas d'écritures comptables lors de la clôture de la session."
#. module: pos_store_draft_order
#: field:pos.order,is_partial_paid:0
msgid "Is Partially Paid"
msgstr "Est partiellement payée"
#. module: pos_store_draft_order
#: model:ir.model,name:pos_store_draft_order.model_pos_order
msgid "Point of Sale"
msgstr "Point de Vente"
#. module: pos_store_draft_order
#: code:addons/pos_store_draft_order/model/pos_session.py:63
#, python-format
msgid "You cannot confirm this session, because '%s' is still in 'draft' state with associated payments.\n"
"\n"
" Please finish to pay this Order first."
msgstr "Vous ne pouvez pas fermer cette session car '%s' est en brouillon avec des paiments.\n"
"\n"
"Merci de compléter les paiments."

51
pos_store_draft_order/i18n/pos_store_draft_order.pot

@ -0,0 +1,51 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_store_draft_order
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-19 11:52+0000\n"
"PO-Revision-Date: 2015-10-19 11:52+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_store_draft_order
#: field:pos.config,allow_store_draft_order:0
msgid "Allow to Store Draft Orders"
msgstr ""
#. module: pos_store_draft_order
#: help:pos.config,allow_store_draft_order:0
msgid "If you check this field, users will have the possibility to let some PoS orders in a draft state, and allow the customer to paid later.\n"
"Order in a draft state will not generate entries during the close of the session."
msgstr ""
#. module: pos_store_draft_order
#: field:pos.order,is_partial_paid:0
msgid "Is Partially Paid"
msgstr ""
#. module: pos_store_draft_order
#: model:ir.model,name:pos_store_draft_order.model_pos_order
msgid "Point of Sale"
msgstr ""
#. module: pos_store_draft_order
#: code:addons/pos_store_draft_order/model/pos_session.py:63
#, python-format
msgid "You cannot confirm this session, because '%s' is still in 'draft' state with associated payments.\n"
"\n"
" Please finish to pay this Order first."
msgstr ""
#. module: pos_store_draft_order
#: view:pos.order:pos_store_draft_order.pos_order_view_form
msgid "red: is_partial_paid==True; blue: state=='draft'; gray: state in ('done','cancel'); black: state not in ('done','cancel')"
msgstr ""

4
pos_store_draft_order/model/__init__.py

@ -0,0 +1,4 @@
# -*- encoding: utf-8 -*-
from . import pos_order
from . import pos_session
from . import pos_config

36
pos_store_draft_order/model/pos_config.py

@ -0,0 +1,36 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Point Of Sale - Store Draft Orders Module for Odoo
# Copyright (C) 2013-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import fields, models
class PosConfig(models.Model):
_inherit = 'pos.config'
# Column Section
allow_store_draft_order = fields.Boolean(
string='Allow to Store Draft Orders', help="If you check this field,"
" users will have the possibility to let some PoS orders in a draft"
" state, and allow the customer to paid later.\n"
"Order in a draft state will not generate entries during the close"
" of the session.")

40
pos_store_draft_order/model/pos_order.py

@ -0,0 +1,40 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Point Of Sale - Store Draft Orders Module for Odoo
# Copyright (C) 2013-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api, fields, models
class PosOrder(models.Model):
_inherit = 'pos.order'
# Column Section
is_partial_paid = fields.Boolean(
string='Is Partially Paid', compute='compute_is_partial_paid',
store=True)
# Compute Section
@api.one
@api.depends('state', 'statement_ids')
def compute_is_partial_paid(self):
self.is_partial_paid =\
(self.state == 'draft') and len(self.statement_ids) != 0

67
pos_store_draft_order/model/pos_session.py

@ -0,0 +1,67 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Point Of Sale - Store Draft Orders Module for Odoo
# Copyright (C) 2013-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api, models
from openerp.exceptions import Warning
from openerp.tools.translate import _
class PosSession(models.Model):
_inherit = 'pos.session'
# Overload Section
@api.model
def create(self, vals):
"""Recover all PoS Order in 'draft' state and associate them to the new
Pos Session"""
order_obj = self.env['pos.order']
res = super(PosSession, self).create(vals)
draftOrders = order_obj.search([
('state', '=', 'draft'), ('user_id', '=', self._uid)])
draftOrders.write({'session_id': res.id})
return res
@api.multi
def wkf_action_closing_control(self):
"""Remove all PoS Orders in 'draft' to the sessions we want
to close.
Check if there is any Partial Paid Orders"""
self._remove_session_from_draft_orders()
return super(PosSession, self).wkf_action_closing_control()
# Custom Section
@api.one
def _remove_session_from_draft_orders(self):
for order in self.order_ids:
# Check if there is a partial payment
if order.is_partial_paid:
raise Warning(_(
"You cannot confirm this session, because '%s' is"
" still in 'draft' state with associated payments.\n\n"
" Please finish to pay this Order first." % (order.name)))
# remove session id on the current Order if it is in draft state
if order.state == 'draft' and\
self.config_id.allow_store_draft_order:
order.write({'session_id': False})

BIN
pos_store_draft_order/static/description/1_before_closing.png

After

Width: 1100  |  Height: 151  |  Size: 23 KiB

BIN
pos_store_draft_order/static/description/2_after_closing.png

After

Width: 1104  |  Height: 152  |  Size: 23 KiB

BIN
pos_store_draft_order/static/description/3_after_opening.png

After

Width: 1106  |  Height: 151  |  Size: 27 KiB

BIN
pos_store_draft_order/static/description/icon.png

After

Width: 64  |  Height: 64  |  Size: 4.4 KiB

BIN
pos_store_draft_order/static/description/pos_order_states.png

After

Width: 1101  |  Height: 119  |  Size: 19 KiB

2
pos_store_draft_order/tests/__init__.py

@ -0,0 +1,2 @@
# -*- encoding: utf-8 -*-
from . import test_pos_store_draft_order

95
pos_store_draft_order/tests/test_pos_store_draft_order.py

@ -0,0 +1,95 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# Point Of Sale - Store Draft Orders Module for Odoo
# Copyright (C) 2015-Today GRAP (http://www.grap.coop)
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.exceptions import Warning
from openerp.tests.common import TransactionCase
class TestPosStoreDraftOrder(TransactionCase):
def setUp(self):
super(TestPosStoreDraftOrder, self).setUp()
self.session_obj = self.env['pos.session']
self.order_obj = self.env['pos.order']
self.pos_config_id = self.ref('point_of_sale.pos_config_main')
self.product_id = self.ref('product.product_product_48')
self.cash_journal_id = self.ref('account.cash_journal')
# Test Section
def test_01_allow_draft_order_unpaid(self):
"""Test the possibility to let a PoS Order in a draft state if it is
not paid at all."""
# Open a new session
session_1 = self.session_obj.create({'config_id': self.pos_config_id})
# Create Order
order = self.order_obj.create({
'session_id': session_1.id,
'lines': [[0, False, {
'discount': 0,
'price_unit': 10,
'product_id': self.product_id,
'qty': 1}]]
})
# Close Session
session_1.signal_workflow('close')
self.assertEquals(
session_1.state, 'closed',
"Unpaid Draft Orders must not block the closing process of the"
" associated session.")
# Open a second session
session_2 = self.session_obj.create({'config_id': self.pos_config_id})
self.assertEquals(
order.session_id.id, session_2.id,
"Draft Orders of a previous session must be associated to the"
" new opened session to allow payment.")
# Test Section
def test_02_block_draft_order_partial_paid(self):
"""Test the unpossibility to let a PoS Order in a draft state if it is
in a partial paid state."""
# Open a new session
session_1 = self.session_obj.create({'config_id': self.pos_config_id})
# Create Order
order = self.order_obj.create({
'session_id': session_1.id,
'lines': [[0, False, {
'discount': 0,
'price_unit': 10,
'product_id': self.product_id,
'qty': 3}]]
})
# Make partial payment
self.order_obj.add_payment(
order.id, {'amount': 1, 'journal': self.cash_journal_id})
# Try Close Session (Must fail)
with self.assertRaises(Warning):
session_1.signal_workflow('close')

49
pos_store_draft_order/view/view.xml

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Point Of Sale - Store Draft Orders Module for Odoo -->
<!--Copyright (C) 2015-Today GRAP (http://www.grap.coop) -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<openerp>
<data>
<!-- Model: pos.order -->
<record id="pos_order_view_form" model="ir.ui.view">
<field name="model">pos.order</field>
<field name="inherit_id" ref="point_of_sale.view_pos_order_tree"/>
<field name="arch" type="xml">
<field name="state" position="after">
<field name="is_partial_paid" invisible="1" />
</field>
<xpath expr="//tree[@string='POS Orders']" position="attributes">
<attribute name="colors">red: is_partial_paid==True; blue: state=='draft'; gray: state in ('done','cancel'); black: state not in ('done','cancel')</attribute>
</xpath>
</field>
</record>
<!-- Model: pos.config -->
<record id="pos_config_view_form" model="ir.ui.view">
<field name="model">pos.config</field>
<field name="inherit_id" ref="point_of_sale.view_pos_config_form"/>
<field name="arch" type="xml">
<field name="group_by" position="after">
<field name="allow_store_draft_order"/>
</field>
</field>
</record>
</data>
</openerp>
Loading…
Cancel
Save