Merge pull request #31 from Tecnativa/9.0-stock_valued_picking_report

[9.0][NEW] stock_valued_picking_report
This commit is contained in:
Pedro M. Baeza
2017-08-30 21:12:00 +02:00
committed by GitHub
12 changed files with 518 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
.. 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
===========================
Stock Valued Picking Report
===========================
Add amount information to Delivery Slip report.
You can select at partner level if picking list report must be valued or not.
Configuration
=============
#. Go to *Customers > (select one of your choice) > Sales & Purchases*.
#. Set *Valued picking* field on.
Usage
=====
To get the stock picking valued report:
#. Create a Sale Order with stockable products a *Valued picking* able
customer.
#. Confirm the Sale Order.
#. Click on *Deliveries* stat button.
#. Go to *Print > Delivery Slip*.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/151/9.0
Known issues / Roadmap
======================
* If the picking is not reserved, values aren't computed.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/stock-logistics-reporting/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.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* Oihane Crucelaegui <oihane.crucelaegi@avanzosc.es>
* Carlos Dauden <carlos.dauden@tecnativa.com>
* David Vidal <david.vidal@tecnativa.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 https://odoo-community.org.

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Pedro M. Baeza - Tecnativa <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa - Tecnativa <antonio.espinosa@tecnativa.com>
# Copyright 2016 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
# Copyright 2017 David Vidal - Tecnativa <david.vidal@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Stock Valued Picking Report",
"summary": "Adding Valued Picking on Delivery Slip report",
"version": "9.0.1.0.0",
"author": "Tecnativa, "
"Odoo Community Association (OCA)",
"website": "https://www.tecnativa.com",
"category": "Warehouse Management",
"license": "AGPL-3",
"depends": [
"account",
"stock",
"sale",
"delivery",
],
"data": [
'views/res_partner_view.xml',
'report/stock_picking_valued_report.xml',
],
"installable": True,
}

View File

@@ -0,0 +1,134 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_valued_picking_report
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-08-21 08:13+0000\n"
"PO-Revision-Date: 2017-08-21 10:13+0200\n"
"Last-Translator: Carlos Dauden <carlos.dauden@tecnativa.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"Language: es\n"
"X-Generator: Poedit 1.8.7.1\n"
#. module: stock_valued_picking_report
#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking
msgid "<strong>Discount</strong>"
msgstr "<strong>Dto</strong>"
#. module: stock_valued_picking_report
#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking
msgid "<strong>Subtotal</strong>"
msgstr "<strong>Subtotal</strong>"
#. module: stock_valued_picking_report
#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking
msgid "<strong>Taxes</strong>"
msgstr "<strong>Impuestos</strong>"
#. module: stock_valued_picking_report
#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking
msgid "<strong>Total</strong>"
msgstr "<strong>Total</strong>"
#. module: stock_valued_picking_report
#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking
msgid "<strong>Unit Price</strong>"
msgstr "<strong>Precio Unidad</strong>"
#. module: stock_valued_picking_report
#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking
msgid "<strong>Untaxed Amount</strong>"
msgstr "<strong>Base imponible</strong>"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_currency_id
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_picking_currency_id
msgid "Currency"
msgstr "Moneda"
#. module: stock_valued_picking_report
#: model:ir.model,name:stock_valued_picking_report.model_stock_pack_operation
msgid "Packing Operation"
msgstr "Operación de empaquetado"
#. module: stock_valued_picking_report
#: model:ir.model,name:stock_valued_picking_report.model_res_partner
msgid "Partner"
msgstr "Empresa"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_price_subtotal
msgid "Price subtotal"
msgstr "Subtotal"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_line
msgid "Related order line"
msgstr "Línea de pedido relacionada"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_discount
msgid "Sale discount (%)"
msgstr "Descuento venta (%)"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_price_unit
msgid "Sale price unit"
msgstr "Precio venta"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_tax_description
msgid "Tax Description"
msgstr "Descripción de impuesto"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_price_tax
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_tax_id
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_picking_amount_tax
msgid "Taxes"
msgstr "Impuestos"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_pack_operation_sale_price_total
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_picking_amount_total
msgid "Total"
msgstr "Total"
#. module: stock_valued_picking_report
#: model:ir.model,name:stock_valued_picking_report.model_stock_picking
msgid "Transfer"
msgstr "Transferir"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_picking_amount_untaxed
msgid "Untaxed Amount"
msgstr "Base imponible"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_res_partner_valued_picking
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_picking_valued
msgid "Valued picking"
msgstr "Albarán valorado"
#. module: stock_valued_picking_report
#: model:ir.model.fields,field_description:stock_valued_picking_report.field_stock_picking_website_message_ids
msgid "Website Messages"
msgstr "Mensajes del sitio web"
#. module: stock_valued_picking_report
#: model:ir.model.fields,help:stock_valued_picking_report.field_stock_picking_website_message_ids
msgid "Website communication history"
msgstr "Historial de comunicaciones del sitio web"
#. module: stock_valued_picking_report
#: model:ir.model.fields,help:stock_valued_picking_report.field_res_partner_valued_picking
#: model:ir.model.fields,help:stock_valued_picking_report.field_stock_picking_valued
msgid "You can select which partners have valued pickings"
msgstr "Puede seleccionar qué empresas tienen albarán valorado"

View File

@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from . import res_partner
from . import stock_pack_operation
from . import stock_picking

View File

@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Pedro M. Baeza - Tecnativa <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa - Tecnativa <antonio.espinosa@tecnativa.com>
# Copyright 2016 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
valued_picking = fields.Boolean(
default=True,
help='You can select which partners have valued pickings',
)

View File

@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Pedro M. Baeza - Tecnativa <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa - Tecnativa <antonio.espinosa@tecnativa.com>
# Copyright 2016 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import api, fields, models
from openerp.addons.decimal_precision import decimal_precision as dp
class StockPackOperation(models.Model):
_inherit = "stock.pack.operation"
currency_id = fields.Many2one(
related='sale_line.currency_id', readonly=True,
string='Currency')
sale_line = fields.Many2one(
comodel_name='sale.order.line',
compute='_compute_sale_order_line_fields',
string="Related order line")
sale_tax_id = fields.Many2many(
comodel_name='account.tax',
compute='_compute_sale_order_line_fields',
string="Taxes")
sale_tax_description = fields.Char(
compute='_compute_sale_order_line_fields',
string='Tax Description')
sale_price_unit = fields.Float(
compute='_compute_sale_order_line_fields',
digits=dp.get_precision('Product Price'),
string="Sale price unit")
sale_discount = fields.Float(
compute='_compute_sale_order_line_fields',
digits=dp.get_precision('Discount'),
string="Sale discount (%)")
sale_price_subtotal = fields.Monetary(
compute='_compute_sale_order_line_fields',
string="Price subtotal")
sale_price_tax = fields.Float(
compute='_compute_sale_order_line_fields',
string='Taxes')
sale_price_total = fields.Monetary(
compute='_compute_sale_order_line_fields',
string='Total')
@api.multi
def _compute_sale_order_line_fields(self):
for operation in self:
sale_lines = operation.mapped(
'linked_move_operation_ids.move_id.procurement_id.'
'sale_line_id')
operation.update(operation.sale_lines_values(sale_lines))
@api.multi
def sale_lines_values(self, sale_lines):
if len(sale_lines) <= 1:
price_unit = sale_lines.price_unit
discount = sale_lines.discount
else:
sum_qty = 0.0
sum_price = 0.0
sum_discount = 0.0
for sale_line in sale_lines:
sum_qty += sale_line.product_uom_qty
sum_price += sale_line.price_unit * sale_line.product_uom_qty
sum_discount += sale_line.discount * sale_line.product_uom_qty
price_unit = sum_price / (sum_qty or 1)
discount = sum_discount / (sum_qty or 1)
price_reduce = price_unit * (1 - (discount or 0.0) / 100.0)
sale_line = sale_lines[:1]
sale_tax = sale_line.tax_id
taxes = sale_tax.compute_all(
price_unit=price_reduce,
currency=sale_line.currency_id,
quantity=self.product_qty,
product=sale_line.product_id,
partner=sale_line.order_id.partner_id)
if sale_line.company_id.tax_calculation_rounding_method == (
'round_globally'):
price_tax = sum(
t.get('amount', 0.0) for t in taxes.get('taxes', []))
else:
price_tax = taxes['total_included'] - taxes['total_excluded']
return {
'sale_line': sale_line,
'sale_tax_id': sale_tax,
'sale_tax_description': ', '.join(map(lambda x: (
x.description or x.name), sale_tax)),
'sale_price_unit': price_unit,
'sale_discount': discount,
'sale_price_subtotal': taxes['total_excluded'],
'sale_price_tax': price_tax,
'sale_price_total': taxes['total_included'],
}

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Copyright 2014 Pedro M. Baeza - Tecnativa <pedro.baeza@tecnativa.com>
# Copyright 2015 Antonio Espinosa - Tecnativa <antonio.espinosa@tecnativa.com>
# Copyright 2016 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import api, fields, models
class StockPicking(models.Model):
_inherit = "stock.picking"
valued = fields.Boolean(
related='partner_id.valued_picking', readonly=True,
)
currency_id = fields.Many2one(
related='sale_id.currency_id', readonly=True,
string='Currency')
amount_untaxed = fields.Monetary(
compute='_compute_amount_all',
string='Untaxed Amount')
amount_tax = fields.Monetary(
compute='_compute_amount_all',
string='Taxes')
amount_total = fields.Monetary(
compute='_compute_amount_all',
string='Total')
@api.multi
def _compute_amount_all(self):
for pick in self:
amount_untaxed = sum(pick.pack_operation_ids.mapped(
'sale_price_subtotal'))
amount_tax = sum(pick.pack_operation_ids.mapped(
'sale_price_tax'))
pick.update({
'amount_untaxed': amount_untaxed,
'amount_tax': amount_tax,
'amount_total': amount_untaxed + amount_tax,
})

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="valued_report_picking" inherit_id="stock.report_delivery_document">
<xpath expr="//table[@t-if='o.pack_operation_ids']/thead/tr"
position="inside">
<t t-if="o.valued and o.sale_id and o.pack_operation_ids">
<th class="text-right"><strong>Unit Price</strong></th>
<th class="text-right" groups="sale.group_discount_per_so_line">
<strong>Discount</strong>
</th>
<th class="text-right"><strong>Subtotal</strong></th>
<th class="text-right"><strong>Taxes</strong></th>
</t>
</xpath>
<xpath expr="//span[@t-field='pack_operation.product_uom_id']/.." position="after">
<t t-if="o.valued">
<td class="text-right"><span t-field="pack_operation.sale_price_unit" /></td>
<td class="text-right" groups="sale.group_discount_per_so_line">
<span t-field="pack_operation.sale_discount" />
</td>
<td class="text-right"><span t-field="pack_operation.sale_price_subtotal" /></td>
<td class="text-right"><span t-field="pack_operation.sale_tax_description"/></td>
</t>
</xpath>
<xpath expr="//table[@t-if='o.pack_operation_ids']" position="after">
<t t-if="o.valued and o.sale_id and o.pack_operation_ids">
<table class="table table-condensed mt32">
<thead>
<tr>
<th class="text-right"><strong>Untaxed Amount</strong></th>
<th class="text-right"><strong>Taxes</strong></th>
<th class="text-right"><strong>Total</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-right">
<span t-field="o.amount_untaxed"/>
</td>
<td class="text-right">
<span t-field="o.amount_tax"/>
</td>
<td class="text-right">
<span t-field="o.amount_total"/>
</td>
</tr>
</tbody>
</table>
</t>
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import test_stock_picking_valued

View File

@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Tecnativa - David Vidal
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp.tests import common
class TestStockPickingValued(common.SavepointCase):
@classmethod
def setUpClass(cls):
super(TestStockPickingValued, cls).setUpClass()
cls.tax = cls.env['account.tax'].create({
'name': 'TAX 15%',
'amount_type': 'percent',
'type_tax_use': 'sale',
'amount': 15.0,
})
cls.product = cls.env['product.product'].create({
'name': 'Test stuff',
'list_price': 100.0,
'taxes_id': [(6, 0, cls.tax.ids)],
})
cls.partner = cls.env['res.partner'].create({
'name': 'Mr. Odoo',
})
cls.sale_order = cls.env['sale.order'].create({
'partner_id': cls.partner.id,
'order_line': [(0, 0, {'product_id': cls.product.id})],
})
def test_01_confirm_order(self):
self.assertTrue(self.partner.valued_picking)
self.sale_order.action_confirm()
self.assertTrue(len(self.sale_order.picking_ids))
for picking in self.sale_order.picking_ids:
self.assertEqual(picking.amount_untaxed, 100.0)
self.assertEqual(picking.amount_tax, 15.0)
self.assertEqual(picking.amount_total, 115.0)
def test_02_confirm_order(self):
""" Valued picking isn't computed if not reserved """
self.sale_order.action_confirm()
for picking in self.sale_order.picking_ids:
picking.do_unreserve()
self.assertEqual(picking.amount_untaxed, 0.0)
self.assertEqual(picking.amount_tax, 0.0)
self.assertEqual(picking.amount_total, 0.0)

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="view_partner_valued_picking">
<field name="name">Partner view (Valued picking)</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="valued_picking"
attrs="{'invisible': [('customer', '=', False)]}"/>
</field>
</field>
</record>
</odoo>