diff --git a/website_sale_stock_provisioning_date/__manifest__.py b/website_sale_stock_provisioning_date/__manifest__.py index debc6b5634..2950226e95 100644 --- a/website_sale_stock_provisioning_date/__manifest__.py +++ b/website_sale_stock_provisioning_date/__manifest__.py @@ -20,7 +20,7 @@ ], "web.assets_tests": [ "/website_sale_stock_provisioning_date/static/src/js/" - "website_sale_stock_provisioning_date_tour.js", + "website_sale_stock_provisioning_date_tour.esm.js", ], }, } diff --git a/website_sale_stock_provisioning_date/models/product_template.py b/website_sale_stock_provisioning_date/models/product_template.py index 84c41acd43..cdcb4eb821 100644 --- a/website_sale_stock_provisioning_date/models/product_template.py +++ b/website_sale_stock_provisioning_date/models/product_template.py @@ -14,6 +14,40 @@ class ProductTemplate(models.Model): "shows the inventory of the product in the website shop." ) + free_qty = fields.Float( + "Free To Use Quantity ", + compute="_compute_quantities", + search="_search_free_qty", + digits="Product Unit of Measure", + compute_sudo=False, + ) + + def _search_free_qty(self, operator, value): + domain = [("free_qty", operator, value)] + product_variant_query = self.env["product.product"]._search(domain) + return [("product_variant_ids", "in", product_variant_query)] + + def _compute_free_qty_dict(self): + prod_available = {} + variants_available = { + p["id"]: p for p in self.product_variant_ids._origin.read(["free_qty"]) + } + for template in self: + free_qty = 0 + for p in template.product_variant_ids._origin: + free_qty += variants_available[p.id]["free_qty"] + prod_available.setdefault( + template.id, prod_available.get(template.id, {}) + ).update({"free_qty": free_qty}) + return prod_available + + def _compute_quantities(self): + result = super()._compute_quantities() + res = self._compute_free_qty_dict() + for template in self: + template.free_qty = res[template.id]["free_qty"] + return result + def _get_next_provisioning_date(self, company): return self.product_variant_ids._get_next_provisioning_date(company) @@ -22,7 +56,6 @@ def _get_combination_info( combination=False, product_id=False, add_qty=1, - pricelist=False, parent_combination=False, only_template=False, ): @@ -30,7 +63,6 @@ def _get_combination_info( combination=combination, product_id=product_id, add_qty=add_qty, - pricelist=pricelist, parent_combination=parent_combination, only_template=only_template, ) @@ -42,13 +74,11 @@ def _get_combination_info( ) else: product = self.sudo() + website = self.env["website"].get_current_website() provisioning_date = False - if ( - product.show_next_provisioning_date - and product.qty_available - product.outgoing_qty <= 0 - ): - website_id = self.env.context.get("website_id") - company = self.env["website"].browse(website_id).company_id + free_qty = website._get_product_available_qty(product) + if product.show_next_provisioning_date and free_qty <= 0: + company = website.company_id provisioning_date = product._get_next_provisioning_date(company) provisioning_date = format_date(self.env, provisioning_date) combination_info.update(provisioning_date=provisioning_date) diff --git a/website_sale_stock_provisioning_date/static/src/js/website_sale_stock_provisioning_date_tour.esm.js b/website_sale_stock_provisioning_date/static/src/js/website_sale_stock_provisioning_date_tour.esm.js new file mode 100644 index 0000000000..c7da13008e --- /dev/null +++ b/website_sale_stock_provisioning_date/static/src/js/website_sale_stock_provisioning_date_tour.esm.js @@ -0,0 +1,24 @@ +/** @odoo-module **/ +/* Copyright 2020 Tecnativa - Ernesto Tejeda + * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ + +import {registry} from "@web/core/registry"; +import tourUtils from "@website_sale/js/tours/tour_utils"; +import wTourUtils from "@website/js/tours/tour_utils"; + +registry.category("web_tour.tours").add("website_sale_stock_provisioning_date", { + test: true, + url: "/shop", + steps: () => [ + ...tourUtils.searchProduct("provisioning date"), + wTourUtils.clickOnElement( + "click on product test", + '.oe_product_cart a:contains("provisioning date")' + ), + { + trigger: "a#add_to_cart", + extra_trigger: + ".availability_messages:has(span:contains('Next provisioning date:'))", + }, + ], +}); diff --git a/website_sale_stock_provisioning_date/static/src/js/website_sale_stock_provisioning_date_tour.js b/website_sale_stock_provisioning_date/static/src/js/website_sale_stock_provisioning_date_tour.js deleted file mode 100644 index d1f27d3e31..0000000000 --- a/website_sale_stock_provisioning_date/static/src/js/website_sale_stock_provisioning_date_tour.js +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2020 Tecnativa - Ernesto Tejeda - * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */ -odoo.define("website_sale_stock_provisioning_date.tour", function (require) { - "use strict"; - - var tour = require("web_tour.tour"); - - var steps = [ - { - content: "search provisioning date", - trigger: 'form input[name="search"]', - run: "text provisioning date", - }, - { - content: "search provisioning date", - trigger: 'form:has(input[name="search"]) .oe_search_button', - }, - { - content: "click on product test", - trigger: '.oe_product_cart a:contains("provisioning date")', - }, - { - trigger: "a#add_to_cart", - extra_trigger: - ".availability_messages:has(span:contains('Next provisioning date:'))", - }, - ]; - tour.register( - "website_sale_stock_provisioning_date", - { - url: "/shop", - test: true, - }, - steps - ); - return { - steps: steps, - }; -}); diff --git a/website_sale_stock_provisioning_date/static/src/xml/website_sale_stock_product_availability.xml b/website_sale_stock_provisioning_date/static/src/xml/website_sale_stock_product_availability.xml index 24b0ccb13c..9388b591c4 100644 --- a/website_sale_stock_provisioning_date/static/src/xml/website_sale_stock_product_availability.xml +++ b/website_sale_stock_provisioning_date/static/src/xml/website_sale_stock_product_availability.xml @@ -2,13 +2,8 @@ - - - + +
-
+
diff --git a/website_sale_stock_provisioning_date/tests/test_website_sale_stock_provisioning_date.py b/website_sale_stock_provisioning_date/tests/test_website_sale_stock_provisioning_date.py index ab28b4ca0f..144925cc13 100644 --- a/website_sale_stock_provisioning_date/tests/test_website_sale_stock_provisioning_date.py +++ b/website_sale_stock_provisioning_date/tests/test_website_sale_stock_provisioning_date.py @@ -28,7 +28,7 @@ def setUpClass(cls): limit=1, ) picking_form = Form( - recordp=cls.env["stock.picking"].with_context( + cls.env["stock.picking"].with_context( default_picking_type_id=incoming_picking_type.id ), view="stock.view_picking_form", @@ -42,6 +42,53 @@ def setUpClass(cls): picking = picking_form.save() picking.action_confirm() + cls.warehouse_1 = cls.env["stock.warehouse"].search( + [("company_id", "=", cls.env.company.id)] + ) + # Create two stockable products + cls.product_A = cls.env["product.product"].create( + { + "name": "Product A", + "allow_out_of_stock_order": False, + "type": "product", + "default_code": "E-COM1", + } + ) + cls.partner = cls.env["res.partner"].create( + {"name": "Test Partner", "email": "prueba@pruebae.es"} + ) + # Add 10 Product A in WH1 and 15 Product 1 in WH2 + quants = ( + cls.env["stock.quant"] + .with_context(inventory_mode=True) + .create( + [ + { + "product_id": cls.product_A.id, + "inventory_quantity": 10.0, + "location_id": cls.warehouse_1.lot_stock_id.id, + } + ] + ) + ) + quants.action_apply_inventory() + sale = cls.env["sale.order"].create( + { + "partner_id": cls.partner.id, + "order_line": [ + ( + 0, + 0, + { + "product_id": cls.product_A.id, + "product_uom_qty": 3, + }, + ) + ], + } + ) + sale.action_confirm() + def test_ui_website(self): """Test frontend tour.""" self.start_tour( @@ -49,3 +96,9 @@ def test_ui_website(self): "website_sale_stock_provisioning_date", login="admin", ) + + def test_search_qty_free(self): + templates = self.env["product.template"].search( + [("free_qty", ">", 0), ("id", "=", self.product_A.product_tmpl_id.id)] + ) + self.assertEqual(templates.free_qty, 7)