Copied to clipboard

Flag this post as spam?

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


  • Michael Nielsen 82 posts 362 karma points
    Mar 04, 2021 @ 14:56
    Michael Nielsen
    0

    Default currencies for multiple languages

    I have a solution with 3 languages, Danish, Dutch and English, and need the currency to be different on these languages.

    Unfortunately, as of now, the Store Picker cannot be varied by culture https://github.com/vendrhub/vendr/issues/276

    So I'll need to somehow automatically set the currency on each language, i.e. prices should be in DKK on the Danish site, EUR on the Dutch site and English site.

    I figured I would do something like this

    using System;
    using Umbraco.Core.Composing;
    using Umbraco.Web.Routing;
    using Vendlet.Library.Extensions;
    using Vendr.Core;
    using Vendr.Core.Services;
    using Vendr.Core.Session;
    
    namespace Vendlet.Library.Composers
    {
        class PublishedRequestComposer : ComponentComposer<PublishedRequestComponent>
        {
    
        }
    
        public class PublishedRequestComponent : IComponent
        {
            private readonly ISessionManager _sessionManager;
            private readonly IUnitOfWorkProvider _uowProvider;
            private readonly IOrderService _orderService;
    
            public PublishedRequestComponent(ISessionManager sessionManager,
                IUnitOfWorkProvider uowProvider,
                IOrderService orderService)
            {
                _sessionManager = sessionManager;
                _uowProvider = uowProvider;
                _orderService = orderService;
            }
    
            public void Initialize()
            {
                PublishedRequest.Prepared += PublishedRequest_Prepared;
            }
    
            private void PublishedRequest_Prepared(object sender, EventArgs e)
            {
                var request = sender as PublishedRequest;
                var content = request.PublishedContent;
    
                //Use PublishedContentExtension to get store
                var store = content.GetStore();
    
                //Use PublishedContentExtension to get root node
                var site = content.GetSite();
    
                //Vendr Store EntityPicket set to Currency
                var currency = site.Currency;
    
                // applyToCurrentOrder does not seem to work, so we need to change it on the existing order first, or else we'll get an error
                var currentOrder = _sessionManager.GetCurrentOrder(store.Id);
                if (currentOrder != null)
                {
                    using (var uow = _uowProvider.Create())
                    {
                        var order = currentOrder.AsWritable(uow).SetCurrency(currency);
    
                        _orderService.SaveOrder(order);
    
                        uow.Complete();
                    }
                }
    
                _sessionManager.SetDefaultCurrency(store.Id, currency.Id, applyToCurrentOrder: true);
            }
    
            public void Terminate()
            {
                //unsubscribe during shutdown
                PublishedRequest.Prepared -= PublishedRequest_Prepared;
            }
        }
    }
    

    Which works.

    I do wonder why the applyToCurrentOrder does not work, I don't know if I'm misunderstanding what it does?

    I'm also not sure if there's a better way than to use PublishedRequest.Prepared?

    Any input would be welcome...

  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Mar 04, 2021 @ 15:03
    Matt Brailsford
    0

    Hey Michael,

    That's a really clever solution and I think hooking into the request pipeline is a great approach 👍

    I'd be interested to know what error you are seeing when using applyToCurrentOrder?

    Internally, the SetDefaultCurrency method isn't too far different to what you have

    var defaultPaymentCountry = GetDefaultPaymentCountry(storeId);
    if (currency != null && currency.StoreId == storeId && !currency.IsDeleted 
        && defaultPaymentCountry != null && currency.IsAllowedInCountry(defaultPaymentCountry.Id))
    {
        if (applyToCurrentOrder)
        {
            // Update current order with currency change
            var currentOrder = GetCurrentOrder(storeId);
            if (currentOrder != null && currentOrder.CurrencyId != currency.Id)
            {
                using (var uow = _uowProvider.Create())
                {
                    var writableOrder = currentOrder.AsWritable(uow)
                        .SetCurrency(currency.Id);
    
                    _orderService.SaveOrder(writableOrder);
    
                    uow.Complete();
                }
            }
        }
    
        _sessionStore.SetValue<Guid>(storeId, DefaultCurrencyIdSessionKey, entity.Id);
    }
    

    Unless it's an issue with the default payment country check 🤔

  • Michael Nielsen 82 posts 362 karma points
    Mar 05, 2021 @ 07:40
    Michael Nielsen
    0

    Well using

    _sessionManager.SetDefaultCurrency(store.Id, currency.Id, applyToCurrentOrder: true);
    

    alone, actually doesn't do anything, it does not switch the currency.

    Using

    _sessionManager.SetDefaultPaymentCountry(store.Id, country.Id, applyToCurrentOrder: true);
    

    works fine, and does switch the currency.

    Until you put something in the cart on one language, and switches to the other, then I get an error saying

    Can't set order country / region to one not allowed by the order Currency

    https://prnt.sc/10dhzp2

    I'm guessing it's caused by when using the SetDefault methods, they do not change the default currency/country if the current is not allowed. But it must somehow do that when changing it on the current order 🤷‍♂️

    But the code in my original post works fine, so I'll stick with that. I don't know what the overhead of those calls are, but I'm thinking instead of doing it at every page request, then maybe saving current culture in a cookie, and only set the currency if the culture changes.

  • Michael Nielsen 82 posts 362 karma points
    Mar 05, 2021 @ 08:21
    Michael Nielsen
    0

    Correction, I do have to use both SetDefaultCurrency and SetDefaultCurrency, or else the currency won't switch when having no current order.

    So the full working code, for anyone else who might need something similar, is this:

    using System;
    using System.Web;
    using Umbraco.Core.Composing;
    using Umbraco.Web.Routing;
    using Vendlet.Library.Extensions;
    using Vendr.Core;
    using Vendr.Core.Services;
    using Vendr.Core.Session;
    
    namespace Vendlet.Library.Composers
    {
        class PublishedRequestComposer : ComponentComposer<PublishedRequestComponent>
        {
    
        }
    
        public class PublishedRequestComponent : IComponent
        {
            private readonly ISessionManager _sessionManager;
            private readonly IUnitOfWorkProvider _uowProvider;
            private readonly IOrderService _orderService;
            private readonly HttpContextBase _httpContextBase;
    
            public PublishedRequestComponent(ISessionManager sessionManager,
                IUnitOfWorkProvider uowProvider,
                IOrderService orderService,
                HttpContextBase httpContextBase)
            {
                _sessionManager = sessionManager;
                _uowProvider = uowProvider;
                _orderService = orderService;
                _httpContextBase = httpContextBase;
            }
    
            public void Initialize()
            {
                PublishedRequest.Prepared += PublishedRequest_Prepared;
            }
    
            private void PublishedRequest_Prepared(object sender, EventArgs e)
            {
                var request = sender as PublishedRequest;
    
                HttpCookie language = _httpContextBase.Request.Cookies["language"];
                var currentCulture = request.Culture.TwoLetterISOLanguageName;
    
                //If the culture has been changed
                if (language == null || language.Value != currentCulture)
                {
                    var content = request.PublishedContent;
    
                    //Use PublishedContentExtension to get store
                    var store = content.GetStore();
    
                    //Use PublishedContentExtension to get root node
                    var site = content.GetSite();
    
                    //Vendr Store EntityPicket set to Currency
                    var currency = site.Currency;
    
                    //Vendr Store EntityPicket set to Country
                    var country = site.Country;
    
                    // applyToCurrentOrder does not seem to work, so we need to change currency on the current order, or else we get an error
                    var currentOrder = _sessionManager.GetCurrentOrder(store.Id);
                    if (currentOrder != null)
                    {
                        using (var uow = _uowProvider.Create())
                        {
                            var order = currentOrder.AsWritable(uow).SetCurrency(currency);
    
                            _orderService.SaveOrder(order);
    
                            uow.Complete();
                        }
                    }
    
                    //Set default, will be used when there is no current order
                    _sessionManager.SetDefaultPaymentCountry(store.Id, country.Id, applyToCurrentOrder: true);
                    _sessionManager.SetDefaultCurrency(store.Id, currency.Id, applyToCurrentOrder: true);
    
                    //Set cookie value to new language
                    language = new HttpCookie("language");
                    language.Value = currentCulture;
                    _httpContextBase.Response.SetCookie(language);
                }
            }
    
            public void Terminate()
            {
                //unsubscribe during shutdown
                PublishedRequest.Prepared -= PublishedRequest_Prepared;
            }
        }
    }
    
  • Matt Brailsford 4125 posts 22223 karma points MVP 9x c-trib
    Mar 05, 2021 @ 09:07
    Matt Brailsford
    0

    Interesting!

    Thanks for sharing this, I'll defo look into why applyToCurrentOrder isn't doing what it should.

    Matt

    PS I've raised this as an issue on our issue tracker, linking back to this forum post for us to keep track of this https://github.com/vendrhub/vendr/issues/278

    Thanks again for the explanation.

Please Sign in or register to post replies

Write your reply to:

Draft