Skip to content

Commit 7b0ecd2

Browse files
committed
Product bundle: Pricing for product page
1 parent 4bd7c19 commit 7b0ecd2

19 files changed

Lines changed: 387 additions & 216 deletions

src/Libraries/SmartStore.Core/Domain/Catalog/ProductBundleItem.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ public partial class ProductBundleItem : BaseEntity, ILocalizedEntity, ICloneabl
7979
[DataMember]
8080
public DateTime UpdatedOnUtc { get; set; }
8181

82+
/// <summary>
83+
/// The calculated price including discount
84+
/// </summary>
85+
public decimal PriceWithDiscount { get; set; }
86+
87+
/// <summary>
88+
/// The calculated price excluding discount
89+
/// </summary>
90+
public decimal PriceWithoutDiscount { get; set; }
91+
8292
/// <summary>
8393
/// Gets the product
8494
/// </summary>

src/Libraries/SmartStore.Data/Mapping/Catalog/ProductBundleItemMap.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public ProductBundleItemMap()
1313
this.Property(pbi => pbi.Discount).HasPrecision(18, 4);
1414
this.Property(pbi => pbi.Name).HasMaxLength(400);
1515
this.Property(pbi => pbi.ShortDescription).IsMaxLength();
16+
17+
this.Ignore(pbi => pbi.PriceWithDiscount);
18+
this.Ignore(pbi => pbi.PriceWithoutDiscount);
1619

1720
this.HasRequired(pbi => pbi.Product)
1821
.WithMany(p => p.ProductBundleItems)

src/Libraries/SmartStore.Services/Catalog/IPriceCalculationService.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,14 @@ decimal GetFinalPrice(Product product,
5858
/// <param name="additionalCharge">Additional charge</param>
5959
/// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param>
6060
/// <param name="quantity">Shopping cart item quantity</param>
61+
/// <param name="bundleItem">A product bundle item</param>
6162
/// <returns>Final price</returns>
6263
decimal GetFinalPrice(Product product,
6364
Customer customer,
6465
decimal additionalCharge,
6566
bool includeDiscounts,
66-
int quantity);
67+
int quantity,
68+
ProductBundleItem bundleItem = null);
6769

6870
/// <summary>
6971
/// Gets discount amount
@@ -113,12 +115,14 @@ decimal GetDiscountAmount(Product product,
113115
/// <param name="additionalCharge">Additional charge</param>
114116
/// <param name="quantity">Product quantity</param>
115117
/// <param name="appliedDiscount">Applied discount</param>
118+
/// <param name="bundleItem">A product bbundle item</param>
116119
/// <returns>Discount amount</returns>
117120
decimal GetDiscountAmount(Product product,
118121
Customer customer,
119122
decimal additionalCharge,
120123
int quantity,
121-
out Discount appliedDiscount);
124+
out Discount appliedDiscount,
125+
ProductBundleItem bundleItem = null);
122126

123127

124128
/// <summary>

src/Libraries/SmartStore.Services/Catalog/PriceCalculationService.cs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,15 @@ public virtual decimal GetFinalPrice(Product product,
240240
/// <param name="additionalCharge">Additional charge</param>
241241
/// <param name="includeDiscounts">A value indicating whether include discounts or not for final price computation</param>
242242
/// <param name="quantity">Shopping cart item quantity</param>
243+
/// <param name="bundleItem">A product bbundle item</param>
243244
/// <returns>Final price</returns>
244245
public virtual decimal GetFinalPrice(Product product,
245246
Customer customer,
246247
decimal additionalCharge,
247248
bool includeDiscounts,
248-
int quantity)
249+
int quantity,
250+
ProductBundleItem bundleItem = null)
249251
{
250-
251252
//initial price
252253
decimal result = product.Price;
253254

@@ -257,7 +258,7 @@ public virtual decimal GetFinalPrice(Product product,
257258
result = specialPrice.Value;
258259

259260
//tier prices
260-
if (product.HasTierPrices)
261+
if (product.HasTierPrices && bundleItem == null)
261262
{
262263
decimal? tierPrice = GetMinimumTierPrice(product, customer, quantity);
263264
if (tierPrice.HasValue)
@@ -268,7 +269,7 @@ public virtual decimal GetFinalPrice(Product product,
268269
if (includeDiscounts)
269270
{
270271
Discount appliedDiscount = null;
271-
decimal discountAmount = GetDiscountAmount(product, customer, additionalCharge, quantity, out appliedDiscount);
272+
decimal discountAmount = GetDiscountAmount(product, customer, additionalCharge, quantity, out appliedDiscount, bundleItem);
272273
result = result + additionalCharge - discountAmount;
273274
}
274275
else
@@ -344,21 +345,36 @@ public virtual decimal GetDiscountAmount(Product product,
344345
/// <param name="additionalCharge">Additional charge</param>
345346
/// <param name="quantity">Product quantity</param>
346347
/// <param name="appliedDiscount">Applied discount</param>
348+
/// <param name="bundleItem">A product bbundle item</param>
347349
/// <returns>Discount amount</returns>
348350
public virtual decimal GetDiscountAmount(Product product,
349351
Customer customer,
350352
decimal additionalCharge,
351353
int quantity,
352-
out Discount appliedDiscount)
354+
out Discount appliedDiscount,
355+
ProductBundleItem bundleItem = null)
353356
{
354357
appliedDiscount = null;
355358
decimal appliedDiscountAmount = decimal.Zero;
356359

357-
//we don't apply discounts to products with price entered by a customer
358-
if (product.CustomerEntersPrice)
359-
return appliedDiscountAmount;
360+
if (bundleItem == null)
361+
{
362+
//we don't apply discounts to products with price entered by a customer
363+
if (product.CustomerEntersPrice)
364+
return appliedDiscountAmount;
365+
366+
appliedDiscount = GetPreferredDiscount(product, customer, additionalCharge, quantity);
367+
}
368+
else if (bundleItem.Discount.HasValue && bundleItem.BundleProduct.BundlePerItemPricing)
369+
{
370+
appliedDiscount = new Discount()
371+
{
372+
UsePercentage = bundleItem.DiscountPercentage,
373+
DiscountPercentage = bundleItem.Discount.Value,
374+
DiscountAmount = bundleItem.Discount.Value
375+
};
376+
}
360377

361-
appliedDiscount = GetPreferredDiscount(product, customer, additionalCharge, quantity);
362378
if (appliedDiscount != null)
363379
{
364380
decimal finalPriceWithoutDiscount = GetFinalPrice(product, customer, additionalCharge, false, quantity);

src/Presentation/SmartStore.Web/Administration/Controllers/ProductController.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,8 @@ public ActionResult BundleItemList(GridCommand command, int productId)
17211721
ProductId = x.Product.Id,
17221722
ProductName = x.Product.Name,
17231723
Sku = x.Product.Sku,
1724+
Quantity = x.Quantity,
1725+
Discount = x.Discount,
17241726
DisplayOrder = x.DisplayOrder,
17251727
Published = x.Published
17261728
};

src/Presentation/SmartStore.Web/Administration/Infrastructure/AutoMapperStartupTask.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,9 @@ public void Execute()
546546
Mapper.CreateMap<ProductBundleItem, ProductBundleItemModel>()
547547
.ForMember(dest => dest.Locales, mo => mo.Ignore())
548548
.ForMember(dest => dest.CustomProperties, mo => mo.Ignore());
549-
Mapper.CreateMap<ProductBundleItemModel, ProductBundleItem>();
549+
Mapper.CreateMap<ProductBundleItemModel, ProductBundleItem>()
550+
.ForMember(dest => dest.PriceWithDiscount, mo => mo.Ignore())
551+
.ForMember(dest => dest.PriceWithoutDiscount, mo => mo.Ignore());
550552

551553
//discounts
552554
Mapper.CreateMap<Discount, DiscountModel>()

src/Presentation/SmartStore.Web/Administration/Models/Catalog/ProductModel.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,15 @@ public partial class BundleItemModel : EntityModelBase
554554
[SmartResourceDisplayName("Admin.Catalog.Products.Fields.Sku")]
555555
public string Sku { get; set; }
556556

557+
[SmartResourceDisplayName("Admin.Catalog.Products.BundleItems.Fields.Quantity")]
558+
public int Quantity { get; set; }
559+
557560
[SmartResourceDisplayName("Admin.Catalog.Products.BundleItems.Fields.DisplayOrder")]
558561
public int DisplayOrder { get; set; }
559562

563+
[SmartResourceDisplayName("Admin.Catalog.Products.BundleItems.Fields.Discount")]
564+
public decimal? Discount { get; set; }
565+
560566
[SmartResourceDisplayName("Admin.Catalog.Products.BundleItems.Fields.Published")]
561567
public bool Published { get; set; }
562568
}

src/Presentation/SmartStore.Web/Administration/Views/Product/_CreateOrUpdate.BundleItems.cshtml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@
8686
.ClientTemplate("<a href=\"" + @Url.Content("~/Admin/Product/Edit/") + "<#= ProductId #>\"><#= ProductName #></a>");
8787
columns.Bound(x => x.Sku)
8888
.ReadOnly();
89+
columns.Bound(x => x.Quantity)
90+
.Width(80)
91+
.Centered();
92+
columns.Bound(x => x.Discount)
93+
.Width(80)
94+
.Centered();
8995
columns.Bound(x => x.Published)
9096
.Width(100)
9197
.Template(item => @Html.SymbolForBool(item.Published))

0 commit comments

Comments
 (0)