Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][ADD] website_sale_float_cart_qty: Add float qty in cart #966

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions setup/website_sale_float_cart_qty/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
54 changes: 54 additions & 0 deletions website_sale_float_cart_qty/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

================================
Website Sale Float Cart Quantity
================================

Overview
--------

This module extends the functionality of the `website_sale` module in Odoo by allowing float quantities in the shopping cart instead of integer quantities.

Features
--------

- Enables users to add fractional quantities of products to the shopping cart.
- Overrides the `_changeCartQuantity` function from `website_sale` to handle float quantities.
- Uses `parseFloat` instead of `parseInt` for value conversion on the client-side.

Usage
-----

- Users can add decimal quantities of products to the shopping cart from the online store.

- Quantities are dynamically updated in the user interface after each quantity change.

Development
-----------

The `website_sale_float_cart_qty` module uses JavaScript to extend the functionality of Odoo's `website_sale` module. The `website_sale_float_cart_qty.js` file overrides the `_changeCartQuantity` function to handle float quantities and perform server communication via RPC.

Contributions
-------------

Contributions are welcome! If you want to contribute to the development of this module, feel free to submit a pull request or report issues on the official repository.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues
<https://github.com/avanzosc/odoo-addons/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.

Credits
=======

Contributors
------------
* Ana Juaristi <anajuaristi@avanzosc.es>
* Unai Beristain <unaiberistain@avanzosc.es>

Do not contact contributors directly about support or help with technical issues.
1 change: 1 addition & 0 deletions website_sale_float_cart_qty/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
18 changes: 18 additions & 0 deletions website_sale_float_cart_qty/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Website Sale Float Cart Quantity",
"summary": "Allow float quantities in cart for website sale module",
"version": "16.0.1.0.0",
"category": "Website",
"license": "LGPL-3",
"website": "https://github.com/OCA/e-commerce",
"author": "AvanzOSC, Odoo Community Association (OCA)",
"depends": [
"website_sale",
],
"assets": {
"web.assets_frontend": [
"website_sale_float_cart_qty/static/src/js/float_qty.js",
],
},
"installable": True,
}
1 change: 1 addition & 0 deletions website_sale_float_cart_qty/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import sale_order
97 changes: 97 additions & 0 deletions website_sale_float_cart_qty/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from odoo import fields, models


class SaleOrderInherit(models.Model):
_inherit = "sale.order"

cart_quantity = fields.Float(
compute="_compute_cart_info",
)

def _cart_update(self, product_id, line_id=None, add_qty=0, set_qty=0, **kwargs):
if (
(isinstance(add_qty, int) or isinstance(set_qty, int))
and add_qty is not False
and set_qty is not False
):
return super()._cart_update(product_id, line_id, add_qty, set_qty, **kwargs)
else:
# Add or set product quantity, add_qty can be negative
self.ensure_one()
self = self.with_company(self.company_id)

# if self.state != "draft":
# self.env["request"].session.pop("sale_order_id", None)
# self.env["request"].session.pop("website_sale_cart_quantity", None)

self.env["product.product"].browse(product_id).exists()

if line_id is not False:
order_line = self._cart_find_product_line(
product_id, line_id, **kwargs
)[:1]
else:
order_line = self.env["sale.order.line"]

quantity = 0
if set_qty:
quantity = set_qty
elif add_qty:
if order_line:
quantity = order_line.product_uom_qty + add_qty
else:
quantity = add_qty

warning = ""

if quantity > 0:
quantity, warning = self._verify_updated_quantity(
order_line,
product_id,
quantity,
**kwargs,
)

# Round it to avoid infinite 0 with a one after it
quantity = round(quantity, 9)

order_line = self._cart_update_order_line(
product_id, quantity, order_line, **kwargs
)

return {
"line_id": order_line.id,
"quantity": quantity,
"option_ids": list(
set(
order_line.option_line_ids.filtered(
lambda line: line.order_id == order_line.order_id
).ids
)
),
"warning": warning,
}

def _compute_cart_info(self):
all_sums_are_int = True
for order in self:
total_quantity = sum(order.mapped("website_order_line.product_uom_qty"))

if not isinstance(total_quantity, int):
all_sums_are_int = False

only_services = all(
line.product_id.type == "service" for line in order.website_order_line
)
order.only_services = only_services
if all_sums_are_int:
return super()._compute_cart_info()
else:
for order in self:
order.cart_quantity = sum(
order.mapped("website_order_line.product_uom_qty")
)
order.only_services = all(
line.product_id.type == "service"
for line in order.website_order_line
)
86 changes: 86 additions & 0 deletions website_sale_float_cart_qty/static/src/js/float_qty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
odoo.define("website_sale_float_cart_qty.float_qty", function (require) {
"use strict";

var publicWidget = require("web.public.widget");
var wSaleUtils = require("website_sale.utils");
var core = require("web.core");
require("website_sale.website_sale");

publicWidget.registry.WebsiteSale.include({
/**
* Override the _changeCartQuantity method of WebsiteSale
* @param {jQuery} $input - The jQuery object representing the input field.
* @param {Number} value - The new value of the input field.
* @param {Array} $dom_optional - Array of DOM elements.
* @param {Number} line_id - The line ID associated with the cart line.
* @param {Array} productIDs - Array of product IDs.
*/

_changeCartQuantity: function (
$input,
value,
$dom_optional,
line_id,
productIDs
) {
_.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);

$input.val($input.val().replace(",", "."));

this._rpc({
route: "/shop/cart/update_json",
params: {
line_id: line_id,
product_id: parseInt($input.data("product-id"), 10),
set_qty: value,
},
}).then(function (data) {
$input.data("update_change", false);
var check_value = parseFloat($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);
});
},

_onChangeCartQuantity: function (ev) {
var $input = $(ev.currentTarget);
if ($input.data("update_change")) {
return;
}
var value = $input.val().replace(",", ".");
value = parseFloat(value);
var $dom = $input.closest("tr");
var $dom_optional = $dom.nextUntil(":not(.optional_product.info)");
var line_id = parseInt($input.data("line-id"), 10);
var productIDs = [parseInt($input.data("product-id"), 10)];
this._changeCartQuantity($input, value, $dom_optional, line_id, productIDs);
},
});
});
1 change: 1 addition & 0 deletions website_sale_float_cart_qty/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_cart_float_qty
Loading
Loading