Skip to content

Revolutionize Your Odoo 18 BOM Quantity Management: A Powerful 7-Step Tutorial

  • owl
odoo 18 bom quantity

Imagine a common scenario in the fast-paced world of manufacturing: you’re reviewing a Bill of Materials (BOM) report, and a client urgently requests a change to a component’s quantity. What if you could make that adjustment directly from the report view, with the changes saved instantly? This is precisely where dynamic management of Odoo 18 BOM quantity becomes not just a convenience, but a powerful efficiency booster.

Gone are the days of navigating through multiple screens or refreshing pages to see your updates reflected. With Odoo 18’s robust framework and a bit of custom development, you can empower your team to modify material requirements with unprecedented speed and accuracy. This guide will walk you through the essential steps, leveraging the power of Odoo’s front-end capabilities and ORM services to create an interactive experience.

Before we dive into the practical steps, let’s acknowledge the brilliant insight that underpins this dynamic interaction: understanding event handling. Special thanks to Ali Alaa’s LinkedIn post for highlighting the crucial distinction between t-on-input and t-on-change, which is fundamental to achieving optimal performance in such live updates.

The Challenge of Static Bills of Materials (BOMs)

In many Odoo implementations, particularly older ones or those with minimal customization, the Bill of Materials view is primarily a display-only interface. While it provides a comprehensive overview of components and their quantities, making an adjustment typically requires:

  • Navigating to the individual BOM record.
  • Clicking an “Edit” button.
  • Finding the specific component line.
  • Updating the quantity.
  • Saving the record.
  • Returning to the overview if you need to see the change in context.

This multi-step process can be cumbersome, time-consuming, and prone to errors, especially when dealing with frequent or numerous adjustments to Odoo 18 BOM quantity values. It directly impacts productivity and can introduce delays in manufacturing processes.

The Solution: Dynamic Odoo 18 BOM Quantity Management

The core of our solution lies in transforming a static display of the Odoo 18 BOM quantity into an interactive input field. This allows users to directly type in new component amounts, and upon confirmation, have these changes reflected in the backend database instantly. This not only streamlines the workflow but also significantly enhances the user experience, making Odoo even more intuitive and powerful for manufacturing operations.

By implementing this, you will empower your production managers, planners, and engineers to react swiftly to supply chain fluctuations, design revisions, or production schedule changes, ensuring that your Bill of Materials always reflects the most current requirements.

Mastering Event Handling: t-on-input vs. t-on-change

Before we write any code, it’s vital to understand the difference between t-on-input and t-on-change in Odoo’s OWL framework. Choosing the right event handler is crucial for optimizing performance, especially when dealing with database interactions for Odoo 18 BOM quantity updates.

  • t-on-input: This event listener fires every single time a user types a character into an input field. For instance, if a user types “15”, the event is triggered twice: once after “1” is entered, and again after “5”.
    • Pros: Ideal for real-time feedback, like instant search filtering, dynamic color changes, or displaying temporary messages as the user types.
    • Cons: Can be a performance bottleneck if each event triggers a complex operation or, more critically, a server request. Imagine sending two server requests for typing “15” – this quickly adds up and can slow down the system, particularly when updating many material requirements.
  • t-on-change: This event listener executes only after the user has finished typing and “confirms” the input. This typically happens when they press Enter, click outside the input field (blur event), or tab to another field.
    • Pros: Far more suitable for actions that involve saving data to the server or triggering complex backend logic. It ensures that the action is performed only once per completed edit, minimizing server load and improving overall system performance for Odoo 18 BOM quantity adjustments.
    • Cons: Does not provide instant, character-by-character feedback, which might not be suitable for certain UI elements like live search suggestions.

For our goal of dynamically updating the Odoo 18 BOM quantity and saving it to the database, t-on-change is the unequivocal choice. It ensures that the database update only occurs once the user has finalized their input, preventing unnecessary server calls and optimizing system resources.


Step-by-Step Tutorial: Implementing Dynamic Odoo 18 BOM Quantity Updates

Now, let’s roll up our sleeves and implement this powerful feature. This tutorial assumes you have a basic understanding of Odoo module development and JavaScript.

Prerequisites:

  • An Odoo 18 instance (Community or Enterprise).
  • The Manufacturing app installed.
  • Access to your Odoo custom addons path.
  • Basic knowledge of XML templating and JavaScript.

1. Create a Custom Odoo Module

First, we need a dedicated Odoo module to house our customizations. This ensures that your changes are organized, maintainable, and upgrade-safe. Let’s name our module bom_dynamic_updates.

Your module structure should look like this:

bom_dynamic_updates/
├── __init__.py
├── __manifest__.py
├── static/
│   └── src/
│       └── bom_overview_line.js
└── views/
    ├── assets.xml
    └── views.xml

2. Define Module Manifest (__manifest__.py)

Create or update your bom_dynamic_updates/__manifest__.py file with the following content. Pay close attention to the depends key, which is crucial for linking our module to Odoo’s manufacturing capabilities.


{
    'name': 'BOM Dynamic Quantity Updates',
    'version': '1.0',
    'summary': 'Enables dynamic editing of Bill of Materials component quantities.',
    'description': 'Allows users to modify Odoo 18 BOM quantity directly from the overview, '
                   'improving efficiency and real-time data accuracy.',
    'category': 'Manufacturing',
    'author': 'Your Name',
    'depends': ['mrp', 'web'], # Depend on manufacturing and web for core functionalities
    'data': [
        'views/views.xml',
        'views/assets.xml', # Link our assets file
    ],
    'installable': True,
    'application': False,
    'auto_install': False,
    'license': 'LGPL-3',
}

This manifest file declares our module’s identity, its purpose, and its dependencies. The depends on mrp is essential as we are extending an existing mrp component. We also depend on web for core Odoo web functionalities.

3. Create the XML View (views/views.xml)

This XML file will contain the template extension that replaces the static quantity display with an interactive input field. Create bom_dynamic_updates/views/views.xml:


<?xml version="1.0" encoding="UTF-8"?>
<odoo>
    <data>
        <template id="bom_dynamic_updates.BomOverviewSpecialline" inherit_id="mrp.BomOverviewLine" inherit_mode="extension">
            <xpath expr="//td[@name='quantity']" position="replace">
                <td>
                    <input
                        type="number"
                        t-model="data.quantity"
                        t-on-change="onChangeModelQuantity"
                        t-att-data-vendor-id="data.supplier_id"
                        t-att-data-bom-id="data.bom_id"
                        t-att-data-product-quantity="data.quantity"
                        class="form-control"
                        step="0.01"
                    />
                </td>
            </xpath>
        </template>
    </data>
</odoo>

Key Explanations:

  • inherit_id="mrp.BomOverviewLine": This tells Odoo that we are extending the default template used for rendering each line in the Bill of Materials overview.
  • xpath expr="//td[@name='quantity']" position="replace": This is an XPath expression that precisely targets the <td> element responsible for displaying the quantity and replaces its entire content with our custom input field.
  • <input type="number" ...>: We introduce an HTML input element of type number, which provides built-in numeric input validation and controls.
  • t-model="data.quantity": This Odoo directive binds the input field’s value directly to the quantity property of the data object available in the BomOverviewLine‘s context. This ensures that the initial value is displayed and automatically updates the client-side data.quantity when the user types.
  • t-on-change="onChangeModelQuantity": This is the most critical part from an interaction standpoint. It binds the change event of our input field to an asynchronous JavaScript function named onChangeModelQuantity. This function, which we will define next, will handle the server-side update of the Odoo 18 BOM quantity.
  • t-att-data-vendor-id="data.supplier_id", t-att-data-bom-id="data.bom_id", t-att-data-product-quantity="data.quantity": These attributes are vital for passing necessary data from the template to our JavaScript function. They attach the supplier_id, bom_id, and the original quantity as custom data-* attributes to the input element. Our JavaScript can then easily retrieve these values to construct its database query.
  • class="form-control": Applies Bootstrap styling for a consistent Odoo look and feel.
  • step="0.01": Allows for decimal inputs, useful for fractional Odoo 18 BOM quantity values.

4. Create the Static JavaScript File (static/src/bom_overview_line.js)

This file contains the core logic for handling the quantity updates. Create bom_dynamic_updates/static/src/bom_overview_line.js:


/** @odoo-module **/

import { patch } from "@web/core/utils/patch";
import { BomOverviewLine } from "@mrp/components/bom_overview_line/mrp_bom_overview_line";
import { useService } from "@web/core/utils/hooks";

patch(BomOverviewLine.prototype, "setup", {
    setup() {
        super.setup();
        console.log("Setting up BomOverviewLine patch for Odoo 18 BOM quantity updates");
        this.orm = useService('orm'); // Initialize the ORM service
    },

    /**
     * Handles the change event for the quantity input field.
     * Updates the product_quantity in mrp.bom.line model.
     * @param {Event} event The change event object.
     */
    async onChangeModelQuantity(event) {
        const input = event.target;
        const qty = parseFloat(input.value); // Parse the new quantity
        const vendorId = +input.dataset.vendorId; // Retrieve vendor ID from data attribute
        const bomId = +input.dataset.bomId; // Retrieve BOM ID from data attribute

        // 1. Input Validation: Check for invalid quantity, vendor ID, or BOM ID
        if (isNaN(qty) || !vendorId || !bomId || qty < 0) {
            input.classList.add("bg-danger"); // Highlight input with danger background
            input.value = input.dataset.productQuantity || 0; // Revert to original value
            console.warn("Invalid input for Odoo 18 BOM quantity:", { qty, vendorId, bomId });
            return;
        }

        try {
            // 2. Search for existing BOM line: Use ORM to find a matching record
            const [record] = await this.orm.call(
                "mrp.bom.line", // Model name
                "search_read", // Method to call
                [
                    ["supplier_id", "=", vendorId],
                    ["bom_id", "=", bomId],
                ],
                ["id"] // Fields to read (we only need the ID to update)
            );

            if (record) {
                // 3. Update existing BOM line: If a record is found, update its product_quantity
                await this.orm.call("mrp.bom.line", "write", [
                    [record.id], // ID of the record to update
                    { product_quantity: qty }, // New quantity value
                ]);
                console.log(`Updated Odoo 18 BOM quantity for record ${record.id} to ${qty}`);
            } else {
                // 4. Create new BOM line: If no record is found, create a new one
                // This scenario might be less common for direct edits but handles creation if needed.
                await this.orm.call("mrp.bom.line", "create", [{
                    supplier_id: vendorId,
                    bom_id: bomId,
                    product_quantity: qty,
                }, ]);
                console.log(`Created new Odoo 18 BOM quantity record for BOM ${bomId}, supplier ${vendorId} with quantity ${qty}`);
            }

            // 5. Update UI and data attributes after successful operation
            input.dataset.productQuantity = qty; // Update the original quantity data attribute
            input.value = qty.toFixed(2); // Format and display the new quantity (e.g., 5.00)
            input.classList.remove("bg-danger"); // Remove danger class if successful

        } catch (e) {
            // 6. Error Handling: Log error and revert UI if something goes wrong
            console.error("Failed to update Odoo 18 BOM quantity:", e);
            input.value = input.dataset.productQuantity || 0; // Revert input to original
            input.classList.add("bg-danger"); // Indicate error to the user
            // Optionally, show an Odoo notification here for a better UX.
        }
    },
});

Detailed JavaScript Explanation:

  • import { patch } ...: Odoo’s OWL framework allows us to “patch” existing components to extend their functionality without directly modifying core files. We’re patching the BomOverviewLine component.
  • setup(): This method is called when the patched component is initialized. We call super.setup() to maintain original behavior and then initialize this.orm = useService('orm'). The ORM (Object Relational Mapper) service is Odoo’s primary way for JavaScript to interact with the backend database models.
  • async onChangeModelQuantity(event): This asynchronous function is triggered by our t-on-change event.
    • Data Extraction: It extracts the qty from the input field’s value and vendorId, bomId, and productQuantity (original value) from the data-* attributes we set in the XML. The + prefix (+input.dataset.vendorId) is a shorthand to convert string values to numbers.
    • Input Validation: A crucial step! It checks if the qty is a valid number, if vendorId and bomId exist, and if qty is not negative. If any validation fails, it highlights the input field in red (bg-danger), reverts its value to the original, logs a warning, and stops execution. Robust validation is essential for data integrity for Odoo 18 BOM quantity values.
    • Database Interaction (ORM):
      • this.orm.call("mrp.bom.line", "search_read", [...], ["id"]): This line searches the mrp.bom.line model for a record that matches our supplier_id (vendorId) and bom_id. We only request the id field as we only need to know if the record exists for updating.
      • if (record): If a matching record is found, we call this.orm.call("mrp.bom.line", "write", [[record.id], { product_quantity: qty }]) to update the product_quantity of that existing record with the new qty.
      • else: If no matching record is found (which might occur if the component line is newly added or somehow not yet linked), we create a new mrp.bom.line record using this.orm.call("mrp.bom.line", "create", [...]).
    • UI Update & Error Handling:
      • After a successful database operation, input.dataset.productQuantity = qty; updates the stored original quantity, input.value = qty.toFixed(2); formats the displayed value, and input.classList.remove("bg-danger"); clears any error styling.
      • The try...catch block gracefully handles any errors that might occur during the ORM calls (e.g., network issues, permission errors, database constraints). If an error occurs, it’s logged to the console, the input value reverts, and the bg-danger class is reapplied, giving visual feedback to the user.

5. Link JavaScript File in Assets (views/assets.xml)

To ensure our JavaScript code is loaded and executed by Odoo, we need to link it in the backend assets. Create bom_dynamic_updates/views/assets.xml:


<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        <template id="bom_dynamic_updates_assets_backend" inherit_id="web.assets_backend">
            <xpath expr="." position="inside">
                <script type="text/javascript" src="/bom_dynamic_updates/static/src/bom_overview_line.js"/>
            </xpath>
        </template>
    </data>
</odoo>

This XML snippet tells Odoo to include our bom_overview_line.js file in the web.assets_backend bundle, making it available throughout the Odoo backend interface.

6. Install and Test the Module

With all files in place, it’s time to see your dynamic Odoo 18 BOM quantity updates in action!

  1. Restart your Odoo server.
  2. Update the module list in Odoo (Settings -> Developer Tools -> Update Apps List).
  3. Install the BOM Dynamic Quantity Updates module from the Apps menu.
  4. Navigate to the Manufacturing app.
  5. Open any existing Bill of Materials.
  6. Go to the Components tab or the BOM Overview.
  7. You should now see the quantity field for each component as an editable input box.
  8. Change a quantity, then press Enter or click outside the input field.
  9. Observe the change being saved. You might notice a brief flicker as the database update occurs, but the value should remain updated.
  10. Refresh the page or navigate away and back to confirm that the change is persisted in the database.
  11. Test invalid inputs (e.g., text, negative numbers) to see the error handling.

7. Key Considerations for a Robust Odoo 18 BOM Quantity Implementation

While the core functionality is now in place, several factors will influence the robustness and user-friendliness of your dynamic Odoo 18 BOM quantity management system:

  • Permissions and Access Rights: Ensure that users who need to modify BOM quantities have the appropriate Odoo access rights for the mrp.bom.line model. Without proper permissions, the ORM write or create calls will fail, leading to errors. You might need to adjust security rules within your module if standard user roles don’t suffice. Learn more about Odoo security rules in the official Odoo documentation.
  • Performance Optimization: While t-on-change is generally efficient, consider the scale of your operations. If you have extremely large BOMs or hundreds of simultaneous users, further optimizations might be needed. This could include batching updates, using more specific ORM queries, or client-side debouncing if your onChangeModelQuantity function becomes very complex.
  • Enhanced Error Handling and User Feedback: The current error handling simply reverts the input and logs to the console. For a better user experience, consider integrating Odoo’s built-in notification system to display user-friendly messages directly on the screen (e.g., using this.notification.addError from @web/core/notifications/notification_service). This immediately informs the user about a successful save or a failed attempt.
  • Edge Cases and Validation:
    • What if a user enters a non-numeric value? Our current code handles isNaN and reverts.
    • What if the supplier_id or bom_id is somehow missing from the data-* attributes? Our code validates for !vendorId || !bomId.
    • Consider specific business rules: e.g., should quantity always be an integer? Should it have a maximum limit? Implement these checks in your JavaScript validation logic.
  • Compatibility: Always test your module thoroughly after any Odoo version upgrades or significant module installations to ensure continued compatibility. This ensures your Odoo 18 BOM quantity updates remain seamless.
  • Testing: Implement automated tests for your custom module to catch regressions and ensure the functionality remains stable over time.

Conclusion: Empowering Your Odoo 18 Manufacturing

By following these steps, you’ve transformed a static BOM overview into a dynamic, interactive tool that dramatically enhances efficiency in managing Odoo 18 BOM quantity. This direct editing capability minimizes clicks, reduces errors, and provides real-time updates, making your manufacturing processes more agile and responsive.

Embrace the power of Odoo’s flexibility to tailor your ERP system to your exact needs. This tutorial provides a solid foundation for empowering your users with immediate, impactful data entry. Don’t stop here; explore other areas where such dynamic interactions can streamline your operations! For more advanced Odoo development insights, consider exploring the Odoo developer documentation.


Discover more from teguhteja.id

Subscribe to get the latest posts sent to your email.

Tags:

Leave a Reply

WP Twitter Auto Publish Powered By : XYZScripts.com