November Happy Hour will be moved to Thursday December 5th.

When adding a ShippingMethod programmatically, getting ForeignKeyConstraint error

Vote:
 

I'm trying to set shipping methods through initialization and don't see why I'm getting this ForeignKeyConstraint exception. 

ForeignKeyConstraint FK_ShippingOption_ShippingMethod requires the child key values (18ede71f-3df3-4d9e-a4cb-3d25881c1ec6) to exist in the parent table

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.DataAbstraction;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.Logging;
using EPiServer.ServiceLocation;
using Mediachase.Commerce;
using Mediachase.Commerce.Orders.Dto;
using Mediachase.Commerce.Orders.Managers;
using Mediachase.Commerce.Plugins.Shipping.Generic;

namespace Business.Initialization
{
    [InitializableModule]
    public class ShippingMethodIntialization : IInitializableModule
    {
        private readonly ILogger _logger = LogManager.GetLogger();
        private readonly Injected _currentMarket = default(Injected);

        public void Initialize(InitializationEngine context)
        {

            var currentMarketId = _currentMarket.Service.GetCurrentMarket().MarketId.Value.ToString();

            var shippingMethod = ShippingManager.GetShippingMethods("en");

//this is the shippingMethodOptionId -> 18ede71f-3df3-4d9e-a4cb-3d25881c1ec6
            var shippingMethodOptionId = shippingMethod.ShippingOption[0].ShippingOptionId;


            var shippingMethodInfo = new List
            {
                new ShippingMethodInfo("ShippingMethodTest", "ShippingMethodTest name", "ShippingMethodTest description", "USD", 100, 1, false, shippingMethodOptionId)

            };

            CreateForEnabledLanguages(shippingMethodInfo);

        }

        public void Uninitialize(InitializationEngine context)
        {

        }

        private void Create(ShippingMethodInfo shippingMethodInfo, Guid guid, string languageId)
        {
            ShippingMethodDto shippingMethod = new ShippingMethodDto();
            ShippingMethodDto.ShippingMethodRow shippingMethodRow = shippingMethod.ShippingMethod.NewShippingMethodRow();

            shippingMethodRow[shippingMethod.ShippingMethod.ShippingMethodIdColumn] = guid;
            shippingMethodRow[shippingMethod.ShippingMethod.LanguageIdColumn] = languageId;
            shippingMethodRow[shippingMethod.ShippingMethod.NameColumn] = shippingMethodInfo.Name;
            shippingMethodRow[shippingMethod.ShippingMethod.DisplayNameColumn] = shippingMethodInfo.DisplayName;
            shippingMethodRow[shippingMethod.ShippingMethod.DescriptionColumn] = shippingMethodInfo.Description;
            shippingMethodRow[shippingMethod.ShippingMethod.CurrencyColumn] = shippingMethodInfo.Currency;
            shippingMethodRow[shippingMethod.ShippingMethod.BasePriceColumn] = shippingMethodInfo.BasePrice;
            shippingMethodRow[shippingMethod.ShippingMethod.ShippingOptionIdColumn] = shippingMethodInfo.ShippingOptionIdColumn;
            shippingMethodRow[shippingMethod.ShippingMethod.IsActiveColumn] = true;
            shippingMethodRow[shippingMethod.ShippingMethod.IsDefaultColumn] = true;
            shippingMethodRow[shippingMethod.ShippingMethod.OrderingColumn] = shippingMethodInfo.Ordering;
            shippingMethodRow[shippingMethod.ShippingMethod.CreatedColumn] = FrameworkContext.Current.CurrentDateTime;
            shippingMethodRow[shippingMethod.ShippingMethod.ModifiedColumn] = FrameworkContext.Current.CurrentDateTime;


            shippingMethod.ShippingMethod.Rows.Add(shippingMethodRow);
           

            ShippingManager.SaveShipping(shippingMethod);
        }

        private void CreateForEnabledLanguages(List shippingMethodInfos)
        {
            var enabledSiteLanguages = GetEnabledSiteLanguages();
            foreach (var enabledSiteLanguage in enabledSiteLanguages)
            {
                var shippingMethodsForLanguage = GetShippingMethodsForLanguage(enabledSiteLanguage.LanguageID);

                foreach (ShippingMethodInfo shippingMethodInfo in shippingMethodInfos)
                {
                    if (shippingMethodsForLanguage.Exists(p => p.Name == shippingMethodInfo.Name))
                        continue;

                    try
                    {
                        Guid shippingMethodId = GenerateShippingMethodId();
                        Create(shippingMethodInfo, shippingMethodId, enabledSiteLanguage.LanguageID);
                    }
                    catch (Exception e)
                    {
                        _logger.Error("Could not create shipping method. See next log item for more information.", e);
                        _logger.Error($"Could not create payment method with name: {shippingMethodInfo.DisplayName} for language:{enabledSiteLanguage.LanguageID} during initialization");
                    }
                }
            }
        }

        private List GetShippingMethodsForLanguage(string languageId)
        {
            return ShippingManager.GetShippingMethods(languageId, true).ShippingMethod.ToList();
        }

        private IEnumerable GetEnabledSiteLanguages()
        {
            var languageBranchRepository = ServiceLocator.Current.GetInstance();
            return languageBranchRepository.ListEnabled();
        }

        private Guid GenerateShippingMethodId()
        {
            var id = Guid.NewGuid();
            while (ShippingManager.GetShippingMethod(id, true).ShippingMethod.Count > 0)
            {
                id = Guid.NewGuid();
            }
            return id;
        }

        private class ShippingMethodInfo
        {
            public string Name { get; set; }
            public string DisplayName { get; set; }
            public string Description { get; set; }
            public string Currency { get; set; }
            public decimal BasePrice { get; set; }
            public int Ordering { get; set; }
            public bool IsDefault { get; set; }
            public Guid ShippingOptionIdColumn { get; set; }

            public ShippingMethodInfo(
             string name,
             string displayName,
             string description,
             string currency,
             decimal basePrice,
             int ordering,
             bool isDefault,
             Guid shippingOptionIdColumn)
            {
                Name = name;
                DisplayName = displayName;
                Description = description;
                Currency = currency;
                BasePrice = basePrice;
                Ordering = ordering;
                IsDefault = isDefault;
                ShippingOptionIdColumn = shippingOptionIdColumn;
            }
        }
    }
}



#192631
Edited, May 21, 2018 21:34
Vote:
 

Not sure what is wrong, but this is how we do it, perhaps it's useful for you?

private void ConfigureShippingMethods()
        {
            var marketService = ServiceLocator.Current.GetInstance<IMarketService>();
            var enabledMarkets = marketService.GetAllMarkets().Where(x => x.IsEnabled).ToList();
            foreach (var language in enabledMarkets.SelectMany(x => x.Languages).Distinct())
            {
                var languageId = language.TwoLetterISOLanguageName;
                var dto = ShippingManager.GetShippingMethods(languageId);
                var workingDto = (ShippingMethodDto)dto.Copy();
                DeleteShippingMethods(workingDto);
                ShippingManager.SaveShipping(workingDto);

                var marketsForCurrentLanguage = enabledMarkets.Where(x => x.Languages.Contains(language)).ToList();
                var shippingSet = CreateShippingMethodsForLanguageAndCurrencies(workingDto, marketsForCurrentLanguage, languageId);
                ShippingManager.SaveShipping(workingDto);

                AssociateShippingMethodWithMarkets(workingDto, marketsForCurrentLanguage, shippingSet);
                ShippingManager.SaveShipping(workingDto);
            }
        }

        private void DeleteShippingMethods(ShippingMethodDto dto)
        {
            foreach (var method in dto.ShippingMethod)
            {
                method.Delete();
            }
        }

        private void ImportTaxes()
        {
            _taxImportExport.Service.Import(Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"App_Data\Taxes.csv"), ',');
        }

        private IEnumerable<ShippingMethodDto.ShippingMethodRow> CreateShippingMethodsForLanguageAndCurrencies(ShippingMethodDto dto, IEnumerable<IMarket> markets, string languageId)
        {
            var shippingOption = dto.ShippingOption.First(x => x.Name == "Generic Gateway");
            var shippingMethods = new List<ShippingMethodDto.ShippingMethodRow>();
            var sortOrder = 1;

            var usdCostExpress = new Money(20, Currency.USD);
            var usdCostFast = new Money(15, Currency.USD);
            var usdCostRegular = new Money(5, Currency.USD);

            foreach (var currency in markets.SelectMany(m => m.Currencies).Distinct())
            {
                shippingMethods.Add(CreateShippingMethod(dto, shippingOption, languageId, sortOrder++, "Express-" + currency, $"Express {currency} (1 day)({languageId})", usdCostExpress, currency));
                shippingMethods.Add(CreateShippingMethod(dto, shippingOption, languageId, sortOrder++, "Fast-" + currency, $"Fast {currency} (2-3 days)({languageId})", usdCostFast, currency));
                shippingMethods.Add(CreateShippingMethod(dto, shippingOption, languageId, sortOrder++, "Regular-" + currency, $"Regular {currency} (4-7 days)({languageId})", usdCostRegular, currency));
            }

            return shippingMethods;
        }

        private ShippingMethodDto.ShippingMethodRow CreateShippingMethod(ShippingMethodDto dto, ShippingMethodDto.ShippingOptionRow shippingOption, string languageId, int sortOrder, string name, string description, Money costInUsd, Currency currency)
        {
            Money shippingCost = CurrencyFormatter.ConvertCurrency(costInUsd, currency);
            if (shippingCost.Currency != currency)
            {
                throw new InvalidOperationException("Cannot convert to currency " + currency + " Missing conversion data.");
            }
            return dto.ShippingMethod.AddShippingMethodRow(
                Guid.NewGuid(),
                shippingOption,
                languageId,
                true,
                name,
                "",
                shippingCost.Amount,
                shippingCost.Currency,
                description,
                false,
                sortOrder,
                DateTime.Now,
                DateTime.Now);
        }

        private void AssociateShippingMethodWithMarkets(ShippingMethodDto dto, IEnumerable<IMarket> markets, IEnumerable<ShippingMethodDto.ShippingMethodRow> shippingSet)
        {
            foreach (var shippingMethod in shippingSet)
            {
                foreach (var market in markets.Where(m => m.Currencies.Contains(shippingMethod.Currency)))
                {
                    dto.MarketShippingMethods.AddMarketShippingMethodsRow(market.MarketId.Value, shippingMethod);
                }
            }
        }
#192652
May 22, 2018 10:34
Vote:
 

I will give it a try and let you know, thanks for your help!

#192687
May 22, 2018 23:23
Vote:
 

That worked beautifully, thank you Quan laughing

#193191
May 24, 2018 19:27
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.