London Dev Meetup Rescheduled! Due to unavoidable reasons, the event has been moved to 21st May. Speakers remain the same—any changes will be communicated. Seats are limited—register here to secure your spot!

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.