Skip to content

Commit

Permalink
Resolves #1569 Show login note if no prices are displayed due to cust…
Browse files Browse the repository at this point in the history
…omer group permissions
  • Loading branch information
mgesing committed Feb 8, 2019
1 parent f5b62c3 commit 7fe1ffb
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 135 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* OpenTrans: added customer number to parties
* Do not filter cookie using resources if cookie usage has not yet been consented to.
* #1563 QueuedMessagesClearTask: add a setting for the age of the mails to be deleted.
* #1569 Added a setting to show login note if no prices are displayed due to customer group permissions.

### Bugfixes
* In a multi-store environment, multiple topics with the same system name cannot be resolved reliably.
Expand Down
15 changes: 10 additions & 5 deletions src/Libraries/SmartStore.Core/Domain/Catalog/CatalogSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public CatalogSettings()
ShowColorSquaresInLists = true;
ShowDiscountSign = true;
ShowVariantCombinationPriceAdjustment = true;
ShowLinkedAttributeValueImage = true;
ShowLinkedAttributeValueImage = true;
EnableDynamicPriceUpdate = true;
ShowProductReviewsInProductDetail = true;
EnableHtmlTextCollapser = true;
Expand Down Expand Up @@ -129,10 +129,15 @@ public CatalogSettings()
/// </summary>
public bool ShowVariantCombinationPriceAdjustment { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to display quantity of linked product at attribute values
/// </summary>
public bool ShowLinkedAttributeValueQuantity { get; set; }
/// <summary>
/// Indicates whether to show a login note if the user is not authorized to see prices.
/// </summary>
public bool ShowLoginForPriceNote { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to display quantity of linked product at attribute values
/// </summary>
public bool ShowLinkedAttributeValueQuantity { get; set; }

/// <summary>
/// Gets or sets a value indicating whether to display the image of linked product at attribute values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,16 @@ public void MigrateLocaleResources(LocaleResourcesBuilder builder)

builder.Delete("Admin.Customers.Customers.List.SearchDeletedOnly");
builder.AddOrUpdate("Admin.Customers.Customers.List.SearchActiveOnly", "Only activated customers", "Nur aktivierte Kunden");

builder.AddOrUpdate("Products.LoginForPrice",
"Prices will be displayed after login.",
"Preise werden nach Anmeldung angezeigt.");

builder.AddOrUpdate("Admin.Configuration.Settings.Catalog.ShowLoginForPriceNote",
"Show login for price note",
"Hinweis \"Preis nach Anmeldung\" anzeigen",
"Specifies whether to display a message stating that prices will not be displayed until login.",
"Legt fest, ob ein Hinweis erscheinen soll, dass Preise erst nach Anmeldung angezeigt werden.");
}
}
}
52 changes: 25 additions & 27 deletions src/Libraries/SmartStore.Services/Security/PermissionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@

namespace SmartStore.Services.Security
{
/// <summary>
/// Permission service
/// </summary>
public partial class PermissionService : IPermissionService
/// <summary>
/// Permission service
/// </summary>
public partial class PermissionService : IPermissionService
{
#region Constants
/// <summary>
/// Cache key for storing a valie indicating whether a certain customer role has a permission
/// </summary>
Expand All @@ -25,20 +24,12 @@ public partial class PermissionService : IPermissionService
/// </remarks>
private const string PERMISSIONS_ALLOWED_KEY = "permission:allowed-{0}-{1}";
private const string PERMISSIONS_PATTERN_KEY = "permission:*";
#endregion

#region Fields

private readonly IRepository<PermissionRecord> _permissionRecordRepository;
private readonly IRepository<CustomerRole> _customerRoleRepository;
private readonly ICustomerService _customerService;
private readonly IWorkContext _workContext;
private readonly ICacheManager _cacheManager;

#endregion

#region Ctor

/// <summary>
/// Ctor
/// </summary>
Expand All @@ -48,19 +39,16 @@ public partial class PermissionService : IPermissionService
/// <param name="cacheManager">Cache manager</param>
public PermissionService(
IRepository<PermissionRecord> permissionRecordRepository,
IRepository<CustomerRole> customerRoleRepository,
ICustomerService customerService,
IWorkContext workContext, ICacheManager cacheManager)
IWorkContext workContext,
ICacheManager cacheManager)
{
this._permissionRecordRepository = permissionRecordRepository;
this._customerRoleRepository = customerRoleRepository;
this._customerService = customerService;
this._workContext = workContext;
this._cacheManager = cacheManager;
_permissionRecordRepository = permissionRecordRepository;
_customerService = customerService;
_workContext = workContext;
_cacheManager = cacheManager;
}

#endregion

#region Utilities

/// <summary>
Expand All @@ -71,15 +59,21 @@ public PermissionService(
/// <returns>true - authorized; otherwise, false</returns>
protected virtual bool Authorize(string permissionRecordSystemName, CustomerRole customerRole)
{
if (String.IsNullOrEmpty(permissionRecordSystemName))
if (string.IsNullOrEmpty(permissionRecordSystemName))
{
return false;
}

string key = string.Format(PERMISSIONS_ALLOWED_KEY, customerRole.Id, permissionRecordSystemName);
var key = string.Format(PERMISSIONS_ALLOWED_KEY, customerRole.Id, permissionRecordSystemName);
return _cacheManager.Get(key, () =>
{
foreach (var permission1 in customerRole.PermissionRecords)
{
if (permission1.SystemName.Equals(permissionRecordSystemName, StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}

return false;
});
Expand Down Expand Up @@ -311,16 +305,20 @@ public virtual bool Authorize(string permissionRecordSystemName)
/// <returns>true - authorized; otherwise, false</returns>
public virtual bool Authorize(string permissionRecordSystemName, Customer customer)
{
if (String.IsNullOrEmpty(permissionRecordSystemName))
if (string.IsNullOrEmpty(permissionRecordSystemName))
{
return false;
}

var customerRoles = customer.CustomerRoles.Where(cr => cr.Active);
foreach (var role in customerRoles)
{
if (Authorize(permissionRecordSystemName, role))
//yes, we have such permission
{
return true;
}
}

//no permission found
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ public CatalogSettingsModel()
[SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowVariantCombinationPriceAdjustment")]
public bool ShowVariantCombinationPriceAdjustment { get; set; }

[SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowLoginForPriceNote")]
public bool ShowLoginForPriceNote { get; set; }

[SmartResourceDisplayName("Admin.Configuration.Settings.Catalog.ShowLinkedAttributeValueQuantity")]
public bool ShowLinkedAttributeValueQuantity { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,15 @@
@Html.ValidationMessageFor(model => model.ShowVariantCombinationPriceAdjustment)
</td>
</tr>
<tr>
<td class="adminTitle">
@Html.SmartLabelFor(model => model.ShowLoginForPriceNote)
</td>
<td class="adminData">
@Html.SettingEditorFor(model => model.ShowLoginForPriceNote)
@Html.ValidationMessageFor(model => model.ShowLoginForPriceNote)
</td>
</tr>
<tr>
<td class="adminTitle">
@Html.SmartLabelFor(model => model.ShowLinkedAttributeValueQuantity)
Expand Down
86 changes: 39 additions & 47 deletions src/Presentation/SmartStore.Web/Controllers/CatalogHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -634,36 +634,34 @@ public ProductDetailsModel PrepareProductDetailModel(
IList<ProductBundleItemData> productBundleItems = null,
int selectedQuantity = 1)
{
if (product == null)
throw new ArgumentNullException("product");

if (model == null)
throw new ArgumentNullException("model");
Guard.NotNull(model, nameof(model));
Guard.NotNull(product, nameof(product));

var store = _services.StoreContext.CurrentStore;
var customer = _services.WorkContext.CurrentCustomer;
var currency = _services.WorkContext.WorkingCurrency;

decimal preSelectedPriceAdjustmentBase = decimal.Zero;
decimal preSelectedWeightAdjustment = decimal.Zero;
bool displayPrices = _services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices);
bool isBundle = (product.ProductType == ProductType.BundledProduct);
bool isBundleItemPricing = (productBundleItem != null && productBundleItem.Item.BundleProduct.BundlePerItemPricing);
bool isBundlePricing = (productBundleItem != null && !productBundleItem.Item.BundleProduct.BundlePerItemPricing);
int bundleItemId = (productBundleItem == null ? 0 : productBundleItem.Item.Id);
var preSelectedPriceAdjustmentBase = decimal.Zero;
var preSelectedWeightAdjustment = decimal.Zero;
var displayPrices = _services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices);
var isBundle = product.ProductType == ProductType.BundledProduct;
var isBundleItemPricing = productBundleItem != null && productBundleItem.Item.BundleProduct.BundlePerItemPricing;
var isBundlePricing = productBundleItem != null && !productBundleItem.Item.BundleProduct.BundlePerItemPricing;
var bundleItemId = productBundleItem == null ? 0 : productBundleItem.Item.Id;

bool hasSelectedAttributesValues = false;
bool hasSelectedAttributes = query.Variants.Count > 0;
var hasSelectedAttributesValues = false;
var hasSelectedAttributes = query.Variants.Count > 0;
List<ProductVariantAttributeValue> selectedAttributeValues = null;

var variantAttributes = (isBundle ? new List<ProductVariantAttribute>() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id));
var variantAttributes = isBundle ? new List<ProductVariantAttribute>() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id);

model.IsBundlePart = product.ProductType != ProductType.BundledProduct && productBundleItem != null;
model.ProductPrice.DynamicPriceUpdate = _catalogSettings.EnableDynamicPriceUpdate;
model.ProductPrice.BundleItemShowBasePrice = _catalogSettings.BundleItemShowBasePrice;

if (!model.ProductPrice.DynamicPriceUpdate)
selectedQuantity = 1;
if (!model.ProductPrice.DynamicPriceUpdate)
{
selectedQuantity = 1;
}

#region Product attributes

Expand Down Expand Up @@ -1075,11 +1073,11 @@ public ProductDetailsModel PrepareProductDetailModel(
#region Product price

model.ProductPrice.ProductId = product.Id;
model.ProductPrice.HidePrices = !displayPrices;
model.ProductPrice.ShowLoginNote = !displayPrices && productBundleItem == null && _catalogSettings.ShowLoginForPriceNote;

if (displayPrices)
if (displayPrices)
{
model.ProductPrice.HidePrices = false;

if (product.CustomerEntersPrice && !isBundleItemPricing)
{
model.ProductPrice.CustomerEntersPrice = true;
Expand All @@ -1092,26 +1090,25 @@ public ProductDetailsModel PrepareProductDetailModel(
}
else
{
decimal taxRate = decimal.Zero;
decimal oldPrice = decimal.Zero;
decimal finalPriceWithoutDiscountBase = decimal.Zero;
decimal finalPriceWithDiscountBase = decimal.Zero;
decimal attributesTotalPriceBase = decimal.Zero;
decimal attributesTotalPriceBaseOrig = decimal.Zero;
decimal finalPriceWithoutDiscount = decimal.Zero;
decimal finalPriceWithDiscount = decimal.Zero;

decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate);
var taxRate = decimal.Zero;
var oldPrice = decimal.Zero;
var finalPriceWithoutDiscountBase = decimal.Zero;
var finalPriceWithDiscountBase = decimal.Zero;
var attributesTotalPriceBase = decimal.Zero;
var attributesTotalPriceBaseOrig = decimal.Zero;
var finalPriceWithoutDiscount = decimal.Zero;
var finalPriceWithDiscount = decimal.Zero;
var oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate);

if (model.ProductPrice.DynamicPriceUpdate && !isBundlePricing)
{
if (selectedAttributeValues != null)
{
selectedAttributeValues.Each(x => attributesTotalPriceBase += _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(x,
product, _services.WorkContext.CurrentCustomer, null, selectedQuantity));
product, customer, null, selectedQuantity));

selectedAttributeValues.Each(x => attributesTotalPriceBaseOrig += _priceCalculationService.GetProductVariantAttributeValuePriceAdjustment(x,
product, _services.WorkContext.CurrentCustomer, null, 1));
product, customer, null, 1));
}
else
{
Expand Down Expand Up @@ -1208,36 +1205,32 @@ public ProductDetailsModel PrepareProductDetailModel(
}
else
{
model.ProductPrice.HidePrices = true;
model.ProductPrice.OldPrice = null;
model.ProductPrice.OldPrice = null;
model.ProductPrice.Price = null;
}

#endregion

#region 'Add to cart' model

model.AddToCart.ProductId = product.Id;

//quantity
model.AddToCart.EnteredQuantity = product.OrderMinimumQuantity;

model.AddToCart.MinOrderAmount = product.OrderMinimumQuantity;
model.AddToCart.MaxOrderAmount = product.OrderMaximumQuantity;
model.AddToCart.QuantityUnitName = model.QuantityUnitName; // TODO: (mc) remove 'QuantityUnitName' from parent model later
model.AddToCart.QuantityStep = product.QuantityStep > 0 ? product.QuantityStep : 1;
model.AddToCart.HideQuantityControl = product.HideQuantityControl;
model.AddToCart.QuantiyControlType = product.QuantiyControlType;
model.AddToCart.AvailableForPreOrder = product.AvailableForPreOrder;

//'add to cart', 'add to wishlist' buttons
model.AddToCart.DisableBuyButton = !displayPrices || product.DisableBuyButton || !_services.Permissions.Authorize(StandardPermissionProvider.EnableShoppingCart);
model.AddToCart.DisableWishlistButton = !displayPrices || product.DisableWishlistButton
|| !_services.Permissions.Authorize(StandardPermissionProvider.EnableWishlist)
|| product.ProductType == ProductType.GroupedProduct;
// 'add to cart', 'add to wishlist' buttons.
model.AddToCart.DisableBuyButton = !displayPrices || product.DisableBuyButton ||
!_services.Permissions.Authorize(StandardPermissionProvider.EnableShoppingCart);

//pre-order
model.AddToCart.AvailableForPreOrder = product.AvailableForPreOrder;
model.AddToCart.DisableWishlistButton = !displayPrices || product.DisableWishlistButton
|| product.ProductType == ProductType.GroupedProduct
|| !_services.Permissions.Authorize(StandardPermissionProvider.EnableWishlist);

//customer entered price
model.AddToCart.CustomerEntersPrice = product.CustomerEntersPrice;
if (model.AddToCart.CustomerEntersPrice)
{
Expand All @@ -1251,7 +1244,6 @@ public ProductDetailsModel PrepareProductDetailModel(
_priceFormatter.FormatPrice(maximumCustomerEnteredPrice, true, false));
}

//allowed quantities
var allowedQuantities = product.ParseAllowedQuatities();
foreach (var qty in allowedQuantities)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,9 @@ public partial class ProductPriceModel : ModelBase
public int ProductId { get; set; }

public bool HidePrices { get; set; }
public bool ShowLoginNote { get; set; }

public bool DynamicPriceUpdate { get; set; }
public bool DynamicPriceUpdate { get; set; }
public bool BundleItemShowBasePrice { get; set; }

public string NoteWithDiscount { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ $pd-offer-spacing: $grid-gutter-width / 2;
color: $danger;
}

.pd-callforprice {
.pd-callforprice,
.pd-loginforprice {
font-size: 1.2rem;
}

Expand Down
Loading

0 comments on commit 7fe1ffb

Please sign in to comment.