diff --git a/sale_packaging_report/README.rst b/sale_packaging_report/README.rst new file mode 100644 index 000000000..bf9d6c681 --- /dev/null +++ b/sale_packaging_report/README.rst @@ -0,0 +1,124 @@ +===================== +Sale Packaging Report +===================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:9b7a90bc7bfae3b4e1954987a103106426d960d4df5ce12f99b29abb73855f01 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsale--reporting-lightgray.png?logo=github + :target: https://github.com/OCA/sale-reporting/tree/17.0/sale_packaging_report + :alt: OCA/sale-reporting +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/sale-reporting-17-0/sale-reporting-17-0-sale_packaging_report + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/sale-reporting&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module displays packaging data (quantity and type) in: + +- Sale order printed reports. +- Sale BI reports. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +1. Go to *Sales > Configuration > Settings*. +2. Enable *Product Packagings*. +3. Save. + +Now, make sure the products you use for testing this module have some +packaging configured. + +Usage +===== + +To print sale order packaging data: + +1. Go to *Sales > Orders > Quotations* and pick or create one. +2. Add some product(s) with packaging information (type and quantity). +3. Print it. + +To query sale packaging BI data: + +1. Go to *Sales > Reporting*. +2. Use the new options at will: + + - *Measures > Packaging Qty* + - *Measures > Packaging Delivered Qty* (based on a ratio between *Qty + Delivered* and *Packaging Qty*). + - *Group By > Packaging*. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Moduon + +Contributors +------------ + +- Jairo Llopis (`Moduon `__) +- `Heliconia Solutions Pvt. Ltd. `__ + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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. + +.. |maintainer-yajo| image:: https://github.com/yajo.png?size=40px + :target: https://github.com/yajo + :alt: yajo + +Current `maintainer `__: + +|maintainer-yajo| + +This module is part of the `OCA/sale-reporting `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sale_packaging_report/__init__.py b/sale_packaging_report/__init__.py new file mode 100644 index 000000000..4c4f242fa --- /dev/null +++ b/sale_packaging_report/__init__.py @@ -0,0 +1 @@ +from . import report diff --git a/sale_packaging_report/__manifest__.py b/sale_packaging_report/__manifest__.py new file mode 100644 index 000000000..4d4f5d4ff --- /dev/null +++ b/sale_packaging_report/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2023 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +{ + "name": "Sale Packaging Report", + "summary": "Packaging data in sale reports", + "version": "17.0.1.0.0", + "development_status": "Alpha", + "category": "Sales", + "website": "https://github.com/OCA/sale-reporting", + "author": "Moduon, Odoo Community Association (OCA)", + "maintainers": ["yajo"], + "license": "LGPL-3", + "application": False, + "installable": True, + "depends": ["sale"], + "data": [ + "report/sale_report_view.xml", + "views/report_sale_order.xml", + ], +} diff --git a/sale_packaging_report/i18n/es.po b/sale_packaging_report/i18n/es.po new file mode 100644 index 000000000..141fc1490 --- /dev/null +++ b/sale_packaging_report/i18n/es.po @@ -0,0 +1,39 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_packaging_report +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-09-08 10:27+0000\n" +"PO-Revision-Date: 2023-09-08 11:27+0100\n" +"Last-Translator: Jairo Llopis \n" +"Language-Team: \n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 3.3.1\n" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_id +#: model_terms:ir.ui.view,arch_db:sale_packaging_report.view_order_product_search_inherit_sale +msgid "Packaging" +msgstr "Envase" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_qty_delivered +msgid "Packaging Delivered Qty" +msgstr "Cant. de envases entregados" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_qty +msgid "Packaging Qty" +msgstr "Cant. de envases" + +#. module: sale_packaging_report +#: model:ir.model,name:sale_packaging_report.model_sale_report +msgid "Sales Analysis Report" +msgstr "Informe de análisis de ventas" diff --git a/sale_packaging_report/i18n/it.po b/sale_packaging_report/i18n/it.po new file mode 100644 index 000000000..0b0805be8 --- /dev/null +++ b/sale_packaging_report/i18n/it.po @@ -0,0 +1,38 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_packaging_report +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-12-12 11:34+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\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" +"X-Generator: Weblate 4.17\n" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_id +#: model_terms:ir.ui.view,arch_db:sale_packaging_report.view_order_product_search_inherit_sale +msgid "Packaging" +msgstr "Imballaggio" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_qty_delivered +msgid "Packaging Delivered Qty" +msgstr "Q.tà consegnata imballaggio" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_qty +msgid "Packaging Qty" +msgstr "Q.tà imballagio" + +#. module: sale_packaging_report +#: model:ir.model,name:sale_packaging_report.model_sale_report +msgid "Sales Analysis Report" +msgstr "Resoconto analisi vendite" diff --git a/sale_packaging_report/i18n/sale_packaging_report.pot b/sale_packaging_report/i18n/sale_packaging_report.pot new file mode 100644 index 000000000..630304748 --- /dev/null +++ b/sale_packaging_report/i18n/sale_packaging_report.pot @@ -0,0 +1,35 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_packaging_report +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.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: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_id +#: model_terms:ir.ui.view,arch_db:sale_packaging_report.view_order_product_search_inherit_sale +msgid "Packaging" +msgstr "" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_qty_delivered +msgid "Packaging Delivered Qty" +msgstr "" + +#. module: sale_packaging_report +#: model:ir.model.fields,field_description:sale_packaging_report.field_sale_report__product_packaging_qty +msgid "Packaging Qty" +msgstr "" + +#. module: sale_packaging_report +#: model:ir.model,name:sale_packaging_report.model_sale_report +msgid "Sales Analysis Report" +msgstr "" diff --git a/sale_packaging_report/pyproject.toml b/sale_packaging_report/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/sale_packaging_report/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/sale_packaging_report/readme/CONFIGURE.md b/sale_packaging_report/readme/CONFIGURE.md new file mode 100644 index 000000000..31483e791 --- /dev/null +++ b/sale_packaging_report/readme/CONFIGURE.md @@ -0,0 +1,8 @@ +To configure this module, you need to: + +1. Go to *Sales \> Configuration \> Settings*. +2. Enable *Product Packagings*. +3. Save. + +Now, make sure the products you use for testing this module have some +packaging configured. diff --git a/sale_packaging_report/readme/CONTRIBUTORS.md b/sale_packaging_report/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..945803c8e --- /dev/null +++ b/sale_packaging_report/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Jairo Llopis ([Moduon](https://www.moduon.team/)) +- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io) diff --git a/sale_packaging_report/readme/DESCRIPTION.md b/sale_packaging_report/readme/DESCRIPTION.md new file mode 100644 index 000000000..5e12e8195 --- /dev/null +++ b/sale_packaging_report/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +This module displays packaging data (quantity and type) in: + +- Sale order printed reports. +- Sale BI reports. diff --git a/sale_packaging_report/readme/USAGE.md b/sale_packaging_report/readme/USAGE.md new file mode 100644 index 000000000..8db8b9edc --- /dev/null +++ b/sale_packaging_report/readme/USAGE.md @@ -0,0 +1,14 @@ +To print sale order packaging data: + +1. Go to *Sales \> Orders \> Quotations* and pick or create one. +2. Add some product(s) with packaging information (type and quantity). +3. Print it. + +To query sale packaging BI data: + +1. Go to *Sales \> Reporting*. +2. Use the new options at will: + - *Measures \> Packaging Qty* + - *Measures \> Packaging Delivered Qty* (based on a ratio between + *Qty Delivered* and *Packaging Qty*). + - *Group By \> Packaging*. diff --git a/sale_packaging_report/report/__init__.py b/sale_packaging_report/report/__init__.py new file mode 100644 index 000000000..cd23411b8 --- /dev/null +++ b/sale_packaging_report/report/__init__.py @@ -0,0 +1 @@ +from . import sale_report diff --git a/sale_packaging_report/report/sale_report.py b/sale_packaging_report/report/sale_report.py new file mode 100644 index 000000000..36abe2fdc --- /dev/null +++ b/sale_packaging_report/report/sale_report.py @@ -0,0 +1,50 @@ +# Copyright 2023 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + + +from odoo import fields, models + + +class Name(models.AbstractModel): + _inherit = "sale.report" + + product_packaging_id = fields.Many2one( + "product.packaging", + string="Packaging", + readonly=True, + ) + product_packaging_qty = fields.Float(string="Packaging Qty", readonly=True) + product_packaging_qty_delivered = fields.Float( + string="Packaging Delivered Qty", + readonly=True, + ) + + def _select_additional_fields(self): + result = super()._select_additional_fields() + return dict( + result, + product_packaging_id="l.product_packaging_id", + product_packaging_qty="SUM(l.product_packaging_qty)", + product_packaging_qty_delivered=""" + COALESCE( + SUM( + l.qty_delivered + / u.factor * u2.factor + / product_packaging.qty + ), + 0 + ) + """, + ) + + def _from_sale(self): + result = super()._from_sale() + return f""" + {result} + LEFT JOIN product_packaging + ON l.product_packaging_id = product_packaging.id + """ + + def _group_by_sale(self): + result = super()._group_by_sale() + return f"{result}, l.product_packaging_id" diff --git a/sale_packaging_report/report/sale_report_view.xml b/sale_packaging_report/report/sale_report_view.xml new file mode 100644 index 000000000..e122d2c54 --- /dev/null +++ b/sale_packaging_report/report/sale_report_view.xml @@ -0,0 +1,26 @@ + + + + + Sale report: search packagings + sale.report + + + + + + + + + + + diff --git a/sale_packaging_report/static/description/icon.png b/sale_packaging_report/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/sale_packaging_report/static/description/icon.png differ diff --git a/sale_packaging_report/static/description/index.html b/sale_packaging_report/static/description/index.html new file mode 100644 index 000000000..eaf1cbb73 --- /dev/null +++ b/sale_packaging_report/static/description/index.html @@ -0,0 +1,469 @@ + + + + + +Sale Packaging Report + + + +
+

Sale Packaging Report

+ + +

Alpha License: LGPL-3 OCA/sale-reporting Translate me on Weblate Try me on Runboat

+

This module displays packaging data (quantity and type) in:

+
    +
  • Sale order printed reports.
  • +
  • Sale BI reports.
  • +
+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Go to Sales > Configuration > Settings.
  2. +
  3. Enable Product Packagings.
  4. +
  5. Save.
  6. +
+

Now, make sure the products you use for testing this module have some +packaging configured.

+
+
+

Usage

+

To print sale order packaging data:

+
    +
  1. Go to Sales > Orders > Quotations and pick or create one.
  2. +
  3. Add some product(s) with packaging information (type and quantity).
  4. +
  5. Print it.
  6. +
+

To query sale packaging BI data:

+
    +
  1. Go to Sales > Reporting.
  2. +
  3. Use the new options at will:
      +
    • Measures > Packaging Qty
    • +
    • Measures > Packaging Delivered Qty (based on a ratio between Qty +Delivered and Packaging Qty).
    • +
    • Group By > Packaging.
    • +
    +
  4. +
+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Moduon
  • +
+
+ +
+

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.

+

Current maintainer:

+

yajo

+

This module is part of the OCA/sale-reporting project on GitHub.

+

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

+
+
+
+ + diff --git a/sale_packaging_report/tests/__init__.py b/sale_packaging_report/tests/__init__.py new file mode 100644 index 000000000..4dd957169 --- /dev/null +++ b/sale_packaging_report/tests/__init__.py @@ -0,0 +1 @@ +from . import test_sale_packaging_report diff --git a/sale_packaging_report/tests/test_sale_packaging_report.py b/sale_packaging_report/tests/test_sale_packaging_report.py new file mode 100644 index 000000000..1a2fa0329 --- /dev/null +++ b/sale_packaging_report/tests/test_sale_packaging_report.py @@ -0,0 +1,102 @@ +# Copyright 2023 Moduon Team S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0) + +from odoo import Command + +from odoo.addons.base.tests.common import BaseCommon + + +class TestSaleReportPackaging(BaseCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.partner = cls.env.ref("base.res_partner_12") + cls.product = cls.env.ref("product.product_product_9") + cls.product_packaging = cls.env["product.packaging"].create( + { + "name": "Box of 12", + "qty": 12, + "product_id": cls.product.id, + } + ) + cls.order = cls.env["sale.order"].create( + { + "partner_id": cls.partner.id, + "order_line": [ + Command.create( + { + "product_id": cls.product.id, + "product_uom": cls.product.uom_id.id, + "product_uom_qty": 24.0, + "product_packaging_id": cls.product_packaging.id, + "product_packaging_qty": 2, + }, + ) + ], + } + ) + + def test_product_packaging_fields_in_report(self): + self.order.action_confirm() + + select_fields = self.env["sale.report"]._select_additional_fields() + group_by_fields = self.env["sale.report"]._group_by_sale() + from_clause = self.env["sale.report"]._from_sale() + + self.assertIn( + "product_packaging_id", + select_fields, + "'product_packaging_id' is not in the select fields.", + ) + self.assertIn( + "product_packaging_qty", + select_fields, + "'product_packaging_qty' is not in the select fields.", + ) + self.assertIn( + "product_packaging_qty_delivered", + select_fields, + "'product_packaging_qty_delivered' is not in the select fields.", + ) + + self.assertIn( + "l.product_packaging_id", + group_by_fields, + "'product_packaging_id' is not in the GROUP BY clause.", + ) + + self.assertIn( + "LEFT JOIN product_packaging", + from_clause, + "LEFT JOIN with 'product_packaging' is missing in the FROM clause.", + ) + + def test_product_packaging_report_values(self): + self.order.action_confirm() + self.env.invalidate_all() + sale_report = self.env["sale.report"].read_group( + domain=[("order_reference", "=", f"sale.order,{self.order.id}")], + fields=[ + "product_packaging_id", + "product_packaging_qty", + "product_packaging_qty_delivered", + ], + groupby=["product_packaging_id"], + ) + self.assertTrue(sale_report, "No sale report entries found for the sale order.") + report_entry = sale_report[0] + self.assertEqual( + report_entry["product_packaging_id"][0], + self.product_packaging.id, + "Incorrect product packaging in the report.", + ) + self.assertEqual( + report_entry["product_packaging_qty"], + 2, + "Incorrect product packaging quantity in the report.", + ) + self.assertEqual( + report_entry["product_packaging_qty_delivered"], + 0, + "Incorrect product packaging delivered quantity in the report.", + ) diff --git a/sale_packaging_report/views/report_sale_order.xml b/sale_packaging_report/views/report_sale_order.xml new file mode 100644 index 000000000..1dd7b0a92 --- /dev/null +++ b/sale_packaging_report/views/report_sale_order.xml @@ -0,0 +1,21 @@ + + + + +