Browse Source

[ADD] margin_percent field on pos_order ;

[ADD] margin and margin_percent on pos_order tree view ;
[IMP] make faster installation on database with many pos_orders, using pre_init_hook
[FIX] remove compute method for pos_order_line.purchase_price, cortesy @sebastienbeau
[fix] description
pull/422/head
Sylvain LE GAL 7 years ago
parent
commit
416fc6b3d6
  1. 30
      pos_margin/README.rst
  2. 1
      pos_margin/__init__.py
  3. 6
      pos_margin/__openerp__.py
  4. 25
      pos_margin/hooks.py
  5. 16
      pos_margin/i18n/fr.po
  6. 16
      pos_margin/models/pos_order.py
  7. 43
      pos_margin/models/pos_order_line.py
  8. BIN
      pos_margin/static/description/pos_order_form.png
  9. BIN
      pos_margin/static/description/pos_order_form_view.png
  10. BIN
      pos_margin/static/description/pos_order_tree_view.png
  11. 20
      pos_margin/views/view_pos_order.xml

30
pos_margin/README.rst

@ -1,15 +1,10 @@
=============================================
This module adds the 'Margin' on sales order.
=============================================
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
Margin on PoS order
===================
====================
Margin on PoS Orders
====================
This module extends the functionality of point of sale to support margin on This module extends the functionality of point of sale to support margin on
pos orders. pos orders.
@ -17,16 +12,29 @@ pos orders.
This gives the profitability by calculating the difference between the Unit This gives the profitability by calculating the difference between the Unit
Price and Cost Price. Price and Cost Price.
Configuration
=============
this module create a new Decimal precision for the field 'Margin (%)' of the
pos.order model, with two digits, by default. you can change the precision,
going to 'Settings' / 'Technical' / 'Database Structure' / 'Decimal Accuracy'
Usage Usage
===== =====
To use this module, you need to: To use this module, you need to:
#. Go to 'Point Of Sale' / 'Daily Operations' / 'Orders'
#. Open an order
* Go to 'Point Of Sale' / 'Daily Operations' / 'Orders'
* View Orders
.. figure:: static/description/pos_order_tree_view.png
:width: 800px
* Open an Order
.. figure:: ./pos_margin/static/description/pos_order_form.png
.. figure:: static/description/pos_order_form_view.png
:width: 800px :width: 800px
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas

1
pos_margin/__init__.py

@ -1,2 +1,3 @@
# -#- coding: utf-8 -#- # -#- coding: utf-8 -#-
from . import models from . import models
from .hooks import pre_init_hook

6
pos_margin/__openerp__.py

@ -5,12 +5,11 @@
{ {
'name': 'POS Margin', 'name': 'POS Margin',
'version': '8.0.1.0.0',
'version': '8.0.1.0.1',
'category': 'Point Of Sale', 'category': 'Point Of Sale',
'sequence': 1,
'author': "GRAP," 'author': "GRAP,"
"Odoo Community Association (OCA)", "Odoo Community Association (OCA)",
'summary': 'Margin on PoS Order',
'summary': 'Margin on PoS Orders',
'depends': [ 'depends': [
'point_of_sale', 'point_of_sale',
], ],
@ -18,4 +17,5 @@
'views/view_pos_order.xml', 'views/view_pos_order.xml',
], ],
'installable': True, 'installable': True,
'pre_init_hook': 'pre_init_hook',
} }

25
pos_margin/hooks.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).
import logging
_logger = logging.getLogger(__name__)
def _create_column(cr, table_name, column_name, column_type):
_logger.info("Fast creation of the column %s.%s" % (
table_name, column_name))
req = "ALTER TABLE %s ADD COLUMN %s %s" % (
table_name, column_name, column_type)
cr.execute(req)
def pre_init_hook(cr):
_create_column(cr, 'pos_order_line', 'purchase_price', 'numeric')
_create_column(cr, 'pos_order_line', 'margin', 'numeric')
_create_column(cr, 'pos_order_line', 'margin_percent', 'numeric')
_create_column(cr, 'pos_order', 'margin', 'numeric')
_create_column(cr, 'pos_order', 'margin_percent', 'numeric')

16
pos_margin/i18n/fr.po

@ -38,17 +38,19 @@ msgid "Lines of Point of Sale"
msgstr "Lignes de Points de Vente" msgstr "Lignes de Points de Vente"
#. module: pos_margin #. module: pos_margin
#: field:pos.order,margin:0 field:pos.order.line,margin:0
#: view:pos.order:pos_margin.view_pos_order_form
#: field:pos.order,margin:0
#: field:pos.order.line,margin:0
msgid "Margin" msgid "Margin"
msgstr "Marge" msgstr "Marge"
#. module: pos_margin
#: field:pos.order,margin_percent:0
#: field:pos.order.line,margin_percent:0
msgid "Margin (%)"
msgstr "Marge (%)"
#. module: pos_margin #. module: pos_margin
#: model:ir.model,name:pos_margin.model_pos_order #: model:ir.model,name:pos_margin.model_pos_order
msgid "Point of Sale" msgid "Point of Sale"
msgstr "Point de Vente" msgstr "Point de Vente"
#~ msgid "Margin (%)"
#~ msgstr "Marge (%)"
#~ msgid "Total"
#~ msgstr "Total"

16
pos_margin/models/pos_order.py

@ -12,14 +12,24 @@ class PosOrder(models.Model):
# Columns Section # Columns Section
margin = fields.Float( margin = fields.Float(
'Margin', compute='_compute_margin', store=True,
'Margin', compute='_compute_margin', store=True, multi='margin',
digits_compute=dp.get_precision('Product Price'), digits_compute=dp.get_precision('Product Price'),
help="It gives profitability by calculating the difference between" help="It gives profitability by calculating the difference between"
" the Unit Price and the cost price.") " the Unit Price and the cost price.")
margin_percent = fields.Float(
'Margin (%)', compute='_compute_margin', store=True, multi='margin',
digits_compute=dp.get_precision('Product Price'))
# Compute Section # Compute Section
@api.multi @api.multi
@api.depends('lines.margin')
@api.depends('lines.margin', 'lines.price_subtotal')
def _compute_margin(self): def _compute_margin(self):
for order in self: for order in self:
order.margin = sum(order.mapped('lines.margin'))
tmp_margin = sum(order.mapped('lines.margin'))
tmp_subtotal = sum(order.mapped('lines.price_subtotal'))
order.update({
'margin': tmp_margin,
'margin_percent': tmp_margin / tmp_subtotal * 100 if
tmp_subtotal else 0.0,
})

43
pos_margin/models/pos_order_line.py

@ -17,19 +17,44 @@ class PosOrderLine(models.Model):
digits_compute=dp.get_precision('Product Price')) digits_compute=dp.get_precision('Product Price'))
purchase_price = fields.Float( purchase_price = fields.Float(
'Cost Price', compute='_compute_multi_margin', store=True,
'Cost Price', digits_compute=dp.get_precision('Product Price'))
margin_percent = fields.Float(
'Margin (%)', compute='_compute_multi_margin', store=True,
multi='multi_margin', multi='multi_margin',
digits_compute=dp.get_precision('Product Price')) digits_compute=dp.get_precision('Product Price'))
# Onchange Section
@api.multi
def onchange_product_id(
self, pricelist, product_id, qty=0, partner_id=False):
product_obj = self.env['product.product']
res = super(PosOrderLine, self).onchange_product_id(
pricelist, product_id, qty=qty, partner_id=partner_id)
if product_id:
product = product_obj.browse(product_id)
res['value']['purchase_price'] = product.standard_price
return res
# Compute Section # Compute Section
@api.multi @api.multi
@api.depends('product_id', 'qty', 'price_subtotal')
@api.depends('purchase_price', 'qty', 'price_subtotal')
def _compute_multi_margin(self): def _compute_multi_margin(self):
for line in 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)
tmp_margin = line.price_subtotal - (line.purchase_price * line.qty)
line.update({
'margin': tmp_margin,
'margin_percent': (
tmp_margin / line.price_subtotal * 100.0 if
line.price_subtotal else 0.0),
})
# Overload Section. necessary, to manage pos order line creation from
# create_from_ui, because onchange section is not raised
@api.model
def create(self, vals):
if not vals.get('purchase_price', False):
product_obj = self.env['product.product']
product = product_obj.browse(vals.get('product_id'))
vals['purchase_price'] = product.standard_price
return super(PosOrderLine, self).create(vals)

BIN
pos_margin/static/description/pos_order_form.png

Before

Width: 776  |  Height: 419  |  Size: 28 KiB

BIN
pos_margin/static/description/pos_order_form_view.png

After

Width: 926  |  Height: 537  |  Size: 37 KiB

BIN
pos_margin/static/description/pos_order_tree_view.png

After

Width: 1139  |  Height: 105  |  Size: 19 KiB

20
pos_margin/views/view_pos_order.xml

@ -12,12 +12,26 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/> <field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//group[@name='order_total']" position="after"> <xpath expr="//group[@name='order_total']" position="after">
<group name="margin">
<field name="margin" widget='monetary'/>
<group name="margin" string="Margin">
<field name="margin" widget="monetary"/>
<field name="margin_percent"/>
</group> </group>
</xpath> </xpath>
<xpath expr="//field[@name='lines']/tree/field[@name='price_unit']" position="after">
<xpath expr="//field[@name='lines']/tree/field[@name='price_subtotal']" position="before">
<field name="purchase_price"/> <field name="purchase_price"/>
<field name="margin"/>
<field name="margin_percent"/>
</xpath>
</field>
</record>
<record id="view_pos_order_tree" model="ir.ui.view">
<field name="model">pos.order</field>
<field name="inherit_id" ref="point_of_sale.view_pos_order_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_id']" position="after">
<field name="margin" widget="monetary" sum="Total"/>
<field name="margin_percent"/>
</xpath> </xpath>
</field> </field>
</record> </record>

Loading…
Cancel
Save