diff --git a/stock_valued_picking_report/README.rst b/stock_valued_picking_report/README.rst new file mode 100644 index 0000000..491d490 --- /dev/null +++ b/stock_valued_picking_report/README.rst @@ -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 +`_. 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 `_. + +Contributors +------------ + +* Pedro M. Baeza +* Antonio Espinosa +* Oihane Crucelaegui +* Carlos Dauden +* David Vidal + +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/stock_valued_picking_report/__init__.py b/stock_valued_picking_report/__init__.py new file mode 100644 index 0000000..cde864b --- /dev/null +++ b/stock_valued_picking_report/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/stock_valued_picking_report/__openerp__.py b/stock_valued_picking_report/__openerp__.py new file mode 100644 index 0000000..5cee1f6 --- /dev/null +++ b/stock_valued_picking_report/__openerp__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 Pedro M. Baeza - Tecnativa +# Copyright 2015 Antonio Espinosa - Tecnativa +# Copyright 2016 Carlos Dauden - Tecnativa +# Copyright 2017 David Vidal - Tecnativa +# 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, +} diff --git a/stock_valued_picking_report/i18n/es.po b/stock_valued_picking_report/i18n/es.po new file mode 100644 index 0000000..b258761 --- /dev/null +++ b/stock_valued_picking_report/i18n/es.po @@ -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 \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 "Discount" +msgstr "Dto" + +#. module: stock_valued_picking_report +#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking +msgid "Subtotal" +msgstr "Subtotal" + +#. module: stock_valued_picking_report +#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking +msgid "Taxes" +msgstr "Impuestos" + +#. module: stock_valued_picking_report +#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking +msgid "Total" +msgstr "Total" + +#. module: stock_valued_picking_report +#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking +msgid "Unit Price" +msgstr "Precio Unidad" + +#. module: stock_valued_picking_report +#: model:ir.ui.view,arch_db:stock_valued_picking_report.valued_report_picking +msgid "Untaxed Amount" +msgstr "Base imponible" + +#. 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" diff --git a/stock_valued_picking_report/models/__init__.py b/stock_valued_picking_report/models/__init__.py new file mode 100644 index 0000000..bd44108 --- /dev/null +++ b/stock_valued_picking_report/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +from . import res_partner +from . import stock_pack_operation +from . import stock_picking diff --git a/stock_valued_picking_report/models/res_partner.py b/stock_valued_picking_report/models/res_partner.py new file mode 100644 index 0000000..cb471a4 --- /dev/null +++ b/stock_valued_picking_report/models/res_partner.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 Pedro M. Baeza - Tecnativa +# Copyright 2015 Antonio Espinosa - Tecnativa +# Copyright 2016 Carlos Dauden - Tecnativa +# 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', + ) diff --git a/stock_valued_picking_report/models/stock_pack_operation.py b/stock_valued_picking_report/models/stock_pack_operation.py new file mode 100644 index 0000000..8536327 --- /dev/null +++ b/stock_valued_picking_report/models/stock_pack_operation.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 Pedro M. Baeza - Tecnativa +# Copyright 2015 Antonio Espinosa - Tecnativa +# Copyright 2016 Carlos Dauden - Tecnativa +# 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'], + } diff --git a/stock_valued_picking_report/models/stock_picking.py b/stock_valued_picking_report/models/stock_picking.py new file mode 100644 index 0000000..8e4333d --- /dev/null +++ b/stock_valued_picking_report/models/stock_picking.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Copyright 2014 Pedro M. Baeza - Tecnativa +# Copyright 2015 Antonio Espinosa - Tecnativa +# Copyright 2016 Carlos Dauden - Tecnativa +# 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, + }) diff --git a/stock_valued_picking_report/report/stock_picking_valued_report.xml b/stock_valued_picking_report/report/stock_picking_valued_report.xml new file mode 100644 index 0000000..d8d2cac --- /dev/null +++ b/stock_valued_picking_report/report/stock_picking_valued_report.xml @@ -0,0 +1,54 @@ + + + + + + diff --git a/stock_valued_picking_report/tests/__init__.py b/stock_valued_picking_report/tests/__init__.py new file mode 100644 index 0000000..84e9599 --- /dev/null +++ b/stock_valued_picking_report/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import test_stock_picking_valued diff --git a/stock_valued_picking_report/tests/test_stock_picking_valued.py b/stock_valued_picking_report/tests/test_stock_picking_valued.py new file mode 100644 index 0000000..04a4d64 --- /dev/null +++ b/stock_valued_picking_report/tests/test_stock_picking_valued.py @@ -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) diff --git a/stock_valued_picking_report/views/res_partner_view.xml b/stock_valued_picking_report/views/res_partner_view.xml new file mode 100644 index 0000000..e331eaf --- /dev/null +++ b/stock_valued_picking_report/views/res_partner_view.xml @@ -0,0 +1,16 @@ + + + + + Partner view (Valued picking) + res.partner + + + + + + + + +