Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Kyle Eck 130 posts 280 karma points
    Mar 21, 2022 @ 14:21
    Kyle Eck
    0

    Tax Exemption for Customers

    Matt,

    My client deals with first responders (fire, ems, police) etc. due to their clientele often times departments are tax exempt and wish to exercise that when purchasing goods.

    I have so far put a boolean on the customer to know their tax exemption status (this is a manual review process on our end).

    From their I am looking for a way to make tax 0 across the board if the current logged in customer is tax exempt, while leaving tax as is if they are not...

    So far I have implemented a public override TaxRate CalculateShippingMethodTaxRate() function but this is only for the current shipping method I believe.

    Where/ What method overrides the TaxRate completely, or can I compose a TaxRate on app start that is persistent for the duration of the customer login?

    Thanks

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Mar 21, 2022 @ 14:37
    Matt Brailsford
    0

    Hi Kyle,

    If you want to set the whole order to be a tax rate of zero, you can set the orders Tax Class to a zero rate value.

    I'd maybe create two Tax Classes, one with your standard Tax rates and another Tax Exempt tax rate with everything set to zero. Then potentially on order Saving, see if the customer is logged in / text exempt and if they are set the order tax class to exempt, and if they are not, then set it back to the standard tax rate.

    var taxClass = _vendrApi.GetTaxClass(storeId, "taxExempt");
    
    order.SetTaxClass(taxClass.Id);
    
  • Kyle Eck 130 posts 280 karma points
    Mar 21, 2022 @ 15:17
    Kyle Eck
    0

    When exactly does the order saving get triggered?

    What I was thinking is that when the customer logs into their account and starts an order initially just set the tax class to a zeroed out tax class.

    At what point is an order created? Somewhere prior to adding to the cart etc?

    So would the OrderCreatingNotification be the right event for something like this?

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Mar 21, 2022 @ 15:22
    Matt Brailsford
    0

    Sure, you could do that.

    So when your user logs in / out you'll want to call the following with the relevant tax class IDs

    _vendrApi.SetDefaultTaxClass(taxClassId, applyToCurrentOrder:true);
    

    This will set the sessions default tax class to be whatever you determine it to be and thus whenever a new order is created in that session, it should take that tax class. By passing applyToCurrentOrder:true you are also saying to apply that to any open orders for this current session too.

  • Kyle Eck 130 posts 280 karma points
    Mar 21, 2022 @ 16:08
    Kyle Eck
    0

    Matt,

    Interestingly enough the .04 cents comes into pla when moving from Customer Information to the Payment Method in Vendr Checkout.

    This leads me to believe it may be the payment provider cost, however all of my payment providers are explicitly set to zero.

    See the correct price on the customer info below: enter image description here

    Then i move to payment-method and see the .04 cent difference: enter image description here

    Im looking into what happens between the steps but until i find something i figured i would pick your brain

  • Kyle Eck 130 posts 280 karma points
    Mar 21, 2022 @ 16:00
    Kyle Eck
    0

    Matt,

    Thanks for this, easy enough its implemented already.

    However, im getting an odd .04 cents on the tax yet, even with a zeroed tax class etc.

    Investigating now but any thoughts on where it may come from?

  • Kyle Eck 130 posts 280 karma points
    Apr 04, 2022 @ 17:50
    Kyle Eck
    0

    Matt,

    See my above note. I have looked an dug around but cannot find where a random .04 cents would be added if I have a zeroed tax class for each region?

    Thanks

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 05, 2022 @ 08:05
    Matt Brailsford
    0

    Hey Kyle,

    I'm not exactly sure where it's coming from. I've just tried in the demo store setting the tax rate to zero and then adding items to the cart / going through the checkout with shipping / payment method being zero value and everything is adding up correctly.

    Do you have anything else in place that could be affecting this?

  • Kyle Eck 130 posts 280 karma points
    Apr 05, 2022 @ 10:31
    Kyle Eck
    0

    Matt,

    When I initially come into the checkout to customer information the price is correct, however when I move to the next step and do GetCurrentOrder() I see the price difference.

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 05, 2022 @ 10:38
    Matt Brailsford
    0

    Hi Kyle,

    Sure, but I'm doing the exact same thing and getting a correct result so something else is a foot. I really need to be able to replicate it to debug it.

  • Kyle Eck 130 posts 280 karma points
    Apr 05, 2022 @ 10:44
    Kyle Eck
    0

    Matt,

    Totally understandable. I thought it was odd when I mentioned it to you and have been trying to find it for some time.

    I wonder if have tax and then setting it to zero has anything to do with it,

    Again, I’ll do my best to find it as it’s clearly something specific to me.

    Just to be clear, setting an order tax class id to a zeroed out tax class and saving the order is the appropriate way to zero out tax correct?

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 05, 2022 @ 10:46
    Matt Brailsford
    0

    Hey Kyle,

    It is yea, and it's what we do on Vendr too when someone provides a VAT number in Europe which means we don't charge tax, so it should all be working.

  • Kyle Eck 130 posts 280 karma points
    Apr 05, 2022 @ 14:49
    Kyle Eck
    0

    Matt,

    Can you elaborate the process of what GetCurrentOrder() does? It seems that when getting the current order, I am calculating taxes, what would the injection point be for when an order is started and tax is calculated, I need to check is a member is logged in and if so check a status on my end to determine if they are tax exempt...

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 05, 2022 @ 14:57
    Matt Brailsford
    0

    Hey Kyle

    GetCurrentOrder simply looks for an order ID in a the Vendr cookie and if one exists, calls orderService.GetOrder(id) for it which will either get the order from the DB if one isn't in cache, or just retrieve it from the cache.

    GetCurrentOrder shouldn't be doing anything to modify the order.

  • Kyle Eck 130 posts 280 karma points
    Apr 05, 2022 @ 15:12
    Kyle Eck
    0

    Makes sense as it returns a read only order, so with that in mind it also shouldn't do any calculations on the order as well, which then means I am not zeroing out the tax properly somewhere....

    When does OrderCalculation pickup the order?

    Ideally, I need to check a property at the time when the OrderCalculation Object picks up the order.

    My reasoning is this: when the OrderCalculation object picks up an order, if I check whether I have a member logged in or not i could then further check if they are tax exempt, if they are, assign a taxClassId to the order instead of the default one for the region they are in.

    As the OrderCalculation object always holds the absolute most up to date Order

    I hope this makes sense.

    So for example, I have a customer logged in and they add something to their cart, right now I show a taxRate of 6%, when in reality, i know they are tax exempt because I set them this way, I would expect a taxRate of 0.00%

  • Kyle Eck 130 posts 280 karma points
    Apr 05, 2022 @ 15:17
    Kyle Eck
    0

    Matt,

    When I move from Customer information checkout step to the next step, looking at the current order context I see the following

    context.order has a 0% taxRate

    but

    context.OrderCalculation has a 6% taxRate.

    Do you always use the order calculation instead of the order to get the most up to date order there is?

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 06, 2022 @ 08:06
    Matt Brailsford
    0

    Hey Kyle,

    What are you currently overriding such that you have an OrderCalculation context?

    OrderCalculation is created during a re-calculation of an order and whatever is in the context is what will get applied to the order at the end once the calculation is complete.

    Generally speaking though, calling SetTaxClass() on the order should require that the order is re-calculated when any price property is accessed.

  • Kyle Eck 130 posts 280 karma points
    Apr 06, 2022 @ 10:11
    Kyle Eck
    0

    Matt

    I am overriding the CalculateShippungMEthodPrice with the code below. You can see I check OrderCalculation, Ive done that as this method is called via an AJAX call and when updating via ajax i found that the shippping cost would be one call behind when using just the order context.

    I debuged it and found orderCalcultion held the correct values for me.

    Certainly I could debug this further if something isnt quite right

    Not sure if this is right or wrong.

    public override Price CalculateShippingMethodPrice(ShippingMethodReadOnly shippingMethod, Guid currencyId, Guid? countryId, Guid? regionId, TaxRate taxRate, ShippingCalculatorContext context)
            {
                var shippingPrice = new Decimal();
    
                var allLineItemsPrice = new Decimal();
                if (context.OrderCalculation != null)
                {
                    foreach (var lineItem in context.OrderCalculation.OrderLines)
                    {
                        allLineItemsPrice += lineItem.Value.TotalPrice.Value.WithoutTax;
                    }
                }
                else
                {
                    foreach (var lineItem in context.Order.OrderLines)
                    {
                        allLineItemsPrice += lineItem.TotalPrice.Value.WithoutTax;
                    }
                }
    
                shippingPrice = SMMoyerFireEcommerce.Core.Extensions.PublishedContentExtensions.CalculateShippingCostForOrder(allLineItemsPrice);
    
                if (context.Order.Discounts.Any())
                {
                    var discounts = VendrApi.Instance.GetActiveDiscounts(context.Order.StoreId);
                    foreach (var discount in discounts)
                    {
                        if (discount.Name == "Free Shipping")
                        {
                            shippingPrice = 0;
                        }
                    }
    
                }
    
    
                var price = new Price(shippingPrice, taxRate, currencyId);
    
                //var shippingPrice = _shippingService.GetShippingPrice(context.Order, currencyId);
    
                if (price == null)
                {
                    price = base.CalculateShippingMethodPrice(shippingMethod, currencyId, countryId, regionId, taxRate, context);
                }
    
                return price;
            }
    
  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 06, 2022 @ 10:26
    Matt Brailsford
    0

    Hey Kyle,

    Ok, yea. If there is an OrderCalculation then you should use it as yes, this will be the most up to date for that given execution (you can read more about this here https://vendr.net/docs/core/2.1.0/umbraco-v9/key-concepts/order-calculation-state/)

    So the only thing I can potentially see wrong here is that during a calculation process things work in cycles, first working out the un-discounted price and then working out discounts and then the final totals. Shipping calculators will run in the first wave calculating the un-discounted price but this means accessing the TotalPrice.Value of anything is likely un-set as the actual totals haven't been calculated yet. So you would need to access the TotalPrice.WithoutAdjustments property value instead (I have a fix for this coming in the next patch release as this also confused someone else so I'm now setting all prices temporarily and then just overriding them when I have the discounted version)

    I'm not exactly sure if this is your issue though. Are you saying this code work and you no-longer have an issue? or this code works but you are still seeing the .04 cent bad calculation?

  • Kyle Eck 130 posts 280 karma points
    Apr 06, 2022 @ 10:39
    Kyle Eck
    0

    Matt,

    With the code as it sits I see the bad $0.04 issue.

    So you are saying access the TotalPrice.WithoutAdjustments for my proper tax calculation?

    The only other thing I notice is that the TaxRate parameter in that method when run comes in one time with 0% and then a second time with 6%, I imagine these are the cycles your talking about during calculation

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 06, 2022 @ 12:29
    Matt Brailsford
    0

    Hey Kyle,

    For the time you have an OrderCalculation yes you should use WithoutAdjustments if you just have an order, you can use whatever makes sense.

    RE cycles, the calculator should only be executed once per calculation so if it's coming around twice, then the order must be being re-calculated multiple times.

    What is the code you are using for setting the tax rate?

  • Kyle Eck 130 posts 280 karma points
    Apr 06, 2022 @ 12:45
    Kyle Eck
    0

    Matt,

    When a user logs into their account, I check if their tax status is true/false (true = tax exempt, false = not).

    With that in mind I run this code:

                       if(member.ContentType.Name == "Business")
                        {
                            //check to see if the user thats logged in is tax exempt or not
                            if (Convert.ToBoolean(member.Properties["taxExemptionStatus"].GetValue()))
                            {
                                var taxExemptTaxClass = _vendrApi.GetTaxClass(_storeService.GetStore("sMMoyerFireEquipment").Id, "taxExemptCustomers");
                                _vendrApi.SetDefaultTaxClass(_storeService.GetStore("sMMoyerFireEquipment").Id, taxExemptTaxClass.Id, true);
                            }
                        } 
    

    This may be irrelevant but when a customer adds something to their cart, I also call this code, which to my knowledge will also cause a calculation when using SaveOrder()

    order.SetShippingMethod(_sessionManager.GetDefaultShippingMethod(store.Id));
    order.SetShippingCountryRegion(_sessionManager.GetDefaultShippingCountry(store.Id));
    
    _orderService.SaveOrder(order);
    

    I run this code in my AddToCart Method in order to set the proper shipping method and region for calculating shipping cost for the order as the shipping cost is just a percentage on the sub total, which I show in the cart. This is where I would be using the OrderCalculation context as well as this AddToCart method is called with AJAX

    This could be where the additional calcs are coming in but Im not 100% sure.

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Apr 06, 2022 @ 13:46
    Matt Brailsford
    0

    Hmm, I can't really see anything that would be a problem here. Maybe just make sure you fetch the order after you have set the default tax class as that will apply the tax rate in the background but it won't update any existing instances of the order you have.

    But I can't really see anything here that would relate to the .04 cent issue 🤔

  • Kyle Eck 130 posts 280 karma points
    Apr 05, 2022 @ 11:00
    Kyle Eck
    0

    I guess what’s confusing me is that when I initially call GetCurrentOrder() when loading Customer information everything is kosher.

    But when hitting next and going to Payment Method (I skip shipping because it’s flat rate based on subtotal) I call GetCurrentOrder again for that template and see the issue,

    Does GetCurrentOrder pull from a session guid or from Umbraco Context? Setting the tax class obviously hits the database but I’m curious of the inner workings of GetCurrentOrder() as I only see it when moving checkout screens

    Really odd one here

Please Sign in or register to post replies

Write your reply to:

Draft