0

I'm currently implementing a new carrier method and would like to access additional information on the Shipment/Sales Order object which is not passed through in the GetRateQuote & Ship functions of the implemented ICarrierService class.

The carrier method implements the ICarrierService interface and subsequently does not have access to a Graph where one would typically be able to access the current (cached?) document, etc.

How could I, for example, access the shipment number for which the Ship function is called?

My ultimate goal is to be able to generate a label for the shipment package, and in order to do so, I need to obtain the Shipment Number.

using PX.Api;
using PX.CarrierService;
using PX.CS.Contracts.Interfaces;
using PX.Data;
using PX.Data.Reports;
using PX.Objects.Common.Extensions;
using PX.Reports;
using PX.Reports.Data;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyCarriers.CollectCarrier
{
    public class CollectCarrier : ICarrierService
    {
        private List<CarrierMethod> methods;
        private List<string> attributes;

        public IList<string> Attributes => (IList<string>)this.attributes;
        public string CarrierID { get; set; }
        public string Method { get; set; }
        public ReadOnlyCollection<CarrierMethod> AvailableMethods => this.methods.AsReadOnly();

        public CollectCarrier()
        {
            this.methods = new List<CarrierMethod>(1);
            this.methods.Add(new CarrierMethod("CLT", "Collect"));
            this.attributes = new List<string>(1);
        }

        [...]

        public CarrierResult<ShipResult> Ship(CarrierRequest cr)
        {
            if (cr.Packages == null || cr.Packages.Count == 0)
            {
                throw new InvalidOperationException("CarrierRequest.Packages must be contain atleast one Package");
            }

            CarrierResult<ShipResult> carrierResult;

            try
            {
                CarrierResult<RateQuote> rateQuote = this.GetRateQuote(cr, true);
                ShipResult result = new ShipResult(rateQuote.Result);

                //Report Parameters
                Dictionary<String, String> parameters = new Dictionary<String, String>();

                // ************************************************************************************
                // At this point, I would like to be able to retrieve the current SOShipment's Shipment Number
                // ************************************************************************************
                parameters["shipmentNbr"] = "000009"; // Hard-coded this value to get the PDF generated.

                //Report Processing
                PX.Reports.Controls.Report _report = PXReportTools.LoadReport("SO645000", null);
                PXReportTools.InitReportParameters(_report, parameters, SettingsProvider.Instance.Default);
                ReportNode reportNode = ReportProcessor.ProcessReport(_report);

                //Generation PDF
                result.Image = PX.Reports.Mail.Message.GenerateReport(reportNode, ReportProcessor.FilterPdf).First();
                result.Format = "pdf";

                result.Data.Add(new PackageData(
                    cr.Packages.FirstOrDefault().RefNbr,
                    this.RandomString(6),
                    result.Image,
                    "pdf"
                )
                {
                    TrackingData = this.RandomString(6)
                });

                carrierResult = new CarrierResult<ShipResult>(result);
            }
            catch (Exception ex)
            {
                if (this.LogTrace)
                {
                    this.WriteToLog(ex, this.GetType().Name + ".Ship().Exception");
                }
                List<Message> messageList = this.HandleException(ex);
                messageList?.Insert(0, new Message("", "Failed to generate the collection label: "));
                carrierResult = new CarrierResult<ShipResult>(false, null, (IList<Message>)messageList);
            }
            return carrierResult;
        }

        [...]
    }
}

For reference, the CarrierRequest object that is passed to the functions contain the following information:

public class CarrierRequest
    {
        public string ThirdPartyAccountID
        {
            get;
            set;
        }

        public string ThirdPartyPostalCode
        {
            get;
            set;
        }

        public string ThirdPartyCountryCode
        {
            get;
            set;
        }

        public IAddressBase Shipper
        {
            get;
            set;
        }

        public IContactBase ShipperContact
        {
            get;
            set;
        }

        public IAddressBase Origin
        {
            get;
            set;
        }

        public IContactBase OriginContact
        {
            get;
            set;
        }

        public IAddressBase Destination
        {
            get;
            set;
        }

        public IContactBase DestinationContact
        {
            get;
            set;
        }

        public IList<CarrierBox> Packages
        {
            get;
            set;
        }

        public IList<CarrierBoxEx> PackagesEx
        {
            get;
            set;
        }

        public IList<string> Methods
        {
            get;
            set;
        }

        public DateTime ShipDate
        {
            get;
            set;
        }

        public UnitsType Units
        {
            get;
            private set;
        }

        public bool SaturdayDelivery
        {
            get;
            set;
        }

        public bool Resedential
        {
            get;
            set;
        }

        public bool Insurance
        {
            get;
            set;
        }

        public string CuryID
        {
            get;
            private set;
        }

        public IList<string> Attributes
        {
            get;
            set;
        }

        public decimal InvoiceLineTotal
        {
            get;
            set;
        }

        public string FreightClass
        {
            get;
            set;
        }

        public bool SkipAddressVerification
        {
            get;
            set;
        }

        public IList<ISETerritoriesMappingBase> TerritoriesMapping
        {
            get;
            set;
        }

        public CarrierRequest(UnitsType units, string curyID)
        {
            if (string.IsNullOrEmpty(curyID))
            {
                throw new ArgumentNullException("curyID");
            }

            Units = units;
            CuryID = curyID;
        }
    }

I have seen a similar question here on SO, but I'm not entirely sure that is applicable to my specific request?

Any assistance will be highly appreciated.

1 Answers1

0

See below as an option to loop through your currents and search for the specific current object:

SOShipment ship = null;

for (int i = 0; i < Caches.Currents.Length; i++)
{
   if (Caches.Currents[i].GetType() == typeof(SOShipment))
   {
      ship = (SOShipment)Caches.Currents[i];
      break;
   }
}
Gerhard-ZA
  • 41
  • 8