Browse Source

Merge PR #370 into 12.0

Signed-off-by legalsylvain
pull/417/head
OCA-git-bot 5 years ago
parent
commit
e14d6fb502
  1. 112
      pos_invoicing/README.rst
  2. 1
      pos_invoicing/__init__.py
  3. 20
      pos_invoicing/__manifest__.py
  4. 56
      pos_invoicing/i18n/fr.po
  5. 56
      pos_invoicing/i18n/pos_invoicing.pot
  6. 4
      pos_invoicing/models/__init__.py
  7. 41
      pos_invoicing/models/account_invoice.py
  8. 22
      pos_invoicing/models/account_payment.py
  9. 17
      pos_invoicing/models/pos_order.py
  10. 21
      pos_invoicing/models/pos_session.py
  11. 2
      pos_invoicing/readme/CONTRIBUTORS.rst
  12. 39
      pos_invoicing/readme/DESCRIPTION.rst
  13. BIN
      pos_invoicing/static/description/account_invoice_form.png
  14. 1
      pos_invoicing/tests/__init__.py
  15. 102
      pos_invoicing/tests/test_module.py
  16. 20
      pos_invoicing/views/view_account_invoice.xml

112
pos_invoicing/README.rst

@ -0,0 +1,112 @@
=========================
Point Of Sale - Invoicing
=========================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! 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-OCA%2Fpos-lightgray.png?logo=github
:target: https://github.com/OCA/pos/tree/12.0/pos_invoicing
:alt: OCA/pos
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/pos-12-0/pos-12-0-pos_invoicing
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/184/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module extend the Point of Sale Odoo module, regarding invoicing.
This module prevent to make some mistakes in Odoo Point of Sale
regarding invoices generated via Point of Sale.
Without this module
~~~~~~~~~~~~~~~~~~~
When an invoice generated from Point of Sale is confirmed
it is in a 'open' state, until the session is closed, and the entries are
generated. At this step, invoice will be marked as 'paid' and the related
accounting moves will be reconcilied.
So, as long as the session is not closed, any user can:
* cancel the invoice;
* register a payment;
* reconcile the invoice with an existing payment;
All that action should be prohibited because the payment exists.
With that module
~~~~~~~~~~~~~~~~
All those actions will not be possible anymore.
Note that the changes only impact the opened invoice coming from point of sale,
before the session is closed.
Technically
-----------
* add a ``pos_pending_payment`` field on the ``account.invoice`` to mark the
items that shouldn't be paid.
This field is checked when the invoice is created from point of sale,
and is unchecked, when the session is closed.
.. figure:: https://raw.githubusercontent.com/OCA/pos/12.0/pos_invoicing/static/description/account_invoice_form.png
**Table of contents**
.. contents::
:local:
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 <https://github.com/OCA/pos/issues/new?body=module:%20pos_invoicing%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* GRAP
Contributors
~~~~~~~~~~~~
* Sylvain LE GAL <https://twitter.com/legalsylvain>
* Julien WESTE
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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 `OCA/pos <https://github.com/OCA/pos/tree/12.0/pos_invoicing>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
pos_invoicing/__init__.py

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

20
pos_invoicing/__manifest__.py

@ -0,0 +1,20 @@
# Copyright (C) 2013 - Today: GRAP (http://www.grap.coop)
# @author: Julien WESTE
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Point Of Sale - Invoicing',
'summary': 'Handle invoicing from Point Of Sale',
'version': '12.0.3.0.0',
'category': 'Point of Sale',
'author': 'GRAP, Odoo Community Association (OCA)',
'website': 'http://www.github.com/OCA/pos',
'license': 'AGPL-3',
'depends': [
'point_of_sale',
],
'data': [
'views/view_account_invoice.xml',
],
'installable': True,
}

56
pos_invoicing/i18n/fr.po

@ -0,0 +1,56 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_invoicing
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-11 16:18+0000\n"
"PO-Revision-Date: 2019-07-11 16:18+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_invoicing
#: model:ir.model.fields,help:pos_invoicing.field_account_invoice__pos_pending_payment
msgid "Indicates an invoice for which there are pending payments in the Point of Sale. \n"
"The invoice will be marked as paid when the session will be closed."
msgstr "La case est cochée si il y a des paiements en cours dans le point de vente. \n"
"La facture sera marquée comme payée quand la session sera fermée."
#. module: pos_invoicing
#: model:ir.model,name:pos_invoicing.model_account_invoice
msgid "Invoice"
msgstr "Facture"
#. module: pos_invoicing
#: model:ir.model,name:pos_invoicing.model_account_payment
msgid "Payments"
msgstr "Paiements"
#. module: pos_invoicing
#: model:ir.model.fields,field_description:pos_invoicing.field_account_invoice__pos_pending_payment
msgid "PoS - Pending Payment"
msgstr "PdV - Paiement en cours"
#. module: pos_invoicing
#: model:ir.model,name:pos_invoicing.model_pos_session
msgid "Point of Sale Session"
msgstr "Session du point de vente"
#. module: pos_invoicing
#: code:addons/pos_invoicing/models/account_invoice.py:36
#: code:addons/pos_invoicing/models/account_invoice.py:38
#, python-format
msgid "You can not realize this action on the invoice(s) %s because there are pending payments in the Point of Sale."
msgstr "Vous ne pouvez pas réaliser cette action sur la / les facture(s) %s car il y a des paiements en cours dans le point de vente."
#. module: pos_invoicing
#: code:addons/pos_invoicing/models/account_payment.py:17
#, python-format
msgid "You can not realize this action on the payments(s) %s because there are pending payments in the Point of Sale."
msgstr "Vous ne pouvez pas réaliser cette action sur la / les paiement(s) %s car il y a des paiements en cours dans le point de vente."

56
pos_invoicing/i18n/pos_invoicing.pot

@ -0,0 +1,56 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_invoicing
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-11 16:17+0000\n"
"PO-Revision-Date: 2019-07-11 16:17+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_invoicing
#: model:ir.model.fields,help:pos_invoicing.field_account_invoice__pos_pending_payment
msgid "Indicates an invoice for which there are pending payments in the Point of Sale. \n"
"The invoice will be marked as paid when the session will be closed."
msgstr ""
#. module: pos_invoicing
#: model:ir.model,name:pos_invoicing.model_account_invoice
msgid "Invoice"
msgstr ""
#. module: pos_invoicing
#: model:ir.model,name:pos_invoicing.model_account_payment
msgid "Payments"
msgstr ""
#. module: pos_invoicing
#: model:ir.model.fields,field_description:pos_invoicing.field_account_invoice__pos_pending_payment
msgid "PoS - Pending Payment"
msgstr ""
#. module: pos_invoicing
#: model:ir.model,name:pos_invoicing.model_pos_session
msgid "Point of Sale Session"
msgstr ""
#. module: pos_invoicing
#: code:addons/pos_invoicing/models/account_invoice.py:36
#: code:addons/pos_invoicing/models/account_invoice.py:38
#, python-format
msgid "You can not realize this action on the invoice(s) %s because there are pending payments in the Point of Sale."
msgstr ""
#. module: pos_invoicing
#: code:addons/pos_invoicing/models/account_payment.py:17
#, python-format
msgid "You can not realize this action on the payments(s) %s because there are pending payments in the Point of Sale."
msgstr ""

4
pos_invoicing/models/__init__.py

@ -0,0 +1,4 @@
from . import pos_order
from . import pos_session
from . import account_invoice
from . import account_payment

41
pos_invoicing/models/account_invoice.py

@ -0,0 +1,41 @@
# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop)
# @author: Julien WESTE
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, api, fields, models
from odoo.exceptions import Warning as UserError
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
pos_pending_payment = fields.Boolean(
string='PoS - Pending Payment', readonly=True,
oldname='forbid_payment',
help="Indicates an invoice for which there are pending payments in the"
" Point of Sale. \nThe invoice will be marked as paid when the session"
" will be closed.")
# Overload Section
@api.multi
def action_cancel(self):
self._check_pos_pending_payment()
return super(AccountInvoice, self).action_cancel()
@api.multi
def _get_outstanding_info_JSON(self):
self.ensure_one()
if self.pos_pending_payment:
return
else:
return super()._get_outstanding_info_JSON()
@api.multi
def _check_pos_pending_payment(self):
invoices = self.filtered(lambda x: x.pos_pending_payment)
if invoices:
raise UserError(_(
"You can not realize this action on the invoice(s) %s because"
" there are pending payments in the Point of Sale.") % (
', '.join(invoices.mapped('name'))))

22
pos_invoicing/models/account_payment.py

@ -0,0 +1,22 @@
# 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).
from odoo import _, api, models
from odoo.exceptions import Warning as UserError
class AccountPayment(models.Model):
_inherit = 'account.payment'
@api.multi
def post(self):
payments = self.filtered(
lambda x: any(x.mapped('invoice_ids.pos_pending_payment')))
if payments:
raise UserError(_(
"You can not realize this action on the payments(s) %s because"
" there are pending payments in the Point of Sale.") % (
', '.join(
[x for x in payments.mapped('communication') if x])))
return super().post()

17
pos_invoicing/models/pos_order.py

@ -0,0 +1,17 @@
# Copyright (C) 2013 - Today: GRAP (http://www.grap.coop)
# @author: Julien WESTE
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models
class PosOrder(models.Model):
_inherit = 'pos.order'
def _prepare_invoice(self):
res = super()._prepare_invoice()
res.update({
'pos_pending_payment': True,
})
return res

21
pos_invoicing/models/pos_session.py

@ -0,0 +1,21 @@
# Copyright (C) 2013 - Today: GRAP (http://www.grap.coop)
# @author: Julien WESTE
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from odoo import api, models
_logger = logging.getLogger(__name__)
class PosSession(models.Model):
_inherit = 'pos.session'
@api.multi
def action_pos_session_close(self):
res = super().action_pos_session_close()
orders = self.mapped('order_ids').filtered(lambda x: x.invoice_id)
orders.mapped('invoice_id').write({'pos_pending_payment': False})
return res

2
pos_invoicing/readme/CONTRIBUTORS.rst

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

39
pos_invoicing/readme/DESCRIPTION.rst

@ -0,0 +1,39 @@
This module extend the Point of Sale Odoo module, regarding invoicing.
This module prevent to make some mistakes in Odoo Point of Sale
regarding invoices generated via Point of Sale.
Without this module
~~~~~~~~~~~~~~~~~~~
When an invoice generated from Point of Sale is confirmed
it is in a 'open' state, until the session is closed, and the entries are
generated. At this step, invoice will be marked as 'paid' and the related
accounting moves will be reconcilied.
So, as long as the session is not closed, any user can:
* cancel the invoice;
* register a payment;
* reconcile the invoice with an existing payment;
All that action should be prohibited because the payment exists.
With that module
~~~~~~~~~~~~~~~~
All those actions will not be possible anymore.
Note that the changes only impact the opened invoice coming from point of sale,
before the session is closed.
Technically
-----------
* add a ``pos_pending_payment`` field on the ``account.invoice`` to mark the
items that shouldn't be paid.
This field is checked when the invoice is created from point of sale,
and is unchecked, when the session is closed.
.. figure:: ../static/description/account_invoice_form.png

BIN
pos_invoicing/static/description/account_invoice_form.png

After

Width: 1196  |  Height: 385  |  Size: 38 KiB

1
pos_invoicing/tests/__init__.py

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

102
pos_invoicing/tests/test_module.py

@ -0,0 +1,102 @@
# Copyright (C) 2013 - Today: GRAP (http://www.grap.coop)
# @author: Julien WESTE
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields
from odoo.tests.common import TransactionCase
from odoo.exceptions import Warning as UserError
class TestModule(TransactionCase):
def setUp(self):
super(TestModule, self).setUp()
# Get Registry
self.PosOrder = self.env['pos.order']
self.AccountPayment = self.env['account.payment']
# Get Object
self.pos_product = self.env.ref('point_of_sale.whiteboard_pen')
self.pricelist = self.env.ref('product.list0')
self.partner = self.env.ref('base.res_partner_12')
# Create a new pos config and open it
self.pos_config = self.env.ref('point_of_sale.pos_config_main').copy()
self.pos_config.open_session_cb()
# Test Section
def test_order_invoice(self):
order = self._create_order()
# Check if invoice is correctly set
self.assertEquals(order.invoice_id.pos_pending_payment, True)
# Try to register payment should fail on this invoice should fail
with self.assertRaises(UserError):
payment = self.register_payment(order.invoice_id)
payment.post()
# Try to register a payment not linked to this invoice should be ok
payment = self.register_payment()
payment.post()
# Once closed check if the invoice is correctly set
self.pos_config.current_session_id.action_pos_session_closing_control()
self.assertEquals(order.invoice_id.pos_pending_payment, False)
# Private Section
def register_payment(self, invoice_id=False):
journal = self.pos_config.journal_ids[0]
return self.AccountPayment.create({
'invoice_ids': invoice_id and [(4, invoice_id.id, None)] or False,
'payment_type': 'inbound',
'partner_type': 'customer',
'payment_date': fields.Datetime.now(),
'partner_id': self.partner.id,
'amount': 0.9,
'journal_id': journal.id,
'payment_method_id': journal.inbound_payment_method_ids[0].id,
})
def _create_order(self):
# Create order
order_data = {
'id': u'0006-001-0010',
'to_invoice': True,
'data': {
'pricelist_id': self.pricelist.id,
'user_id': 1,
'name': 'Order 0006-001-0010',
'partner_id': self.partner.id,
'amount_paid': 0.9,
'pos_session_id': self.pos_config.current_session_id.id,
'lines': [[0, 0, {
'product_id': self.pos_product.id,
'price_unit': 0.9,
'qty': 1,
'price_subtotal': 0.9,
'price_subtotal_incl': 0.9,
}]],
'statement_ids': [[0, 0, {
'journal_id': self.pos_config.journal_ids[0].id,
'amount': 0.9,
'name': fields.Datetime.now(),
'account_id':
self.env.user.partner_id.property_account_receivable_id.id,
'statement_id':
self.pos_config.current_session_id.statement_ids[0].id,
}]],
'creation_date': u'2018-09-27 15:51:03',
'amount_tax': 0,
'fiscal_position_id': False,
'uid': u'00001-001-0001',
'amount_return': 0,
'sequence_number': 1,
'amount_total': 0.9,
}}
result = self.PosOrder.create_from_ui([order_data])
order = self.PosOrder.browse(result[0])
return order

20
pos_invoicing/views/view_account_invoice.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2013 - Today: GRAP (http://www.grap.coop)
@author Julien WESTE
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="view_account_invoice_form" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<field name="reference" position="after">
<field name="pos_pending_payment"/>
</field>
</field>
</record>
</odoo>
Loading…
Cancel
Save