diff --git a/custom_mrp_line_cost/models/stock_move_line.py b/custom_mrp_line_cost/models/stock_move_line.py index f807e1649..96e9d7642 100644 --- a/custom_mrp_line_cost/models/stock_move_line.py +++ b/custom_mrp_line_cost/models/stock_move_line.py @@ -195,6 +195,8 @@ def _compute_expense_kg(self): "production_id.is_deconstruction", "production_id.move_line_ids", "production_id.move_line_ids.amount", + "production_id.move_line_ids.lot_id", + "lot_id", ) def _compute_base_price(self): for line in self: diff --git a/mrp_bom_structure_xlsx_cost/README.rst b/mrp_bom_structure_xlsx_cost/README.rst new file mode 100644 index 000000000..dfdcbde13 --- /dev/null +++ b/mrp_bom_structure_xlsx_cost/README.rst @@ -0,0 +1,53 @@ +.. 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 Structure XLSX Cost +=========================== + +This module provides an XLSX report detailing the BOM (Bill of Materials) structure at the product level. It utilizes Odoo’s XLSX reporting engine and XlsxWriter library. + +Overview +-------- + +### Class `BomStructureXlsxL1` + +- **Purpose**: Generates a Level 1 BOM structure report in XLSX format. +- **Inherits**: Extends `report.mrp_bom_structure_xlsx.bom_structure_xlsx`. + +### Key Methods + +- **`print_bom_children(self, ch, sheet, row, level)`**: + - Writes BOM line details to the XLSX sheet, including product code, name, quantity, unit of measure, reference, and cost. + - Recursively processes child BOM lines. + +- **`generate_xlsx_report(self, workbook, data, objects)`**: + - Configures the XLSX workbook and sheet, sets column widths, applies formatting, and writes report data. + - Calls `print_bom_children` to include child BOM lines. + +### Report Configuration + +- **Sheet Layout**: Landscape orientation, 80% zoom, with adjusted column widths. +- **Formatting**: Bold headers and data rows. +- **Freezing Panes**: Keeps the header row visible when scrolling. + +This setup allows for a detailed and organized BOM report in an easy-to-read XLSX format. + +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_structure_xlsx_cost/__init__.py b/mrp_bom_structure_xlsx_cost/__init__.py new file mode 100644 index 000000000..4c4f242fa --- /dev/null +++ b/mrp_bom_structure_xlsx_cost/__init__.py @@ -0,0 +1 @@ +from . import report diff --git a/mrp_bom_structure_xlsx_cost/__manifest__.py b/mrp_bom_structure_xlsx_cost/__manifest__.py new file mode 100644 index 000000000..b74b29eb5 --- /dev/null +++ b/mrp_bom_structure_xlsx_cost/__manifest__.py @@ -0,0 +1,16 @@ +{ + "name": "MRP BOM Structure XLSX Cost", + "version": "14.0.1.0.0", + "website": "https://github.com/avanzosc/mrp-addons", + "summary": "Customization to add cost information to MRP BOM structure XLSX.", + "category": "Manufacturing", + "author": "Avanzosc", + "license": "AGPL-3", + "depends": ["mrp_bom_structure_xlsx"], + "data": [ + "report/bom_structure_xlsx.xml", + ], + "installable": True, + "application": False, + "auto_install": False, +} diff --git a/mrp_bom_structure_xlsx_cost/report/__init__.py b/mrp_bom_structure_xlsx_cost/report/__init__.py new file mode 100644 index 000000000..6bfc60043 --- /dev/null +++ b/mrp_bom_structure_xlsx_cost/report/__init__.py @@ -0,0 +1 @@ +from . import bom_structure_xlsx diff --git a/mrp_bom_structure_xlsx_cost/report/bom_structure_xlsx.py b/mrp_bom_structure_xlsx_cost/report/bom_structure_xlsx.py new file mode 100644 index 000000000..64b617009 --- /dev/null +++ b/mrp_bom_structure_xlsx_cost/report/bom_structure_xlsx.py @@ -0,0 +1,98 @@ +import logging + +from odoo import _, models +from odoo.exceptions import CacheMiss + +_logger = logging.getLogger(__name__) + + +class BomStructureXlsxL1(models.AbstractModel): + _name = "report.mrp_bom_structure_xlsx_cost.bom_structure_xlsx_cost" + _description = "BOM Structure XLSX Level 1 Report" + _inherit = "report.mrp_bom_structure_xlsx.bom_structure_xlsx" + + def print_bom_children(self, ch, sheet, row, level): + i, j = row, level + j += 1 + sheet.write(i, 1, "> " * j) + sheet.write(i, 2, ch.product_id.default_code or "") + sheet.write(i, 3, ch.product_id.display_name or "") + sheet.write( + i, + 4, + ch.product_uom_id._compute_quantity(ch.product_qty, ch.product_id.uom_id) + or "", + ) + sheet.write(i, 5, ch.product_id.uom_id.name or "") + sheet.write(i, 6, ch.bom_id.code or "") + sheet.write( + i, + 7, + "{:.4f}".format( + ch.product_uom_id._compute_quantity( + ch.product_qty, ch.product_id.uom_id + ) + * ch.product_id.standard_price + or 0 + ).replace(".", ","), + ) + + i += 1 + # self.env.cache.invalidate() + try: + for child in ch.child_line_ids: + i = self.print_bom_children(child, sheet, i, j) + + except CacheMiss: + # The Bom has no childs, thus it is the last level. + # When a BoM has no childs, chlid_line_ids is None, this creates a + # CacheMiss Error. However, this is expected because there really + # cannot be child_line_ids. + pass + + j -= 1 + return i + + def generate_xlsx_report(self, workbook, data, objects): + workbook.set_properties( + {"comments": "Created with Python and XlsxWriter from Odoo 11.0"} + ) + sheet = workbook.add_worksheet(_("BOM Structure")) + sheet.set_landscape() + sheet.fit_to_pages(1, 0) + sheet.set_zoom(80) + sheet.set_column(0, 0, 40) + sheet.set_column(1, 2, 20) + sheet.set_column(3, 3, 40) + sheet.set_column(4, 6, 20) + bold = workbook.add_format({"bold": True}) + title_style = workbook.add_format( + {"bold": True, "bg_color": "#FFFFCC", "bottom": 1} + ) + sheet_title = [ + _("BOM Name"), + _("Level"), + _("Product Reference"), + _("Product Name"), + _("Quantity"), + _("Unit of Measure"), + _("Reference"), + _("Cost"), + ] + sheet.set_row(0, None, None, {"collapsed": 1}) + sheet.write_row(1, 0, sheet_title, title_style) + sheet.freeze_panes(2, 0) + i = 2 + for o in objects: + sheet.write(i, 0, o.product_tmpl_id.name or "", bold) + sheet.write(i, 1, "", bold) + sheet.write(i, 2, o.product_id.default_code or "", bold) + sheet.write(i, 3, o.product_id.name or "", bold) + sheet.write(i, 4, o.product_qty, bold) + sheet.write(i, 5, o.product_uom_id.name or "", bold) + sheet.write(i, 6, o.code or "", bold) + sheet.write(i, 7, o.product_id.standard_price or "", bold) + i += 1 + j = 0 + for ch in o.bom_line_ids: + i = self.print_bom_children(ch, sheet, i, j) diff --git a/mrp_bom_structure_xlsx_cost/report/bom_structure_xlsx.xml b/mrp_bom_structure_xlsx_cost/report/bom_structure_xlsx.xml new file mode 100644 index 000000000..882681ae2 --- /dev/null +++ b/mrp_bom_structure_xlsx_cost/report/bom_structure_xlsx.xml @@ -0,0 +1,14 @@ + + + + Export BoM Structure to Excel Cost + mrp.bom + + ir.actions.report + mrp_bom_structure_xlsx_cost.bom_structure_xlsx_cost + xlsx + mrp_bom + + diff --git a/setup/mrp_bom_structure_xlsx_cost/odoo/addons/mrp_bom_structure_xlsx_cost b/setup/mrp_bom_structure_xlsx_cost/odoo/addons/mrp_bom_structure_xlsx_cost new file mode 120000 index 000000000..bda147f45 --- /dev/null +++ b/setup/mrp_bom_structure_xlsx_cost/odoo/addons/mrp_bom_structure_xlsx_cost @@ -0,0 +1 @@ +../../../../mrp_bom_structure_xlsx_cost \ No newline at end of file diff --git a/setup/mrp_bom_structure_xlsx_cost/setup.py b/setup/mrp_bom_structure_xlsx_cost/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/mrp_bom_structure_xlsx_cost/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)