AI OnAI Off
Hi Noel,
I am not sure why you are getting reference key error, could you please try below code.
public class CreateShippingMethod
{
private readonly IMarketService _marketService;
public CreateShippingMethod(IMarketService marketService)
{
_marketService = marketService ?? throw new ArgumentNullException(nameof(marketService));
}
public void ConfigureShippingMethods()
{
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();
this.DeleteShippingMethods(workingDto);
ShippingManager.SaveShipping(workingDto);
var marketsForCurrentLanguage = enabledMarkets.Where(x => x.Languages.Contains(language)).ToList();
var shippingSet = this.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 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;
//TODO: Add wishing price and currency
var usdCostExpress = new Money(20, Currency.USD);
foreach (var currency in markets.SelectMany(m => m.Currencies).Distinct())
{
shippingMethods.Add(this.Create(dto, shippingOption, languageId, sortOrder++,
"Express-" + currency, $"Express {currency} (1 day)({languageId})", usdCostExpress, currency));
// TODO: Add more shipping methods.
}
return shippingMethods;
}
private ShippingMethodDto.ShippingMethodRow Create(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);
}
}
}
}
Thank you Sanjay,
i actually found code very similar to that here and adapted it too only create a single shipping method with the string i give it (all my shipping methods are 'discovered' during import from another system)
using EPiServer.ServiceLocation;
using Mediachase.Commerce;
using Mediachase.Commerce.Markets;
using Mediachase.Commerce.Orders.Dto;
using Mediachase.Commerce.Orders.Managers;
using Mediachase.Commerce.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
public class ShippingMethodHelper
{
#region singleton
private static readonly Lazy<ShippingMethodHelper> lazy = new Lazy<ShippingMethodHelper>(() =>
{
return new ShippingMethodHelper();
});
public static ShippingMethodHelper Instance => lazy.Value;
#endregion
public void ConfigureShippingMethods(string methodName)
{
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 = CreateShippingMethodForLanguageAndCurrencies(workingDto, marketsForCurrentLanguage, languageId, methodName);
ShippingManager.SaveShipping(workingDto);
AssociateShippingMethodWithMarkets(workingDto, marketsForCurrentLanguage, shippingSet);
ShippingManager.SaveShipping(workingDto);
}
}
private IEnumerable<ShippingMethodDto.ShippingMethodRow> CreateShippingMethodForLanguageAndCurrencies(ShippingMethodDto dto, IEnumerable<IMarket> markets, string languageId, string methodName)
{
var shippingOption = dto.ShippingOption.First(x => x.Name == "Generic Gateway");
var shippingMethods = new List<ShippingMethodDto.ShippingMethodRow>();
var sortOrder = 1;
foreach (var currency in markets.SelectMany(m => m.Currencies).Distinct())
{
shippingMethods.Add(CreateShippingMethod(dto, shippingOption, languageId, 0, methodName, methodName, new Money(0, Currency.GBP), 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);
}
}
}
I'm getting this error:
"ForeignKeyConstraint FK_ShippingOption_ShippingMethod requires the child key values (18ede71f-3df3-4d9e-a4cb-3d25881c1ec6) to exist in the parent table."
and here is my code:
it's essentially complaining about the shipping Option ID that i'm passing in, but that ID is being loaded via EPiServer libs anyway. What am i missing?