diff --git a/pos_change_payment/README.rst b/pos_change_payment/README.rst new file mode 100644 index 00000000..c71d715e --- /dev/null +++ b/pos_change_payment/README.rst @@ -0,0 +1,91 @@ +=============================== +Point Of Sale - Payments Change +=============================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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-grap%2Fgrap--odoo--incubator-lightgray.png?logo=github + :target: https://github.com/grap/grap-odoo-incubator/tree/8.0/pos_change_payment + :alt: grap/grap-odoo-incubator + +|badge1| |badge2| |badge3| + +Improve payment changes when user did a mistake and disable some actions on +Point of Sale Bank Statement Line + +* Add the possibility to switch a payment (account.bank.statement.line) + of an order from a journal to another. This feature is usefull when + the user realized that he did a mistake, during the close of the session, + or just after he marked the order as paid + (Only if entries has not been generated) + +.. figure:: https://raw.githubusercontent.com/grap/grap-odoo-incubator/8.0/pos_change_payment/static/description/pos_order_switch_payment.png + +* Add the possibility to change all payments (method and amount) of a POS + (Only if entries has not been generated) + +.. figure:: https://raw.githubusercontent.com/grap/grap-odoo-incubator/8.0/pos_change_payment/static/description/pos_order_change_payments.png + +Bug Fixes / Improvement +~~~~~~~~~~~~~~~~~~~~~~~ + +* In the pos.payment wizard, display only the payment methods defined in + the current POS session + +* Disable the possibility to edit / delete a bank statement line on a POS + Order that has generated his entries, except using the wizard of this + module. This will prevent the generation of bad account move during + the close of the session; (mainly unbalanced moves) + +* All the cash payment are merged into a single one statement line. This + feature is usefull if the user use OpenERP as a calculator, writing + for a payment: + +1. Payment 1/ Cash 50 €; +2. Payment 2/ Cash -3,56 €; +3. With this module, the final statement line is a single line Payment 1/ Cash 46,44 € + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* GRAP + +Contributors +~~~~~~~~~~~~ + +* Sylvain LE GAL +* Julien WESTE + +Maintainers +~~~~~~~~~~~ + +This module is part of the `grap/grap-odoo-incubator `_ project on GitHub. + +You are welcome to contribute. diff --git a/pos_change_payment/__init__.py b/pos_change_payment/__init__.py new file mode 100644 index 00000000..1ff6b9e1 --- /dev/null +++ b/pos_change_payment/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from . import models diff --git a/pos_change_payment/__openerp__.py b/pos_change_payment/__openerp__.py new file mode 100644 index 00000000..f9bc6956 --- /dev/null +++ b/pos_change_payment/__openerp__.py @@ -0,0 +1,23 @@ +# coding: utf-8 +# Copyright (C) 2013 - 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). +{ + 'name': 'Point Of Sale - Payments Change', + 'version': '8.0.1.0.0', + 'category': 'Point Of Sale', + 'author': 'GRAP', + 'website': 'http://www.grap.coop', + 'license': 'AGPL-3', + 'depends': [ + 'point_of_sale', + ], + 'data': [ + 'views/action.xml', + 'views/view_account_bank_statement.xml', + 'views/view_pos_change_payments_wizard.xml', + 'views/view_pos_order.xml', + 'views/view_pos_switch_journal_wizard.xml', + ], + 'installable': True, +} diff --git a/pos_change_payment/i18n/fr.po b/pos_change_payment/i18n/fr.po new file mode 100644 index 00000000..2a1d7bac --- /dev/null +++ b/pos_change_payment/i18n/fr.po @@ -0,0 +1,168 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * pos_change_payment +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-01 14:25+0000\n" +"PO-Revision-Date: 2015-04-01 14:25+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_change_payment +#: field:pos.change.payments.wizard.line,amount:0 +#: field:pos.switch.journal.wizard,amount:0 +msgid "Amount" +msgstr "Montant" + +#. module: pos_change_payment +#: code:_description:0 +#: model:ir.model,name:pos_change_payment.model_account_bank_statement_line +#, python-format +msgid "Bank Statement Line" +msgstr "Ligne de relevé de banque" + +#. module: pos_change_payment +#: view:pos.change.payments.wizard:0 +#: view:pos.switch.journal.wizard:0 +msgid "Cancel" +msgstr "Annuler" + +#. module: pos_change_payment +#: model:ir.actions.act_window,name:pos_change_payment.action_pos_change_payments_wizard +#: view:pos.change.payments.wizard:0 +#: view:pos.order:0 +msgid "Change Payments" +msgstr "Changer les paiements" + +#. module: pos_change_payment +#: code:addons/pos_change_payment/model/pos_change_payments_wizard.py:77 +#, python-format +msgid "Differences between the two values for the POS Order '%s':\n" +"\n" +" * Total of all the new payments %s;\n" +" * Total of the POS Order %s;\n" +"\n" +"Please change the payments." +msgstr "Différences entre les deux valeurs pour la vente '%s':\n" +"\n" +" * Total des nouveaux paiements %s;\n" +" * Total de la vente %s;\n" +"\n" +"Veuillez changer les paiements." + +#. module: pos_change_payment +#: code:addons/pos_change_payment/model/account_bank_statement_line.py:78 +#: code:addons/pos_change_payment/model/pos_change_payments_wizard.py:36 +#: code:addons/pos_change_payment/model/pos_change_payments_wizard.py:72 +#: code:addons/pos_change_payment/model/pos_order.py:76 +#: code:addons/pos_change_payment/model/pos_switch_journal_wizard.py:64 +#, python-format +msgid "Error!" +msgstr "Erreur !" + +#. module: pos_change_payment +#: code:addons/pos_change_payment/model/pos_change_payments_wizard.py:36 +#: code:addons/pos_change_payment/model/pos_switch_journal_wizard.py:64 +#, python-format +msgid "Incorrect Call!" +msgstr "Appel incorrect !" + +#. module: pos_change_payment +#: code:_description:0 +#: model:ir.model,name:pos_change_payment.model_account_journal +#: field:pos.change.payments.wizard.line,journal_id:0 +#, python-format +msgid "Journal" +msgstr "Journal" + +#. module: pos_change_payment +#: field:pos.switch.journal.wizard,new_statement_id:0 +msgid "New Journal" +msgstr "Nouveau journal" + +#. module: pos_change_payment +#: field:pos.switch.journal.wizard,old_journal_id:0 +msgid "Old Journal" +msgstr "Ancien journal" + +#. module: pos_change_payment +#: field:pos.change.payments.wizard,order_id:0 +msgid "POS Order" +msgstr "Vente" + +#. module: pos_change_payment +#: view:pos.order:0 +msgid "Payment" +msgstr "Paiement" + +#. module: pos_change_payment +#: view:pos.change.payments.wizard:0 +msgid "Payment Lines" +msgstr "Lignes de paiement" + +#. module: pos_change_payment +#: code:_description:0 +#: model:ir.model,name:pos_change_payment.model_pos_order +#, python-format +msgid "Point of Sale" +msgstr "Point de Vente" + +#. module: pos_change_payment +#: code:_description:0 +#: model:ir.model,name:pos_change_payment.model_pos_make_payment +#, python-format +msgid "Point of Sale Payment" +msgstr "Paiement du ticket" + +#. module: pos_change_payment +#: field:pos.switch.journal.wizard,statement_line_id:0 +msgid "Statement" +msgstr "Relevé bancaire" + +#. module: pos_change_payment +#: view:account.bank.statement:0 +#: model:ir.actions.act_window,name:pos_change_payment.action_pos_switch_journal_wizard +#: view:pos.order:0 +#: view:pos.switch.journal.wizard:0 +msgid "Switch Journal" +msgstr "Changer de Journal" + +#. module: pos_change_payment +#: field:pos.change.payments.wizard,amount_total:0 +msgid "Total" +msgstr "Total" + +#. module: pos_change_payment +#: field:pos.change.payments.wizard,line_ids:0 +msgid "Wizard Lines" +msgstr "Lignes" + +#. module: pos_change_payment +#: field:pos.change.payments.wizard.line,wizard_id:0 +msgid "Wizard Ref" +msgstr "Référence" + +#. module: pos_change_payment +#: code:addons/pos_change_payment/model/account_bank_statement_line.py:79 +#, python-format +msgid "You can not change payments of POS by this way. Please use the regular wizard in POS view!" +msgstr "Vous ne pouvez pas changer les paiements de cette vente de cette façon. Veuillez utiliser l'interface prévue à cet effet dans la vue de la vente !" + +#. module: pos_change_payment +#: code:addons/pos_change_payment/model/pos_order.py:78 +#, python-format +msgid "You can not change payments of the POS '%s' because the associated session '%s' has been closed!" +msgstr "Vous ne pouvez pas changer les paiements de la Vente '%s' car la session associée '%s' a été clôturé !" + +#. module: pos_change_payment +#: view:pos.change.payments.wizard:0 +#: view:pos.switch.journal.wizard:0 +msgid "or" +msgstr "ou" diff --git a/pos_change_payment/models/__init__.py b/pos_change_payment/models/__init__.py new file mode 100644 index 00000000..4b15774d --- /dev/null +++ b/pos_change_payment/models/__init__.py @@ -0,0 +1,9 @@ +# coding: utf-8 + +from . import pos_order +from . import account_bank_statement_line +from . import pos_make_payment + +from . import pos_switch_journal_wizard +from . import pos_change_payments_wizard +from . import pos_change_payments_wizard_line diff --git a/pos_change_payment/models/account_bank_statement_line.py b/pos_change_payment/models/account_bank_statement_line.py new file mode 100644 index 00000000..b668e6db --- /dev/null +++ b/pos_change_payment/models/account_bank_statement_line.py @@ -0,0 +1,66 @@ +# coding: utf-8 +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from openerp import _, api, models +from openerp.exceptions import ValidationError + + +class AccountBankStatementLine(models.Model): + _inherit = 'account.bank.statement.line' + + _POS_PAYMENT_ALLOW_WRITE = [ + 'sequence', 'journal_entry_id', + ] + + # Private Function Section + @api.multi + def _check_allow_change_pos_payment(self, vals): + """Allow or block change of account bank statement line, linked to + a non draft POS Order. + * if 'change_pos_payment' is in the context, changes are allowed; + * otherwise: + * allow write of some fields only; + * forbid deletion;""" + values = vals.copy() if vals else {} + check_pos_order = False + + if values: + # Allow some write + for key in self._POS_PAYMENT_ALLOW_WRITE: + if key in values: + del values[key] + if not values: + return + + # Allow changes, if user use the wizard + if self._context.get('change_pos_payment', False): + check_pos_order = True + + for statement_line in self: + order = statement_line.pos_statement_id + if order: + if order.state != 'draft': + if check_pos_order: + order._allow_change_payments() + else: + if values.keys() == ['partner_id']: + order._allow_change_payments() + else: + raise ValidationError(_( + "You can not change payments of POS by this" + " way. Please use the regular wizard in POS" + " view!")) + + # Overload Section + @api.multi + def write(self, vals): + self._check_allow_change_pos_payment(vals) + return super(AccountBankStatementLine, self).write(vals) + + @api.multi + def unlink(self): + self._check_allow_change_pos_payment(None) + return super(AccountBankStatementLine, self).unlink() diff --git a/pos_change_payment/models/pos_change_payments_wizard.py b/pos_change_payment/models/pos_change_payments_wizard.py new file mode 100644 index 00000000..a34ef4b1 --- /dev/null +++ b/pos_change_payment/models/pos_change_payments_wizard.py @@ -0,0 +1,72 @@ +# coding: utf-8 +# Copyright (C) 2015-Today GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import _, api, fields, models +from openerp.exceptions import Warning as UserError + + +class PosChangePaymentsWizard(models.TransientModel): + _name = 'pos.change.payments.wizard' + + # Column Section + order_id = fields.Many2one( + comodel_name='pos.order', string='Order', readonly=True) + + session_id = fields.Many2one( + comodel_name='pos.session', string='Session', readonly=True) + + line_ids = fields.One2many( + comodel_name='pos.change.payments.wizard.line', + inverse_name='wizard_id', string='Payment Lines') + + amount_total = fields.Float(string='Total', readonly=True) + + # View Section + @api.model + def default_get(self, fields): + order_obj = self.env['pos.order'] + res = super(PosChangePaymentsWizard, self).default_get(fields) + order = order_obj.browse(self._context.get('active_id')) + res.update({'order_id': order.id}) + res.update({'session_id': order.session_id.id}) + res.update({'amount_total': order.amount_total}) + return res + + # View section + @api.multi + def button_change_payments(self): + self.ensure_one() + order = self.order_id + + # Check if the total is correct + total = 0 + for line in self.line_ids: + total += line.amount + if total != self.amount_total: + raise UserError(_( + "Differences between the two values for the POS" + " Order '%s':\n\n" + " * Total of all the new payments %s;\n" + " * Total of the POS Order %s;\n\n" + "Please change the payments." % ( + order.name, total, order.amount_total))) + + # Check if change payments is allowed + order._allow_change_payments() + + # Remove old statements + order.statement_ids.with_context(change_pos_payment=True).unlink() + + # Create new payment + for line in self.line_ids: + order.add_payment_v8({ + 'journal': line.new_journal_id.id, + 'amount': line.amount, + }) + + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } diff --git a/pos_change_payment/models/pos_change_payments_wizard_line.py b/pos_change_payment/models/pos_change_payments_wizard_line.py new file mode 100644 index 00000000..b9f62f41 --- /dev/null +++ b/pos_change_payment/models/pos_change_payments_wizard_line.py @@ -0,0 +1,25 @@ +# coding: utf-8 +# Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class PosChangePaymentsWizardLine(models.TransientModel): + _name = 'pos.change.payments.wizard.line' + + wizard_id = fields.Many2one( + comodel_name='pos.change.payments.wizard', ondelete='cascade') + + new_journal_id = fields.Many2one( + comodel_name='account.journal', string='Journal', required=True, + domain=lambda s: s._domain_new_journal_id()) + + amount = fields.Float(string='Amount', required=True) + + @api.model + def _domain_new_journal_id(self): + PosOrder = self.env['pos.order'] + order = PosOrder.browse(self.env.context.get('active_id')) + return [('id', 'in', order.session_id.journal_ids.ids)] diff --git a/pos_change_payment/models/pos_make_payment.py b/pos_change_payment/models/pos_make_payment.py new file mode 100644 index 00000000..85b605af --- /dev/null +++ b/pos_change_payment/models/pos_make_payment.py @@ -0,0 +1,25 @@ +# coding: utf-8 +# Copyright (C) 2015-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 openerp import api, models, fields + + +class PosMakePayment(models.TransientModel): + _inherit = 'pos.make.payment' + + # # Column Section (Overload) + journal_id = fields.Many2one( + default=False, + domain=lambda s: s._domain_journal_id()) + + @api.model + def _domain_journal_id(self): + session_obj = self.env['pos.session'] + if self.env.context.get('pos_session_id', False): + session = session_obj.browse( + int(self._context.get('pos_session_id'))) + return [('id', 'in', session.journal_ids.ids)] + return [] diff --git a/pos_change_payment/models/pos_order.py b/pos_change_payment/models/pos_order.py new file mode 100644 index 00000000..e1c32ee0 --- /dev/null +++ b/pos_change_payment/models/pos_order.py @@ -0,0 +1,57 @@ +# coding: utf-8 +# Copyright (C) 2015 - 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 openerp import _, api, models +from openerp.exceptions import Warning as UserError + + +class PosOrder(models.Model): + _inherit = 'pos.order' + + # Overload Section + @api.multi + def action_paid(self): + """ Merge all cash statement line of the Order""" + self._merge_cash_payment() + return super(PosOrder, self).action_paid() + + @api.multi + def add_payment_v8(self, data): + """Hack to call old api. TODO-V10 : remove me.""" + for order in self: + self.pool['pos.order'].add_payment( + self._cr, self._uid, order.id, data, context=self._context) + return True + + # Private Function Section + @api.multi + def _merge_cash_payment(self): + for order in self: + cash_statements = order.statement_ids.filtered( + lambda x: x.journal_id.type == 'cash') + if len(cash_statements) < 2: + continue + + main_statement = cash_statements[0] + cash_total = sum(cash_statements.mapped('amount')) + + # Unlink all statements except one + cash_statements.filtered( + lambda x: x.id != main_statement.id).unlink() + main_statement.write({'amount': cash_total}) + + @api.multi + def _allow_change_payments(self): + """Return True if the user can change the payment of a POS, depending + of the state of the current session.""" + closed_orders = self.filtered( + lambda x: x.session_id.state == 'closed') + if len(closed_orders): + raise UserError(_( + "You can not change payments of the POS '%s' because" + " the associated session '%s' has been closed!" % ( + ', '.join(closed_orders.mapped('name')), + ', '.join(closed_orders.mapped('session_id.name'))))) diff --git a/pos_change_payment/models/pos_switch_journal_wizard.py b/pos_change_payment/models/pos_switch_journal_wizard.py new file mode 100644 index 00000000..ec9cb277 --- /dev/null +++ b/pos_change_payment/models/pos_switch_journal_wizard.py @@ -0,0 +1,78 @@ +# coding: utf-8 +# Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp import api, fields, models + + +class PosSwitchJournalWizard(models.TransientModel): + _name = 'pos.switch.journal.wizard' + + order_id = fields.Many2one( + comodel_name='pos.order', string='PoS Order', + required=True, readonly=True) + + statement_line_id = fields.Many2one( + comodel_name='account.bank.statement.line', string='Statement', + required=True, readonly=True) + + old_journal_id = fields.Many2one( + comodel_name='account.journal', string='Old Journal', + required=True, readonly=True) + + new_journal_id = fields.Many2one( + comodel_name='account.journal', string='New Journal', + required=True, domain=lambda s: s._domain_new_journal_id()) + + amount = fields.Float(string='Amount', readonly=True) + + @api.model + def _domain_new_journal_id(self): + AccountBankStatementLine = self.env['account.bank.statement.line'] + statement_line = AccountBankStatementLine.browse( + self.env.context.get('active_id')) + return [( + 'id', 'in', + statement_line.pos_statement_id.session_id.journal_ids.ids)] + + @api.model + def default_get(self, fields): + AccountBankStatementLine = self.env['account.bank.statement.line'] + res = super(PosSwitchJournalWizard, self).default_get(fields) + statement_line = AccountBankStatementLine.browse( + self.env.context.get('active_id')) + res.update({'statement_line_id': statement_line.id}) + res.update({'order_id': statement_line.pos_statement_id.id}) + res.update({'old_journal_id': statement_line.journal_id.id}) + res.update({'amount': statement_line.amount}) + return res + + # Action section + @api.multi + def button_switch_journal(self): + self.ensure_one() + # Check if changing payment is allowed + self.order_id._allow_change_payments() + + # TODO (FIXME) when upstream is fixed. + # We do 2 write, one in the old statement, one in the new, with + # 'amount' value each time to recompute all the functional fields + # of the Account Bank Statements + amount = self.amount + self.statement_line_id.with_context(change_pos_payment=True).write({ + 'amount': 0.0, + }) + + # Change statement of the statement line + new_statement = self.order_id.session_id.statement_ids.filtered( + lambda x: x.journal_id == self.new_journal_id)[0] + self.statement_line_id.with_context(change_pos_payment=True).write({ + 'amount': amount, + 'statement_id': new_statement.id, + }) + + return { + 'type': 'ir.actions.client', + 'tag': 'reload', + } diff --git a/pos_change_payment/readme/CONTRIBUTORS.rst b/pos_change_payment/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..7754037b --- /dev/null +++ b/pos_change_payment/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Sylvain LE GAL +* Julien WESTE diff --git a/pos_change_payment/readme/DESCRIPTION.rst b/pos_change_payment/readme/DESCRIPTION.rst new file mode 100644 index 00000000..9d62db1c --- /dev/null +++ b/pos_change_payment/readme/DESCRIPTION.rst @@ -0,0 +1,34 @@ +Improve payment changes when user did a mistake and disable some actions on +Point of Sale Bank Statement Line + +* Add the possibility to switch a payment (account.bank.statement.line) + of an order from a journal to another. This feature is usefull when + the user realized that he did a mistake, during the close of the session, + or just after he marked the order as paid + (Only if entries has not been generated) + +.. figure:: ../static/description/pos_order_switch_payment.png + +* Add the possibility to change all payments (method and amount) of a POS + (Only if entries has not been generated) + +.. figure:: ../static/description/pos_order_change_payments.png + +Bug Fixes / Improvement +~~~~~~~~~~~~~~~~~~~~~~~ + +* In the pos.payment wizard, display only the payment methods defined in + the current POS session + +* Disable the possibility to edit / delete a bank statement line on a POS + Order that has generated his entries, except using the wizard of this + module. This will prevent the generation of bad account move during + the close of the session; (mainly unbalanced moves) + +* All the cash payment are merged into a single one statement line. This + feature is usefull if the user use OpenERP as a calculator, writing + for a payment: + +1. Payment 1/ Cash 50 €; +2. Payment 2/ Cash -3,56 €; +3. With this module, the final statement line is a single line Payment 1/ Cash 46,44 € diff --git a/pos_change_payment/static/description/icon.png b/pos_change_payment/static/description/icon.png new file mode 100644 index 00000000..c5d87de7 Binary files /dev/null and b/pos_change_payment/static/description/icon.png differ diff --git a/pos_change_payment/static/description/pos_order_change_payments.png b/pos_change_payment/static/description/pos_order_change_payments.png new file mode 100644 index 00000000..ff32d529 Binary files /dev/null and b/pos_change_payment/static/description/pos_order_change_payments.png differ diff --git a/pos_change_payment/static/description/pos_order_switch_payment.png b/pos_change_payment/static/description/pos_order_switch_payment.png new file mode 100644 index 00000000..dc593c62 Binary files /dev/null and b/pos_change_payment/static/description/pos_order_switch_payment.png differ diff --git a/pos_change_payment/tests/__init__.py b/pos_change_payment/tests/__init__.py new file mode 100644 index 00000000..17b82062 --- /dev/null +++ b/pos_change_payment/tests/__init__.py @@ -0,0 +1,2 @@ +# coding: utf-8 +from . import test_module diff --git a/pos_change_payment/tests/test_module.py b/pos_change_payment/tests/test_module.py new file mode 100644 index 00000000..27507b04 --- /dev/null +++ b/pos_change_payment/tests/test_module.py @@ -0,0 +1,157 @@ +# coding: 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). + +from openerp.tests.common import TransactionCase +from openerp.exceptions import Warning as UserError + + +class TestModule(TransactionCase): + """Tests for 'Point of Sale - Change Payment' Module""" + + def setUp(self): + super(TestModule, self).setUp() + self.PosSession = self.env['pos.session'] + self.PosOrder = self.env['pos.order'] + self.PosMakePayment = self.env['pos.make.payment'] + self.PosSwitchJournalWizard = self.env['pos.switch.journal.wizard'] + self.PosChangePaymentsWizard = self.env['pos.change.payments.wizard'] + self.PosChangePaymentsWizardLine =\ + self.env['pos.change.payments.wizard.line'] + self.product = self.env.ref('product.product_product_3') + self.pos_config = self.env.ref('point_of_sale.pos_config_main') + self.check_journal = self.env.ref('account.check_journal') + self.cash_journal = self.env.ref('account.cash_journal') + + # create new session and open it + self.session = self.PosSession.create( + {'config_id': self.pos_config.id}) + self.session.open_cb() + self.check_statement = self.session.statement_ids.filtered( + lambda x: x.journal_id == self.check_journal) + self.cash_statement = self.session.statement_ids.filtered( + lambda x: x.journal_id == self.cash_journal) + + def _sale(self, session, journal_1, price_1, journal_2=False, price_2=0.0): + order = self.PosOrder.create({ + 'session_id': session.id, + 'lines': [[0, False, { + 'name': 'OL/0001', + 'product_id': self.product.id, + 'qty': 1.0, + 'price_unit': price_1 + price_2, + }]], + }) + payment = self.PosMakePayment.with_context(active_id=order.id).create({ + 'journal_id': journal_1.id, + 'amount': price_1, + }) + payment.with_context(active_id=order.id).check() + if journal_2: + payment = self.PosMakePayment.with_context( + active_id=order.id).create({ + 'journal_id': journal_2.id, + 'amount': price_2, + }) + payment.with_context(active_id=order.id).check() + return order + + # Test Section + def test_01_pos_switch_journal(self): + # Make a sale with 100 in cash journal + order = self._sale(self.session, self.cash_journal, 100) + statement_line = order.statement_ids[0] + + # Switch to check journal + wizard = self.PosSwitchJournalWizard.with_context( + active_id=statement_line.id).create({ + 'new_journal_id': self.check_journal.id, + }) + wizard.button_switch_journal() + + # Check Order + self.assertEqual( + len(order.statement_ids.filtered( + lambda x: x.journal_id == self.cash_journal)), 0, + "Altered order should not have the original payment journal") + + self.assertEqual( + len(order.statement_ids.filtered( + lambda x: x.journal_id == self.check_journal)), 1, + "Altered order should have the final payment journal") + + # Check Session + self.assertEqual( + self.cash_statement.balance_end, 0, + "Bad recompute of the balance for the old statement") + + self.assertEqual( + self.check_statement.balance_end, 100, + "Bad recompute of the balance for the new statement") + + def test_02_pos_change_payment(self): + # Make a sale with 35 in cash journal and 65 in check + order = self._sale( + self.session, self.cash_journal, 35, self.check_journal, 65) + + # Switch to check journal + wizard = self.PosChangePaymentsWizard.with_context( + active_id=order.id).create({}) + self.PosChangePaymentsWizardLine.with_context( + active_id=order.id).create({ + 'wizard_id': wizard.id, + 'new_journal_id': self.cash_journal.id, + 'amount': 10, + }) + self.PosChangePaymentsWizardLine.with_context( + active_id=order.id).create({ + 'wizard_id': wizard.id, + 'new_journal_id': self.check_journal.id, + 'amount': 40, + }) + + with self.assertRaises(UserError): + # Should not work if total is not correct + wizard.button_change_payments() + + # Finish payement + self.PosChangePaymentsWizardLine.with_context( + active_id=order.id).create({ + 'wizard_id': wizard.id, + 'new_journal_id': self.check_journal.id, + 'amount': 50, + }) + wizard.button_change_payments() + + # check Session + self.assertEqual( + self.cash_statement.balance_end, 10, + "Bad recompute of the balance for the old statement") + + self.assertEqual( + self.check_statement.balance_end, 90, + "Bad recompute of the balance for the new statement") + + def test_03_merge_statement(self): + # Make a sale with multiple cash payement + order = self._sale( + self.session, self.cash_journal, 100, + journal_2=self.cash_journal, price_2=200) + # Check that statement has been merged + self.assertEqual( + len(order.statement_ids), 1, + "Adding many cash statement for an order should merge them.") + + self.assertEqual( + order.statement_ids[0].amount, 300, + "Invalid total amount for merged cash statements") + + # Make a sale with multiple check payement + order = self._sale( + self.session, self.check_journal, 100, + self.check_journal, 200) + # Check that statement has been merged + self.assertEqual( + len(order.statement_ids), 2, + "Adding many check statement for an order should not merge them.") diff --git a/pos_change_payment/views/action.xml b/pos_change_payment/views/action.xml new file mode 100644 index 00000000..83e3bc6e --- /dev/null +++ b/pos_change_payment/views/action.xml @@ -0,0 +1,26 @@ + + + + + + + Switch Journal + pos.switch.journal.wizard + form + form + new + + + + Change Payments + pos.change.payments.wizard + form + form + new + + + diff --git a/pos_change_payment/views/view_account_bank_statement.xml b/pos_change_payment/views/view_account_bank_statement.xml new file mode 100644 index 00000000..6256b9da --- /dev/null +++ b/pos_change_payment/views/view_account_bank_statement.xml @@ -0,0 +1,21 @@ + + + + + + + account.bank.statement + + + + + + + + +