Browse Source

[IMP] Show aggregated taxes detail in pos.order and when printing ticket

pull/39/head
Antonio Espinosa 9 years ago
parent
commit
5c33dbf8df
  1. 80
      pos_pricelist/README.rst
  2. 4
      pos_pricelist/__openerp__.py
  3. 25
      pos_pricelist/data/pos_order.yml
  4. 110
      pos_pricelist/models/point_of_sale.py
  5. 36
      pos_pricelist/report/report_receipt.xml
  6. 11
      pos_pricelist/views/point_of_sale_view.xml

80
pos_pricelist/README.rst

@ -1,3 +1,6 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License: AGPL-3
Dynamic Price for Odoo Point of Sale Dynamic Price for Odoo Point of Sale
==================================== ====================================
@ -20,13 +23,31 @@ Goal of the module
The goal of this module is to bring the pricelist computation engine to the POS. The goal of this module is to bring the pricelist computation engine to the POS.
This module loads all the necessary data into the POS in order to have a coherent behaviour (offline/online/backend). This module loads all the necessary data into the POS in order to have a coherent behaviour (offline/online/backend).
Implemented features
--------------------
Installation
============
Nothing special is needed to install this module.
Configuration
=============
You'll have new configuration parameters at Point of Sale > Configuration > Point of Sales
* Price with Taxes: Show prices with taxes in POS session or not
Usage
=====
Implemented features at POS Session
-----------------------------------
1. Attached pricelist on partner will take effect on the POS, which means that if we attach a pricelist to a partner. 1. Attached pricelist on partner will take effect on the POS, which means that if we attach a pricelist to a partner.
The POS will recognize it and will compute the price according to the rule defined. The POS will recognize it and will compute the price according to the rule defined.
2. Fiscal Position of each partner will also be present so taxes will be correctly computed
2. Fiscal Position of each partner will also be present so taxes will be correctly computed
(conforming to the fiscal position). (conforming to the fiscal position).
- Implemented Rules are : - Implemented Rules are :
@ -44,7 +65,60 @@ The computation take in account the pricelist and the fiscal position of the cus
3x -> 70 € 3x -> 70 €
5x -> 50 € 5x -> 50 €
Implemented features at backend
-------------------------------
1. Tax details
- Tax details per order line
- Tax details aggregated by tax at order level
2. Ticket
- Tax details table added at end of printed ticket
Known issues / Roadmap
======================
Missing features Missing features
---------------- ----------------
* As you may know, product template is not fully implemented in the POS, so I decided to drop it from this module. * As you may know, product template is not fully implemented in the POS, so I decided to drop it from this module.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/pos/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
`here <https://github.com/OCA/pos/issues/new?body=module:%20pos_pricelist%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Adil Houmadi <ah@taktik.be>
* Pablo Cayuela <pablo.cayuela@aserti.es>
* Antonio Espinosa <antonioea@antiun.com>
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 http://odoo-community.org.

4
pos_pricelist/__openerp__.py

@ -34,7 +34,9 @@ New feature for the Point Of Sale:
'data': [ 'data': [
"views/pos_pricelist_template.xml", "views/pos_pricelist_template.xml",
"views/pos_pricelist_views.xml", "views/pos_pricelist_views.xml",
"views/point_of_sale_view.xml"
"views/point_of_sale_view.xml",
"report/report_receipt.xml",
"data/pos_order.yml",
], ],
'demo': [ 'demo': [
'demo/pos_pricelist_demo.yml', 'demo/pos_pricelist_demo.yml',

25
pos_pricelist/data/pos_order.yml

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Python source code encoding : https://www.python.org/dev/peps/pep-0263/
##############################################################################
#
# OpenERP, Open Source Management Solution
# This module copyright :
# (c) 2015 Antiun Ingenieria, SL (Madrid, Spain, http://www.antiun.com)
# Antonio Espinosa <antonioea@antiun.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
- !function {model: pos.order, name: _install_tax_detail}

110
pos_pricelist/models/point_of_sale.py

@ -20,19 +20,47 @@
from openerp import models, fields, api from openerp import models, fields, api
from openerp.addons import decimal_precision as dp
import logging
_logger = logging.getLogger(__name__)
class PosOrderTax(models.Model):
_name = 'pos.order.tax'
pos_order = fields.Many2one('pos.order', string='POS Order',
ondelete='cascade', index=True)
tax = fields.Many2one('account.tax', string='Tax')
name = fields.Char(string='Tax Description', required=True)
base = fields.Float(string='Base', digits=dp.get_precision('Account'))
amount = fields.Float(string='Amount', digits=dp.get_precision('Account'))
class PosOrderLine(models.Model): class PosOrderLine(models.Model):
_inherit = "pos.order.line" _inherit = "pos.order.line"
@api.multi
def _compute_taxes(self):
res = {
'total': 0,
'total_included': 0,
'taxes': [],
}
for line in self:
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
taxes = line.tax_ids.compute_all(
price, line.qty, product=line.product_id,
partner=line.order_id.partner_id)
res['total'] += taxes['total']
res['total_included'] += taxes['total_included']
res['taxes'] += taxes['taxes']
return res
@api.one @api.one
@api.depends('tax_ids', 'qty', 'price_unit', @api.depends('tax_ids', 'qty', 'price_unit',
'product_id', 'discount', 'order_id.partner_id') 'product_id', 'discount', 'order_id.partner_id')
def _amount_line_all(self): def _amount_line_all(self):
price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
taxes = self.tax_ids.compute_all(
price, self.qty, product=self.product_id,
partner=self.order_id.partner_id)
taxes = self._compute_taxes()
self.price_subtotal = taxes['total'] self.price_subtotal = taxes['total']
self.price_subtotal_incl = taxes['total_included'] self.price_subtotal_incl = taxes['total_included']
@ -46,6 +74,9 @@ class PosOrderLine(models.Model):
class PosOrder(models.Model): class PosOrder(models.Model):
_inherit = "pos.order" _inherit = "pos.order"
taxes = fields.One2many(comodel_name='pos.order.tax',
inverse_name='pos_order')
@api.model @api.model
def _amount_line_tax(self, line): def _amount_line_tax(self, line):
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
@ -56,3 +87,74 @@ class PosOrder(models.Model):
for c in taxes: for c in taxes:
val += c.get('amount', 0.0) val += c.get('amount', 0.0)
return val return val
@api.multi
def _tax_list_get(self):
agg_taxes = {}
tax_lines = []
for order in self:
for line in order.lines:
tax_lines.append({
'base': line.price_subtotal,
'taxes': line._compute_taxes()['taxes']
})
for tax_line in tax_lines:
base = tax_line['base']
for tax in tax_line['taxes']:
tax_id = str(tax['id'])
if tax_id in agg_taxes:
agg_taxes[tax_id]['base'] += base
agg_taxes[tax_id]['amount'] += tax['amount']
else:
agg_taxes[tax_id] = {
'tax_id': tax_id,
'name': tax['name'],
'base': base,
'amount': tax['amount'],
}
return agg_taxes
@api.multi
def compute_tax_detail(self):
taxes_to_delete = False
for order in self:
taxes_to_delete = self.env['pos.order.tax'].search(
[('pos_order', '=', order.id)])
# Update order taxes list
for key, tax in self._tax_list_get().iteritems():
current = taxes_to_delete.filtered(
lambda r: r.tax.id == tax['tax_id'])
if current:
current.write({
'base': tax['base'],
'amount': tax['amount'],
})
taxes_to_delete -= current
else:
current = self.env['pos.order.tax'].create({
'pos_order': order.id,
'tax': tax['tax_id'],
'name': tax['name'],
'base': tax['base'],
'amount': tax['amount'],
})
if taxes_to_delete:
taxes_to_delete.unlink()
@api.multi
def action_paid(self):
result = super(PosOrder, self).action_paid()
self.compute_tax_detail()
return result
@api.model
def _install_tax_detail(self):
"""Create tax details to pos.order's already paid, done or invoiced.
"""
# Find orders with state : paid, done or invoiced
orders = self.search([('state', 'in', ('paid', 'done', 'invoiced')),
('taxes', '=', False)])
# Compute tax detail
orders.compute_tax_detail()
_logger.info("%d orders computed installing module.", len(orders))

36
pos_pricelist/report/report_receipt.xml

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="report_receipt"
inherit_id="point_of_sale.report_receipt"
name="Add taxes detail">
<xpath expr="//div[@class='page']" position="inside">
<table class="table table-condensed">
<thead>
<tr>
<th>Tax</th>
<th class="text-right">Base</th>
<th class="text-right">Amount</th>
</tr>
</thead>
<tbody>
<tr t-foreach="o.taxes" t-as="tax">
<td>
<span t-esc="tax.name"/>
</td>
<td class="text-right">
<span t-esc="formatLang(tax.base, currency_obj=res_company.currency_id)"/>
</td>
<td class="text-right">
<span t-esc="formatLang(tax.amount, currency_obj=res_company.currency_id)"/>
</td>
</tr>
</tbody>
</table>
</xpath>
</template>
</data>
</openerp>

11
pos_pricelist/views/point_of_sale_view.xml

@ -10,6 +10,17 @@
<xpath expr="//field[@name='lines']/tree/field[@name='discount']" position="after"> <xpath expr="//field[@name='lines']/tree/field[@name='discount']" position="after">
<field name="tax_ids" widget="many2many_tags"/> <field name="tax_ids" widget="many2many_tags"/>
</xpath> </xpath>
<page string="Payments" position="after">
<page string="Taxes">
<field name="taxes" widget="one2many_list">
<tree string="Taxes detail">
<field name="name"/>
<field name="base"/>
<field name="amount"/>
</tree>
</field>
</page>
</page>
</field> </field>
</record> </record>

Loading…
Cancel
Save