From bf1d130c45b724aa90e31ed1d652ccd4a7d9caa6 Mon Sep 17 00:00:00 2001 From: Unai Beristain Date: Wed, 19 Jun 2024 09:48:48 +0200 Subject: [PATCH] [IMP] Add rounding to 0.001 and column Prod Qty * Prod Price [IMP] Improvements [IMP] Improvements [IMP] Improvements --- custom_mrp_descarga/models/stock_move_line.py | 11 + .../models/stock_move_line.py | 13 +- mrp_bom_price_and_qty/README.rst | 45 ++++ mrp_bom_price_and_qty/__manifest__.py | 23 +- mrp_bom_price_and_qty/models/__init__.py | 3 +- .../models/mrp_bom_line_extension.py | 16 -- .../models/mrp_report_bom_structure.py | 142 +++++++++++++ mrp_bom_price_and_qty/models/uom_uom.py | 22 ++ .../views/mrp_bom_line_templates.xml | 200 +++++++++++++++++- .../odoo/addons/mrp_bom_price_and_qty | 1 + setup/mrp_bom_price_and_qty/setup.py | 6 + 11 files changed, 442 insertions(+), 40 deletions(-) create mode 100644 mrp_bom_price_and_qty/README.rst delete mode 100644 mrp_bom_price_and_qty/models/mrp_bom_line_extension.py create mode 100644 mrp_bom_price_and_qty/models/mrp_report_bom_structure.py create mode 100644 mrp_bom_price_and_qty/models/uom_uom.py create mode 120000 setup/mrp_bom_price_and_qty/odoo/addons/mrp_bom_price_and_qty create mode 100644 setup/mrp_bom_price_and_qty/setup.py diff --git a/custom_mrp_descarga/models/stock_move_line.py b/custom_mrp_descarga/models/stock_move_line.py index 9910924f6..b7deed47a 100644 --- a/custom_mrp_descarga/models/stock_move_line.py +++ b/custom_mrp_descarga/models/stock_move_line.py @@ -175,4 +175,15 @@ def write(self, values): if line.move_id.state == "cancel" and values.get("qty_done") != 0: line.move_id.state = "done" line.state = "done" + if "qty_done" or "amount" or "state" in values: + for line in self: + if line.lot_id and line.company_id.paasa: + quartering = line.lot_id.move_line_ids.filtered( + lambda c: c.production_id + and c.production_id.quartering + and (c.location_id == c.production_id.location_src_id) + ) + for record in quartering: + if record.standard_price != line.lot_id.average_price: + record.standard_price = line.lot_id.average_price return result diff --git a/custom_mrp_line_cost/models/stock_move_line.py b/custom_mrp_line_cost/models/stock_move_line.py index ece3c02fc..a54ab0b4a 100644 --- a/custom_mrp_line_cost/models/stock_move_line.py +++ b/custom_mrp_line_cost/models/stock_move_line.py @@ -201,12 +201,13 @@ def _compute_base_price(self): elif line.production_id and line.move_id.byproduct_id: cost = line.move_id.byproduct_id.cost if line.expense_kg: - entry_same_lots = ( - line.production_id.move_line_ids.filtered( - lambda c: c.lot_id.name == line.lot_id.name - ) - ) - if not entry_same_lots or sum(entry_same_lots.mapped("qty_done")) == 0: + entry_same_lots = line.production_id.move_line_ids.filtered( + lambda c: c.lot_id.name == line.lot_id.name + ) + if ( + not entry_same_lots + or sum(entry_same_lots.mapped("qty_done")) == 0 + ): cost = 0 else: entry_cost = sum(entry_same_lots.mapped("amount")) / sum( diff --git a/mrp_bom_price_and_qty/README.rst b/mrp_bom_price_and_qty/README.rst new file mode 100644 index 000000000..01c83bc16 --- /dev/null +++ b/mrp_bom_price_and_qty/README.rst @@ -0,0 +1,45 @@ +.. 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 + +======================================== +MRP BOM Line and BOM Report Enhancements +======================================== + +Functionality +------------- + +- **Enhanced BoM Line Report**: Adds additional columns and formatting to the Bill of Materials (BoM) line report. Includes calculations for product quantity multiplied by product cost, formatted with currency symbols. +- **Enhanced BoM Report**: Extends the BoM report with new columns for calculated costs and quantities, formatted with currency symbols. Adds columns in both the header and footer sections to provide additional details for product costs and totals. + +Details of Changes +------------------ + +### BoM Line Report (`report_mrp_bom_line_inherit`) + +- **Column 6**: Adds a new column that shows the calculated value of `prod_qty * prod_cost`, formatted according to the currency's position (before or after the amount). +- **Column 3**: Removes the original content and replaces it with a new column that displays the `prod_qty`, formatted to four decimal places. +- **Column 5**: Removes the original content and replaces it with a new column that shows `prod_cost`, formatted similarly to the new column in column 6. +- **Column 6 (footer)**: Removes the original content and replaces it with a new column that shows the `total` value divided by `bom_qty`, formatted with currency symbols. + +### BoM Report (`report_mrp_bom_inherit`) + +- **Header Column 6**: Adds a new header column for "Prod Qty * Prod Price" if the report structure is not 'bom_structure'. +- **Footer Column 5**: Adds a new footer column that displays the calculated value of `price / bom_qty`, formatted with currency symbols. +- **Footer Column 6**: Adds a new footer column showing `total / bom_qty`, formatted with currency symbols. +- **Columns 3 and 5 in tbody**: Adds new columns for `bom_qty` and `price`, respectively, formatted with currency symbols. + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ +* Ana Juaristi +* Unai Beristain + +Do not contact contributors directly about support or help with technical issues. diff --git a/mrp_bom_price_and_qty/__manifest__.py b/mrp_bom_price_and_qty/__manifest__.py index 19706efc4..15e3d7eb6 100644 --- a/mrp_bom_price_and_qty/__manifest__.py +++ b/mrp_bom_price_and_qty/__manifest__.py @@ -1,15 +1,14 @@ { - 'name': 'MRP BOM Extension', - 'version': '1.0', - 'category': 'Manufacturing', - 'summary': 'Add a computed column to the MRP BOM lines', - 'description': ''' - This module adds a new column to the MRP BOM lines that shows the product quantity multiplied by the product price. - ''', - 'depends': ['mrp'], - 'data': [ - 'views/mrp_bom_line_templates.xml', + "name": "MRP BOM Line and BOM Report Enhancements", + "version": "14.0.1.0.0", + "category": "Manufacturing", + "summary": "Add a computed column to the MRP BOM lines", + "license": "LGPL-3", + "website": "https://github.com/avanzosc/mrp-addons", + "depends": ["mrp"], + "data": [ + "views/mrp_bom_line_templates.xml", ], - 'installable': True, - 'application': False, + "installable": True, + "application": False, } diff --git a/mrp_bom_price_and_qty/models/__init__.py b/mrp_bom_price_and_qty/models/__init__.py index f67479175..ea9f9bb3f 100644 --- a/mrp_bom_price_and_qty/models/__init__.py +++ b/mrp_bom_price_and_qty/models/__init__.py @@ -1 +1,2 @@ -from . import mrp_bom_line_extension +from . import mrp_report_bom_structure +from . import uom_uom diff --git a/mrp_bom_price_and_qty/models/mrp_bom_line_extension.py b/mrp_bom_price_and_qty/models/mrp_bom_line_extension.py deleted file mode 100644 index 39400d327..000000000 --- a/mrp_bom_price_and_qty/models/mrp_bom_line_extension.py +++ /dev/null @@ -1,16 +0,0 @@ -from odoo import models, fields, api -import requests - -class MrpBomLineExtension(models.Model): - _inherit = 'mrp.bom.line' - - prod_price = fields.Float(string='Product Price', compute='_compute_prod_price') - - @api.depends('product_id') - def _compute_prod_price(self): - for line in self: - if line.product_id: - response = requests.get(f'http://example.com/api/product_price/{line.product_id.id}') - if response.status_code == 200: - price = response.json().get('price', 0.0) - line.prod_price = round(price, 4) diff --git a/mrp_bom_price_and_qty/models/mrp_report_bom_structure.py b/mrp_bom_price_and_qty/models/mrp_report_bom_structure.py new file mode 100644 index 000000000..a1a2c7b5f --- /dev/null +++ b/mrp_bom_price_and_qty/models/mrp_report_bom_structure.py @@ -0,0 +1,142 @@ +from odoo import models +from odoo.tools import float_round + + +class ReportBomStructurePrecision(models.AbstractModel): + _inherit = "report.mrp.report_bom_structure" + + def _get_bom( + self, bom_id=False, product_id=False, line_qty=False, line_id=False, level=False + ): + bom = self.env["mrp.bom"].browse(bom_id) + company = bom.company_id or self.env.company + bom_quantity = line_qty + if line_id: + current_line = self.env["mrp.bom.line"].browse(int(line_id)) + bom_quantity = ( + current_line.product_uom_id._compute_quantity( + line_qty, bom.product_uom_id + ) + or 0 + ) + # Display bom components for current selected product variant + if product_id: + product = self.env["product.product"].browse(int(product_id)) + else: + product = bom.product_id or bom.product_tmpl_id.product_variant_id + if product: + price = ( + product.uom_id._compute_price( + product.with_company(company).standard_price, bom.product_uom_id + ) + * bom_quantity + ) + attachments = self.env["mrp.document"].search( + [ + "|", + "&", + ("res_model", "=", "product.product"), + ("res_id", "=", product.id), + "&", + ("res_model", "=", "product.template"), + ("res_id", "=", product.product_tmpl_id.id), + ] + ) + else: + # Use the product template instead of the variant + price = ( + bom.product_tmpl_id.uom_id._compute_price( + bom.product_tmpl_id.with_company(company).standard_price, + bom.product_uom_id, + ) + * bom_quantity + ) + attachments = self.env["mrp.document"].search( + [ + ("res_model", "=", "product.template"), + ("res_id", "=", bom.product_tmpl_id.id), + ] + ) + operations = self._get_operation_line( + bom, + float_round(bom_quantity, precision_rounding=1, rounding_method="UP"), + 0, + ) + lines = { + "bom": bom, + "bom_qty": bom_quantity, + "bom_prod_name": product.display_name, + "currency": company.currency_id, + "product": product, + "code": bom and bom.display_name or "", + "price": round(price, 4), # Set precision to 4 decimals for price + "total": sum([op["total"] for op in operations]), + "level": level or 0, + "operations": operations, + "operations_cost": sum([op["total"] for op in operations]), + "attachments": attachments, + "operations_time": sum([op["duration_expected"] for op in operations]), + } + components, total = self._get_bom_lines( + bom, bom_quantity, product, line_id, level + ) + lines["components"] = components + lines["total"] += total + return lines + + def _get_bom_lines(self, bom, bom_quantity, product, line_id, level): + components = [] + total = 0 + for line in bom.bom_line_ids: + line_quantity = (bom_quantity / (bom.product_qty or 1.0)) * line.product_qty + if line._skip_bom_line(product): + continue + company = bom.company_id or self.env.company + price = ( + line.product_id.uom_id._compute_price( + line.product_id.with_company(company).standard_price, + line.product_uom_id, + ) + * line_quantity + ) + if line.child_bom_id: + factor = line.product_uom_id._compute_quantity( + line_quantity, line.child_bom_id.product_uom_id + ) + sub_total = self._get_price(line.child_bom_id, factor, line.product_id) + else: + sub_total = price + sub_total = self.env.company.currency_id.round(sub_total) + components.append( + { + "prod_id": line.product_id.id, + "prod_name": line.product_id.display_name, + "code": line.child_bom_id and line.child_bom_id.display_name or "", + "prod_qty": line_quantity, + "prod_uom": line.product_uom_id.name, + "prod_cost": round( + price, 4 + ), # Set precision to 4 decimals for price + "parent_id": bom.id, + "line_id": line.id, + "level": level or 0, + "total": sub_total, + "child_bom": line.child_bom_id.id, + "phantom_bom": line.child_bom_id + and line.child_bom_id.type == "phantom" + or False, + "attachments": self.env["mrp.document"].search( + [ + "|", + "&", + ("res_model", "=", "product.product"), + ("res_id", "=", line.product_id.id), + "&", + ("res_model", "=", "product.template"), + ("res_id", "=", line.product_id.product_tmpl_id.id), + ] + ), + } + ) + total += sub_total + return components, total diff --git a/mrp_bom_price_and_qty/models/uom_uom.py b/mrp_bom_price_and_qty/models/uom_uom.py new file mode 100644 index 000000000..8c4785f60 --- /dev/null +++ b/mrp_bom_price_and_qty/models/uom_uom.py @@ -0,0 +1,22 @@ +from odoo import models + + +class UomUom(models.Model): + _inherit = "uom.uom" + + def _compute_price(self, price, to_unit): + self.ensure_one() + + # Establecer el atributo rounding a 0.001 + self.rounding = 0.001 + to_unit.rounding = 0.001 + + if not self or not price or not to_unit or self == to_unit: + return price + if self.category_id.id != to_unit.category_id.id: + return price + + amount = price * self.factor + if to_unit: + amount = amount / to_unit.factor + return amount diff --git a/mrp_bom_price_and_qty/views/mrp_bom_line_templates.xml b/mrp_bom_price_and_qty/views/mrp_bom_line_templates.xml index eef7070a7..287c37329 100644 --- a/mrp_bom_price_and_qty/views/mrp_bom_line_templates.xml +++ b/mrp_bom_price_and_qty/views/mrp_bom_line_templates.xml @@ -1,16 +1,206 @@ - diff --git a/setup/mrp_bom_price_and_qty/odoo/addons/mrp_bom_price_and_qty b/setup/mrp_bom_price_and_qty/odoo/addons/mrp_bom_price_and_qty new file mode 120000 index 000000000..347d488e1 --- /dev/null +++ b/setup/mrp_bom_price_and_qty/odoo/addons/mrp_bom_price_and_qty @@ -0,0 +1 @@ +../../../../mrp_bom_price_and_qty \ No newline at end of file diff --git a/setup/mrp_bom_price_and_qty/setup.py b/setup/mrp_bom_price_and_qty/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/mrp_bom_price_and_qty/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)