Umbraco uCommerce - 非空属性引用NHibernate

时间:2015-08-13 17:07:18

标签: c# nhibernate umbraco

从VolumeShippingMethodService返回运费值时发生TransationLibrary.CreateShipment错误

使用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);
    }
}

1 个答案:

答案 0 :(得分:0)

需要将PriceGroup添加到送货对象

shippingMethod.AddShippingMethodPrice(new ShippingMethodPrice
{
       Currency = basket.BillingCurrency,
       Price = rateToAdd.TotalCharges,
       PriceGroup = PriceGroup.FirstOrDefault(x => x.Name.Equals("US Dollar"))
});