Skip to content

Commit

Permalink
Merge PR #330 into 12.0
Browse files Browse the repository at this point in the history
Signed-off-by fcayre
  • Loading branch information
github-grap-bot committed Oct 25, 2024
2 parents da7fcb9 + 748dcb7 commit 0376418
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 31 deletions.
5 changes: 4 additions & 1 deletion product_rental/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,11 @@ def setUp(self):
env = api.Environment(self.env.cr, self.partner.user_ids[0].id, {})
self.website = self.env.ref("website.default_website").with_env(env)

def render_view(self, ref, **render_kwargs):
def render_view(self, ref, sudo_as=None, **render_kwargs):
view = self.env.ref(ref)
if sudo_as:
view = view.sudo(sudo_as)

with patch.object(Website, "get_alternate_languages", return_value=()):
with MockRequest(self.env, website=self.website) as request:
request.httprequest.args = []
Expand Down
185 changes: 178 additions & 7 deletions website_sale_b2b/tests/test_payment_portal_templates.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,185 @@
from odoo.addons.product_rental.tests.test_website import WebsiteBaseTC


class PaymentPortalTemplatesTC(WebsiteBaseTC):
def clean_text(html_node):
"Return the \n and multiple whitespaces cleaned-up text content of given node"
return " ".join(html_node.text_content().split())


class PortalPaymentTemplatesTC(WebsiteBaseTC):
"""Test class for the payment of orders by portal users.
There are two different situations, both tested here:
1. the user is buying a product and wants to pay its basket
2. commercial services asked the user to validate a prepared order; its state
is then 'sent'.
"""

def setUp(self):
super().setUp()

def test_render_payment_portal_templates(self):
view = self.render_view(
"website_sale_b2b.payment_tokens_list",
is_big_b2b=True,
is_authorized_to_order=True,
self.order = self.env.ref("sale.portal_sale_order_1")
self.order.require_signature = False

self.env["payment.token"].create(
{
"partner_id": self.order.partner_id.id,
"acquirer_id": self.env.ref("payment.payment_acquirer_stripe").id,
"acquirer_ref": "test-ref",
"verified": True,
}
)

# Necessary (but not sufficient) to make is_big_b2b True.
# A last criterion is needed that can be set using the force_big_b2b method.
b2b_website = self.env.ref("website_sale_b2b.b2b_website")
self.order.partner_id.user_ids.update({"website_id": b2b_website.id})
product = self.order.order_line[0].product_id
ct = self.env.ref("product_rental.contract_tmpl_basic")
product.property_contract_template_id = ct.id

def setup_preconditions(self, big_b2b, authorized, sent):
"""Setup and check the given preconditions:
- `big_b2b` forces the order's big B2B evaluation to given boolean
- `authorized` forces the user's permission to make an order to given boolean
"""

user = self.order.partner_id.user_ids[0]
failed = "Prerequisite failed"

if not authorized:
# User is B2B but not in the dedicated group
self.order.partner_id.parent_id = self.env.ref("base.res_partner_1").id
_group_ref = "customer_manager_base.group_customer_purchase"
self.assertFalse(user.has_group(_group_ref))
self.assertIs(bool(authorized), user.is_authorized_to_order(), failed)

set_param = self.env["ir.config_parameter"].set_param
set_param("website_sale_b2b.big_b2b_min_qty", 0 if bool(big_b2b) else 10000)
self.assertIs(bool(big_b2b), self.order.is_big_b2b(), failed)

if not sent:
self.order.action_cancel()
self.order.action_draft()
self.assertIs(bool(sent), self.order.state == "sent", failed)

def render_payment(self, big_b2b, authorized, sent):
"Setup the case and mimic the /shop/payment website_sale module controller"

self.setup_preconditions(big_b2b, authorized, sent)

render_values = dict(
order=self.order,
website_sale_order=self.order,
errors=[],
partner=self.order.partner_id.id,
only_services=self.order.only_services,
payment_action_id=self.env.ref("payment.action_payment_acquirer").id,
return_url="/shop/payment/validate",
bootstrap_formatting=True,
access_token=self.order.access_token,
tokens=self.order.partner_id.payment_token_ids,
)

return self.render_view(
"website_sale_b2b.payment",
sudo_as=self.order.partner_id.user_ids,
**render_values
)

def render_order(self, big_b2b, authorized, sent):
self.setup_preconditions(big_b2b, authorized, sent)

order_sudo = self.order.sudo()
payment_token = self.order.partner_id.payment_token_ids[0]
render_values = {
"sale_order": order_sudo,
"token": "no matter",
"return_url": "/shop/payment/validate",
"bootstrap_formatting": True,
"partner_id": order_sudo.partner_id.id,
"report_type": "html",
"res_company": order_sudo.company_id,
"pms": payment_token,
"acquirers": payment_token.acquirer_id,
}

return self.render_view(
"sale.sale_order_portal_template",
sudo_as=self.order.partner_id.user_ids,
**render_values
)
self.assertIn("Submit my request", view.text_content())

def assertWarning(self, html_doc, true_false, warning, err_msg):
nodes = html_doc.xpath("//*[hasclass('alert-warning')]")
found = any(warning in clean_text(node) for node in nodes)
err_msg += " found" if found else " not found"
self.assertIs(bool(true_false), found, err_msg)

def assertSubmitButton(self, html_doc, true_false, text):
buttons = html_doc.xpath("//button[@type='submit']")
found = any(text in clean_text(button) for button in buttons)
err_msg = "Submit button entitled '%s'" % text
err_msg += " found" if found else " not found"
self.assertIs(bool(true_false), found, err_msg)

def assertCommercialSubmitButton(self, html_doc, true_false):
self.assertSubmitButton(html_doc, true_false, "Submit my request")

def assertCommercialRequestMessage(self, html_doc, true_false):
warning = "a member of our sales team will contact you"
self.assertWarning(html_doc, true_false, warning, "Commercial request message")

def assertUnauthorizedMessage(self, html_doc, true_false):
warning = "You are not allowed to place an order"
self.assertWarning(html_doc, true_false, warning, "Unauthorized message")

def assertPayAndConfirmSubmitButton(self, html_doc, true_false):
self.assertSubmitButton(html_doc, true_false, "Pay & Confirm")

def test_render_payment_template_big_b2b_authorized(self):
html_doc = self.render_payment(big_b2b=True, authorized=True, sent=True)

self.assertCommercialSubmitButton(html_doc, True)
self.assertCommercialRequestMessage(html_doc, True)
self.assertUnauthorizedMessage(html_doc, False)
self.assertPayAndConfirmSubmitButton(html_doc, False)

def test_render_payment_template_big_b2b_not_authorized(self):
html_doc = self.render_payment(big_b2b=True, authorized=False, sent=True)

self.assertCommercialSubmitButton(html_doc, False)
self.assertCommercialRequestMessage(html_doc, False)
self.assertUnauthorizedMessage(html_doc, True)
self.assertPayAndConfirmSubmitButton(html_doc, False)

def test_render_payment_template_not_big_b2b_not_authorized(self):
html_doc = self.render_payment(big_b2b=False, authorized=False, sent=True)

self.assertCommercialSubmitButton(html_doc, False)
self.assertCommercialRequestMessage(html_doc, False)
self.assertUnauthorizedMessage(html_doc, True)
self.assertPayAndConfirmSubmitButton(html_doc, False)

def test_render_order_template_big_b2b_authorized_sent(self):
html_doc = self.render_order(big_b2b=True, authorized=True, sent=True)

self.assertCommercialSubmitButton(html_doc, False)
self.assertCommercialRequestMessage(html_doc, False)
self.assertUnauthorizedMessage(html_doc, False)
self.assertPayAndConfirmSubmitButton(html_doc, True)

def test_render_order_template_big_b2b_not_authorized_sent(self):
"""Even if not authorized, the user as received a link with the order's access
token, so it may be unauthenticated but should be able to validate the order.
In this case, the Pay & Confirm button must thus be present.
"""

html_doc = self.render_order(big_b2b=True, authorized=False, sent=True)

self.assertCommercialSubmitButton(html_doc, False)
self.assertCommercialRequestMessage(html_doc, False)
self.assertUnauthorizedMessage(html_doc, False)
self.assertPayAndConfirmSubmitButton(html_doc, True)
51 changes: 29 additions & 22 deletions website_sale_b2b/views/payment_portal_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@

</template>

<!-- /!\ See also website_sale_b2b/views/sale_portal_templates.xml /!\
Used in two different templates:
- payment (see above): user is paying its just filled basket
- sale_order_portal_template: user is validating a quotation
Warning the order is NOT available here (and it has not the same name in both
templates named above: order in one case, sale_order in the other).
-->
<template id="payment_tokens_list" inherit_id="payment.payment_tokens_list">

<xpath expr="//form" position="attributes">
Expand All @@ -21,29 +30,27 @@
<xpath expr="//form" position="before">

<!-- Too big order: post a demand instead -->
<form t-if="is_big_b2b and is_authorized_to_order"
action="/shop/submit_order"
method="post"
class="clearfix">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="order_id" t-att-value="order_id"/>
<div class="float-left mt-2">
<a role="button" href="/shop/cart" class="btn btn-secondary">
<i class="fa fa-chevron-left"/>
<span>Back to shopping cart</span>
</a>
</div>
<div class="float-right mt-2">
<button type="submit" class="btn btn-primary">
<span>Submit my request</span> <i class="fa fa-chevron-right"/>
</button>
</div>
</form>
<t t-if="is_big_b2b and is_authorized_to_order">
<form action="/shop/submit_order" method="post" class="clearfix">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<div class="float-left mt-2">
<a role="button" href="/shop/cart" class="btn btn-secondary">
<i class="fa fa-chevron-left"/>
<span>Back to shopping cart</span>
</a>
</div>
<div class="float-right mt-2">
<button type="submit" class="btn btn-primary">
<span>Submit my request</span> <i class="fa fa-chevron-right"/>
</button>
</div>
</form>

<div t-if="is_big_b2b" class="mt-2 alert alert-warning" role="alert">
Due to the large number of units required, a member of our sales team will
contact you shortly to finalize your order.
</div>
<div class="mt-2 alert alert-warning" role="alert">
Due to the large number of units required, a member of our sales team will
contact you shortly to finalize your order.
</div>
</t>

<!-- Not authorized to order: contact a purchase group member -->
<div t-if="not is_authorized_to_order">
Expand Down
4 changes: 3 additions & 1 deletion website_sale_b2b/views/sale_portal_templates.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
considered always True because current user has this token.
-->
<xpath expr="//*[@t-call='payment.payment_tokens_list']" position="inside">
<t t-set="is_big_b2b" t-value="sale_order.is_big_b2b()" />
<!-- If the order validated and sent by Commown, the user can validate it: -->
<t t-set="is_big_b2b"
t-value="sale_order.is_big_b2b() and sale_order.state != 'sent'" />
<t t-set="is_authorized_to_order" t-value="True" />
<t t-set="can_order" t-value="is_authorized_to_order and not is_big_b2b" />
</xpath>
Expand Down

0 comments on commit 0376418

Please sign in to comment.