Help with applying fee (or negative discount) to subtotal below $75

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
11 anni tempo fa
I'm using nopCommerce 2.80.  Our client made a last minute request to apply a $10 fee to orders with subtotals below $75.  The website is expected to go live tomorrow, and I'm pulling my hair out trying to figure out how to do this.

I've tried many different ideas.  The closest I have gotten so far is to create a custom Discount Requirement that checks the cart subtotal, and applies the discount based on the requirement amount.  As long as I don't use a negative value for discount amount, then it works.  The problem is, I must use a negative value in order to apply the discount as a fee.  (The discount amount also must be a flat rate of $10.00, not a percentage)

Currently, it always returns a discount value of $0.00 when the discount amount is negative.


Can anyone help me with this or offer some sage advice?

Is there some better method for doing this?
  -  I've tried custom discount requirements with negative discount amount
  -  Checkout Attributes (which won't work due to the lack of conditional logic based on cart subtotal)
  -  nopTools Payment Director (couldn't figure out how to write an expression that does what I need)


If there are better options, please let me know!
11 anni tempo fa
I think there is some currency conversion taking place, which automatically sets a negative value to $0.00

Is there a safe way to modify this without potentially breaking other portions of the website?
11 anni tempo fa
It's not a currency conversion.  The same thing happens with shipping rates too.  There's some code in the core that does

if (x < 0.00)
  x == 0.00;


For Payment Director, the expression is easy - just use the ternary if-then-else operator ("  ? :  ").  E.g.

you can set up a variable named Surcharge, so it can be used in each payment method:

   Decimal  Surcharge  OrderTotalWithoutPaymentFee  < 75 ? 10 : 0

Then reference the variable in the Fee Expression of each payment option  as  [Surcharge]   (needs brackets)  E.g.

   Option  Payments.CashOnDelivery  true  [Surcharge]


You can read more about it in this blog
11 anni tempo fa
Thank you!  It worked!

I was planning on purchasing a license for Payment Director already, because we will need to restrict purchase orders to specific member roles eventually.  Glad to see it's even more capable than I thought!

On a side note, I tried searching that blog for Payment Director info, but for some reason I was only getting Shipping Director results.  Not sure how I missed that post!


Thanks man, you really saved the day!
11 anni tempo fa
New York wrote:
It's not a currency conversion.  The same thing happens with shipping rates too.  There's some code in the core that does

if (x < 0.00)
  x == 0.00;


Thanks for that tip.  I'm going to continue working on a custom Discount Requirement, just so I can get more familiar with the code.  Seems like as good as any challenge to help learn the system.


On the Payment Director, I've got it working perfectly for adding the $10 fee, but is there a way to append a small description after the fee, something like "( $10.00 ) Small order fee"?  I tried setting the Friendly Name Expression, but couldn't figure it out.  I'm sure I could do this easily in the view, but just wanted to see if it could be done within the Payment Director configuration.

One last question about Payment Director: can you have multiple records per option?  For example, I would have:

0  True  Decimal  Surcharge  OrderTotalWithoutPaymentFee < 75 ? 10 : 0    FriendlyName + " (Small order fee)"
0  True  Option  Payments.PurchaseOrder    [Surcharge]  FriendlyName + " (Small order fee)"
0  True  Option  Payments.PurchaseOrder    Customer.IsInRole("PurchaseOrderMembers")
11 anni tempo fa
Yes, the FriendlyDescription can be set - it requires that you update the PaymentMethod View.  As per the Readme.txt file in the downloaded .zip:
In order to utilize the features to have disabled payment methods, and to change the name of payment methods that the customer sees, replace your checkout views (.cshtml files) with the ones provided in the View\Checkout sub folder.

For example, this record will show a disabled radio button and the message  "(Available only for In-Store Pickup)" appended to the FriendlyName if the selected shipping option is not "Pickup in store"   (This lets the customer know that the option would have been available.  You could of course just choose to hide the option altogether):

Type:    Option
Name:    Payments.PayInStore
Expression:  ShippingOptionName.Contains("Pick up") ? Show : Disabled
FriendlyNameExpression:     ShippingOptionName.Contains("Pick up") ? "" : FriendlyName + "(Available only for In-Store Pickup)"

(When the FriendlyNameExpression evaluates to blank (""), then the normal FriendlyName is the result - that's why the ternary if-then-else expression has ' ? "" '  -i.e.  if selected shipping is pickup, then just show the friendly name, else append message)

The expression could also be written this way:
FriendlyName + (ShippingOptionName.Contains("Pick up") ? "" : "(Available only for In-Store Pickup)")


You don't need 'FriendlyName + " (Small order fee)" ' in the Surcharge variable record; only the Option record uses it (it will just be ignored).


You can't have multiple records per option (You will see warning message "Duplicate active payment method" when you add it.)  This is due to the way the core nopC identifies the customer selected payment method when needing to get the additional fee - it uses only the system name, so there can't be dups - PaymentDirector would not know which one to return.

To get the result you want, just check both order total AND whether is a member:

Create another variable (I like variables :)

Boolean  IsMember  Customer.IsInRole("PurchaseOrderMembers")

Then check IsMember to adjust the surcharge (The "!" is a NOT)

OrderTotalWithoutPaymentFee < 75 and ![IsMember] ? 10 : 0

And then use the ternary operator in the FriendlyNameExpression like example above:

[IsMember] ? "" : FriendlyName + " (Small order fee)"


(P.S.  You can actually Test the FriendlyName Expression without having to replace PaymentMethod View, but you will need the new view(s) for the customer to see desired result)
10 anni tempo fa
Thanks for the detailed info New York!


That certainly explains why it wasn't working when I tried it on the Surcharge variable.  The first thing I did before I started using Payment Director was read the readme file.  I swapped the views, but that obviously didn't help because the FriendlyName was set on the surcharge variable.


Thanks for the info about the multiple records per option.  I figured it would be a situation where I'd just have to write an expression that performs everything.  I imagine the expressions can get pretty complex the more conditions that need to be evaluated.  That's why I was wondering if there could be multiple records, rather than continuing to tack more conditions onto an ever growing expression!  Like you said though, variables are good.  I'm sure creating variable records will go a long way in reducing the length of an Option's expression.


Thank you again for your help!  C# isn't my primary language (not to mention learning MVC and the inner workings of nopCommerce as I go), so you've been very helpful with the tips about the ternary operator and how they can be used in the Payment Director expressions.  I appreciate the time you took to answer my questions!


One more question concerning Payment Director: if all payment methods have the same fee, and all payment methods meet the conditions for applying the fee, is there a way to always show the fee in the shopping cart order totals?  Specifically, is it possible to show the fee in the shopping cart order totals before the user clicks the Checkout button?
10 anni tempo fa
diyerxa wrote:
...One more question concerning Payment Director: if all payment methods have the same fee, and all payment methods meet the conditions for applying the fee, is there a way to always show the fee in the shopping cart order totals?  Specifically, is it possible to show the fee in the shopping cart order totals before the user clicks the Checkout button?

It's not possible out of the box.  If you custom code it, consider using a Checkout Attribute: create one with a single Attribute Value, give it a Price Adjustment, make it required.  Then, you won't have to deal with how to make it part of the subtotal (because it's already supported).  
A while back, I made a core change for a customer that did conditional checkout attributes (it was a bit of a hack).  I've not yet created a "Checkout Attribute Director" plugin (I'm waiting to come up with a better name :))
10 anni tempo fa
New York wrote:
...One more question concerning Payment Director: if all payment methods have the same fee, and all payment methods meet the conditions for applying the fee, is there a way to always show the fee in the shopping cart order totals?  Specifically, is it possible to show the fee in the shopping cart order totals before the user clicks the Checkout button?
It's not possible out of the box.  If you custom code it, consider using a Checkout Attribute: create one with a single Attribute Value, give it a Price Adjustment, make it required.  Then, you won't have to deal with how to make it part of the subtotal (because it's already supported).  
A while back, I made a core change for a customer that did conditional checkout attributes (it was a bit of a hack).  I've not yet created a "Checkout Attribute Director" plugin (I'm waiting to come up with a better name :))


I spent a few hours yesterday modifying OrderTotalCalulationService to add a fee to the subtotal, and I got it working beautifully... until the client changed the requirements.   So I'm back at square one, but if anyone's interested, here's what you can do to add a fee to the subtotal:

I added a few localization settings which contain values for the requirements of the Small order fee:
SmallOrderFee.Requirement = 75
SmallOrderFee.Fee = 10
(This way the values aren't hardcoded and can be edited by anyone with proper access to the localization strings)

Then in GetShoppingCartSubTotal in OrderTotalCalculationService.cs, I added

            if (subTotalExclTaxWithoutDiscount <= Convert.ToDecimal(_localizationService.GetResource("SmallOrderFee.Requirement")))
                subTotalExclTaxWithoutDiscount += Convert.ToDecimal(_localizationService.GetResource("SmallOrderFee.Fee"));

(need to add "using Nop.Services.Localization;" in order to use _localizationService.GetResource)

That properly adds a fee of '_localizationService.GetResource("SmallOrderFee.Fee")' to a subTotal Excluding Tax Without Discount less than '_localizationService.GetResource("SmallOrderFee.Requirement")'

From there, I had to add logic to OrderTotals in ShoppingCartController.cs which returns a boolean (a new boolean I added to OrderTotalsModel named SmallOrderFeeApplied), and checks the subtotal of items in cart and compares to '_localizationService.GetResource("SmallOrderFee.Requirement")'.  If the subtotal is less than, then return true, otherwise it's false.

In OrderTotals.cshtml, if Model.SmallOrderFeeApplied is true, then add a row to the cart totals table which displays the fee added to the subtotal.

It works, but only for subtotal excluding taxes and discount, and also excluding shipping.  The problem is, after I got all that done, the client requested to factor in the shipping rate.  So if the subtotal AND the shipping rate combined are less than $75, then add a $10 fee.

And of course the way I programmed it doesn't quite allow for checking the shipping rate at the point I perform the evaluation of the subtotal compared to the value in SmallOrderFee.Requirement.




So, I'll probably keep tinkering with that.  In the mean time, is "OrderTotalWithoutPaymentFee" the only way to evaluate the current cost in Payment Director?  Is there a way to evaluate with only subtotal and shipping charges (exclude tax and discounts from the evaluation)?

It looks like Shipping Director has some variables that won't work in Payment Director (i.e. "$SubTotalWithoutDiscounts").

Would it be possible to accomplish what I need with Shipping Director (add the $10 fee for (subtotal+shipping) <= 75)?
10 anni tempo fa
You should use Settings rather than Localization (which is for language strings).

e.g.
    _settingService.GetSettingByKey<Decimal>("SmallOrderFee.Requirement")


re:  "OrderTotalWithoutPaymentFee"

These are still avail:
  $ProductTotalWithDiscounts
  $ProductTotalWithoutDiscounts

But the others are not (they caused autofac circular references, and I decided not to hack it with a manual resolve, because...)
I felt that, generally, if you're calculating payment fees, it would be based on the entire total - since that's what would be paid by the customer.

re:  Shipping Director (add the $10 fee for (subtotal+shipping) <= 75)?
Yes.  You can have a Surcharge Expression.  (You would need it on each shipping option if you offer multiple)
When calling other shipping methods (internal e.g. Fixed Rate, or external e.g. FedEx, UPS, etc) which can return multiple options, use the $Rate variable to get the specific method charge.  If calculating your own rate, then factor that into the surcharge - e.g. set a variable with calculated rate, then use that variable in the Rate Expression, and then some conditional calculation ( if-then-else ternary operator " ? : " )in the Surcharge Expression.  E.g.

Decimal  Charge  10.00
Option   true    [Charge]      [$SubTotalWithoutDiscounts] + [Charge] < 75 ? 10 : 0


See this blog for sample with $Rate
See this blog for the other built-in total related variables
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.