[Python] How to handle onchange in owl odoo 18

Discussão em 'Python' iniciado por Stack, Março 1, 2025.

  1. Stack

    Stack Membro Participativo

    this is my custom template that inherited website_sale.cart in odoo 18

    <template id="shop_selection_cart" inherit_id="website_sale.cart">
    <xpath expr="//div[hasclass('col')]" position="before">
    <t t-if="website_sale_order and website_sale_order.website_order_line">
    <div class="col-12 mb-4">
    <div class="card">
    <div class="card-body">
    <h4 class="text-uppercase small fs-6 fw-bold">Select Shop</h4>
    <select name="shop_id" class="form-select" required="required" t-on-change="onShopChange">
    <option value="">Select a Shop</option>
    <t t-foreach="shops" t-as="shop">
    <option t-att-value="shop.id"
    t-att-selected="website_sale_order.shop_company_id and website_sale_order.shop_company_id.id == shop.id">
    <t t-esc="shop.name"/>
    </option>
    </t>
    </select>
    <div class="text-danger mt-2">
    Please select the shop nearest to your location.
    </div>
    <div class="shop-selection-errors mt-3"></div>
    </div>
    </div>
    </div>
    </t>
    </xpath>
    </template>
    <!-- Add error messages to cart lines -->
    <template id="cart_lines_shop_errors" inherit_id="website_sale.cart_lines">
    <xpath expr="//h6[@t-field='line.name_short']" position="after">
    <div t-attf-class="shop-selection-errors-#{line.product_id.id} mt-2"/>
    </xpath>
    </template>


    and this is my Javascript code where i defined the onchange

    import { _t } from "@web/core/l10n/translation";

    export class ShopSelection extends Component {
    setup() {
    this.rpc = useService("rpc");
    }

    async onShopChange(ev) {
    const shopId = ev.target.value;
    if (!shopId) return;

    try {
    const result = await this.rpc("/select/shop", {
    shop_id: parseInt(shopId)
    });

    if (result.success) {
    console.log("Shop changed successfully");
    window.location.reload(); // Refresh to apply company changes
    } else {
    this.showStockErrors(result);
    }
    } catch (error) {
    console.error("Error:", error);
    alert(_t("Operation failed"));
    }
    }

    showStockErrors(result) {
    // Clear previous errors
    document.querySelectorAll("[class^='shop-selection-errors-']").forEach(el => el.innerHTML = "");

    // Display new errors
    result.products?.forEach(p => {
    const errorDiv = document.querySelector(`.shop-selection-errors-${p.id}`);
    if (errorDiv) {
    errorDiv.innerHTML = `
    <div class="alert alert-danger mb-2">
    <small>
    ${_t("Available")}: ${p.available} (${_t("Required")}: ${p.required})
    </small>
    </div>
    `;
    }
    });
    alert(result.message || _t("Insufficient stock"));
    }
    }


    Also, this is my controller where i defined the route and the logic i want implemented, which is to check if the order(product) in the cart is available in the selected shop(company). this part of the customization i am doing on odoo eCommerce module.

    @http.route(['/select/shop'], type='json', auth="public", website=True)
    def stock_check(self, shop_id, **kwargs):
    order = request.website.sale_get_order(force_create=True)
    if not order or not shop_id:
    return {'success': False}
    try:
    shop = request.env['res.company'].sudo().browse(int(shop_id))
    if not shop.exists() or not shop.is_shop:
    return {'success': False, 'message': _("Invalid shop")}

    # Get ALL internal locations for the shop's company
    locations = request.env['stock.location'].sudo().search([
    ('company_id', '=', shop.id),
    ('usage', '=', 'internal') # Stock locations only
    ])
    if not locations:
    return {'success': False, 'message': _("No stock locations found for this shop")}

    out_of_stock = []
    for line in order.order_line:
    # Only check storable products
    if line.product_id.detailed_type != 'product':
    continue

    # Sum on-hand quantity across all shop's locations
    total_available = sum(
    line.product_id.with_context(location=loc.id).qty_available
    for loc in locations
    )

    if total_available < line.product_uom_qty:
    out_of_stock.append({
    'id': line.product_id.id,
    'name': line.product_id.name,
    'available': total_available,
    'required': line.product_uom_qty
    })

    if out_of_stock:
    return {
    'success': False,
    'message': _("Insufficient stock for %d products", len(out_of_stock)),
    'products': out_of_stock
    }

    # Update order's company
    order.sudo().write({
    'company_id': shop.id,
    'shop_company_id': shop.id
    })
    return {'success': True}

    except Exception as e:
    _logger.error("Shop Selection Error: %s", str(e))
    return {'success': False, 'message': _("Technical error")}


    but the problem i am facing is that the onchange method is not being triggered so the stock check does not run. I am not sure what the issue is, this is my first time working on odoo 18. any help will be sincerely appreciated. thanks in advance.

    Continue reading...

Compartilhe esta Página