From 87e1a4316e37e9b91e98ac8063a86e31ad91db94 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Mon, 10 Apr 2017 11:04:14 +0200 Subject: [PATCH 01/16] new module pos_margin --- pos_margin/README.rst | 79 ++++++++++++++++++ pos_margin/__init__.py | 2 + pos_margin/__manifest__.py | 22 +++++ pos_margin/i18n/es.po | 50 +++++++++++ pos_margin/i18n/fr.po | 49 +++++++++++ pos_margin/i18n/it.po | 47 +++++++++++ pos_margin/i18n/nl_NL.po | 48 +++++++++++ pos_margin/i18n/pos_margin.pot | 41 +++++++++ pos_margin/models/__init__.py | 3 + pos_margin/models/pos_order.py | 25 ++++++ pos_margin/models/pos_order_line.py | 33 ++++++++ .../static/description/pos_order_form.png | Bin 0 -> 28285 bytes pos_margin/views/view_pos_order.xml | 25 ++++++ 13 files changed, 424 insertions(+) create mode 100644 pos_margin/README.rst create mode 100644 pos_margin/__init__.py create mode 100644 pos_margin/__manifest__.py create mode 100644 pos_margin/i18n/es.po create mode 100644 pos_margin/i18n/fr.po create mode 100644 pos_margin/i18n/it.po create mode 100644 pos_margin/i18n/nl_NL.po create mode 100644 pos_margin/i18n/pos_margin.pot create mode 100644 pos_margin/models/__init__.py create mode 100644 pos_margin/models/pos_order.py create mode 100644 pos_margin/models/pos_order_line.py create mode 100644 pos_margin/static/description/pos_order_form.png create mode 100644 pos_margin/views/view_pos_order.xml diff --git a/pos_margin/README.rst b/pos_margin/README.rst new file mode 100644 index 0000000000..4554966ca9 --- /dev/null +++ b/pos_margin/README.rst @@ -0,0 +1,79 @@ +.. 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 + +=================== +Margin on PoS order +=================== + +This module extends the functionality of point of sale to support margin on +pos orders. + +This gives the profitability by calculating the difference between the Unit +Price and Cost Price. + + +Usage +===== + +To use this module, you need to: + +#. Go to 'Point Of Sale' / 'Daily Operations' / 'Orders' +#. Open an order + +.. figure:: ./pos_margin/static/description/pos_order_form.png + :width: 800px + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/184/8.0 + + +Technical information +===================== + +This module is highly inspired from the module 'Sale Order Margin', by Odoo SA. + +Known issues / Roadmap +====================== + +* include extra reporting, using the new margin field. + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Sylvain LE GAL (https://twitter.com/legalsylvain) + +Funders +------- + +The development of this module has been financially supported by: + +* GRAP, Groupement Régional Alimentaire de Proximité (www.grap.coop) + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. + diff --git a/pos_margin/__init__.py b/pos_margin/__init__.py new file mode 100644 index 0000000000..402ac47e3f --- /dev/null +++ b/pos_margin/__init__.py @@ -0,0 +1,2 @@ +# -#- coding: utf-8 -#- +from . import models diff --git a/pos_margin/__manifest__.py b/pos_margin/__manifest__.py new file mode 100644 index 0000000000..7569aaa57f --- /dev/null +++ b/pos_margin/__manifest__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2017 - 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': 'POS Margin', + 'version': '10.0.1.0.0', + 'category': 'Point Of Sale', + 'sequence': 1, + 'author': "GRAP," + "Odoo Community Association (OCA)", + 'summary': 'Margin on PoS Order', + 'license': 'AGPL-3', + 'depends': [ + 'point_of_sale', + ], + 'data': [ + 'views/view_pos_order.xml', + ], + 'installable': True, +} diff --git a/pos_margin/i18n/es.po b/pos_margin/i18n/es.po new file mode 100644 index 0000000000..8ab92724b8 --- /dev/null +++ b/pos_margin/i18n/es.po @@ -0,0 +1,50 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_margin +# +# Translators: +# OCA Transbot , 2017 +# enjolras , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-01 02:01+0000\n" +"PO-Revision-Date: 2018-03-01 02:01+0000\n" +"Last-Translator: enjolras , 2018\n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +msgid "Cost Price" +msgstr "Precio de coste" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_order_margin +msgid "" +"It gives profitability by calculating the difference between the Unit Price " +"and the cost price." +msgstr "" +"Indica el beneficio calculando la diferencia entre el precio unitario y el " +"precio de coste." + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "Líneas del punto de venta" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +msgid "Margin" +msgstr "Margen" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order +msgid "Point of Sale Orders" +msgstr "Pedidos del TPV" diff --git a/pos_margin/i18n/fr.po b/pos_margin/i18n/fr.po new file mode 100644 index 0000000000..b982c082fa --- /dev/null +++ b/pos_margin/i18n/fr.po @@ -0,0 +1,49 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_margin +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-04-25 02:39+0000\n" +"PO-Revision-Date: 2017-04-25 02:39+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +msgid "Cost Price" +msgstr "Prix de revient" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_order_margin +msgid "" +"It gives profitability by calculating the difference between the Unit Price " +"and the cost price." +msgstr "" +"Il donne la rentabilité en calculant la différence entre le prix unitaire et " +"le prix de revient." + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "Lignes de Points de Vente" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +msgid "Margin" +msgstr "Marge" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order +msgid "Point of Sale Orders" +msgstr "" diff --git a/pos_margin/i18n/it.po b/pos_margin/i18n/it.po new file mode 100644 index 0000000000..69a4ed6748 --- /dev/null +++ b/pos_margin/i18n/it.po @@ -0,0 +1,47 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_margin +# +# Translators: +# Francesco Fresta , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-01 02:01+0000\n" +"PO-Revision-Date: 2018-03-01 02:01+0000\n" +"Last-Translator: Francesco Fresta , 2018\n" +"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +msgid "Cost Price" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_order_margin +msgid "" +"It gives profitability by calculating the difference between the Unit Price " +"and the cost price." +msgstr "" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +msgid "Margin" +msgstr "Margine" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order +msgid "Point of Sale Orders" +msgstr "Punto di riordino" diff --git a/pos_margin/i18n/nl_NL.po b/pos_margin/i18n/nl_NL.po new file mode 100644 index 0000000000..6d8cd895a5 --- /dev/null +++ b/pos_margin/i18n/nl_NL.po @@ -0,0 +1,48 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_margin +# +# Translators: +# Peter Hageman , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-30 02:44+0000\n" +"PO-Revision-Date: 2017-05-30 02:44+0000\n" +"Last-Translator: Peter Hageman , 2017\n" +"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/" +"teams/23907/nl_NL/)\n" +"Language: nl_NL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +msgid "Cost Price" +msgstr "Kostprijs" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_order_margin +msgid "" +"It gives profitability by calculating the difference between the Unit Price " +"and the cost price." +msgstr "" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +msgid "Margin" +msgstr "Marge" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order +msgid "Point of Sale Orders" +msgstr "Kassaorders" diff --git a/pos_margin/i18n/pos_margin.pot b/pos_margin/i18n/pos_margin.pot new file mode 100644 index 0000000000..b91d0ddbdb --- /dev/null +++ b/pos_margin/i18n/pos_margin.pot @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_margin +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \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_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +msgid "Cost Price" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_order_margin +msgid "It gives profitability by calculating the difference between the Unit Price and the cost price." +msgstr "" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Lines of Point of Sale" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +msgid "Margin" +msgstr "" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + diff --git a/pos_margin/models/__init__.py b/pos_margin/models/__init__.py new file mode 100644 index 0000000000..83e7482117 --- /dev/null +++ b/pos_margin/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import pos_order +from . import pos_order_line diff --git a/pos_margin/models/pos_order.py b/pos_margin/models/pos_order.py new file mode 100644 index 0000000000..824da0b24c --- /dev/null +++ b/pos_margin/models/pos_order.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2017 - 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, fields, models +import openerp.addons.decimal_precision as dp + + +class PosOrder(models.Model): + _inherit = 'pos.order' + + # Columns Section + margin = fields.Float( + 'Margin', compute='_compute_margin', store=True, + digits=dp.get_precision('Product Price'), + help="It gives profitability by calculating the difference between" + " the Unit Price and the cost price.") + + # Compute Section + @api.multi + @api.depends('lines.margin') + def _compute_margin(self): + for order in self: + order.margin = sum(order.mapped('lines.margin')) diff --git a/pos_margin/models/pos_order_line.py b/pos_margin/models/pos_order_line.py new file mode 100644 index 0000000000..ac18deced2 --- /dev/null +++ b/pos_margin/models/pos_order_line.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2017 - 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, fields, models +import openerp.addons.decimal_precision as dp + + +class PosOrderLine(models.Model): + _inherit = 'pos.order.line' + + # Columns Section + margin = fields.Float( + 'Margin', compute='_compute_multi_margin', store=True, + multi='multi_margin', digits=dp.get_precision('Product Price')) + + purchase_price = fields.Float( + 'Cost Price', compute='_compute_multi_margin', store=True, + multi='multi_margin', digits=dp.get_precision('Product Price')) + + # Compute Section + @api.multi + @api.depends('product_id', 'qty', 'price_subtotal') + def _compute_multi_margin(self): + for line in self: + if not line.product_id: + line.purchase_price = 0 + line.margin = 0 + else: + line.purchase_price = line.product_id.standard_price + line.margin = line.price_subtotal - ( + line.product_id.standard_price * line.qty) diff --git a/pos_margin/static/description/pos_order_form.png b/pos_margin/static/description/pos_order_form.png new file mode 100644 index 0000000000000000000000000000000000000000..392b816a6e3800f6ab2e4f18e3e619f0d4380519 GIT binary patch literal 28285 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 Mb^ZH + + + + + + pos.order + + + + + + + + + + + + + + From 7c567daaec1891a625b6506325dbeac41404acff Mon Sep 17 00:00:00 2001 From: Invitu Date: Thu, 25 Oct 2018 21:30:33 -1000 Subject: [PATCH 02/16] [MIG] pos_margin:Migration to 11.0 --- pos_margin/__init__.py | 1 - pos_margin/__manifest__.py | 3 +-- pos_margin/models/__init__.py | 1 - pos_margin/models/pos_order.py | 1 - pos_margin/models/pos_order_line.py | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pos_margin/__init__.py b/pos_margin/__init__.py index 402ac47e3f..0650744f6b 100644 --- a/pos_margin/__init__.py +++ b/pos_margin/__init__.py @@ -1,2 +1 @@ -# -#- coding: utf-8 -#- from . import models diff --git a/pos_margin/__manifest__.py b/pos_margin/__manifest__.py index 7569aaa57f..0ad87fba7f 100644 --- a/pos_margin/__manifest__.py +++ b/pos_margin/__manifest__.py @@ -1,11 +1,10 @@ -# -*- coding: utf-8 -*- # Copyright (C) 2017 - 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': 'POS Margin', - 'version': '10.0.1.0.0', + 'version': '11.0.1.0.0', 'category': 'Point Of Sale', 'sequence': 1, 'author': "GRAP," diff --git a/pos_margin/models/__init__.py b/pos_margin/models/__init__.py index 83e7482117..64f952d518 100644 --- a/pos_margin/models/__init__.py +++ b/pos_margin/models/__init__.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- from . import pos_order from . import pos_order_line diff --git a/pos_margin/models/pos_order.py b/pos_margin/models/pos_order.py index 824da0b24c..63f570cc73 100644 --- a/pos_margin/models/pos_order.py +++ b/pos_margin/models/pos_order.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (C) 2017 - 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). diff --git a/pos_margin/models/pos_order_line.py b/pos_margin/models/pos_order_line.py index ac18deced2..8510d6f3f3 100644 --- a/pos_margin/models/pos_order_line.py +++ b/pos_margin/models/pos_order_line.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (C) 2017 - 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 c45ef36efdf34c4f454a76b9e5fb58c874201e09 Mon Sep 17 00:00:00 2001 From: Invitu Date: Wed, 14 Nov 2018 00:39:47 -1000 Subject: [PATCH 03/16] [IMP] Add pos margin in pos order report --- pos_margin/__init__.py | 1 + pos_margin/i18n/es.po | 21 ++++++++++++++++++++- pos_margin/i18n/fr.po | 20 +++++++++++++++++++- pos_margin/i18n/it.po | 23 +++++++++++++++++++++-- pos_margin/i18n/nl_NL.po | 23 +++++++++++++++++++++-- pos_margin/i18n/pos_margin.pot | 19 +++++++++++++++++-- pos_margin/report/__init__.py | 2 ++ pos_margin/report/pos_order_report.py | 15 +++++++++++++++ pos_margin/static/description/icon.png | Bin 0 -> 9455 bytes 9 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 pos_margin/report/__init__.py create mode 100644 pos_margin/report/pos_order_report.py create mode 100644 pos_margin/static/description/icon.png diff --git a/pos_margin/__init__.py b/pos_margin/__init__.py index 0650744f6b..bf588bc8b8 100644 --- a/pos_margin/__init__.py +++ b/pos_margin/__init__.py @@ -1 +1,2 @@ from . import models +from . import report diff --git a/pos_margin/i18n/es.po b/pos_margin/i18n/es.po index 8ab92724b8..b6116868c9 100644 --- a/pos_margin/i18n/es.po +++ b/pos_margin/i18n/es.po @@ -35,7 +35,8 @@ msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line -msgid "Lines of Point of Sale" +#, fuzzy +msgid "Lines of Point of Sale Orders" msgstr "Líneas del punto de venta" #. module: pos_margin @@ -44,7 +45,25 @@ msgstr "Líneas del punto de venta" msgid "Margin" msgstr "Margen" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate +#, fuzzy +msgid "Margin Rate" +msgstr "Margen" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total +#, fuzzy +msgid "Margin Total" +msgstr "Margen" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" msgstr "Pedidos del TPV" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_report_pos_order +#, fuzzy +msgid "Point of Sale Orders Statistics" +msgstr "Pedidos del TPV" diff --git a/pos_margin/i18n/fr.po b/pos_margin/i18n/fr.po index b982c082fa..33b5016d8a 100644 --- a/pos_margin/i18n/fr.po +++ b/pos_margin/i18n/fr.po @@ -34,7 +34,8 @@ msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line -msgid "Lines of Point of Sale" +#, fuzzy +msgid "Lines of Point of Sale Orders" msgstr "Lignes de Points de Vente" #. module: pos_margin @@ -43,7 +44,24 @@ msgstr "Lignes de Points de Vente" msgid "Margin" msgstr "Marge" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate +#, fuzzy +msgid "Margin Rate" +msgstr "Marge" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total +#, fuzzy +msgid "Margin Total" +msgstr "Marge" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" msgstr "" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_report_pos_order +msgid "Point of Sale Orders Statistics" +msgstr "" diff --git a/pos_margin/i18n/it.po b/pos_margin/i18n/it.po index 69a4ed6748..019547b7d4 100644 --- a/pos_margin/i18n/it.po +++ b/pos_margin/i18n/it.po @@ -32,8 +32,9 @@ msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line -msgid "Lines of Point of Sale" -msgstr "" +#, fuzzy +msgid "Lines of Point of Sale Orders" +msgstr "Punto di riordino" #. module: pos_margin #: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin @@ -41,7 +42,25 @@ msgstr "" msgid "Margin" msgstr "Margine" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate +#, fuzzy +msgid "Margin Rate" +msgstr "Margine" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total +#, fuzzy +msgid "Margin Total" +msgstr "Margine" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" msgstr "Punto di riordino" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_report_pos_order +#, fuzzy +msgid "Point of Sale Orders Statistics" +msgstr "Punto di riordino" diff --git a/pos_margin/i18n/nl_NL.po b/pos_margin/i18n/nl_NL.po index 6d8cd895a5..b560206c61 100644 --- a/pos_margin/i18n/nl_NL.po +++ b/pos_margin/i18n/nl_NL.po @@ -33,8 +33,9 @@ msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line -msgid "Lines of Point of Sale" -msgstr "" +#, fuzzy +msgid "Lines of Point of Sale Orders" +msgstr "Kassaorders" #. module: pos_margin #: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin @@ -42,7 +43,25 @@ msgstr "" msgid "Margin" msgstr "Marge" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate +#, fuzzy +msgid "Margin Rate" +msgstr "Marge" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total +#, fuzzy +msgid "Margin Total" +msgstr "Marge" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" msgstr "Kassaorders" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_report_pos_order +#, fuzzy +msgid "Point of Sale Orders Statistics" +msgstr "Kassaorders" diff --git a/pos_margin/i18n/pos_margin.pot b/pos_margin/i18n/pos_margin.pot index b91d0ddbdb..2f5b529a6c 100644 --- a/pos_margin/i18n/pos_margin.pot +++ b/pos_margin/i18n/pos_margin.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 10.0\n" +"Project-Id-Version: Odoo Server 11.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: <>\n" "Language-Team: \n" @@ -25,7 +25,7 @@ msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line -msgid "Lines of Point of Sale" +msgid "Lines of Point of Sale Orders" msgstr "" #. module: pos_margin @@ -34,8 +34,23 @@ msgstr "" msgid "Margin" msgstr "" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate +msgid "Margin Rate" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total +msgid "Margin Total" +msgstr "" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" msgstr "" +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_report_pos_order +msgid "Point of Sale Orders Statistics" +msgstr "" + diff --git a/pos_margin/report/__init__.py b/pos_margin/report/__init__.py new file mode 100644 index 0000000000..225fc1d2af --- /dev/null +++ b/pos_margin/report/__init__.py @@ -0,0 +1,2 @@ +from . import pos_order_report + diff --git a/pos_margin/report/pos_order_report.py b/pos_margin/report/pos_order_report.py new file mode 100644 index 0000000000..ae826b405a --- /dev/null +++ b/pos_margin/report/pos_order_report.py @@ -0,0 +1,15 @@ +from odoo import fields, models + + +class PosOrderReport(models.Model): + _inherit = 'report.pos.order' + + margin_total = fields.Float(string='Margin Total') + margin_rate = fields.Float(string='Margin Rate', group_operator='avg') + + def _select(self): + return super(PosOrderReport, self)._select() + """, + SUM(l.margin) as margin_total, + (SUM(l.margin / nullif(l.qty,0)) * 100 / + SUM(nullif(l.purchase_price,0)))::decimal as margin_rate + """ diff --git a/pos_margin/static/description/icon.png b/pos_margin/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 From fe04ea51cf2046ba68bad7d7b56e3da755d1c754 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Thu, 15 Aug 2019 11:48:26 +0200 Subject: [PATCH 04/16] [MIG] pos_margin: Migration to 12.0 --- pos_margin/README.rst | 103 ++-- pos_margin/__manifest__.py | 9 +- pos_margin/i18n/fr.po | 56 +-- pos_margin/i18n/pos_margin.pot | 27 +- pos_margin/models/pos_order.py | 2 +- pos_margin/models/pos_order_line.py | 28 +- pos_margin/readme/CONTRIBUTORS.rst | 2 + pos_margin/readme/DESCRIPTION.rst | 5 + pos_margin/readme/HISTORY.rst | 8 + pos_margin/readme/ROADMAP.rst | 7 + pos_margin/readme/USAGE.rst | 7 + pos_margin/static/description/index.html | 462 ++++++++++++++++++ .../static/description/pos_order_form.png | Bin 28285 -> 30651 bytes pos_margin/tests/__init__.py | 1 + pos_margin/tests/test_module.py | 68 +++ pos_margin/views/view_pos_order.xml | 20 +- 16 files changed, 706 insertions(+), 99 deletions(-) create mode 100644 pos_margin/readme/CONTRIBUTORS.rst create mode 100644 pos_margin/readme/DESCRIPTION.rst create mode 100644 pos_margin/readme/HISTORY.rst create mode 100644 pos_margin/readme/ROADMAP.rst create mode 100644 pos_margin/readme/USAGE.rst create mode 100644 pos_margin/static/description/index.html create mode 100644 pos_margin/tests/__init__.py create mode 100644 pos_margin/tests/test_module.py diff --git a/pos_margin/README.rst b/pos_margin/README.rst index 4554966ca9..6263379a9a 100644 --- a/pos_margin/README.rst +++ b/pos_margin/README.rst @@ -1,10 +1,29 @@ -.. 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 - -=================== -Margin on PoS order -=================== +================ +PoS Order Margin +================ + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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_margin + :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_margin + :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 extends the functionality of point of sale to support margin on pos orders. @@ -12,68 +31,82 @@ pos orders. This gives the profitability by calculating the difference between the Unit Price and Cost Price. +**Table of contents** + +.. contents:: + :local: Usage ===== To use this module, you need to: -#. Go to 'Point Of Sale' / 'Daily Operations' / 'Orders' -#. Open an order +* Go to 'Point Of Sale' / 'Orders' / 'Orders' +* Open an order -.. figure:: ./pos_margin/static/description/pos_order_form.png +.. figure:: https://raw.githubusercontent.com/OCA/pos/12.0/pos_margin/static/description/pos_order_form.png :width: 800px -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/184/8.0 +Known issues / Roadmap +====================== +This module depends on ``sale_margin`` module to reuse algorithm present in the +function ``_get_purchase_price`` of the model ``sale.order.line`` to +compute correctly purchase price, in a multicurrency context. -Technical information -===================== +This dependency can be removed, when Odoo Core will be correctly refactored, +moving this ``@api.model`` function in a more generic module (``account`` +for exemple). -This module is highly inspired from the module 'Sale Order Margin', by Odoo SA. +Changelog +========= -Known issues / Roadmap -====================== +12.0.1.0.0 +~~~~~~~~~~ -* include extra reporting, using the new margin field. +* Migrate to V12.0 +* Reuse ``sale_margin`` computation to handle multi currency context. +* Correct computation of margin, if a module that adds ``uom_id`` on + ``pos.order.line`` is installed. +* Add test 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 smash it by providing detailed and welcomed feedback. +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 ======= -Contributors ------------- +Authors +~~~~~~~ -* Sylvain LE GAL (https://twitter.com/legalsylvain) +* GRAP -Funders -------- +Contributors +~~~~~~~~~~~~ -The development of this module has been financially supported by: +* Sylvain LE GAL (https://twitter.com/legalsylvain) +* Wolfgang Pichler -* GRAP, Groupement Régional Alimentaire de Proximité (www.grap.coop) +Maintainers +~~~~~~~~~~~ -Maintainer ----------- +This module is maintained by the OCA. .. image:: https://odoo-community.org/logo.png :alt: Odoo Community Association :target: https://odoo-community.org -This module is maintained by the OCA. - OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit https://odoo-community.org. +This module is part of the `OCA/pos `_ project on GitHub. +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_margin/__manifest__.py b/pos_margin/__manifest__.py index 0ad87fba7f..38502c1bac 100644 --- a/pos_margin/__manifest__.py +++ b/pos_margin/__manifest__.py @@ -3,16 +3,17 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'POS Margin', - 'version': '11.0.1.0.0', + 'name': 'PoS Order Margin', + 'summary': 'Margin on PoS Order', + 'version': '12.0.1.0.0', 'category': 'Point Of Sale', - 'sequence': 1, 'author': "GRAP," "Odoo Community Association (OCA)", - 'summary': 'Margin on PoS Order', + 'website': 'https://github.com/OCA/pos', 'license': 'AGPL-3', 'depends': [ 'point_of_sale', + 'sale_margin', ], 'data': [ 'views/view_pos_order.xml', diff --git a/pos_margin/i18n/fr.po b/pos_margin/i18n/fr.po index 33b5016d8a..d86a037ab4 100644 --- a/pos_margin/i18n/fr.po +++ b/pos_margin/i18n/fr.po @@ -1,67 +1,61 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * pos_margin +# * pos_margin # -# Translators: -# OCA Transbot , 2017 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 10.0\n" +"Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-04-25 02:39+0000\n" -"PO-Revision-Date: 2017-04-25 02:39+0000\n" -"Last-Translator: OCA Transbot , 2017\n" -"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" -"Language: fr\n" +"POT-Creation-Date: 2019-08-15 11:05+0000\n" +"PO-Revision-Date: 2019-08-15 11:05+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: nplurals=2; plural=(n > 1);\n" +"Plural-Forms: \n" #. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__purchase_price msgid "Cost Price" msgstr "Prix de revient" #. module: pos_margin -#: model:ir.model.fields,help:pos_margin.field_pos_order_margin -msgid "" -"It gives profitability by calculating the difference between the Unit Price " -"and the cost price." +#: model:ir.model.fields,help:pos_margin.field_pos_order__margin +msgid "It gives profitability by calculating the difference between the Unit Price and the cost price." msgstr "" "Il donne la rentabilité en calculant la différence entre le prix unitaire et " "le prix de revient." #. module: pos_margin -#: model:ir.model,name:pos_margin.model_pos_order_line -#, fuzzy -msgid "Lines of Point of Sale Orders" -msgstr "Lignes de Points de Vente" - -#. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin -#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order__margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__margin msgid "Margin" msgstr "Marge" #. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate -#, fuzzy +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__margin_rate msgid "Margin Rate" -msgstr "Marge" +msgstr "Taux de marque" #. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total -#, fuzzy +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__margin_total +#: model_terms:ir.ui.view,arch_db:pos_margin.view_pos_order_tree msgid "Margin Total" -msgstr "Marge" +msgstr "Marge Totale" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Point of Sale Order Lines" +msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" -msgstr "" +msgstr "Commandes du point de vente" #. module: pos_margin #: model:ir.model,name:pos_margin.model_report_pos_order -msgid "Point of Sale Orders Statistics" +msgid "Point of Sale Orders Report" msgstr "" + diff --git a/pos_margin/i18n/pos_margin.pot b/pos_margin/i18n/pos_margin.pot index 2f5b529a6c..db529121fe 100644 --- a/pos_margin/i18n/pos_margin.pot +++ b/pos_margin/i18n/pos_margin.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 11.0\n" +"Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: <>\n" "Language-Team: \n" @@ -14,36 +14,37 @@ msgstr "" "Plural-Forms: \n" #. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_purchase_price +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__purchase_price msgid "Cost Price" msgstr "" #. module: pos_margin -#: model:ir.model.fields,help:pos_margin.field_pos_order_margin +#: model:ir.model.fields,help:pos_margin.field_pos_order__margin msgid "It gives profitability by calculating the difference between the Unit Price and the cost price." msgstr "" #. module: pos_margin -#: model:ir.model,name:pos_margin.model_pos_order_line -msgid "Lines of Point of Sale Orders" -msgstr "" - -#. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line_margin -#: model:ir.model.fields,field_description:pos_margin.field_pos_order_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order__margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__margin msgid "Margin" msgstr "" #. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_rate +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__margin_rate msgid "Margin Rate" msgstr "" #. module: pos_margin -#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order_margin_total +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__margin_total +#: model_terms:ir.ui.view,arch_db:pos_margin.view_pos_order_tree msgid "Margin Total" msgstr "" +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_order_line +msgid "Point of Sale Order Lines" +msgstr "" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order msgid "Point of Sale Orders" @@ -51,6 +52,6 @@ msgstr "" #. module: pos_margin #: model:ir.model,name:pos_margin.model_report_pos_order -msgid "Point of Sale Orders Statistics" +msgid "Point of Sale Orders Report" msgstr "" diff --git a/pos_margin/models/pos_order.py b/pos_margin/models/pos_order.py index 63f570cc73..e3f306bcd5 100644 --- a/pos_margin/models/pos_order.py +++ b/pos_margin/models/pos_order.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import api, fields, models -import openerp.addons.decimal_precision as dp +import odoo.addons.decimal_precision as dp class PosOrder(models.Model): diff --git a/pos_margin/models/pos_order_line.py b/pos_margin/models/pos_order_line.py index 8510d6f3f3..9cb14f33c1 100644 --- a/pos_margin/models/pos_order_line.py +++ b/pos_margin/models/pos_order_line.py @@ -3,7 +3,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import api, fields, models -import openerp.addons.decimal_precision as dp +import odoo.addons.decimal_precision as dp class PosOrderLine(models.Model): @@ -22,11 +22,21 @@ class PosOrderLine(models.Model): @api.multi @api.depends('product_id', 'qty', 'price_subtotal') def _compute_multi_margin(self): - for line in self: - if not line.product_id: - line.purchase_price = 0 - line.margin = 0 - else: - line.purchase_price = line.product_id.standard_price - line.margin = line.price_subtotal - ( - line.product_id.standard_price * line.qty) + for line in self.filtered('product_id'): + purchase_price = self._get_purchase_price(line) + line.purchase_price = purchase_price + line.margin = line.price_subtotal - (purchase_price * line.qty) + + @api.model + def _get_purchase_price(self, line): + # We call _get_purchase_price from sale_margin module, to reuse + # computation that handles multi currencies context and UoM + SaleOrderLine = self.env['sale.order.line'] + + # if used in combination with module which does add the uom_id to line + uom = hasattr(line, 'uom_id') and line.uom_id\ + or line.product_id.uom_id + + return SaleOrderLine._get_purchase_price( + line.order_id.pricelist_id, line.product_id, uom, + line.order_id.date_order)['purchase_price'] diff --git a/pos_margin/readme/CONTRIBUTORS.rst b/pos_margin/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..3b5f099616 --- /dev/null +++ b/pos_margin/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Sylvain LE GAL (https://twitter.com/legalsylvain) +* Wolfgang Pichler diff --git a/pos_margin/readme/DESCRIPTION.rst b/pos_margin/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..48bcde4bca --- /dev/null +++ b/pos_margin/readme/DESCRIPTION.rst @@ -0,0 +1,5 @@ +This module extends the functionality of point of sale to support margin on +pos orders. + +This gives the profitability by calculating the difference between the Unit +Price and Cost Price. diff --git a/pos_margin/readme/HISTORY.rst b/pos_margin/readme/HISTORY.rst new file mode 100644 index 0000000000..04bbd26949 --- /dev/null +++ b/pos_margin/readme/HISTORY.rst @@ -0,0 +1,8 @@ +12.0.1.0.0 +~~~~~~~~~~ + +* Migrate to V12.0 +* Reuse ``sale_margin`` computation to handle multi currency context. +* Correct computation of margin, if a module that adds ``uom_id`` on + ``pos.order.line`` is installed. +* Add test diff --git a/pos_margin/readme/ROADMAP.rst b/pos_margin/readme/ROADMAP.rst new file mode 100644 index 0000000000..c01e849efd --- /dev/null +++ b/pos_margin/readme/ROADMAP.rst @@ -0,0 +1,7 @@ +This module depends on ``sale_margin`` module to reuse algorithm present in the +function ``_get_purchase_price`` of the model ``sale.order.line`` to +compute correctly purchase price, in a multicurrency context. + +This dependency can be removed, when Odoo Core will be correctly refactored, +moving this ``@api.model`` function in a more generic module (``account`` +for exemple). diff --git a/pos_margin/readme/USAGE.rst b/pos_margin/readme/USAGE.rst new file mode 100644 index 0000000000..e719a37a36 --- /dev/null +++ b/pos_margin/readme/USAGE.rst @@ -0,0 +1,7 @@ +To use this module, you need to: + +* Go to 'Point Of Sale' / 'Orders' / 'Orders' +* Open an order + +.. figure:: ../static/description/pos_order_form.png + :width: 800px diff --git a/pos_margin/static/description/index.html b/pos_margin/static/description/index.html new file mode 100644 index 0000000000..f0091af0bb --- /dev/null +++ b/pos_margin/static/description/index.html @@ -0,0 +1,462 @@ + + + + + + +PoS Order Margin + + + +
+

PoS Order Margin

+ + +

Beta License: AGPL-3 OCA/pos Translate me on Weblate Try me on Runbot

+

This module extends the functionality of point of sale to support margin on +pos orders.

+

This gives the profitability by calculating the difference between the Unit +Price and Cost Price.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  • Go to ‘Point Of Sale’ / ‘Orders’ / ‘Orders’
  • +
  • Open an order
  • +
+
+https://raw.githubusercontent.com/OCA/pos/12.0/pos_margin/static/description/pos_order_form.png +
+
+
+

Known issues / Roadmap

+

This module depends on sale_margin module to reuse algorithm present in the +function _get_purchase_price of the model sale.order.line to +compute correctly purchase price, in a multicurrency context.

+

This dependency can be removed, when Odoo Core will be correctly refactored, +moving this @api.model function in a more generic module (account +for exemple).

+
+
+

Changelog

+
+

12.0.1.0.0

+
    +
  • Migrate to V12.0
  • +
  • Reuse sale_margin computation to handle multi currency context.
  • +
  • Correct computation of margin, if a module that adds uom_id on +pos.order.line is installed.
  • +
  • Add test
  • +
+
+
+
+

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

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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 project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/pos_margin/static/description/pos_order_form.png b/pos_margin/static/description/pos_order_form.png index 392b816a6e3800f6ab2e4f18e3e619f0d4380519..22601768290cbc5d364db1d5b5b7397e3f5b7246 100644 GIT binary patch literal 30651 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 Mb^ZHpos.order - - - - - + + + - + + + pos.order + + + + + + + + From a1568144b0ce1622a94ed3a90f6ed18f70166822 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Thu, 10 Jun 2021 13:19:51 +0200 Subject: [PATCH 05/16] [IMP] pos_margin : display margin and margin rate in front-end UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Iván Todorovich --- pos_margin/__manifest__.py | 18 +++-- pos_margin/i18n/fr.po | 43 ++++++++++-- pos_margin/i18n/pos_margin.pot | 27 +++++++- .../migrations/12.0.2.0.0/pre-migration.py | 14 ++++ pos_margin/models/__init__.py | 1 + pos_margin/models/pos_config.py | 15 +++++ pos_margin/readme/CONFIGURE.rst | 4 ++ pos_margin/readme/USAGE.rst | 10 +++ .../static/description/pos_config_form.png | Bin 0 -> 24231 bytes .../static/description/pos_front_end.png | Bin 0 -> 47922 bytes pos_margin/static/src/css/pos_margin.css | 8 +++ pos_margin/static/src/js/models.js | 62 ++++++++++++++++++ pos_margin/static/src/js/screens.js | 22 +++++++ pos_margin/static/src/xml/pos_margin.xml | 35 ++++++++++ pos_margin/views/templates.xml | 16 +++++ pos_margin/views/view_pos_config.xml | 30 +++++++++ 16 files changed, 292 insertions(+), 13 deletions(-) create mode 100644 pos_margin/migrations/12.0.2.0.0/pre-migration.py create mode 100644 pos_margin/models/pos_config.py create mode 100644 pos_margin/readme/CONFIGURE.rst create mode 100644 pos_margin/static/description/pos_config_form.png create mode 100644 pos_margin/static/description/pos_front_end.png create mode 100644 pos_margin/static/src/css/pos_margin.css create mode 100644 pos_margin/static/src/js/models.js create mode 100644 pos_margin/static/src/js/screens.js create mode 100644 pos_margin/static/src/xml/pos_margin.xml create mode 100644 pos_margin/views/templates.xml create mode 100644 pos_margin/views/view_pos_config.xml diff --git a/pos_margin/__manifest__.py b/pos_margin/__manifest__.py index 38502c1bac..9ddcd4a189 100644 --- a/pos_margin/__manifest__.py +++ b/pos_margin/__manifest__.py @@ -5,18 +5,24 @@ { 'name': 'PoS Order Margin', 'summary': 'Margin on PoS Order', - 'version': '12.0.1.0.0', + 'version': '12.0.2.0.0', 'category': 'Point Of Sale', 'author': "GRAP," "Odoo Community Association (OCA)", - 'website': 'https://github.com/OCA/pos', - 'license': 'AGPL-3', - 'depends': [ - 'point_of_sale', - 'sale_margin', + "maintainers": ["legalsylvain"], + "website": "https://github.com/OCA/pos", + "license": "AGPL-3", + "depends": [ + "point_of_sale", + "sale_margin", ], 'data': [ + 'views/templates.xml', + 'views/view_pos_config.xml', 'views/view_pos_order.xml', ], + 'qweb': [ + 'static/src/xml/pos_margin.xml', + ], 'installable': True, } diff --git a/pos_margin/i18n/fr.po b/pos_margin/i18n/fr.po index d86a037ab4..43bbc1e278 100644 --- a/pos_margin/i18n/fr.po +++ b/pos_margin/i18n/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-15 11:05+0000\n" -"PO-Revision-Date: 2019-08-15 11:05+0000\n" +"POT-Creation-Date: 2021-06-11 14:57+0000\n" +"PO-Revision-Date: 2021-06-11 14:57+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -20,12 +20,21 @@ msgstr "" msgid "Cost Price" msgstr "Prix de revient" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_config__iface_display_margin +msgid "Diplay Margin" +msgstr "Afficher la marge" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_config__iface_display_margin +#: model_terms:ir.ui.view,arch_db:pos_margin.view_pos_config_form +msgid "Display Margin and Margin Rate in the frontend" +msgstr "Afficher la marge et le taux de marge sur l'interface tactile" + #. module: pos_margin #: model:ir.model.fields,help:pos_margin.field_pos_order__margin msgid "It gives profitability by calculating the difference between the Unit Price and the cost price." -msgstr "" -"Il donne la rentabilité en calculant la différence entre le prix unitaire et " -"le prix de revient." +msgstr "Il donne la rentabilité en calculant la différence entre le prix unitaire et le prix de revient." #. module: pos_margin #: model:ir.model.fields,field_description:pos_margin.field_pos_order__margin @@ -33,6 +42,12 @@ msgstr "" msgid "Margin" msgstr "Marge" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_order__margin_percent +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__margin_percent +msgid "Margin (%)" +msgstr "Taux de marque (%)" + #. module: pos_margin #: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__margin_rate msgid "Margin Rate" @@ -44,10 +59,22 @@ msgstr "Taux de marque" msgid "Margin Total" msgstr "Marge Totale" +#. module: pos_margin +#. openerp-web +#: code:addons/pos_margin/static/src/xml/pos_margin.xml:26 +#, python-format +msgid "Margin:" +msgstr "Marge :" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Paramétrage du point de vente" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line msgid "Point of Sale Order Lines" -msgstr "" +msgstr "Lignes des commandes du point de vente" #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order @@ -59,3 +86,7 @@ msgstr "Commandes du point de vente" msgid "Point of Sale Orders Report" msgstr "" +#. module: pos_margin +#: model_terms:ir.ui.view,arch_db:pos_margin.view_pos_order_tree +msgid "Total" +msgstr "" diff --git a/pos_margin/i18n/pos_margin.pot b/pos_margin/i18n/pos_margin.pot index db529121fe..d5b834b72c 100644 --- a/pos_margin/i18n/pos_margin.pot +++ b/pos_margin/i18n/pos_margin.pot @@ -1,11 +1,13 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * pos_margin +# * pos_margin # msgid "" msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-06-11 14:57+0000\n" +"PO-Revision-Date: 2021-06-11 14:57+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -18,6 +20,17 @@ msgstr "" msgid "Cost Price" msgstr "" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_config__iface_display_margin +msgid "Diplay Margin" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,help:pos_margin.field_pos_config__iface_display_margin +#: model_terms:ir.ui.view,arch_db:pos_margin.view_pos_config_form +msgid "Display Margin and Margin Rate in the frontend" +msgstr "" + #. module: pos_margin #: model:ir.model.fields,help:pos_margin.field_pos_order__margin msgid "It gives profitability by calculating the difference between the Unit Price and the cost price." @@ -40,6 +53,18 @@ msgstr "" msgid "Margin Total" msgstr "" +#. module: pos_margin +#. openerp-web +#: code:addons/pos_margin/static/src/xml/pos_margin.xml:26 +#, python-format +msgid "Margin:" +msgstr "" + +#. module: pos_margin +#: model:ir.model,name:pos_margin.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + #. module: pos_margin #: model:ir.model,name:pos_margin.model_pos_order_line msgid "Point of Sale Order Lines" diff --git a/pos_margin/migrations/12.0.2.0.0/pre-migration.py b/pos_margin/migrations/12.0.2.0.0/pre-migration.py new file mode 100644 index 0000000000..6f1154cf61 --- /dev/null +++ b/pos_margin/migrations/12.0.2.0.0/pre-migration.py @@ -0,0 +1,14 @@ +# Copyright (C) 2020 - 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). + + +def migrate(cr, version): + cr.execute(""" + ALTER TABLE pos_config + ADD COLUMN iface_display_margin bool; + """) + cr.execute(""" + UPDATE pos_config + SET iface_display_margin = false; + """) diff --git a/pos_margin/models/__init__.py b/pos_margin/models/__init__.py index 64f952d518..947532d9f5 100644 --- a/pos_margin/models/__init__.py +++ b/pos_margin/models/__init__.py @@ -1,2 +1,3 @@ +from . import pos_config from . import pos_order from . import pos_order_line diff --git a/pos_margin/models/pos_config.py b/pos_margin/models/pos_config.py new file mode 100644 index 0000000000..b216dae96a --- /dev/null +++ b/pos_margin/models/pos_config.py @@ -0,0 +1,15 @@ +# Copyright (C) 2021 - 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, models + + +class PosConfig(models.Model): + _inherit = 'pos.config' + + iface_display_margin = fields.Boolean( + string='Diplay Margin', + help='Display Margin and Margin Rate in the frontend', + default=True, + ) diff --git a/pos_margin/readme/CONFIGURE.rst b/pos_margin/readme/CONFIGURE.rst new file mode 100644 index 0000000000..7c161346a4 --- /dev/null +++ b/pos_margin/readme/CONFIGURE.rst @@ -0,0 +1,4 @@ +* If you want to disable the display of the margin, in the front-office UI, you can + uncheck the check box in the ``pos.config`` form: + +.. figure:: ../static/description/pos_config_form.png diff --git a/pos_margin/readme/USAGE.rst b/pos_margin/readme/USAGE.rst index e719a37a36..72157d36fd 100644 --- a/pos_margin/readme/USAGE.rst +++ b/pos_margin/readme/USAGE.rst @@ -1,3 +1,13 @@ +**In the PoS Front Office** + +* Make an order. Each time a line is added, updated, or deleted, the margin and the margin rate + will be updated. + +.. figure:: ../static/description/pos_front_end.png + :width: 800px + +**In the PoS Back Office** + To use this module, you need to: * Go to 'Point Of Sale' / 'Orders' / 'Orders' diff --git a/pos_margin/static/description/pos_config_form.png b/pos_margin/static/description/pos_config_form.png new file mode 100644 index 0000000000000000000000000000000000000000..27275ebc30ee88ee4b141e0f3a14bc43619f1d3f GIT binary patch literal 24231 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 margin += line.get_margin(), 0 + ) + return margin; + }, + + get_margin_rate: function(){ + var priceWithoutTax = this.get_total_without_tax(); + return priceWithoutTax ? ((this.get_margin()) / priceWithoutTax) * 100 : 0; + }, + }); + + models.Order = OrderMargin; + + // ///////////////////////////// + // Overload models.OrderLine + // ///////////////////////////// + var OrderLineMargin = models.Orderline.extend({ + + get_purchase_price: function () { + // Overload the function to use another field that the default standard_price + return this.product.standard_price; + }, + + get_margin: function () { + return this.get_all_prices().priceWithoutTax - ( + this.quantity * this.get_purchase_price() + ); + }, + + get_margin_rate: function () { + var priceWithoutTax = this.get_all_prices().priceWithoutTax; + return priceWithoutTax ? ((this.get_margin()) / priceWithoutTax) * 100 : 0; + }, + + get_margin_rate_str: function() { + return this.pos.chrome.format_pr(this.get_margin_rate(), 0.01) + "%"; + }, + + }); + + models.Orderline = OrderLineMargin; + +}); + + + diff --git a/pos_margin/static/src/js/screens.js b/pos_margin/static/src/js/screens.js new file mode 100644 index 0000000000..55cbb2c37e --- /dev/null +++ b/pos_margin/static/src/js/screens.js @@ -0,0 +1,22 @@ +// Copyright (C) 2021 - 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). + +odoo.define("pos_margin.screens", function (require) { + "use strict"; + + var screens = require("point_of_sale.screens"); + + screens.OrderWidget.include({ + update_summary: function () { + this._super.apply(this, arguments); + var order = this.pos.get_order(); + if (!order.get_orderlines().length) { + return; + } + this.el.querySelector(".summary .order-margin .value-margin-rate").textContent = this.format_pr(order.get_margin_rate(), 0.01) + "%"; + this.el.querySelector(".summary .order-margin .value-margin").textContent = this.format_currency(order.get_margin()); + }, + }); + +}); diff --git a/pos_margin/static/src/xml/pos_margin.xml b/pos_margin/static/src/xml/pos_margin.xml new file mode 100644 index 0000000000..d473fd51f7 --- /dev/null +++ b/pos_margin/static/src/xml/pos_margin.xml @@ -0,0 +1,35 @@ + + + + + + + + + + () + + + + + + + + +
+
+
+ Margin: 0.00 € + (0.00 %) +
+
+
+
+
+
+ +
diff --git a/pos_margin/views/templates.xml b/pos_margin/views/templates.xml new file mode 100644 index 0000000000..f8a8ade243 --- /dev/null +++ b/pos_margin/views/templates.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/pos_margin/views/view_pos_config.xml b/pos_margin/views/view_pos_config.xml new file mode 100644 index 0000000000..3272229d84 --- /dev/null +++ b/pos_margin/views/view_pos_config.xml @@ -0,0 +1,30 @@ + + + + + + + pos.config + + + +
+
+ +
+
+
+
+
+
+
+ +
From b8ee90eeb725aa87058744622dc579bc849e391a Mon Sep 17 00:00:00 2001 From: MurtazaMithaiwala Date: Fri, 11 Oct 2019 00:43:36 +0530 Subject: [PATCH 06/16] [MIG] pos_margin: Migration to 13.0 --- pos_margin/README.rst | 1 + pos_margin/__manifest__.py | 2 +- pos_margin/models/pos_order.py | 1 - pos_margin/models/pos_order_line.py | 1 - pos_margin/readme/CONTRIBUTORS.rst | 1 + pos_margin/readme/HISTORY.rst | 4 ++-- pos_margin/static/description/index.html | 7 ++++--- pos_margin/tests/test_module.py | 9 ++++----- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pos_margin/README.rst b/pos_margin/README.rst index 6263379a9a..8b8d1eb99b 100644 --- a/pos_margin/README.rst +++ b/pos_margin/README.rst @@ -93,6 +93,7 @@ Contributors * Sylvain LE GAL (https://twitter.com/legalsylvain) * Wolfgang Pichler +* Murtaza Mithaiwala (https://twitter.com/MurtazaMithaiw4) Maintainers ~~~~~~~~~~~ diff --git a/pos_margin/__manifest__.py b/pos_margin/__manifest__.py index 9ddcd4a189..b818952669 100644 --- a/pos_margin/__manifest__.py +++ b/pos_margin/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'PoS Order Margin', 'summary': 'Margin on PoS Order', - 'version': '12.0.2.0.0', + 'version': '13.0.1.0.0', 'category': 'Point Of Sale', 'author': "GRAP," "Odoo Community Association (OCA)", diff --git a/pos_margin/models/pos_order.py b/pos_margin/models/pos_order.py index e3f306bcd5..f1125192ab 100644 --- a/pos_margin/models/pos_order.py +++ b/pos_margin/models/pos_order.py @@ -17,7 +17,6 @@ class PosOrder(models.Model): " the Unit Price and the cost price.") # Compute Section - @api.multi @api.depends('lines.margin') def _compute_margin(self): for order in self: diff --git a/pos_margin/models/pos_order_line.py b/pos_margin/models/pos_order_line.py index 9cb14f33c1..84609db6b4 100644 --- a/pos_margin/models/pos_order_line.py +++ b/pos_margin/models/pos_order_line.py @@ -19,7 +19,6 @@ class PosOrderLine(models.Model): multi='multi_margin', digits=dp.get_precision('Product Price')) # Compute Section - @api.multi @api.depends('product_id', 'qty', 'price_subtotal') def _compute_multi_margin(self): for line in self.filtered('product_id'): diff --git a/pos_margin/readme/CONTRIBUTORS.rst b/pos_margin/readme/CONTRIBUTORS.rst index 3b5f099616..947fc88093 100644 --- a/pos_margin/readme/CONTRIBUTORS.rst +++ b/pos_margin/readme/CONTRIBUTORS.rst @@ -1,2 +1,3 @@ * Sylvain LE GAL (https://twitter.com/legalsylvain) * Wolfgang Pichler +* Murtaza Mithaiwala (https://twitter.com/MurtazaMithaiw4) diff --git a/pos_margin/readme/HISTORY.rst b/pos_margin/readme/HISTORY.rst index 04bbd26949..f3639e85f5 100644 --- a/pos_margin/readme/HISTORY.rst +++ b/pos_margin/readme/HISTORY.rst @@ -1,7 +1,7 @@ -12.0.1.0.0 +13.0.1.0.0 ~~~~~~~~~~ -* Migrate to V12.0 +* Migrate to V13.0 * Reuse ``sale_margin`` computation to handle multi currency context. * Correct computation of margin, if a module that adds ``uom_id`` on ``pos.order.line`` is installed. diff --git a/pos_margin/static/description/index.html b/pos_margin/static/description/index.html index f0091af0bb..dfa337b189 100644 --- a/pos_margin/static/description/index.html +++ b/pos_margin/static/description/index.html @@ -413,9 +413,9 @@

Known issues / Roadmap

Changelog

-

12.0.1.0.0

+

13.0.1.0.0

@@ -453,7 +454,7 @@

Maintainers

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 project on GitHub.

+

This module is part of the OCA/pos project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/pos_margin/tests/test_module.py b/pos_margin/tests/test_module.py index 174a26817f..c53e194cd7 100644 --- a/pos_margin/tests/test_module.py +++ b/pos_margin/tests/test_module.py @@ -46,13 +46,13 @@ def _create_order(self): 'price_subtotal_incl': 18.0, }]], 'statement_ids': [[0, 0, { - 'journal_id': self.pos_config.journal_ids[0].id, + 'payment_method_id': + self.pos_config.payment_method_ids[0].id, 'amount': 18.0, '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, + 'session_id' : self.pos_config.current_session_id.id, }]], 'creation_date': u'2018-09-27 15:51:03', 'amount_tax': 0, @@ -62,7 +62,6 @@ def _create_order(self): 'sequence_number': 1, 'amount_total': 18.0, }} - result = self.PosOrder.create_from_ui([order_data]) - order = self.PosOrder.browse(result[0]) + order = self.PosOrder.browse(result[0].get('id')) return order From 4e784b5b8fb94c087a849a830aa5cb10fd87787e Mon Sep 17 00:00:00 2001 From: dsolanki Date: Wed, 2 Jun 2021 14:48:23 +0530 Subject: [PATCH 07/16] [IMP] pos_margin: isort, black, prettier. --- pos_margin/models/pos_order.py | 16 +++-- pos_margin/models/pos_order_line.py | 32 +++++---- pos_margin/report/__init__.py | 1 - pos_margin/report/pos_order_report.py | 11 ++-- pos_margin/tests/test_module.py | 94 +++++++++++++++------------ pos_margin/views/view_pos_order.xml | 18 ++--- 6 files changed, 99 insertions(+), 73 deletions(-) diff --git a/pos_margin/models/pos_order.py b/pos_margin/models/pos_order.py index f1125192ab..ffa7660757 100644 --- a/pos_margin/models/pos_order.py +++ b/pos_margin/models/pos_order.py @@ -3,21 +3,25 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import api, fields, models + import odoo.addons.decimal_precision as dp class PosOrder(models.Model): - _inherit = 'pos.order' + _inherit = "pos.order" # Columns Section margin = fields.Float( - 'Margin', compute='_compute_margin', store=True, - digits=dp.get_precision('Product Price'), + "Margin", + compute="_compute_margin", + store=True, + digits=dp.get_precision("Product Price"), help="It gives profitability by calculating the difference between" - " the Unit Price and the cost price.") + " the Unit Price and the cost price.", + ) # Compute Section - @api.depends('lines.margin') + @api.depends("lines.margin") def _compute_margin(self): for order in self: - order.margin = sum(order.mapped('lines.margin')) + order.margin = sum(order.mapped("lines.margin")) diff --git a/pos_margin/models/pos_order_line.py b/pos_margin/models/pos_order_line.py index 84609db6b4..c973118e95 100644 --- a/pos_margin/models/pos_order_line.py +++ b/pos_margin/models/pos_order_line.py @@ -3,25 +3,34 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import api, fields, models + import odoo.addons.decimal_precision as dp class PosOrderLine(models.Model): - _inherit = 'pos.order.line' + _inherit = "pos.order.line" # Columns Section margin = fields.Float( - 'Margin', compute='_compute_multi_margin', store=True, - multi='multi_margin', digits=dp.get_precision('Product Price')) + "Margin", + compute="_compute_multi_margin", + store=True, + multi="multi_margin", + digits=dp.get_precision("Product Price"), + ) purchase_price = fields.Float( - 'Cost Price', compute='_compute_multi_margin', store=True, - multi='multi_margin', digits=dp.get_precision('Product Price')) + "Cost Price", + compute="_compute_multi_margin", + store=True, + multi="multi_margin", + digits=dp.get_precision("Product Price"), + ) # Compute Section - @api.depends('product_id', 'qty', 'price_subtotal') + @api.depends("product_id", "qty", "price_subtotal") def _compute_multi_margin(self): - for line in self.filtered('product_id'): + for line in self.filtered("product_id"): purchase_price = self._get_purchase_price(line) line.purchase_price = purchase_price line.margin = line.price_subtotal - (purchase_price * line.qty) @@ -30,12 +39,11 @@ def _compute_multi_margin(self): def _get_purchase_price(self, line): # We call _get_purchase_price from sale_margin module, to reuse # computation that handles multi currencies context and UoM - SaleOrderLine = self.env['sale.order.line'] + SaleOrderLine = self.env["sale.order.line"] # if used in combination with module which does add the uom_id to line - uom = hasattr(line, 'uom_id') and line.uom_id\ - or line.product_id.uom_id + uom = hasattr(line, "uom_id") and line.uom_id or line.product_id.uom_id return SaleOrderLine._get_purchase_price( - line.order_id.pricelist_id, line.product_id, uom, - line.order_id.date_order)['purchase_price'] + line.order_id.pricelist_id, line.product_id, uom, line.order_id.date_order + )["purchase_price"] diff --git a/pos_margin/report/__init__.py b/pos_margin/report/__init__.py index 225fc1d2af..1ddfcaae89 100644 --- a/pos_margin/report/__init__.py +++ b/pos_margin/report/__init__.py @@ -1,2 +1 @@ from . import pos_order_report - diff --git a/pos_margin/report/pos_order_report.py b/pos_margin/report/pos_order_report.py index ae826b405a..4c83eec8c4 100644 --- a/pos_margin/report/pos_order_report.py +++ b/pos_margin/report/pos_order_report.py @@ -2,14 +2,17 @@ class PosOrderReport(models.Model): - _inherit = 'report.pos.order' + _inherit = "report.pos.order" - margin_total = fields.Float(string='Margin Total') - margin_rate = fields.Float(string='Margin Rate', group_operator='avg') + margin_total = fields.Float(string="Margin Total") + margin_rate = fields.Float(string="Margin Rate", group_operator="avg") def _select(self): - return super(PosOrderReport, self)._select() + """, + return ( + super(PosOrderReport, self)._select() + + """, SUM(l.margin) as margin_total, (SUM(l.margin / nullif(l.qty,0)) * 100 / SUM(nullif(l.purchase_price,0)))::decimal as margin_rate """ + ) diff --git a/pos_margin/tests/test_module.py b/pos_margin/tests/test_module.py index c53e194cd7..39eb667110 100644 --- a/pos_margin/tests/test_module.py +++ b/pos_margin/tests/test_module.py @@ -6,15 +6,14 @@ class TestModule(TransactionCase): - def setUp(self): super(TestModule, self).setUp() - self.PosOrder = self.env['pos.order'] - self.pos_product = self.env.ref('point_of_sale.whiteboard_pen') - self.pricelist = self.env.ref('product.list0') + self.PosOrder = self.env["pos.order"] + self.pos_product = self.env.ref("point_of_sale.whiteboard_pen") + self.pricelist = self.env.ref("product.list0") # Create a new pos config and open it - self.pos_config = self.env.ref('point_of_sale.pos_config_main').copy() + self.pos_config = self.env.ref("point_of_sale.pos_config_main").copy() self.pos_config.open_session_cb() def test_margin(self): @@ -22,46 +21,57 @@ def test_margin(self): self.pos_product.standard_price = 0.5 order = self._create_order() - self.assertEqual( - order.margin, 10 * (1.8 - 0.5), - "Bad computation of margin") + self.assertEqual(order.margin, 10 * (1.8 - 0.5), "Bad computation of margin") def _create_order(self): # Create order order_data = { - 'id': u'0006-001-0010', - 'to_invoice': False, - 'data': { - 'pricelist_id': self.pricelist.id, - 'user_id': 1, - 'name': 'Order 0006-001-0010', - 'partner_id': False, - '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': self.pos_product.list_price, - 'qty': 10, - 'price_subtotal': 18.0, - 'price_subtotal_incl': 18.0, - }]], - 'statement_ids': [[0, 0, { - 'payment_method_id': - self.pos_config.payment_method_ids[0].id, - 'amount': 18.0, - 'name': fields.Datetime.now(), - 'account_id': - self.env.user.partner_id.property_account_receivable_id.id, - 'session_id' : self.pos_config.current_session_id.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': 18.0, - }} + "id": u"0006-001-0010", + "to_invoice": False, + "data": { + "pricelist_id": self.pricelist.id, + "user_id": 1, + "name": "Order 0006-001-0010", + "partner_id": False, + "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": self.pos_product.list_price, + "qty": 10, + "price_subtotal": 18.0, + "price_subtotal_incl": 18.0, + }, + ] + ], + "statement_ids": [ + [ + 0, + 0, + { + "payment_method_id": self.pos_config.payment_method_ids[ + 0 + ].id, + "amount": 18.0, + "name": fields.Datetime.now(), + "account_id": self.env.user.partner_id.property_account_receivable_id.id, + "session_id": self.pos_config.current_session_id.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": 18.0, + }, + } result = self.PosOrder.create_from_ui([order_data]) - order = self.PosOrder.browse(result[0].get('id')) + order = self.PosOrder.browse(result[0].get("id")) return order diff --git a/pos_margin/views/view_pos_order.xml b/pos_margin/views/view_pos_order.xml index 75d2445214..f68cc30762 100644 --- a/pos_margin/views/view_pos_order.xml +++ b/pos_margin/views/view_pos_order.xml @@ -1,31 +1,33 @@ - + - pos.order - + - + - - + + pos.order - + - + From 62fbec566b63cc843a6af296c80fa8afaf130a07 Mon Sep 17 00:00:00 2001 From: dsolanki Date: Wed, 2 Jun 2021 18:29:17 +0530 Subject: [PATCH 08/16] [MIG] Migrate module pos_margin to v14. --- pos_margin/README.rst | 52 ++++++++++--- pos_margin/__manifest__.py | 26 +++---- pos_margin/i18n/pos_margin.pot | 39 ++++++++-- .../migrations/12.0.2.0.0/pre-migration.py | 12 ++- pos_margin/models/pos_config.py | 6 +- pos_margin/models/pos_order.py | 4 +- pos_margin/models/pos_order_line.py | 49 ++++++++---- pos_margin/readme/CONTRIBUTORS.rst | 1 + pos_margin/readme/HISTORY.rst | 5 ++ pos_margin/readme/ROADMAP.rst | 4 - pos_margin/static/description/index.html | 77 +++++++++++++------ pos_margin/static/src/css/pos_margin.css | 6 +- .../static/src/js/OrderSummaryMargin.js | 17 ++++ pos_margin/static/src/js/OrderWidget.js | 37 +++++++++ pos_margin/static/src/js/models.js | 29 +++---- pos_margin/static/src/js/screens.js | 22 ------ pos_margin/static/src/xml/pos_margin.xml | 48 ++++++------ pos_margin/tests/test_module.py | 3 +- pos_margin/views/templates.xml | 16 ++-- pos_margin/views/view_pos_config.xml | 9 +-- 20 files changed, 297 insertions(+), 165 deletions(-) create mode 100644 pos_margin/static/src/js/OrderSummaryMargin.js create mode 100644 pos_margin/static/src/js/OrderWidget.js delete mode 100644 pos_margin/static/src/js/screens.js diff --git a/pos_margin/README.rst b/pos_margin/README.rst index 8b8d1eb99b..2c0075c1d0 100644 --- a/pos_margin/README.rst +++ b/pos_margin/README.rst @@ -14,13 +14,13 @@ PoS Order Margin :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_margin + :target: https://github.com/OCA/pos/tree/14.0/pos_margin :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_margin + :target: https://translation.odoo-community.org/projects/pos-14-0/pos-14-0-pos_margin :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 + :target: https://runbot.odoo-community.org/runbot/184/14.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -36,24 +36,38 @@ Price and Cost Price. .. contents:: :local: +Configuration +============= + +* If you want to disable the display of the margin, in the front-office UI, you can + uncheck the check box in the ``pos.config`` form: + +.. figure:: https://raw.githubusercontent.com/OCA/pos/14.0/pos_margin/static/description/pos_config_form.png + Usage ===== +**In the PoS Front Office** + +* Make an order. Each time a line is added, updated, or deleted, the margin and the margin rate + will be updated. + +.. figure:: https://raw.githubusercontent.com/OCA/pos/14.0/pos_margin/static/description/pos_front_end.png + :width: 800px + +**In the PoS Back Office** + To use this module, you need to: * Go to 'Point Of Sale' / 'Orders' / 'Orders' * Open an order -.. figure:: https://raw.githubusercontent.com/OCA/pos/12.0/pos_margin/static/description/pos_order_form.png +.. figure:: https://raw.githubusercontent.com/OCA/pos/14.0/pos_margin/static/description/pos_order_form.png :width: 800px Known issues / Roadmap ====================== -This module depends on ``sale_margin`` module to reuse algorithm present in the -function ``_get_purchase_price`` of the model ``sale.order.line`` to -compute correctly purchase price, in a multicurrency context. - This dependency can be removed, when Odoo Core will be correctly refactored, moving this ``@api.model`` function in a more generic module (``account`` for exemple). @@ -61,10 +75,15 @@ for exemple). Changelog ========= -12.0.1.0.0 +14.0.1.0.0 +~~~~~~~~~~ + +* Migrate to V14.0 + +13.0.1.0.0 ~~~~~~~~~~ -* Migrate to V12.0 +* Migrate to V13.0 * Reuse ``sale_margin`` computation to handle multi currency context. * Correct computation of margin, if a module that adds ``uom_id`` on ``pos.order.line`` is installed. @@ -76,7 +95,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -94,6 +113,7 @@ Contributors * Sylvain LE GAL (https://twitter.com/legalsylvain) * Wolfgang Pichler * Murtaza Mithaiwala (https://twitter.com/MurtazaMithaiw4) +* Dhara Solanki Maintainers ~~~~~~~~~~~ @@ -108,6 +128,14 @@ 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 `_ project on GitHub. +.. |maintainer-legalsylvain| image:: https://github.com/legalsylvain.png?size=40px + :target: https://github.com/legalsylvain + :alt: legalsylvain + +Current `maintainer `__: + +|maintainer-legalsylvain| + +This module is part of the `OCA/pos `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_margin/__manifest__.py b/pos_margin/__manifest__.py index b818952669..d00a37adb0 100644 --- a/pos_margin/__manifest__.py +++ b/pos_margin/__manifest__.py @@ -3,26 +3,24 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'PoS Order Margin', - 'summary': 'Margin on PoS Order', - 'version': '13.0.1.0.0', - 'category': 'Point Of Sale', - 'author': "GRAP," - "Odoo Community Association (OCA)", + "name": "PoS Order Margin", + "summary": "Margin on PoS Order", + "version": "14.0.1.0.0", + "category": "Point Of Sale", + "author": "GRAP, Odoo Community Association (OCA)", "maintainers": ["legalsylvain"], "website": "https://github.com/OCA/pos", "license": "AGPL-3", "depends": [ "point_of_sale", - "sale_margin", ], - 'data': [ - 'views/templates.xml', - 'views/view_pos_config.xml', - 'views/view_pos_order.xml', + "data": [ + "views/templates.xml", + "views/view_pos_config.xml", + "views/view_pos_order.xml", ], - 'qweb': [ - 'static/src/xml/pos_margin.xml', + "qweb": [ + "static/src/xml/pos_margin.xml", ], - 'installable': True, + "installable": True, } diff --git a/pos_margin/i18n/pos_margin.pot b/pos_margin/i18n/pos_margin.pot index d5b834b72c..c70a5f6f5f 100644 --- a/pos_margin/i18n/pos_margin.pot +++ b/pos_margin/i18n/pos_margin.pot @@ -1,14 +1,12 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * pos_margin +# * pos_margin # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 12.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-06-11 14:57+0000\n" -"PO-Revision-Date: 2021-06-11 14:57+0000\n" -"Last-Translator: <>\n" +"Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -31,9 +29,35 @@ msgstr "" msgid "Display Margin and Margin Rate in the frontend" msgstr "" +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_config__display_name +#: model:ir.model.fields,field_description:pos_margin.field_pos_order__display_name +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__display_name +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__display_name +msgid "Display Name" +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_config__id +#: model:ir.model.fields,field_description:pos_margin.field_pos_order__id +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line__id +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order__id +msgid "ID" +msgstr "" + #. module: pos_margin #: model:ir.model.fields,help:pos_margin.field_pos_order__margin -msgid "It gives profitability by calculating the difference between the Unit Price and the cost price." +msgid "" +"It gives profitability by calculating the difference between the Unit Price " +"and the cost price." +msgstr "" + +#. module: pos_margin +#: model:ir.model.fields,field_description:pos_margin.field_pos_config____last_update +#: model:ir.model.fields,field_description:pos_margin.field_pos_order____last_update +#: model:ir.model.fields,field_description:pos_margin.field_pos_order_line____last_update +#: model:ir.model.fields,field_description:pos_margin.field_report_pos_order____last_update +msgid "Last Modified on" msgstr "" #. module: pos_margin @@ -55,7 +79,7 @@ msgstr "" #. module: pos_margin #. openerp-web -#: code:addons/pos_margin/static/src/xml/pos_margin.xml:26 +#: code:addons/pos_margin/static/src/xml/pos_margin.xml:0 #, python-format msgid "Margin:" msgstr "" @@ -79,4 +103,3 @@ msgstr "" #: model:ir.model,name:pos_margin.model_report_pos_order msgid "Point of Sale Orders Report" msgstr "" - diff --git a/pos_margin/migrations/12.0.2.0.0/pre-migration.py b/pos_margin/migrations/12.0.2.0.0/pre-migration.py index 6f1154cf61..25bcf902ec 100644 --- a/pos_margin/migrations/12.0.2.0.0/pre-migration.py +++ b/pos_margin/migrations/12.0.2.0.0/pre-migration.py @@ -4,11 +4,15 @@ def migrate(cr, version): - cr.execute(""" + cr.execute( + """ ALTER TABLE pos_config ADD COLUMN iface_display_margin bool; - """) - cr.execute(""" + """ + ) + cr.execute( + """ UPDATE pos_config SET iface_display_margin = false; - """) + """ + ) diff --git a/pos_margin/models/pos_config.py b/pos_margin/models/pos_config.py index b216dae96a..dab34d9587 100644 --- a/pos_margin/models/pos_config.py +++ b/pos_margin/models/pos_config.py @@ -6,10 +6,10 @@ class PosConfig(models.Model): - _inherit = 'pos.config' + _inherit = "pos.config" iface_display_margin = fields.Boolean( - string='Diplay Margin', - help='Display Margin and Margin Rate in the frontend', + string="Diplay Margin", + help="Display Margin and Margin Rate in the frontend", default=True, ) diff --git a/pos_margin/models/pos_order.py b/pos_margin/models/pos_order.py index ffa7660757..6543aa1b83 100644 --- a/pos_margin/models/pos_order.py +++ b/pos_margin/models/pos_order.py @@ -4,8 +4,6 @@ from odoo import api, fields, models -import odoo.addons.decimal_precision as dp - class PosOrder(models.Model): _inherit = "pos.order" @@ -15,7 +13,7 @@ class PosOrder(models.Model): "Margin", compute="_compute_margin", store=True, - digits=dp.get_precision("Product Price"), + digits="Product Price", help="It gives profitability by calculating the difference between" " the Unit Price and the cost price.", ) diff --git a/pos_margin/models/pos_order_line.py b/pos_margin/models/pos_order_line.py index c973118e95..addf8fb344 100644 --- a/pos_margin/models/pos_order_line.py +++ b/pos_margin/models/pos_order_line.py @@ -4,8 +4,6 @@ from odoo import api, fields, models -import odoo.addons.decimal_precision as dp - class PosOrderLine(models.Model): _inherit = "pos.order.line" @@ -15,16 +13,14 @@ class PosOrderLine(models.Model): "Margin", compute="_compute_multi_margin", store=True, - multi="multi_margin", - digits=dp.get_precision("Product Price"), + digits="Product Price", ) purchase_price = fields.Float( "Cost Price", compute="_compute_multi_margin", store=True, - multi="multi_margin", - digits=dp.get_precision("Product Price"), + digits="Product Price", ) # Compute Section @@ -33,17 +29,36 @@ def _compute_multi_margin(self): for line in self.filtered("product_id"): purchase_price = self._get_purchase_price(line) line.purchase_price = purchase_price - line.margin = line.price_subtotal - (purchase_price * line.qty) + if purchase_price: + line.margin = line.price_subtotal - (purchase_price * line.qty) @api.model def _get_purchase_price(self, line): - # We call _get_purchase_price from sale_margin module, to reuse - # computation that handles multi currencies context and UoM - SaleOrderLine = self.env["sale.order.line"] - - # if used in combination with module which does add the uom_id to line - uom = hasattr(line, "uom_id") and line.uom_id or line.product_id.uom_id - - return SaleOrderLine._get_purchase_price( - line.order_id.pricelist_id, line.product_id, uom, line.order_id.date_order - )["purchase_price"] + """Overwrite the method from the module "sale_margin" + (https://github.com/odoo/odoo/blob/14.0/addons/sale_margin/models/sale_order.py#L20)""" + if not line.product_id: + line.purchase_price = 0.0 + line = line.with_company(line.company_id) + product = line.product_id + product_cost = product.standard_price + if not product_cost: + line.purchase_price = 0.0 + fro_cur = product.cost_currency_id + to_cur = line.currency_id or line.order_id.currency_id + if line.product_uom_id and line.product_uom_id != product.uom_id: + product_cost = product.uom_id._compute_price( + product_cost, + line.product_uom, + ) + purchase_price = ( + fro_cur._convert( + from_amount=product_cost, + to_currency=to_cur, + company=line.company_id or self.env.company, + date=line.order_id.date_order or fields.Date.today(), + round=False, + ) + if to_cur and product_cost + else product_cost + ) + return purchase_price diff --git a/pos_margin/readme/CONTRIBUTORS.rst b/pos_margin/readme/CONTRIBUTORS.rst index 947fc88093..2e1a052b2d 100644 --- a/pos_margin/readme/CONTRIBUTORS.rst +++ b/pos_margin/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * Sylvain LE GAL (https://twitter.com/legalsylvain) * Wolfgang Pichler * Murtaza Mithaiwala (https://twitter.com/MurtazaMithaiw4) +* Dhara Solanki diff --git a/pos_margin/readme/HISTORY.rst b/pos_margin/readme/HISTORY.rst index f3639e85f5..df8350ee80 100644 --- a/pos_margin/readme/HISTORY.rst +++ b/pos_margin/readme/HISTORY.rst @@ -1,3 +1,8 @@ +14.0.1.0.0 +~~~~~~~~~~ + +* Migrate to V14.0 + 13.0.1.0.0 ~~~~~~~~~~ diff --git a/pos_margin/readme/ROADMAP.rst b/pos_margin/readme/ROADMAP.rst index c01e849efd..63574222c5 100644 --- a/pos_margin/readme/ROADMAP.rst +++ b/pos_margin/readme/ROADMAP.rst @@ -1,7 +1,3 @@ -This module depends on ``sale_margin`` module to reuse algorithm present in the -function ``_get_purchase_price`` of the model ``sale.order.line`` to -compute correctly purchase price, in a multicurrency context. - This dependency can be removed, when Odoo Core will be correctly refactored, moving this ``@api.model`` function in a more generic module (``account`` for exemple). diff --git a/pos_margin/static/description/index.html b/pos_margin/static/description/index.html index dfa337b189..d550b3b880 100644 --- a/pos_margin/static/description/index.html +++ b/pos_margin/static/description/index.html @@ -367,7 +367,7 @@

PoS Order Margin

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/pos Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/pos Translate me on Weblate Try me on Runbot

This module extends the functionality of point of sale to support margin on pos orders.

This gives the profitability by calculating the difference between the Unit @@ -375,45 +375,69 @@

PoS Order Margin

Table of contents

+
+

Configuration

+
    +
  • If you want to disable the display of the margin, in the front-office UI, you can +uncheck the check box in the pos.config form:
  • +
+
+https://raw.githubusercontent.com/OCA/pos/14.0/pos_margin/static/description/pos_config_form.png +
+
-

Usage

+

Usage

+

In the PoS Front Office

+
    +
  • Make an order. Each time a line is added, updated, or deleted, the margin and the margin rate +will be updated.
  • +
+
+https://raw.githubusercontent.com/OCA/pos/14.0/pos_margin/static/description/pos_front_end.png +
+

In the PoS Back Office

To use this module, you need to:

  • Go to ‘Point Of Sale’ / ‘Orders’ / ‘Orders’
  • Open an order
-https://raw.githubusercontent.com/OCA/pos/12.0/pos_margin/static/description/pos_order_form.png +https://raw.githubusercontent.com/OCA/pos/14.0/pos_margin/static/description/pos_order_form.png
-

Known issues / Roadmap

-

This module depends on sale_margin module to reuse algorithm present in the -function _get_purchase_price of the model sale.order.line to -compute correctly purchase price, in a multicurrency context.

+

Known issues / Roadmap

This dependency can be removed, when Odoo Core will be correctly refactored, moving this @api.model function in a more generic module (account for exemple).

-

Changelog

+

Changelog

-

13.0.1.0.0

+

14.0.1.0.0

+
    +
  • Migrate to V14.0
  • +
+
+
+

13.0.1.0.0

  • Migrate to V13.0
  • Reuse sale_margin computation to handle multi currency context.
  • @@ -424,37 +448,40 @@

    13.0.1.0.0

-

Bug Tracker

+

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.

+feedback.

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • GRAP
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association

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 project on GitHub.

+

Current maintainer:

+

legalsylvain

+

This module is part of the OCA/pos project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/pos_margin/static/src/css/pos_margin.css b/pos_margin/static/src/css/pos_margin.css index aad2409e6c..ef72b5ebe3 100644 --- a/pos_margin/static/src/css/pos_margin.css +++ b/pos_margin/static/src/css/pos_margin.css @@ -1,8 +1,8 @@ -.pos .order .orderline .order-line-margin{ +.pos .order .orderline .order-line-margin { font-weight: normal; color: #888; } -.pos .order .orderline .order-line-margin.margin-negative{ - color: #F00; +.pos .order .orderline .order-line-margin.margin-negative { + color: #f00; } diff --git a/pos_margin/static/src/js/OrderSummaryMargin.js b/pos_margin/static/src/js/OrderSummaryMargin.js new file mode 100644 index 0000000000..ed59e64e10 --- /dev/null +++ b/pos_margin/static/src/js/OrderSummaryMargin.js @@ -0,0 +1,17 @@ +// Copyright (C) 2021 - Initos Gmbh +// @author: Dhara Solanki (dhara.solanki@initos.com) +// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +odoo.define("point_of_sale.OrderSummaryMargin", function (require) { + "use strict"; + + const PosComponent = require("point_of_sale.PosComponent"); + const Registries = require("point_of_sale.Registries"); + + class OrderSummaryMargin extends PosComponent {} + OrderSummaryMargin.template = "OrderSummaryMargin"; + + Registries.Component.add(OrderSummaryMargin); + + return OrderSummaryMargin; +}); diff --git a/pos_margin/static/src/js/OrderWidget.js b/pos_margin/static/src/js/OrderWidget.js new file mode 100644 index 0000000000..412bf0e663 --- /dev/null +++ b/pos_margin/static/src/js/OrderWidget.js @@ -0,0 +1,37 @@ +// Copyright (C) 2021 - 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). + +odoo.define("pos_margin.OrderWidget", function (require) { + "use strict"; + + var OrderWidget = require("point_of_sale.OrderWidget"); + const Registries = require("point_of_sale.Registries"); + var field_utils = require("web.field_utils"); + + const PosOrderWidget = (OrderWidget) => + class extends OrderWidget { + _updateSummary() { + super._updateSummary(...arguments); + var order = this.env.pos.get_order(); + if (!order.get_orderlines().length) { + return; + } + var value_margin = document.getElementsByClassName("value-margin"); + if (value_margin && value_margin.length) { + value_margin[0].textContent = this.env.pos.format_currency( + order.get_margin() + ); + } + var value_margin_rate = document.getElementsByClassName( + "value-margin-rate" + ); + if (value_margin_rate && value_margin_rate.length) { + value_margin_rate[0].textContent = + field_utils.format.float(order.get_margin_rate()) + "%"; + } + } + }; + Registries.Component.extend(OrderWidget, PosOrderWidget); + return OrderWidget; +}); diff --git a/pos_margin/static/src/js/models.js b/pos_margin/static/src/js/models.js index 683afcdc75..85114155b2 100644 --- a/pos_margin/static/src/js/models.js +++ b/pos_margin/static/src/js/models.js @@ -6,22 +6,22 @@ odoo.define("pos_margin.models", function (require) { "use strict"; var models = require("point_of_sale.models"); + var field_utils = require("web.field_utils"); // ///////////////////////////// // Overload models.Order // ///////////////////////////// var OrderMargin = models.Order.extend({ - - get_margin: function() { + get_margin: function () { return this.get_orderlines().reduce( - (margin, line) => margin += line.get_margin(), 0 - ) - return margin; + (margin, line) => (margin += line.get_margin()), + 0 + ); }, - get_margin_rate: function(){ + get_margin_rate: function () { var priceWithoutTax = this.get_total_without_tax(); - return priceWithoutTax ? ((this.get_margin()) / priceWithoutTax) * 100 : 0; + return priceWithoutTax ? (this.get_margin() / priceWithoutTax) * 100 : 0; }, }); @@ -31,32 +31,27 @@ odoo.define("pos_margin.models", function (require) { // Overload models.OrderLine // ///////////////////////////// var OrderLineMargin = models.Orderline.extend({ - get_purchase_price: function () { // Overload the function to use another field that the default standard_price return this.product.standard_price; }, get_margin: function () { - return this.get_all_prices().priceWithoutTax - ( + return ( + this.get_all_prices().priceWithoutTax - this.quantity * this.get_purchase_price() ); }, get_margin_rate: function () { var priceWithoutTax = this.get_all_prices().priceWithoutTax; - return priceWithoutTax ? ((this.get_margin()) / priceWithoutTax) * 100 : 0; + return priceWithoutTax ? (this.get_margin() / priceWithoutTax) * 100 : 0; }, - get_margin_rate_str: function() { - return this.pos.chrome.format_pr(this.get_margin_rate(), 0.01) + "%"; + get_margin_rate_str: function () { + return field_utils.format.float(this.get_margin_rate()) + "%"; }, - }); models.Orderline = OrderLineMargin; - }); - - - diff --git a/pos_margin/static/src/js/screens.js b/pos_margin/static/src/js/screens.js deleted file mode 100644 index 55cbb2c37e..0000000000 --- a/pos_margin/static/src/js/screens.js +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2021 - 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). - -odoo.define("pos_margin.screens", function (require) { - "use strict"; - - var screens = require("point_of_sale.screens"); - - screens.OrderWidget.include({ - update_summary: function () { - this._super.apply(this, arguments); - var order = this.pos.get_order(); - if (!order.get_orderlines().length) { - return; - } - this.el.querySelector(".summary .order-margin .value-margin-rate").textContent = this.format_pr(order.get_margin_rate(), 0.01) + "%"; - this.el.querySelector(".summary .order-margin .value-margin").textContent = this.format_currency(order.get_margin()); - }, - }); - -}); diff --git a/pos_margin/static/src/xml/pos_margin.xml b/pos_margin/static/src/xml/pos_margin.xml index d473fd51f7..3342596cf0 100644 --- a/pos_margin/static/src/xml/pos_margin.xml +++ b/pos_margin/static/src/xml/pos_margin.xml @@ -1,35 +1,39 @@ - + - - - - - - () - - - - - - - -
-
-
- Margin: 0.00 € - (0.00 %) -
-
+ +
+
+
+ Margin: 0.00 € + (0.00 %)
+
+
+
+ + + + + + + + + + + + () + - + diff --git a/pos_margin/tests/test_module.py b/pos_margin/tests/test_module.py index 39eb667110..c0e811a6f6 100644 --- a/pos_margin/tests/test_module.py +++ b/pos_margin/tests/test_module.py @@ -25,6 +25,7 @@ def test_margin(self): def _create_order(self): # Create order + account_id = self.env.user.partner_id.property_account_receivable_id.id order_data = { "id": u"0006-001-0010", "to_invoice": False, @@ -58,7 +59,7 @@ def _create_order(self): ].id, "amount": 18.0, "name": fields.Datetime.now(), - "account_id": self.env.user.partner_id.property_account_receivable_id.id, + "account_id": account_id, "session_id": self.pos_config.current_session_id.id, }, ] diff --git a/pos_margin/views/templates.xml b/pos_margin/views/templates.xml index f8a8ade243..8a5934c351 100644 --- a/pos_margin/views/templates.xml +++ b/pos_margin/views/templates.xml @@ -1,16 +1,22 @@ - + -