使用Umbraco v7,uCommerce v6.6,DotNetShipping (plugin)。请参阅VolumeMethodShippingService
类,方法CalculateShippingPrice
中的评论(帖子底部)。
错误:
not-null property references a null or transient value UCommerce.EntitiesV2.ShippingMethodPrice.PriceGroup
Line 20: {
Line 21: TransactionLibrary.CreateShipment(newShipmentId, overwriteExisting: true);
Line 22: TransactionLibrary.ExecuteBasketPipeline(); // <------ error is here ***************************
Line 23: HttpContext.Current.Response.Redirect("/cart/payment");
Line 24: }
[PropertyValueException: not-null property references a null or transient value UCommerce.EntitiesV2.ShippingMethodPrice.PriceGroup]
NHibernate.Engine.Nullability.CheckNullability(Object[] values, IEntityPersister persister, Boolean isUpdate) +592
NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +832
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) +295
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) +58
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event) +130
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) +470
NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event) +398
NHibernate.Impl.SessionImpl.SaveOrUpdate(String entityName, Object obj) +396
NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) +254
NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled) +639
NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type) +338
NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything) +697
NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource session, IEntityPersister persister, Object key, Object anything) +178
NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource session) +426
NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) +307
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) +214
NHibernate.Impl.SessionImpl.Flush() +516
UCommerce.Pipelines.Common.SavePurchaseOrderTask.Execute(PurchaseOrder purchaseOrder) +20
UCommerce.Pipelines.Pipeline`1.Execute(T subject) +286
我已成功添加&#34; VolumeShippingMethodService&#34;如下所述: http://docs.ucommerce.net/ucommerce/v6.7/extending-ucommerce/shipping-method-service.html
我正在使用FedEx API。当用户进入Shipment
视图时,它会抓取可用的送货方式,并根据当前篮子中的订单行放置该货件的价值(价格)。我看到uCommerce有另一种方法CalculateShippingPrice
,它可以获得运费方法的价格。我当然不需要这个,但是uCommerce会自动调用它,所以我不得不重新调用我的FedEx API以获取价格并将其返回。一旦我退回这个价格,我收到错误。如果我保留了随文档(ucommerce)提供的默认代码,则不会收到任何错误。
在下面的服务代码中,正如我所说,价格回归正常,没有错误。当我再次发布到/ cart / shipping时,它会为篮子创建Shipment
对象,就在我收到错误时。
查看:
@using UCommerce
@using UCommerce.EntitiesV2
@using UCommerce.Api
@using ExtendedUCommerceServices.Services
@{
if (HttpContext.Current.Request.HttpMethod == "POST" && HttpContext.Current.Request.Form.AllKeys.Any(x => x == "update-shipment"))
{
int newShipmentId;
if (int.TryParse(HttpContext.Current.Request.Form["shipping-method"], out newShipmentId))
{
TransactionLibrary.CreateShipment(newShipmentId, overwriteExisting: true);
TransactionLibrary.ExecuteBasketPipeline();
HttpContext.Current.Response.Redirect("/cart/payment");
}
}
var basket = TransactionLibrary.GetBasket().PurchaseOrder;
var currentShippingMethod = TransactionLibrary.GetShippingMethod();
var shippingCountry = TransactionLibrary.GetShippingInformation().Country;
var availableShippingMethods = new VolumeShippingMethodService().GetShippingRates(TransactionLibrary.GetShippingMethods(shippingCountry).ToList(), basket);
}
VolumeShippingethodService
public class VolumeShippingMethodService : IShippingMethodService
{
// TODO: check if key and password are the same for production account
public string fedexKey = ConfigurationManager.AppSettings["FedExKey"];
public string fedexPassword = ConfigurationManager.AppSettings["FedExPassword"];
// TODO: get actual production account number and meter number
public string fedexAccountNumber = ConfigurationManager.AppSettings["FedExAccountNumber"];
public string fedexMeterNumber = ConfigurationManager.AppSettings["FedExMeterNumber"];
// TODO: remove "false" from FedExProvider when in production ********************8
public bool fedexUseProduction = ConfigurationManager.AppSettings["FedExUseProduction"].ToLower().Equals("false") ? false : true;
/// <summary>
/// Gets shipping rates for FedEx (waiting on UPS) *********************************************
/// </summary>
/// <param name="availableShippingMethods">available shipping methods for the catalog</param>
/// <param name="basket">user's current basket</param>
/// <returns>shipping methods with prices (rates)</returns>
public List<ShippingMethod> GetShippingRates(List<ShippingMethod> availableShippingMethods, PurchaseOrder basket)
{
// create package with weight and size dimensions
// TODO: get this from uCommerce ********************************
var packages = new List<Package>();
packages.Add(new Package(12, 12, 12, 35, 150));
packages.Add(new Package(4, 4, 6, 15, 250));
// TODO: get actual address
var origin = new DotNetShipping.Address("1202 Chalet Ln", "Do Not Delete - Test Account", string.Empty, "Harrison", "AR", "72601", "US");
var destinationAddress = basket.Shipments.First().ShipmentAddress;
var destination = new DotNetShipping.Address(
destinationAddress.Line1,
destinationAddress.Line2,
string.Empty, // Line3
destinationAddress.City,
string.Empty, // State (not needed when postal code and country code are applied)
destinationAddress.PostalCode,
"US" /* country code
* NOTE: if additional countries are added later, then need to get
* a webservice to get country codes from actual country name */
);
var rateManager = new RateManager();
rateManager.AddProvider(new FedExProvider(fedexKey, fedexPassword, fedexAccountNumber, fedexMeterNumber, fedexUseProduction));
DotNetShipping.Shipment shipment = rateManager.GetRates(origin, destination, packages);
foreach (var shippingMethod in availableShippingMethods)
{
var rateToAdd = shipment.Rates.FirstOrDefault(x => x.Name.Equals(shippingMethod.Name));
if (rateToAdd != null)
{
// apparently you can have more than one shipping price.....
if (shippingMethod.ShippingMethodPrices.Count == 0)
{
shippingMethod.AddShippingMethodPrice(new ShippingMethodPrice
{
Currency = basket.BillingCurrency,
Price = rateToAdd.TotalCharges
});
}
else
{
shippingMethod.ShippingMethodPrices.First().Price = rateToAdd.TotalCharges;
}
}
}
return availableShippingMethods;
}
/// <summary>
/// uCommerce automatically calls this method (built in) when creating a shipment (TransactionLibrary.CreateShipment).
/// In order to correctly get price (again), recall the GetShippingRates method and find
/// the appropriate shipping method by name, then retrive price
/// </summary>
/// <param name="shipment">current uCommerce shipment</param>
/// <returns>shipping price for the shipping method</returns>
public Money CalculateShippingPrice(UCommerce.EntitiesV2.Shipment shipment)
{
var rates = this.GetShippingRates(TransactionLibrary.GetShippingMethods(TransactionLibrary.GetShippingInformation().Country).ToList(), TransactionLibrary.GetBasket(false).PurchaseOrder);
var shippingPrice = rates.FirstOrDefault(x => x.Name.Equals(shipment.ShipmentName)).ShippingMethodPrices.First().Price;
// **************************************
// If I keep the above lines uncommented, I receive the error.
// The variable "shippingPrice" above returns a decimal, 36.25
// If I uncomment the lines below, there is no error.
// **************************************
//decimal totalWeight = 0;
//foreach (OrderLine orderline in shipment.OrderLines)
// totalWeight += orderline.Quantity * Convert.ToDecimal(orderline["Weight"]);
//decimal shippingPrice = 0;
//if (totalWeight > 10)
// shippingPrice = 100;
//else if (totalWeight > 20)
// shippingPrice = 200;
//else
// shippingPrice = 300;
return new Money(shippingPrice, shipment.PurchaseOrder.BillingCurrency);
}
}
答案 0 :(得分:0)
需要将PriceGroup添加到送货对象
shippingMethod.AddShippingMethodPrice(new ShippingMethodPrice
{
Currency = basket.BillingCurrency,
Price = rateToAdd.TotalCharges,
PriceGroup = PriceGroup.FirstOrDefault(x => x.Name.Equals("US Dollar"))
});