private void CalculateFreightCost(bool supressErrors) { Carrier carrier = Carrier.PK.Find(Base, "UPSGROUND"); if (carrier != null && carrier.IsExternal == true) { var _doc = new SOOrder(); //_doc = SelectFrom<SOOrder>.Where<SOOrder.orderNbr.IsEqual<P.AsString>.And<SOOrder.orderType.IsEqual<P.AsString>>>.View.Select(Base, "SUS2100212", "SO").RowCast<SOOrder>().FirstOrDefault(); _doc.CuryID = Base.Quote.Current.CuryID; _doc.ShipVia = "UPSGROUND"; _doc.CuryInfoID = Base.Quote.Current.CuryInfoID; _doc.DocDate = Base.Quote.Current.DocumentDate; _doc.IsPackageValid = false; _doc.IsManualPackage = false; CarrierPlugin plugin = CarrierPlugin.PK.Find(Base, carrier.CarrierPluginID); ICarrierService cs = CarrierPluginMaint.CreateCarrierService(Base, plugin); cs.Method = carrier.PluginMethod; var graph = PXGraph.CreateInstance <SOOrderEntry>(); _doc = graph.Document.Insert(_doc); graph.Shipping_Address.Cache.Current = new SOShippingAddress(); CarrierRatesExt(graph).RecalculatePackagesForOrder(graph.Document.Current); CarrierRequest cr = CarrierRatesExt(graph).BuildRateRequest(_doc); CarrierResult <RateQuote> result = cs.GetRateQuote(cr); if (result != null) { StringBuilder sb = new StringBuilder(); foreach (Message message in result.Messages) { sb.AppendFormat("{0}:{1} ", message.Code, message.Description); } if (result.IsSuccess) { throw new PXException(result.Result.Amount.ToString()); //decimal baseCost = ConvertAmtToBaseCury(result.Result.Currency, arsetup.Current.DefaultRateTypeID, Document.Current.OrderDate.Value, result.Result.Amount); //SetFreightCost(baseCost); } } } }
private void SelectLeastExpensiveShipVia() { var sw = new Stopwatch(); sw.Start(); PXTrace.WriteInformation("Starting rate shopping."); var shipment = Base.Document.Current; var shipmentExt = shipment.GetExtension <SOShipmentExt>(); List <CarrierRequestInfo> requests = new List <CarrierRequestInfo>(); var plugins = GetCarrierPluginsForAutoRateShopping(); var carrierRatesExt = Base.GetExtension <SOShipmentEntry.CarrierRates>(); MethodInfo buildQuoteRequestMethod = carrierRatesExt.GetType().GetMethod("BuildQuoteRequest", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); //Unfortunately not exposed by SOShipmentEntry.CarrierRates... foreach (CarrierPlugin plugin in plugins) { //Skip if carrier plugin is specific to a site if (plugin.SiteID != null && plugin.SiteID != shipment.SiteID) { continue; } if (shipmentExt.UsrISPrimeOrder.GetValueOrDefault() != plugin.GetExtension <CarrierPluginExt>().UsrUseForPrimeOrders.GetValueOrDefault()) { continue; } ICarrierService cs = CarrierPluginMaint.CreateCarrierService(Base, plugin); CarrierRequest cr = (CarrierRequest)buildQuoteRequestMethod.Invoke(carrierRatesExt, new object[] { carrierRatesExt.Documents.Cache.GetExtension <PX.Objects.SO.GraphExtensions.CarrierRates.Document>(shipment), plugin }); requests.Add(new CarrierRequestInfo { Plugin = plugin, SiteID = shipment.SiteID.Value, Service = cs, Request = cr }); } Parallel.ForEach(requests, info => info.Result = info.Service.GetRateList(info.Request)); string leastExpensiveCarrier = null; string leastExpensiveMethod = null; DateTime?leastExpensiveShipViaDeliveryDate = null; decimal? amount = null; //We're comparing with a date/time value returned by the carrier; anything delivered on the UsrDeliverByDate meets the SLA DateTime?deliverByDateTime = shipmentExt.UsrDeliverByDate == null ? null : new DateTime?(shipmentExt.UsrDeliverByDate.Value.Date.Add(new TimeSpan(23, 59, 59))); foreach (var request in requests) { if (!request.Result.IsSuccess) { continue; } foreach (var rate in request.Result.Result) { string traceMessage = "Site: " + request.SiteID + " Carrier:" + request.Plugin.Description + " Method: " + rate.Method + " Delivery Date: " + (rate.DeliveryDate == null ? "" : rate.DeliveryDate.ToString()) + " Amount: " + rate.Amount.ToString(); if (rate.IsSuccess) { if (shipmentExt.UsrGuaranteedDelivery.GetValueOrDefault() == false || deliverByDateTime >= rate.DeliveryDate) { if (amount == null || rate.Amount < amount || (rate.Amount == amount && rate.DeliveryDate < leastExpensiveShipViaDeliveryDate)) { leastExpensiveShipViaDeliveryDate = rate.DeliveryDate; leastExpensiveCarrier = request.Plugin.CarrierPluginID; leastExpensiveMethod = rate.Method.Code; amount = rate.Amount; } } else { traceMessage += " [TOO LATE]"; } } else { if (rate.Messages.Count > 0) { traceMessage += " [FAILED: " + rate.Messages[0].Description + "]"; } else { traceMessage += " [FAILED WITH NO ERROR MESSAGE]"; } } PXTrace.WriteInformation(traceMessage); } } if (leastExpensiveCarrier == null) { throw new PXException(Messages.FailedToFindCarrierAndMethod); } else { sw.Stop(); PXTrace.WriteInformation($"Rate shopping completed in {sw.ElapsedMilliseconds}ms. Least expensive carrier: {leastExpensiveCarrier} method: {leastExpensiveMethod} amount: {amount}"); var carrier = (Carrier)PXSelectReadonly <Carrier, Where <Carrier.carrierPluginID, Equal <Required <Carrier.carrierPluginID> >, And <Carrier.pluginMethod, Equal <Required <Carrier.pluginMethod> >, And <Carrier.isExternal, Equal <True> > > > > .Select(Base, leastExpensiveCarrier, leastExpensiveMethod); if (carrier == null) { throw new PXException(Messages.NoShipViaFound, leastExpensiveCarrier, leastExpensiveMethod); } else { Base.Document.Current.ShipVia = carrier.CarrierID; Base.Document.Update(Base.Document.Current); Base.Document.Current.IsPackageValid = true; //Changing ShipVia will otherwise trigger package refresh Base.Document.Update(Base.Document.Current); Base.Save.Press(); } } }
public virtual void UpdateRates() { if (Documents.Current != null) { CarrierRates.Cache.Clear(); ValidatePackages(); bool autoPackWarning = false; List <CarrierRequestInfo> requests = new List <CarrierRequestInfo>(); foreach (CarrierPlugin plugin in GetApplicableCarrierPlugins()) { ICarrierService cs = CarrierPluginMaint.CreateCarrierService(Base, plugin); if (cs != null) { CarrierRequest cRequest = BuildQuoteRequest(Documents.Current, plugin); if (cRequest.PackagesEx.Count == 0) { PXTrace.WriteWarning(Messages.AutoPackagingZeroPackWarning, plugin.CarrierPluginID); autoPackWarning = true; continue; } requests.Add(new CarrierRequestInfo { Plugin = plugin, Service = cs, Request = cRequest }); } } Parallel.ForEach(requests, info => info.Result = info.Service.GetRateList(info.Request)); int cx = 0; StringBuilder errorMessages = new StringBuilder(); foreach (CarrierRequestInfo info in requests) { CarrierResult <IList <RateQuote> > result = info.Result; if (result.IsSuccess) { foreach (RateQuote item in result.Result) { if (item.IsSuccess && item.Currency != Documents.Current.CuryID) { if (string.IsNullOrEmpty(arsetup.Current.DefaultRateTypeID)) { throw new PXException(Messages.RateTypeNotSpecified); } } PXSelectBase <Carrier> selectCarrier = new PXSelectReadonly <Carrier, Where <Carrier.carrierPluginID, Equal <Required <Carrier.carrierPluginID> >, And <Carrier.pluginMethod, Equal <Required <Carrier.pluginMethod> >, And <Carrier.isExternal, Equal <True> > > > >(Base); foreach (Carrier shipVia in selectCarrier.Select(info.Plugin.CarrierPluginID, item.Method.Code)) { var r = new SOCarrierRate { LineNbr = cx++, Method = shipVia.CarrierID, Description = item.Method.Description, Amount = ConvertAmt(item.Currency, Documents.Current.CuryID, arsetup.Current.DefaultRateTypeID, Documents.Current.DocumentDate.Value, item.Amount), DeliveryDate = item.DeliveryDate }; r.Selected = r.Method == Documents.Current.ShipVia; if (item.DaysInTransit > 0) { r.DaysInTransit = item.DaysInTransit; } r = CarrierRates.Insert(r); if (!item.IsSuccess) { CarrierRates.Cache.RaiseExceptionHandling(typeof(SOCarrierRate.method).Name, r, null, new PXSetPropertyException("{0}: {1}", PXErrorLevel.RowError, item.Messages[0].Code, item.Messages[0].Description)); } } } } else { foreach (Message message in result.Messages) { errorMessages.AppendFormat(PXMessages.LocalizeNoPrefix(Messages.ReturnedError), info.Plugin.CarrierPluginID, message.ToString()); } if (!string.IsNullOrEmpty(result.RequestData)) { PXTrace.WriteInformation(result.RequestData); } } } if (errorMessages.Length > 0) { throw new PXException(Messages.CarrierServiceError, errorMessages.ToString()); } if (autoPackWarning) { throw new PXException(Messages.AutoPackagingIssuesCheckTrace); } } }
private int SelectLeastExpensiveShipWarehouse(IEnumerable <int> sites, DateTime?deliverBy, bool guaranteedDelivery) { var carrierRatesExt = Base.GetExtension <SOOrderEntry.CarrierRates>(); var rateShoppingExt = Base.GetExtension <SOCarrierRateShoppingExt>(); try { List <CarrierRequestInfo> requests = new List <CarrierRequestInfo>(); rateShoppingExt.Active = true; var plugins = GetCarrierPluginsForAutoRateShopping(); foreach (int siteID in sites) { foreach (CarrierPlugin plugin in plugins) { //Skip if carrier plugin is specific to a site if (plugin.SiteID != null && plugin.SiteID != siteID) { continue; } rateShoppingExt.OverrideSiteID = siteID; ICarrierService cs = CarrierPluginMaint.CreateCarrierService(Base, plugin); CarrierRequest cr = carrierRatesExt.BuildQuoteRequest(Base.Document.Current, plugin); requests.Add(new CarrierRequestInfo { Plugin = plugin, SiteID = siteID, Service = cs, Request = cr }); } } Parallel.ForEach(requests, info => info.Result = info.Service.GetRateList(info.Request)); int? leastExpensiveSiteID = null; decimal?amount = null; //We're comparing with a date/time value returned by the carrier; anything delivered on the UsrDeliverByDate meets the SLA DateTime?deliverByDateTime = deliverBy == null ? null : new DateTime?(deliverBy.Value.Date.Add(new TimeSpan(23, 59, 59))); Random rand = new Random(); foreach (var request in requests) { if (!request.Result.IsSuccess) { continue; } foreach (var rate in request.Result.Result) { string traceMessage = "Site: " + request.SiteID + " Carrier:" + request.Plugin.Description + " Method: " + rate.Method + " Delivery Date: " + (rate.DeliveryDate == null ? "" : rate.DeliveryDate.ToString()) + " Amount: " + rate.Amount.ToString(); if (!rate.IsSuccess) { continue; } if (guaranteedDelivery == false || deliverByDateTime >= rate.DeliveryDate) { if (amount == null || rate.Amount < amount) { leastExpensiveSiteID = request.SiteID; amount = rate.Amount; } else if (amount == rate.Amount && request.SiteID != leastExpensiveSiteID) { PXTrace.WriteInformation("Same rate found for another site - decide if we use the other site based on random (could be based on actual workload by warehouse instead...)"); if (rand.NextDouble() >= 0.5) { leastExpensiveSiteID = request.SiteID; } } } else { traceMessage += " [TOO LATE]"; } PXTrace.WriteInformation(traceMessage); } } if (leastExpensiveSiteID == null) { throw new PXException(Messages.FailedToFindShipFromWarehouseAndCarrier); } else { return(leastExpensiveSiteID.Value); } } finally { rateShoppingExt.Active = false; } }