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

OCC-173: Discount is not applied if there is also another not discounted product in the shopping cart #323

Merged
merged 7 commits into from
Aug 5, 2023
Merged
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
1 change: 1 addition & 0 deletions .github/actions/spelling/allow/occ.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ pricefield
roadmap
skus
testproduct
testdiscountedproduct
unpublish
webhooks
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,89 @@
"ProductSku": "TESTFREEPRODUCT"
},
"Product": {}
},
{
"ContentItemId": "testdiscountedproduct000",
"ContentItemVersionId": "[js:uuid()]",
"ContentType": "Product",
"DisplayText": "TestDiscountedProduct",
"Latest": true,
"Published": true,
"ModifiedUtc": "2022-08-10T19:34:57.2678948Z",
"PublishedUtc": "2022-08-10T19:34:57.2716912Z",
"CreatedUtc": "2022-08-10T19:34:57.2678948Z",
"Owner": "48a8p8cbg3ksqvyd14d75x9a59",
"Author": "admin",
"TitlePart": {
"Title": "TestDiscountedProduct"
},
"AutoroutePart": {
"Path": "testdiscountedproduct",
"SetHomepage": false,
"Disabled": false,
"RouteContainedItems": false,
"Absolute": false
},
"HtmlBodyPart": {
"Html": ""
},
"ProductPart": {
"Sku": "TESTDISCOUNTEDPRODUCT"
},
"PricePart": {
"Price": {
"value": 5.0,
"currency": "USD"
}
},
"InventoryPart": {
"Inventory": {
"TESTDISCOUNTEDPRODUCT": 5
},
"InventoryKeys": [
"TESTDISCOUNTEDPRODUCT"
],
"AllowsBackOrder": {
"Value": true
},
"IgnoreInventory": {
"Value": false
},
"MaximumOrderQuantity": {
"Value": 2.0
},
"MinimumOrderQuantity": {
"Value": 1.0
},
"OutOfStockMessage": {
"Html": "A professional out of stock message."
},
"ProductSku": "TESTDISCOUNTEDPRODUCT"
},
"DiscountPart": {
"DiscountPercentage": {
"Value": null
},
"DiscountAmount": {
"Amount": {
"value": 2.0,
"currency": "USD"
}
},
"BeginningUtc": {
"Value": null
},
"ExpirationUtc": {
"Value": null
},
"MaximumProducts": {
"Value": null
},
"MinimumProducts": {
"Value": null
}
},
"Product": {}
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Task<bool> IsApplicableAsync(PromotionAndTaxProviderContext model) =>
private static bool IsApplicable(
IList<PromotionAndTaxProviderContextLineItem> lineItems,
DateTime? purchaseDateTime) =>
lineItems.All(item => IsApplicablePerItem(item, purchaseDateTime));
lineItems.Any(item => IsApplicablePerItem(item, purchaseDateTime));

private static bool IsApplicablePerItem(PromotionAndTaxProviderContextLineItem item, DateTime? purchaseDateTime)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@

// Determine which price format to use based on corresponding site setting.
var oldPrice = priceDisplaySettings.UseNetPriceDisplay ? oldNetPrice : oldGrossPrice;

// If old gross price is null, old net price is to be used regardless of price display settings.
if (oldGrossPrice == null)
{
oldPrice = oldNetPrice;
}

// Old price should not be shown if there are no discounts.
if (!line.AdditionalData.GetMaybe("Discounts").Any())
{
oldPrice = null;
}
}

<div class="shopping-cart-table-old-price"><del>@oldPrice</del></div>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Lombiq.Tests.UI.Extensions;
using Lombiq.Tests.UI.Services;
using OpenQA.Selenium;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
using static OrchardCore.Commerce.Tests.UI.Constants.ContentItemIds;
Expand All @@ -11,6 +12,8 @@ namespace OrchardCore.Commerce.Tests.UI.Tests.PromotionTests;

public class PromotionBehaviourTests : UITestBase
{
public const string PriceFieldCssSelector = ".price-part-price-field-value";

public PromotionBehaviourTests(ITestOutputHelper testOutputHelper)
: base(testOutputHelper)
{
Expand All @@ -25,7 +28,7 @@ async Task CheckDiscountPresenceAsync(bool hasNewPrice)
{
await context.GoToContentItemByIdAsync(TestProduct);
context.Exists(By.ClassName("price-part-price-field-value"));
context.CheckExistence(By.CssSelector(".price-part-price-field-value del"), hasNewPrice);
context.CheckExistence(By.CssSelector($"{PriceFieldCssSelector} del"), hasNewPrice);
}

await context.ExecuteRecipeDirectlyAsync("OrchardCore.Commerce.Samples.GlobalDiscount");
Expand All @@ -35,4 +38,42 @@ async Task CheckDiscountPresenceAsync(bool hasNewPrice)
await CheckDiscountPresenceAsync(hasNewPrice: true);
},
browser);

[Theory, Chrome]
public Task DiscountShouldProperlyAppearOnDiscountedProduct(Browser browser) =>
ExecuteTestAfterSetupAsync(
async context =>
{
const string FullPrice = "$5.00";
const string DiscountedPrice = "$3.00";

// Discount should appear on discounted product's page.
await context.GoToRelativeUrlAsync("/testdiscountedproduct");
context.Get(By.CssSelector($"{PriceFieldCssSelector} > del")).Text.ShouldBe(FullPrice);
context.Get(By.CssSelector($"{PriceFieldCssSelector} > span")).Text.ShouldBe(DiscountedPrice);
await context.ClickReliablyOnSubmitAsync();

DemeSzabolcs marked this conversation as resolved.
Show resolved Hide resolved
// Discount should appear in cart when discounted product is the only item in the cart.
context.Get(By.CssSelector(".shopping-cart-table-unit-price")).Text.ShouldBe(DiscountedPrice);

// Old price should be shown in cart.
context.Get(By.CssSelector(".shopping-cart-table-old-price > del")).Text.ShouldBe(FullPrice);

// Discount should appear in cart when discounted product is not the only item in the cart.
await context.GoToRelativeUrlAsync("/testproduct");
await context.ClickReliablyOnSubmitAsync();
context.Get(By.CssSelector(".shopping-cart-table-unit-price")).Text.ShouldBe(DiscountedPrice);

// Old price should be shown for discounted product in cart when the cart contains a full-price item too.
context.Get(By.CssSelector(".shopping-cart-table-old-price > del")).Text.ShouldBe(FullPrice);

// Total should reflect discount as well.
context.Get(By.CssSelector(".shopping-cart-table-totals > div")).Text.ShouldBe("$8.00");

// Discount should still appear on discounted product's page when the cart contains a full-price item.
await context.GoToRelativeUrlAsync("/testdiscountedproduct");
context.Get(By.CssSelector($"{PriceFieldCssSelector} > del")).Text.ShouldBe(FullPrice);
context.Get(By.CssSelector($"{PriceFieldCssSelector} > span")).Text.ShouldBe(DiscountedPrice);
},
browser);
}