MarkHenri
MarkHenri

Reputation: 77

How to handle onchange in owl odoo 18

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.

Upvotes: 0

Views: 30

Answers (0)

Related Questions