Add min,max field to checkout, add field to json request, process fields when updating SaleOrderLine

This commit is contained in:
Matthias Brück 2024-06-20 16:17:41 +10:00
parent e6fec01a60
commit 7cf45db2a3
9 changed files with 190 additions and 18 deletions

View file

@ -10,5 +10,10 @@
"views/sale_order_views.xml",
'views/templates.xml',
],
'assets': {
"web.assets_frontend": [
"nfu_sale_product_min_max_qty/static/src/js/website_sale.js"
]
},
"license": "LGPL-3",
}

View file

@ -0,0 +1 @@
from . import main

View file

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
from odoo.http import request
from odoo import fields, http
from odoo.addons.website_sale.controllers.main import WebsiteSale
class WebsiteSaleMinMax(WebsiteSale):
@http.route()
def cart_update(self, *args, min_qty=None, max_qty=None, **kw):
""" Override to parse to datetime optional pickup and return dates.
"""
product_uom_min_qty = fields.Float(min_qty)
product_uom_max_qty = fields.Float(max_qty)
return super().cart_update(*args, min_qty=product_uom_min_qty, max_qty=product_uom_max_qty, **kw)

View file

@ -1 +1,2 @@
from . import sale_order_line
from . import sale_order

View file

@ -0,0 +1,32 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
def _prepare_order_line_values(
self, product_id, quantity, linked_line_id=False,
no_variant_attribute_values=None, product_custom_attribute_values=None,
**kwargs
):
values = super()._prepare_order_line_values(product_id, quantity, linked_line_id=linked_line_id, no_variant_attribute_values=no_variant_attribute_values, product_custom_attribute_values=product_custom_attribute_values, **kwargs)
values.update({
'product_uom_min_qty': quantity,
'product_uom_max_qty': kwargs.get('max_qty', quantity),
})
return values
def _prepare_order_line_update_values(
self, order_line, quantity, linked_line_id=False, **kwargs
):
values = super()._prepare_order_line_update_values(order_line, quantity, linked_line_id=linked_line_id, **kwargs)
max_qty = kwargs.get('max_qty', quantity)
if quantity != order_line.product_uom_min_qty:
values['product_uom_min_qty'] = quantity
if max_qty and max_qty != order_line.product_uom_max_qty:
values['product_uom_max_qty'] = max_qty
return values

View file

@ -4,5 +4,5 @@ from odoo import models, fields
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
product_uom_min_qty = fields.Float(string="Max quantity", digits="Product Unit of Measure")
product_uom_max_qty = fields.Float(string="Min quantity", digits="Product Unit of Measure")
product_uom_min_qty = fields.Float(string="Min qty.", digits="Product Unit of Measure")
product_uom_max_qty = fields.Float(string="Max qty.", digits="Product Unit of Measure")

View file

@ -0,0 +1,86 @@
odoo.define('nfu_sale_product_min_max_qty.website_min_max_qty', function (require) {
'use strict';
var core = require('web.core');
var _t = core._t;
var core = require('web.core');
var ajax = require('web.ajax');
var wSaleUtils = require('website_sale.utils');
var publicWidget = require('web.public.widget');
require('website_sale.website_sale');
console.log('here1');
publicWidget.registry.WebsiteSale.include({
onClickAddCartJSON: function (ev) {
ev.preventDefault();
$('.css_quantity').popover('dispose');
var $link = $(ev.currentTarget);
var $input = $link.closest('.input-group').find("input");
var min = parseFloat($input.data("min") || 0);
var previousQty = parseFloat($input.val() || 0, 10);
var quantity = ($link.has(".fa-minus").length ? -1 : 1) + previousQty;
if (quantity < min) {
$input.closest('.css_quantity').popover({
content: _t(`Minimum Quantity is ${min}.`),
title: _t("Warning"),
placement: "left",
trigger: 'focus',
html: true,
});
$input.closest('.css_quantity').popover('show');
setTimeout(function () {
$('.css_quantity').popover('dispose')
}, 3000);
}
this._super(ev);
},
/**
* Adds the stock checking to the regular method
* @override
*/
_changeCartQuantity: function ($input, value, $dom_optional, line_id, productIDs) {
console.log('here2');
_.each($dom_optional, function (elem) {
$(elem).find('.js_quantity').text(value);
productIDs.push($(elem).find('span[data-product-id]').data('product-id'));
});
$input.data('update_change', true);
var max_qty = parseInt($input.closest('tr').find('input[name="max-qty"]').val(), 0);
var set_qty = parseInt($input.closest('tr').find('input[name!="max-qty"]').val(), 0);
this._rpc({
route: "/shop/cart/update_json",
params: {
line_id: line_id,
product_id: parseInt($input.data('product-id'), 10),
set_qty: set_qty,
max_qty: max_qty,
},
}).then(function (data) {
$input.data('update_change', false);
var check_value = parseInt($input.val() || 0, 10);
if (isNaN(check_value)) {
check_value = 1;
}
if (value !== check_value) {
$input.trigger('change');
return;
}
sessionStorage.setItem('website_sale_cart_quantity', data.cart_quantity);
if (!data.cart_quantity) {
return window.location = '/shop/cart';
}
$input.val(data.quantity);
$('.js_quantity[data-line-id='+line_id+']').val(data.quantity).text(data.quantity);
wSaleUtils.updateCartNavBar(data);
wSaleUtils.showWarning(data.warning);
// Propagating the change to the express checkout forms
core.bus.trigger('cart_amount_changed', data.amount, data.minor_amount);
});
}
});
});

View file

@ -6,8 +6,8 @@
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="before">
<field name="product_uom_max_qty"/>
<field name="product_uom_min_qty"/>
<field name="product_uom_max_qty"/>
</xpath>
</field>
</record>

View file

@ -1,20 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="product_quantity_min_max" inherit_id="website_sale.product" name="Select Quantity">
<xpath expr="//div[@id='o_wsale_cta_wrapper']/div/a[1]" position="before">
<span class="input-group-text">Min</span>
<template id="cart_lines_min_max_qty" inherit_id="website_sale.cart_lines" name="Shopping Cart Lines">
<xpath expr="//th[hasclass('td-qty')]" position="after">
<th class="text-center td-qty">
<t t-if="show_qty">
<span>Max qty.</span>
</t>
</th>
</xpath>
<xpath expr="//div[@id='add_to_cart_wrap']" position="before">
<div t-attf-class="css_quantity input-group {{'d-none' if combination_info['prevent_zero_price_sale'] else 'd-inline-flex'}} me-2 mb-2 align-middle #{'input-group-lg' if ctaSizeBig else ''}" contenteditable="false">
<span class="input-group-text">Max</span>
<a t-attf-href="#" class="btn btn-link js_add_cart_json" aria-label="Remove one" title="Remove one">
<xpath expr="//td[hasclass('td-qty')]" position="after">
<td class="text-center td-qty">
<div class="css_quantity input-group mx-auto justify-content-center">
<t t-if="not line._is_not_sellable_line()">
<t t-if="show_qty">
<a t-attf-href="#" class="btn btn-link js_add_cart_json d-none d-md-inline-block" aria-label="Remove one" title="Remove one">
<i class="fa fa-minus"></i>
</a>
<input type="text" class="form-control quantity text-center" data-min="1" name="max_qty" t-att-value="max_qty or 1"/>
<a t-attf-href="#" class="btn btn-link float_left js_add_cart_json" aria-label="Add one" title="Add one">
<input type="text" name="max-qty" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="line.product_uom_max_qty and int(line.product_uom_max_qty) or int(line.product_uom_qty)" t-att-data-min="int(line.product_uom_qty)" />
<t t-if="line._get_shop_warning(clear=False)">
<a t-attf-href="#" class="btn btn-link">
<i class='fa fa-warning text-warning' t-att-title="line._get_shop_warning()" role="img" aria-label="Warning"/>
</a>
</t>
<a t-else='' t-attf-href="#" class="btn btn-link float_left js_add_cart_json d-none d-md-inline-block" aria-label="Add one" title="Add one">
<i class="fa fa-plus"></i>
</a>
</t>
<t t-else="">
<input type="hidden" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="int(line.product_uom_qty) == line.product_uom_qty and int(line.product_uom_qty) or line.product_uom_qty" />
</t>
</t>
<t t-else="">
<span class="text-muted w-100" t-esc="int(line.product_uom_qty)"/>
<input type="hidden" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="line.product_uom_qty" />
</t>
</div>
</td>
</xpath>
</template>
<template id="cart_summary_min_max_qty" inherit_id="website_sale.cart_summary" name="Cart right column">
<xpath expr="//th[hasclass('td-qty')]" position="after">
<th class="border-top-0 td-qty">Max qty.</th>
</xpath>
<xpath expr="//td[hasclass('td-qty')]" position="after">
<td class='td-qty'>
<div t-esc="line.product_uom_max_qty" />
</td>
</xpath>
</template>
</odoo>