Skip to content

Commit

Permalink
[IMP] website_product_configurator: Reconfigure cart line
Browse files Browse the repository at this point in the history
  • Loading branch information
SirAionTech committed Jun 25, 2024
1 parent f39aef2 commit ddea5dd
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 8 deletions.
2 changes: 1 addition & 1 deletion website_product_configurator/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Website Product Configurator
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:571a6836c9659722dc42db79a4b0b1d7f1915bf9c139a7a34518f21973cdc009
!! source digest: sha256:5cb6dd72d2d950eb9a268d8cc613db21a735494ec532a55bd472156be9a88b76
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down
1 change: 1 addition & 0 deletions website_product_configurator/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
],
"web.assets_tests": [
"website_product_configurator/static/tests/tours/custom_values.esm.js",
"website_product_configurator/static/tests/tours/reconfigure_cart_line.esm.js",
],
},
"demo": ["demo/product_template_demo.xml"],
Expand Down
63 changes: 60 additions & 3 deletions website_product_configurator/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ def render_form(
config_vals = self.get_render_vals(cfg_session)
values.update(product_values)
values.update(config_vals)
reconfiguring_order_line_id = kwargs.get("reconfiguring_order_line_id")
if reconfiguring_order_line_id:
reconfiguring_order_line = request.env["sale.order.line"].browse(
int(reconfiguring_order_line_id)
)
order = request.website.sale_get_order()
if reconfiguring_order_line.exists() in order.order_line:
values["reconfiguring_order_line"] = reconfiguring_order_line
return request.render(
"website_product_configurator.product_configurator", values
)
Expand Down Expand Up @@ -456,11 +464,11 @@ def save_configuration(
except Exception as Ex:
return {"error": Ex}

Check warning on line 465 in website_product_configurator/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_product_configurator/controllers/main.py#L464-L465

Added lines #L464 - L465 were not covered by tests

form_values = self.get_orm_form_vals(form_values, config_session_id)
config_form_values = self.get_orm_form_vals(form_values, config_session_id)
try:
# save values
config_session_id.sudo().update_session_configuration_value(
vals=form_values, product_tmpl_id=product_template_id
vals=config_form_values, product_tmpl_id=product_template_id
)

# next step
Expand Down Expand Up @@ -495,6 +503,19 @@ def save_configuration(
if product:
redirect_url = "/product_configurator/product"
redirect_url += "/%s" % (slug(config_session_id))
reconfiguring_order_line_id_list = list(
filter(
lambda v: v["name"] == "reconfiguring_order_line_id",
form_values,
)
)
if reconfiguring_order_line_id_list:
reconfiguring_order_line_id = reconfiguring_order_line_id_list[0][
"value"
]
redirect_url += "?reconfiguring_order_line_id={}".format(
reconfiguring_order_line_id
)
return {
"product_id": product.id,
"config_session": config_session_id.id,
Expand Down Expand Up @@ -552,6 +573,15 @@ def cfg_session(self, cfg_session_id, **post):
"vals": vals,
"reconfigure_product_url": reconfigure_product_url,
}
reconfiguring_order_line_id = post.get("reconfiguring_order_line_id")
if reconfiguring_order_line_id:
reconfiguring_order_line = request.env["sale.order.line"].browse(
int(reconfiguring_order_line_id)
)
order = request.website.sale_get_order()
if reconfiguring_order_line.exists() in order.order_line:
values["add_qty"] = int(reconfiguring_order_line.product_uom_qty)
values["reconfiguring_order_line"] = reconfiguring_order_line
return request.render("website_product_configurator.cfg_product", values)

@http.route(
Expand All @@ -568,7 +598,14 @@ def reconfigure_product(self, product_id, **post):
tmpl_value_ids = product_id.product_template_attribute_value_ids
cfg_session.value_ids = tmpl_value_ids.mapped("product_attribute_value_id")
cfg_session.product_id = product_id.id
return request.redirect("/shop/product/%s" % (slug(product_tmpl_id)))

redirect_url = "/shop/product/%s" % (slug(product_tmpl_id))
reconfiguring_order_line_id = post.get("reconfiguring_order_line_id")
if reconfiguring_order_line_id:
redirect_url += "?reconfiguring_order_line_id={}".format(
reconfiguring_order_line_id
)
return request.redirect(redirect_url)
except Exception:
error_code = 1

Check warning on line 610 in website_product_configurator/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_product_configurator/controllers/main.py#L609-L610

Added lines #L609 - L610 were not covered by tests
return request.redirect(
Expand All @@ -595,6 +632,26 @@ def render_error(self, error=None, message="", **post):
vals = {"message": message, "error": error}
return request.render("website_product_configurator.error_page", vals)

Check warning on line 633 in website_product_configurator/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

website_product_configurator/controllers/main.py#L632-L633

Added lines #L632 - L633 were not covered by tests

@http.route()
def cart_update_json(self, product_id, **kwargs):
reconfiguring_order_line_id = kwargs.get("reconfiguring_order_line_id")
line_id = kwargs.get("line_id")
if reconfiguring_order_line_id and not line_id:
reconfiguring_order_line = request.env["sale.order.line"].browse(
int(reconfiguring_order_line_id)
)
order = request.website.sale_get_order()
if reconfiguring_order_line.exists() in order.order_line:
# Set (not add) the `add_qty` in the line we are reconfiguring.
kwargs["line_id"] = reconfiguring_order_line.id
kwargs["set_qty"] = kwargs.pop("add_qty", 1)
# Product has to be changed too
# otherwise the line we are reconfiguring is discarded
# because doesn't match the received product
kwargs["reconfiguring_product_id"] = product_id
product_id = reconfiguring_order_line.product_id.id
return super().cart_update_json(product_id, **kwargs)

@http.route()
def cart_update(self, product_id, add_qty=1, set_qty=0, **kw):
"""This route is called when adding a product to cart (no options)."""
Expand Down
35 changes: 35 additions & 0 deletions website_product_configurator/data/config_form_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@
</div>
</template>

<template
id="warn_reconfigure_order_line"
name="Display warning when reconfiguring an order line"
>
<!-- @param order_line: the line being reconfigured. -->
<div t-if="order_line" class="alert alert-info text-center" role="alert">
<span>You are editing the product in an order line</span>
</div>
</template>

<!-- Base view for website configuration body -->
<template id="product_configurator" name="Product Configuration Interface">
<t t-call="website.layout">
Expand All @@ -25,6 +35,11 @@
id="product_configurator"
class="container py-2 product_configurator"
>
<div t-if="reconfiguring_order_line" class="row">
<t t-call="website_product_configurator.warn_reconfigure_order_line">
<t t-set="order_line" t-value="reconfiguring_order_line" />
</t>
</div>
<div class="row">
<div class="col-lg-12">
<t t-call="website_product_configurator.config_header" />
Expand All @@ -43,6 +58,12 @@
name="csrf_token"
t-att-value="request.csrf_token()"
/>
<input
t-if="reconfiguring_order_line"
type="hidden"
name="reconfiguring_order_line_id"
t-att-value="reconfiguring_order_line.id"
/>
<div class="row">
<div class="col-lg-12">
<div class="config_weight">
Expand Down Expand Up @@ -653,6 +674,13 @@
t-att-data-view-track="view_track and '1' or '0'"
t-att-data-product-tracking-info="json.dumps(request.env['product.template'].get_google_analytics_data(combination_info))"
>
<div t-if="reconfiguring_order_line" class="row">
<t
t-call="website_product_configurator.warn_reconfigure_order_line"
>
<t t-set="order_line" t-value="reconfiguring_order_line" />
</t>
</div>
<div class="row">
<div class="col-md-4">
<ol class="breadcrumb">
Expand Down Expand Up @@ -707,6 +735,13 @@
name="csrf_token"
t-att-value="request.csrf_token()"
/>
<input
t-if="reconfiguring_order_line"
type="hidden"
name="reconfiguring_order_line_id"
t-att-value="reconfiguring_order_line.id"
/>

<div class="js_product js_main_product main_product">
<t t-placeholder="select">
<input
Expand Down
25 changes: 22 additions & 3 deletions website_product_configurator/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,30 @@ def _prepare_order_line_values(
config_session_id_str = kwargs.get("config_session_id")
if config_session_id_str is not None:
values["config_session_id"] = int(config_session_id_str)
# The current configuration has been assigned to an order line,
# new configurations will go in new order lines
del request.session["product_config_session"]
if "product_config_session" in request.session:
# The current configuration has been assigned to an order line,
# new configurations will go in new order lines
del request.session["product_config_session"]
return values

def _prepare_order_line_update_values(self, order_line, quantity, **kwargs):
update_values = super()._prepare_order_line_update_values(
order_line, quantity, **kwargs
)
reconfiguring_product_id = kwargs.get("reconfiguring_product_id")
config_session_id = kwargs.get("config_session_id")
if reconfiguring_product_id and config_session_id:
reconfiguring_product = self.env["product.product"].browse(
int(reconfiguring_product_id)
)
config_session = self.env["product.config.session"].browse(
int(config_session_id)
)
if reconfiguring_product.exists() and config_session.exists():
update_values["config_session_id"] = config_session.id
update_values["product_id"] = reconfiguring_product.id
return update_values

def _cart_find_product_line(self, product_id, line_id=None, **kwargs):
"""Include Config session in search."""
order_line = super()._cart_find_product_line(
Expand Down
2 changes: 1 addition & 1 deletion website_product_configurator/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ <h1 class="title">Website Product Configurator</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:571a6836c9659722dc42db79a4b0b1d7f1915bf9c139a7a34518f21973cdc009
!! source digest: sha256:5cb6dd72d2d950eb9a268d8cc613db21a735494ec532a55bd472156be9a88b76
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/product-configurator/tree/16.0/website_product_configurator"><img alt="OCA/product-configurator" src="https://img.shields.io/badge/github-OCA%2Fproduct--configurator-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/product-configurator-16-0/product-configurator-16-0-website_product_configurator"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/product-configurator&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module facilitates to configure product on website.</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,11 @@ WebsiteSale.include({
this._super(...arguments);
const config_session_id = $form.find('input[name="config_session_id"]').val();
if (config_session_id) this.rootProduct.config_session_id = config_session_id;

const reconfiguring_order_line_id = $form
.find('input[name="reconfiguring_order_line_id"]')
.val();
if (reconfiguring_order_line_id)
this.rootProduct.reconfiguring_order_line_id = reconfiguring_order_line_id;
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/** @odoo-module **/
import tour from "web_tour.tour";

import websiteSaleTourUtils from "website_sale.tour_utils";

tour.register(
"website_product_configurator.reconfigure_cart_line",
{
test: true,
},
[
{
content: "Add to cart",
trigger: "#add_to_cart",
},
websiteSaleTourUtils.goToCart({quantity: 1}),
{
content: "Check Silver car is in cart",
trigger: "#cart_products td.td-product_name strong:contains('Silver')",
// eslint-disable-next-line no-empty-function
run: () => {},
},
{
content: "Click on reconfigure link",
trigger: "td[class='td-reconfigure_action'] > a",
},
{
content: "Check banner is shown",
trigger: "div[role='alert']",
// eslint-disable-next-line no-empty-function
run: () => {},
},
{
content: "Go to Body step",
trigger: "#product_config_form a:contains('Body')",
run: "click",
},
{
content: "Select Red color",
// Paint color is the first select of the active tab
trigger: "div.show[role='tabpanel'] select",
run: function () {
const color_select = $("div.show[role='tabpanel'] select")[0];
const $red = $(color_select).find("option:contains('Red')");
$(color_select).val($red.attr("value")).change();
},
},
{
content: "Go to last step",
trigger: "#product_config_form a:contains('Extras')",
},
{
content: "Confirm",
trigger: "button#form_action span:contains('Continue')",
},
{
content: "Check configured car is red",
trigger: "#product_details span:contains('Red')",
// eslint-disable-next-line no-empty-function
run: () => {},
},
{
content: "Add to cart",
trigger: "#add_to_cart",
},
{
content: "Check banner is shown",
trigger: "div[role='alert']",
// eslint-disable-next-line no-empty-function
run: () => {},
},
websiteSaleTourUtils.goToCart({quantity: 1}),
{
content: "Check Red car is in cart",
trigger: "#cart_products td.td-product_name strong:contains('Red')",
// eslint-disable-next-line no-empty-function
run: () => {},
},
]
);
1 change: 1 addition & 0 deletions website_product_configurator/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from . import test_custom_values
from . import test_reconfigure_cart_line
from . import test_website_product_configurator_values
from . import test_product_config
from . import test_res_config_settings
Expand Down
38 changes: 38 additions & 0 deletions website_product_configurator/tests/test_reconfigure_cart_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2024 Simone Rubino - Aion Tech
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import operator
from functools import reduce

from odoo.tests import HttpCase, tagged

from .test_website_product_configurator_values import TestProductConfiguratorValues


@tagged("post_install", "-at_install")
class TestReconfigureProductHTTP(HttpCase, TestProductConfiguratorValues):
def test_tour(self):
admin_user = self.env.ref("base.user_admin")

session = self.session_id
session.user_id = admin_user
pavs_xmlids = [
"product_configurator.product_attribute_value_gasoline",
"product_configurator.product_attribute_value_218i",
"product_configurator.product_attribute_value_steptronic",
"product_configurator.product_attribute_value_silver",
"product_configurator.product_attribute_value_rims_378",
"product_configurator.product_attribute_value_tapistry_black",
"product_configurator.product_attribute_value_sport_line",
"product_configurator.product_attribute_value_armrest",
]
pavs_list = [self.env.ref(xmlid) for xmlid in pavs_xmlids]
session.value_ids = reduce(operator.or_, pavs_list)
session.action_confirm()

session_url = "/product_configurator/product/%s" % session.id
self.start_tour(
session_url,
"website_product_configurator.reconfigure_cart_line",
login=admin_user.login,
)
Loading

0 comments on commit ddea5dd

Please sign in to comment.