From 9946e1e0b372acee86712654c939b1e30509a3e1 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Mon, 15 Jul 2019 14:47:37 +0200 Subject: [PATCH] [FIX] loaded orders date to local https://github.com/OCA/pos/pull/361 cortesy @chienandalu [FIX] compatibility with pos_restaurant https://github.com/OCA/pos/pull/339 cortesy @carlosDomatix [FIX] add _compute_refund_order_qty [ADD] pos order view form. Add links to original returned order and refund orders. [IMP] when refunding an order via the 'Refund' button in back office, set the correct returned_order_id. [IMP] Add helper on each button [ADD] python test [REF] JS remove useless code [REF] Python remove useless code [FIX] remove bad oldname [FIX] remove gap in bill display, when it is a refund [FIX] when reprinting a bill, the returned order name is displayed, if any [FIX] JS lint, with OCA eslint file [ADD] french translation --- pos_order_mgmt/__manifest__.py | 1 + pos_order_mgmt/i18n/fr.po | 249 +++++++++++++++++++++++ pos_order_mgmt/i18n/pos_order_mgmt.pot | 151 +++++++++++--- pos_order_mgmt/models/pos_config.py | 4 +- pos_order_mgmt/models/pos_order.py | 73 +++++-- pos_order_mgmt/static/src/css/pos.css | 1 + pos_order_mgmt/static/src/js/models.js | 36 +--- pos_order_mgmt/static/src/js/widgets.js | 246 +++++++++++----------- pos_order_mgmt/static/src/xml/pos.xml | 16 +- pos_order_mgmt/tests/__init__.py | 1 + pos_order_mgmt/tests/test_module.py | 80 ++++++++ pos_order_mgmt/views/view_pos_config.xml | 1 - pos_order_mgmt/views/view_pos_order.xml | 22 ++ 13 files changed, 677 insertions(+), 204 deletions(-) create mode 100644 pos_order_mgmt/i18n/fr.po create mode 100644 pos_order_mgmt/tests/__init__.py create mode 100644 pos_order_mgmt/tests/test_module.py create mode 100644 pos_order_mgmt/views/view_pos_order.xml diff --git a/pos_order_mgmt/__manifest__.py b/pos_order_mgmt/__manifest__.py index b139f96e..9a63f15c 100644 --- a/pos_order_mgmt/__manifest__.py +++ b/pos_order_mgmt/__manifest__.py @@ -18,6 +18,7 @@ 'data': [ 'views/assets.xml', 'views/view_pos_config.xml', + 'views/view_pos_order.xml', ], 'qweb': [ 'static/src/xml/pos.xml' diff --git a/pos_order_mgmt/i18n/fr.po b/pos_order_mgmt/i18n/fr.po new file mode 100644 index 00000000..1d0b7b9c --- /dev/null +++ b/pos_order_mgmt/i18n/fr.po @@ -0,0 +1,249 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_order_mgmt +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-15 20:54+0000\n" +"PO-Revision-Date: 2019-07-15 20:54+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_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Allow to duplicate done orders in this POS" +msgstr "Autoriser à dupliquer des commandes réalisées dans l'interface tactile" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Allow to reprint done orders in this POS" +msgstr "Autoriser à réimprimer des commandes réalisées dans l'interface tactile" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Allow to return done orders in this POS" +msgstr "Autoriser à rembourser des commandes réalisées dans l'interface tactile" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_copy_done_order +msgid "Allows to duplicate already done orders in the frontend" +msgstr "Autoriser à dupliquer des commandes réalisées dans l'interface tactile" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_reprint_done_order +msgid "Allows to reprint already done orders in the frontend" +msgstr "Autoriser à réimprimer des commandes réalisées dans l'interface tactile" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_return_done_order +msgid "Allows to return already done orders in the frontend" +msgstr "Autoriser à rembourser des commandes réalisées dans l'interface tactile" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:36 +#, python-format +msgid "Amount Total" +msgstr "Total" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:17 +#, python-format +msgid "Back" +msgstr "Retour" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:341 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:396 +#, python-format +msgid "Can not execute this action because the POS is currently offline" +msgstr "Vous ne pouvez pas exécuter cette action, car le Point de Vente est actuellement hors ligne" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:340 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:395 +#, python-format +msgid "Connection error" +msgstr "Erreur de connexion" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:61 +#, python-format +msgid "Create a new order based on this one" +msgstr "Créer une nouvelle commande basée sur celle-ci" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:64 +#, python-format +msgid "Create a refund order of this order" +msgstr "Rembourser cette commande" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:34 +#, python-format +msgid "Customer" +msgstr "Client" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:89 +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:98 +#, python-format +msgid "DUPLICATE" +msgstr "DUPLICATA" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:35 +#, python-format +msgid "Date" +msgstr "Date" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_copy_done_order +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Duplicate Done Orders" +msgstr "Copier une commande réalisées" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Load Done Order Max Qty." +msgstr "Quantité maximale de commandes à charger" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_load_done_order_max_qty +msgid "Max. Done Orders Quantity To Load" +msgstr "Quantité maximale de commandes à charger" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_load_done_order_max_qty +msgid "Maximum number of orders to load on the PoS at its init. Set it to 0 to load none (it's still possible to load them by ticket code)." +msgstr "" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Maximum number orders to load" +msgstr "Nombre maximum de commande à charger" + +#. module: pos_order_mgmt +#: model:ir.model,name:pos_order_mgmt.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Paramétrage du point de vente" + +#. module: pos_order_mgmt +#: model:ir.model,name:pos_order_mgmt.model_pos_order +msgid "Point of Sale Orders" +msgstr "Commandes du point de vente" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:58 +#, python-format +msgid "Print a duplicate for this order" +msgstr "Imprimer un duplicata de cette commande" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:83 +#, python-format +msgid "Rectifies:" +msgstr "Rectifie : " + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:33 +#, python-format +msgid "Ref." +msgstr "Réf." + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__returned_order_reference +msgid "Reference of the returned Order" +msgstr "Réference de la vente retournée" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:242 +#, python-format +msgid "Refund " +msgstr "Rembourse " + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__refund_order_ids +msgid "Refund Orders" +msgstr "Commandes remboursées" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__refund_order_qty +msgid "Refund Orders Quantity" +msgstr "Nombre de remboursement" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_order_form +msgid "Refunds" +msgstr "Remboursements" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_reprint_done_order +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Reprint Done Orders" +msgstr "Réimprimer le ticket d'une commande réalisée" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_return_done_order +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Return Done Orders" +msgstr "Retourner une commande réalisée" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__returned_order_id +msgid "Returned Order" +msgstr "Commande retournée" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:74 +#, python-format +msgid "Returned order:" +msgstr "Commande retournée:" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:21 +#, python-format +msgid "Search Order" +msgstr "Recherche une commande" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:358 +#, python-format +msgid "Unable to load some order lines because the products are not available in the POS cache.\n" +"\n" +"Please check that lines :\n" +"\n" +" * " +msgstr "Impossible de charger certaines lignes de ticket car les produits ne sont pas disponible dans le point de vente\n" +"Veuillez vérifier les lignes suivantes : \n" +"\n" +" * " + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:357 +#, python-format +msgid "Unknown Products" +msgstr "Produit inconnu" + diff --git a/pos_order_mgmt/i18n/pos_order_mgmt.pot b/pos_order_mgmt/i18n/pos_order_mgmt.pot index 6b2cfa7f..2b39db04 100644 --- a/pos_order_mgmt/i18n/pos_order_mgmt.pot +++ b/pos_order_mgmt/i18n/pos_order_mgmt.pot @@ -1,11 +1,13 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * pos_order_mgmt +# * pos_order_mgmt # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 11.0\n" +"Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-07-15 20:53+0000\n" +"PO-Revision-Date: 2019-07-15 20:53+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -14,13 +16,33 @@ msgstr "" "Plural-Forms: \n" #. module: pos_order_mgmt -#: model:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form -msgid "Allow to load done orders in this POS" +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Allow to duplicate done orders in this POS" msgstr "" #. module: pos_order_mgmt -#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config_iface_load_done_order -msgid "Allows to load already done orders in the frontend to operate over them, allowing reprint the tickets, return items, etc." +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Allow to reprint done orders in this POS" +msgstr "" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Allow to return done orders in this POS" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_copy_done_order +msgid "Allows to duplicate already done orders in the frontend" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_reprint_done_order +msgid "Allows to reprint already done orders in the frontend" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_return_done_order +msgid "Allows to return already done orders in the frontend" msgstr "" #. module: pos_order_mgmt @@ -39,20 +61,34 @@ msgstr "" #. module: pos_order_mgmt #. openerp-web -#: code:addons/pos_order_mgmt/static/src/js/widgets.js:303 -#: code:addons/pos_order_mgmt/static/src/js/widgets.js:331 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:341 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:396 #, python-format msgid "Can not execute this action because the POS is currently offline" msgstr "" #. module: pos_order_mgmt #. openerp-web -#: code:addons/pos_order_mgmt/static/src/js/widgets.js:302 -#: code:addons/pos_order_mgmt/static/src/js/widgets.js:330 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:340 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:395 #, python-format msgid "Connection error" msgstr "" +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:61 +#, python-format +msgid "Create a new order based on this one" +msgstr "" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:64 +#, python-format +msgid "Create a refund order of this order" +msgstr "" + #. module: pos_order_mgmt #. openerp-web #: code:addons/pos_order_mgmt/static/src/xml/pos.xml:34 @@ -60,6 +96,14 @@ msgstr "" msgid "Customer" msgstr "" +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:89 +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:98 +#, python-format +msgid "DUPLICATE" +msgstr "" + #. module: pos_order_mgmt #. openerp-web #: code:addons/pos_order_mgmt/static/src/xml/pos.xml:35 @@ -68,31 +112,36 @@ msgid "Date" msgstr "" #. module: pos_order_mgmt -#: model:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form -msgid "Load Done Order Max Qty." +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_copy_done_order +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Duplicate Done Orders" msgstr "" #. module: pos_order_mgmt -#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config_iface_load_done_order -#: model:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form -msgid "Load Done Orders" +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Load Done Order Max Qty." msgstr "" #. module: pos_order_mgmt -#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config_iface_load_done_order_max_qty +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_load_done_order_max_qty msgid "Max. Done Orders Quantity To Load" msgstr "" #. module: pos_order_mgmt -#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config_iface_load_done_order_max_qty -msgid "Maximum number of orders to load on the PoS at its init. Set it to 0 to load none (it's still posible to load them by ticket code)." +#: model:ir.model.fields,help:pos_order_mgmt.field_pos_config__iface_load_done_order_max_qty +msgid "Maximum number of orders to load on the PoS at its init. Set it to 0 to load none (it's still possible to load them by ticket code)." msgstr "" #. module: pos_order_mgmt -#: model:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form msgid "Maximum number orders to load" msgstr "" +#. module: pos_order_mgmt +#: model:ir.model,name:pos_order_mgmt.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + #. module: pos_order_mgmt #: model:ir.model,name:pos_order_mgmt.model_pos_order msgid "Point of Sale Orders" @@ -100,7 +149,14 @@ msgstr "" #. module: pos_order_mgmt #. openerp-web -#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:80 +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:58 +#, python-format +msgid "Print a duplicate for this order" +msgstr "" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:83 #, python-format msgid "Rectifies:" msgstr "" @@ -112,9 +168,53 @@ msgstr "" msgid "Ref." msgstr "" +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__returned_order_reference +msgid "Reference of the returned Order" +msgstr "" + +#. module: pos_order_mgmt +#. openerp-web +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:242 +#, python-format +msgid "Refund " +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__refund_order_ids +msgid "Refund Orders" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__refund_order_qty +msgid "Refund Orders Quantity" +msgstr "" + +#. module: pos_order_mgmt +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_order_form +msgid "Refunds" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_reprint_done_order +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Reprint Done Orders" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_config__iface_return_done_order +#: model_terms:ir.ui.view,arch_db:pos_order_mgmt.view_pos_config_form +msgid "Return Done Orders" +msgstr "" + +#. module: pos_order_mgmt +#: model:ir.model.fields,field_description:pos_order_mgmt.field_pos_order__returned_order_id +msgid "Returned Order" +msgstr "" + #. module: pos_order_mgmt #. openerp-web -#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:71 +#: code:addons/pos_order_mgmt/static/src/xml/pos.xml:74 #, python-format msgid "Returned order:" msgstr "" @@ -128,7 +228,7 @@ msgstr "" #. module: pos_order_mgmt #. openerp-web -#: code:addons/pos_order_mgmt/static/src/js/widgets.js:280 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:358 #, python-format msgid "Unable to load some order lines because the products are not available in the POS cache.\n" "\n" @@ -139,13 +239,8 @@ msgstr "" #. module: pos_order_mgmt #. openerp-web -#: code:addons/pos_order_mgmt/static/src/js/widgets.js:279 +#: code:addons/pos_order_mgmt/static/src/js/widgets.js:357 #, python-format msgid "Unknown Products" msgstr "" -#. module: pos_order_mgmt -#: model:ir.model,name:pos_order_mgmt.model_pos_config -msgid "pos.config" -msgstr "" - diff --git a/pos_order_mgmt/models/pos_config.py b/pos_order_mgmt/models/pos_config.py index ddd4d814..19141593 100644 --- a/pos_order_mgmt/models/pos_config.py +++ b/pos_order_mgmt/models/pos_config.py @@ -14,14 +14,12 @@ class PosConfig(models.Model): string='Reprint Done Orders', default=True, help='Allows to reprint already done orders in the frontend', - oldname='iface_load_done_order', ) iface_return_done_order = fields.Boolean( string='Return Done Orders', default=True, help='Allows to return already done orders in the frontend', - oldname='iface_load_done_order', ) iface_copy_done_order = fields.Boolean( @@ -35,6 +33,6 @@ class PosConfig(models.Model): default=10, required=True, help='Maximum number of orders to load on the PoS at its init. ' - 'Set it to 0 to load none (it\'s still posible to load them by ' + 'Set it to 0 to load none (it\'s still possible to load them by ' 'ticket code).', ) diff --git a/pos_order_mgmt/models/pos_order.py b/pos_order_mgmt/models/pos_order.py index 11c43cdf..85cac5e3 100644 --- a/pos_order_mgmt/models/pos_order.py +++ b/pos_order_mgmt/models/pos_order.py @@ -13,17 +13,56 @@ class PosOrder(models.Model): string='Returned Order', readonly=True, ) + + returned_order_reference = fields.Char( + related='returned_order_id.pos_reference', + string='Reference of the returned Order') + refund_order_ids = fields.One2many( comodel_name='pos.order', inverse_name='returned_order_id', string='Refund Orders', readonly=True, ) + refund_order_qty = fields.Integer( compute='_compute_refund_order_qty', string='Refund Orders Quantity', ) + @api.multi + @api.depends('refund_order_ids') + def _compute_refund_order_qty(self): + for order in self: + order.refund_order_qty = len(order.refund_order_ids) + + @api.multi + def action_view_refund_orders(self): + self.ensure_one() + + action = self.env.ref('point_of_sale.action_pos_pos_form').read()[0] + + if self.refund_order_qty == 1: + action['views'] = [ + (self.env.ref('point_of_sale.view_pos_pos_form').id, 'form')] + action['res_id'] = self.refund_order_ids.ids[0] + else: + action['domain'] = [('id', 'in', self.refund_order_ids.ids)] + return action + + @api.multi + def refund(self): + return super(PosOrder, self.with_context(refund=True)).refund() + + @api.multi + @api.returns('self', lambda value: value.id) + def copy(self, default=None): + self.ensure_one() + order = super().copy(default=default) + if self.env.context.get('refund', False): + order.returned_order_id = self.id + return order + @api.model def _prepare_filter_for_pos(self, pos_session_id): return [ @@ -43,9 +82,7 @@ class PosOrder(models.Model): def _prepare_fields_for_pos_list(self): return [ 'name', 'pos_reference', 'partner_id', 'date_order', - 'amount_total', 'amount_paid', 'amount_return', 'session_id', - 'amount_tax', 'statement_ids', 'lines', 'invoice_id', - 'returned_order_id', 'fiscal_position_id' + 'amount_total', ] @api.model @@ -76,7 +113,7 @@ class PosOrder(models.Model): payment_line = self._prepare_done_order_payment_for_pos( payment_line) payment_lines.append(payment_line) - return { + res = { 'id': self.id, 'date_order': self.date_order, 'pos_reference': self.pos_reference, @@ -85,11 +122,11 @@ class PosOrder(models.Model): 'fiscal_position': self.fiscal_position_id.id, 'line_ids': order_lines, 'statement_ids': payment_lines, - 'origin_invoice_id': bool(self.invoice_id), - 'returned_order_id': (self.returned_order_id and - self.returned_order_id.pos_reference or - False), + 'to_invoice': bool(self.invoice_id), + 'returned_order_id': self.returned_order_id.id, + 'returned_order_reference': self.returned_order_reference, } + return res @api.multi def _prepare_done_order_line_for_pos(self, order_line): @@ -115,17 +152,9 @@ class PosOrder(models.Model): return self._prepare_done_order_for_pos() @api.model - def _process_order(self, pos_order): - if (not pos_order.get('return') or - not pos_order.get('returned_order_id')): - return super()._process_order(pos_order) - order = super(PosOrder, self)._process_order(pos_order) - returned_order_id = pos_order.get('returned_order_id') - if isinstance(returned_order_id, int): - order.returned_order_id = self.browse(returned_order_id) - # Only if the order is returned from the browser saved orders. - else: - order.returned_order_id = self.search([ - ('pos_reference', '=', returned_order_id)]) - order.returned_order_id.refund_order_ids |= order - return order + def _order_fields(self, ui_order): + res = super()._order_fields(ui_order) + res.update({ + 'returned_order_id': ui_order.get('returned_order_id', False), + }) + return res diff --git a/pos_order_mgmt/static/src/css/pos.css b/pos_order_mgmt/static/src/css/pos.css index 7ebf180e..1f2544e3 100644 --- a/pos_order_mgmt/static/src/css/pos.css +++ b/pos_order_mgmt/static/src/css/pos.css @@ -31,4 +31,5 @@ padding: 8px 0; background-color: rgb(239, 153, 65); color: white; + text-align: center; } diff --git a/pos_order_mgmt/static/src/js/models.js b/pos_order_mgmt/static/src/js/models.js index 0a6c4bb3..d57e8456 100644 --- a/pos_order_mgmt/static/src/js/models.js +++ b/pos_order_mgmt/static/src/js/models.js @@ -6,40 +6,24 @@ odoo.define('pos_order_mgmt.models', function (require) { var models = require('point_of_sale.models'); - var _PosModel_push_order = models.PosModel.prototype.push_order; - models.PosModel.prototype.push_order = function () { - var res = _PosModel_push_order.apply(this, arguments); - if (arguments.length && arguments[0] && arguments[0].uid) { - var order = this.db.get_order(arguments[0].uid); - if (order && order.data) { - var data = _.extend({}, order.data); - var partner = this.db.get_partner_by_id(data.partner_id); - if (partner && partner.id && partner.name) { - data.partner_id = [partner.id, partner.name]; - } - data.date_order = moment(order.data.creation_date) - .format('YYYY-MM-DD HH:mm:ss'); - this.gui.screen_instances.orderlist.orders.unshift(data); - } - } - return res; - }; - var order_super = models.Order.prototype; + models.Order = models.Order.extend({ init_from_JSON: function (json) { order_super.init_from_JSON.apply(this, arguments); - this.return = json.return; this.returned_order_id = json.returned_order_id; - this.origin_name = json.origin_name; + this.returned_order_reference = json.returned_order_reference; }, export_as_JSON: function () { var res = order_super.export_as_JSON.apply(this, arguments); - if (this.return) { - res.origin_name = this.origin_name; - res.returned_order_id = this.returned_order_id; - res.return = this.return; - } + res.returned_order_id = this.returned_order_id; + res.returned_order_reference = this.returned_order_reference; + return res; + }, + export_for_printing: function () { + var res = order_super.export_for_printing.apply(this, arguments); + res.returned_order_id = this.returned_order_id; + res.returned_order_reference = this.returned_order_reference; return res; }, }); diff --git a/pos_order_mgmt/static/src/js/widgets.js b/pos_order_mgmt/static/src/js/widgets.js index 18dbeb62..8d7630fa 100644 --- a/pos_order_mgmt/static/src/js/widgets.js +++ b/pos_order_mgmt/static/src/js/widgets.js @@ -65,9 +65,10 @@ odoo.define('pos_order_mgmt.widgets', function (require) { show: function () { var self = this; - var previous_screen; + var previous_screen = false; if (this.pos.get_order()) { - previous_screen = this.pos.get_order().get_screen_data('previous-screen'); + previous_screen = this.pos.get_order().get_screen_data( + 'previous-screen'); } if (previous_screen === 'receipt') { this.gui.screen_instances.receipt.click_next(); @@ -80,12 +81,14 @@ odoo.define('pos_order_mgmt.widgets', function (require) { return self.gui.show_screen(self.gui.startup_screen); }); - if (this.pos.config.iface_vkeyboard && this.chrome.widget.keyboard) { - this.chrome.widget.keyboard.connect(this.$('.searchbox input')); + if (this.pos.config.iface_vkeyboard && + this.chrome.widget.keyboard) { + this.chrome.widget.keyboard.connect( + this.$('.searchbox input')); } var search_timeout = null; - this.$('.searchbox input').on('keyup', function (event) { + this.$('.searchbox input').on('keyup', function () { self.search_query = this.value; clearTimeout(search_timeout); search_timeout = setTimeout(function () { @@ -105,9 +108,12 @@ odoo.define('pos_order_mgmt.widgets', function (require) { var orders = this.orders; var contents = this.$el[0].querySelector('.order-list-contents'); contents.innerHTML = ""; - for (var i = 0, len = Math.min(orders.length, 1000); i < len; i++) { + for ( + var i = 0, len = Math.min(orders.length, 1000); i < len; i++ + ) { var order = orders[i]; - var orderline = this.order_cache.get_node(order.id || order.uid); + var orderline = this.order_cache.get_node( + order.id || order.uid); if (!orderline) { var orderline_html = QWeb.render('OrderLine', { widget: this, @@ -116,7 +122,8 @@ odoo.define('pos_order_mgmt.widgets', function (require) { orderline = document.createElement('tbody'); orderline.innerHTML = orderline_html; orderline = orderline.childNodes[1]; - this.order_cache.cache_node(order.id || order.uid, orderline); + this.order_cache.cache_node( + order.id || order.uid, orderline); } if (order === this.old_order) { orderline.classList.add('highlight'); @@ -130,54 +137,50 @@ odoo.define('pos_order_mgmt.widgets', function (require) { this.$('.order-list-return').off('click'); this.$('.order-list-reprint').off('click'); this.$('.order-list-copy').off('click'); - this.$('.order-list-return').click(function (event) { - self.order_list_actions(event, 'return'); - }); this.$('.order-list-reprint').click(function (event) { self.order_list_actions(event, 'print'); }); - this.$('.order-list-copy').click(function(event) { + this.$('.order-list-copy').click(function (event) { self.order_list_actions(event, 'copy'); }); + this.$('.order-list-return').click(function (event) { + self.order_list_actions(event, 'return'); + }); }, order_list_actions: function (event, action) { var self = this; - var order_data; var dataset = event.target.parentNode.dataset; - if (dataset.orderId) { - self.load_order_data(parseInt(dataset.orderId, 10)) - .then(function(order_data) { + self.load_order_data(parseInt(dataset.orderId, 10)) + .then(function (order_data) { self.order_action(order_data, action); - }) - } else { - _.each(this.orders, function (order_data) { - if (order.uid === dataset.uid) { - self.order_action(order_data, action); - } }); - } }, - order_action: function(order_data, action) { - this.gui.back(); - this['action_' + action](order_data); + order_action: function (order_data, action) { + if (this.old_order !== null) { + this.gui.back(); + } + var order = this.load_order_from_data(order_data, action); + if (!order) { + // The load of the order failed. (products not found, ... + // We cancel the action + return; + } + this['action_' + action](order_data, order); }, - action_print: function (order_data) { - var order = this.load_order_from_data(order_data, true); - if (!order) return false; - // Restore the previous name - order.name = order_data.pos_reference || order_data.name; - var receipt = order.export_for_printing(); + action_print: function (order_data, order) { // We store temporarily the current order so we can safely compute // taxes based on fiscal position - this.pos.current_order = this.pos.get_order() + this.pos.current_order = this.pos.get_order(); + this.pos.set_order(order); + if (this.pos.config.iface_print_via_proxy) { this.pos.proxy.print_receipt(QWeb.render( 'XmlReceipt', { - receipt: receipt, + receipt: order.export_for_printing(), widget: this, pos: this.pos, order: order, @@ -193,57 +196,33 @@ odoo.define('pos_order_mgmt.widgets', function (require) { } }, - action_copy: function(order_data) { - // Remove payments from original data - order_data.statement_ids = false; - var order = this.load_order_from_data(order_data, true); - if (!order) { return false; } - // If previous order was invoiced, we need a refund too - order.set_to_invoice(order_data.origin_invoice_id); - order.formatted_validation_date = false; + action_copy: function (order_data, order) { order.trigger('change'); this.pos.get('orders').add(order); this.pos.set('selectedOrder', order); return order; }, - action_return: function (order_data) { - //var order_data = _.cloneDeep(order_data); - // Remove payments from original data - order_data.statement_ids = false; - // Invert line quantities - var order_lines = order_data.line_ids || order_data.lines || []; - _.each(order_lines, function(line) { line.qty = -1 * line.qty }) - // Load from new data and change some stuff - var order = this.load_order_from_data(order_data); - if (!order) { return false; } - order.return = true; - order.name = _t("Refund ") + order.uid;; - order.origin_name = order_data.pos_reference || order.returned_order_id; - // If previous order was invoiced, we need a refund too - order.set_to_invoice(order_data.origin_invoice_id); - order.formatted_validation_date = false; + action_return: function (order_data, order) { order.trigger('change'); - // Add to pos this.pos.get('orders').add(order); this.pos.set('selectedOrder', order); return order; }, - _prepare_order_from_order_data: function (order_data, temporary) { + _prepare_order_from_order_data: function (order_data, action) { var self = this; var order = new pos.Order({}, { pos: this.pos, - temporary: !!temporary, }); - if (order_data.partner_id.length) { - order_data.partner_id = order_data.partner_id[0]; + // Get Customer + if (order_data.partner_id) { + order.set_client( + this.pos.db.get_partner_by_id(order_data.partner_id)); } - order.set_client(this.pos.db.get_partner_by_id(order_data.partner_id)); - - // Set fiscal position + // Get fiscal position if (order_data.fiscal_position && this.pos.fiscal_positions) { var fiscal_positions = this.pos.fiscal_positions; order.fiscal_position = fiscal_positions.filter(function (p) { @@ -252,40 +231,71 @@ odoo.define('pos_order_mgmt.widgets', function (require) { order.trigger('change'); } - // Set order lines - var orderLines = order_data.line_ids || order_data.lines || []; - self._prepare_orderlines_from_order_data(order, order_data, orderLines); + // Get order lines + self._prepare_orderlines_from_order_data( + order, order_data, action); - if (order_data.returned_order_id) { - order.origin_name = order_data.returned_order_id; + // Get Name + if (['print'].indexOf(action) !== -1) { + order.name = order_data.pos_reference; + } else if (['return'].indexOf(action) !== -1) { + order.name = _t("Refund ") + order.uid; } - order.formatted_validation_date = moment(order_data.date_order).format('YYYY-MM-DD HH:mm:ss'); + // Get to invoice + if (['return', 'copy'].indexOf(action) !== -1) { + // If previous order was invoiced, we need a refund too + order.set_to_invoice(order_data.to_invoice); + } - // Set Payment lines - var paymentLines = order_data.statement_ids || []; - _.each(paymentLines, function (paymentLine) { - var line = paymentLine; - // In case of local data - if (line.length === 3) { - line = line[2]; - } - _.each(self.pos.cashregisters, function (cashregister) { - if (cashregister.journal.id === line.journal_id) { - if (line.amount > 0) { - // If it is not change - order.add_paymentline(cashregister); - order.selected_paymentline.set_amount(line.amount); - } + // Get returned Order + if (['print'].indexOf(action) !== -1) { + // Get the same value as the original + order.returned_order_id = order_data.returned_order_id; + order.returned_order_reference = + order_data.returned_order_reference; + } else if (['return'].indexOf(action) !== -1) { + order.returned_order_id = order_data.id; + order.returned_order_reference = order_data.pos_reference; + } + + // Get Date + if (['print'].indexOf(action) !== -1) { + order.formatted_validation_date = + moment(order_data.date_order).format('YYYY-MM-DD HH:mm:ss'); + } + + // Get Payment lines + if (['print'].indexOf(action) !== -1) { + var paymentLines = order_data.statement_ids || []; + _.each(paymentLines, function (paymentLine) { + var line = paymentLine; + // In case of local data + if (line.length === 3) { + line = line[2]; } + _.each(self.pos.cashregisters, function (cashregister) { + if (cashregister.journal.id === line.journal_id) { + if (line.amount > 0) { + // If it is not change + order.add_paymentline(cashregister); + order.selected_paymentline.set_amount( + line.amount); + } + } + }); }); - }); + } return order; }, - _prepare_orderlines_from_order_data: function(order, order_data, orderLines) { + _prepare_orderlines_from_order_data: function ( + order, order_data, action) { + var orderLines = order_data.line_ids || order_data.lines || []; + var self = this; - _.each(orderLines, function(line) { + _.each(orderLines, function (orderLine) { + var line = orderLine; // In case of local data if (line.length === 3) { line = line[2]; @@ -295,10 +305,15 @@ odoo.define('pos_order_mgmt.widgets', function (require) { if (_.isUndefined(product)) { self.unknown_products.push(String(line.product_id)); } else { + var qty = line.qty; + if (['return'].indexOf(action) !== -1) { + // Invert line quantities + qty *= -1; + } // Create a new order line order.add_product(product, { price: line.price_unit, - quantity: line.qty, + quantity: qty, discount: line.discount, merge: false, }); @@ -306,13 +321,13 @@ odoo.define('pos_order_mgmt.widgets', function (require) { }); }, - load_order_data: function(order_id) { + load_order_data: function (order_id) { var self = this; return this._rpc({ model: 'pos.order', method: 'load_done_order_for_pos', args: [order_id], - }).fail(function (error, event) { + }).fail(function (error) { if (parseInt(error.code, 10) === 200) { // Business Logic Error, not a connection problem self.gui.show_popup( @@ -323,45 +338,33 @@ odoo.define('pos_order_mgmt.widgets', function (require) { } else { self.gui.show_popup('error', { 'title': _t('Connection error'), - 'body': _t('Can not execute this action because the POS is currently offline'), + 'body': _t( + 'Can not execute this action because the POS' + + ' is currently offline'), }); } }); }, - load_order_from_data: function(order_data) { + load_order_from_data: function (order_data, action) { var self = this; this.unknown_products = []; - var order = self._prepare_order_from_order_data(order_data); + var order = self._prepare_order_from_order_data( + order_data, action); // Forbid POS Order loading if some products are unknown if (self.unknown_products.length > 0) { self.gui.show_popup('error-traceback', { 'title': _t('Unknown Products'), 'body': _t('Unable to load some order lines because the ' + 'products are not available in the POS cache.\n\n' + - 'Please check that lines :\n\n * ') + self.unknown_products.join("; \n *"), + 'Please check that lines :\n\n * ') + + self.unknown_products.join("; \n *"), }); return false; } return order; }, - /* deprecated */ - load_order: function (order_id) { - var self = this; - var done = new $.Deferred(); - this.load_order_data(order_id) - .then(function(order_data) { - self.gui.show_screen('orderlist'); - var order = self.load_order_from_data(order_data); - if (!order) { return done.fail(); } - done.resolve(order); - }).fail(function() { - done.fail(); - }); - return done; - }, - // Search Part search_done_orders: function (query) { var self = this; @@ -371,6 +374,13 @@ odoo.define('pos_order_mgmt.widgets', function (require) { args: [query || '', this.pos.pos_session.id], }).then(function (result) { self.orders = result; + // Get the date in local time + _.each(self.orders, function (order) { + if (order.date_order) { + order.date_order = moment.utc(order.date_order) + .local().format('YYYY-MM-DD HH:mm:ss'); + } + }); }).fail(function (error, event) { if (parseInt(error.code, 10) === 200) { // Business Logic Error, not a connection problem @@ -383,17 +393,21 @@ odoo.define('pos_order_mgmt.widgets', function (require) { } else { self.gui.show_popup('error', { 'title': _t('Connection error'), - 'body': _t('Can not execute this action because the POS is currently offline'), + 'body': _t( + 'Can not execute this action because the POS' + + ' is currently offline'), }); } event.preventDefault(); }); }, - perform_search: function() { + perform_search: function () { var self = this; return this.search_done_orders(self.search_query) - .done(function () { self.render_list(); }); + .done(function () { + self.render_list(); + }); }, clear_search: function () { diff --git a/pos_order_mgmt/static/src/xml/pos.xml b/pos_order_mgmt/static/src/xml/pos.xml index 728d2762..9615dae8 100644 --- a/pos_order_mgmt/static/src/xml/pos.xml +++ b/pos_order_mgmt/static/src/xml/pos.xml @@ -55,13 +55,13 @@ - + - + - + @@ -69,18 +69,18 @@ - -
- Returned order: + +
+ Returned order:
- +
- Rectifies: + Rectifies: diff --git a/pos_order_mgmt/tests/__init__.py b/pos_order_mgmt/tests/__init__.py new file mode 100644 index 00000000..d9b96c4f --- /dev/null +++ b/pos_order_mgmt/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/pos_order_mgmt/tests/test_module.py b/pos_order_mgmt/tests/test_module.py new file mode 100644 index 00000000..1478a90a --- /dev/null +++ b/pos_order_mgmt/tests/test_module.py @@ -0,0 +1,80 @@ +# 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 fields +from odoo.tests.common import TransactionCase + + +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_load_order(self): + order = self._create_order() + orders_data = self.PosOrder.search_done_orders_for_pos( + [], self.pos_config.current_session_id.id) + self.assertEqual(len(orders_data), 1) + self.assertEqual( + orders_data[0]['id'], order.id) + + detail_data = order.load_done_order_for_pos() + self.assertEqual( + len(detail_data.get('line_ids', [])), 1, + "Loading order detail failed") + + 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 diff --git a/pos_order_mgmt/views/view_pos_config.xml b/pos_order_mgmt/views/view_pos_config.xml index aa5c540c..c49f5ba0 100644 --- a/pos_order_mgmt/views/view_pos_config.xml +++ b/pos_order_mgmt/views/view_pos_config.xml @@ -6,7 +6,6 @@ - pos.config.form pos.config diff --git a/pos_order_mgmt/views/view_pos_order.xml b/pos_order_mgmt/views/view_pos_order.xml new file mode 100644 index 00000000..b89354e4 --- /dev/null +++ b/pos_order_mgmt/views/view_pos_order.xml @@ -0,0 +1,22 @@ + + + + + + pos.order + + + + + + + + + + + +