Reputation: 77
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