Skip to main content
Solved

I am Get erorr "Object reference not set to an instance of an object" when trying insert shipment


Forum|alt.badge.img
  • Freshman I
  • 25 replies

I am Get erorr "Object reference not set to an instance of an object" when trying insert shipment,

Why Like This ?
This the problem track

Please Help me Sense

 


Thanks you

Best answer by harutyungevorgyan

Febri wrote:

Can this method include lot number field ?
 

or if the goods have the same inventory, subitem, warehouse and location but the lot number is different, the details must be entered in Line Details ?


please help me

Hi ​@Febri ,

The method I gave you uses OrderLineNbr, which means the system will automatically pull the data from the SOOrderLine into your shipment line.

However, when it comes to Line Details (commonly referred to as line splitting or allocation), that logic needs to be handled separately. If you want to control splits manually, you’ll need to explicitly add the required allocations yourself. To do this correctly, I strongly recommend first understanding how the allocation process works—especially its impact on Qty. On Hand, Qty. Available, and related inventory quantities. Also, make sure that the lot/serial number you’re trying to use is available in the exact warehouse and location you're assigning it to.

At this point, the discussion is moving into more advanced customization, and it’s no longer related to the original error you reported. If the issue with adding lines from the Sales Order is now resolved, I’d suggest closing this topic. You can open a new thread specifically focused on handling splits or allocation logic when you're ready to explore that further.

Hope this helps!

View original
Did this topic help you find an answer to your question?

13 replies

Forum|alt.badge.img

Hi ​@Febri 

This error usually happens when the code tries to use an object that hasn't been initialized or it is null.

Can you share your customization or the code you're using? That will help in finding the exact issue.


Forum|alt.badge.img
  • Author
  • Freshman I
  • 25 replies
  • March 25, 2025

Thanks 
This is error code



and than the track like this



this is full code for metod rilise button 

public PXAction<ITMarking> Release;

[PXUIField(DisplayName = "RELEASE", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false)]
[PXButton(SpecialType = PXSpecialButtonType.Process, Connotation = PX.Data.WorkflowAPI.ActionConnotation.Success)]
public virtual IEnumerable release(PXAdapter adapter)
{
    PXTrace.WriteInformation("step 1");
    ITMarking rilise = MasterView.Current;

    if (rilise?.MarkingNbr != null && rilise.MarkingNbr != "" && rilise.MarkingNbr != "[DocumentID]" && rilise.MarkingNbr != "<NEW>")
    {
        SOShipmentEntry shipmentGraph = PXGraph.CreateInstance<SOShipmentEntry>();

        ShipementDua shipementLine = PXGraph.CreateInstance<ShipementDua>();

        var customerID = SelectFrom<SOOrder>
            .Where<SOOrder.orderNbr.IsEqual<P.AsString>>
            .View.Select(this, rilise.Sonbr)
            .TopFirst?.CustomerID;

        var customerLocationID = SelectFrom<SOOrder>
            .Where<SOOrder.orderNbr.IsEqual<P.AsString>>
            .View.Select(this, rilise.Sonbr)
            .TopFirst?.CustomerLocationID;

        PXTrace.WriteInformation("step 2");
        
        SOShipment shipment = new SOShipment
        {
            ShipDate = rilise.DocumentDate,
            ShipmentType = SOShipmentType.Issue,
            Operation = SOOperation.Issue,
            CustomerID = customerID,
            CustomerLocationID = customerLocationID,
            SiteID = rilise.Warehouse,
            Insurance = false,
            IsManualPackage = true,
        };
        shipment = shipmentGraph.Document.Insert(shipment);

        PXTrace.WriteInformation("step 3");
        if (shipment == null)
        {
            // Acuminator disable once PX1050 HardcodedStringInLocalizationMethod [Justification]
            throw new PXException("Gagal membuat Shipment.");
        }

        shipmentGraph.Save.Press();

        PXTrace.WriteInformation("step 4");

        SOOrderShipment shipmentorder = new SOOrderShipment
        {
            OrderType = "SO",
            OrderNbr = rilise.Sonbr,
            ShipmentNbr = shipment.ShipmentNbr,
            Operation = SOOperation.Issue
        };

        shipmentorder = shipmentGraph.OrderList.Insert(shipmentorder);
        shipmentGraph.Save.Press();

        var detailsList = DetailsView.Select().RowCast<ITMarkingDetail>().ToList();
        if (detailsList == null || !detailsList.Any())
        {
            // Acuminator disable once PX1050 HardcodedStringInLocalizationMethod [Justification]
            throw new PXException("Tidak ada data detail untuk diproses.");
        }

        PXTrace.WriteInformation("step 5");


        foreach (ITMarkingDetail details in detailsList)
        {
            //var lastShipLine = shipmentGraph.Transactions.Select().RowCast<SOShipLine>().FirstOrDefault(x => x.InventoryID == details.InventoryID);

            //if (lastShipLine == null)
            //{
            //    // Acuminator disable once PX1050 HardcodedStringInLocalizationMethod [Justification]
            //    throw new PXException($"Tidak ditemukan SOShipLine untuk InventoryID: {details.InventoryID}");
            //}
           

            SOShipLineSplit shipLineSplit = new SOShipLineSplit
            {
                ShipmentNbr = shipment.ShipmentNbr,
                SiteID = details.Warehouse,
                InventoryID = details.InventoryID,
                SubItemID = details.SubItem,
                Qty = details.ShipQty,
                UOM = details.Uom,
                LocationID = details.Location,
                LotSerialNbr = details.LotNbr,
                OrigOrderType="SO",
                OrigOrderNbr = rilise.Sonbr,
                LineNbr = 1,
                OrigLineNbr = 1,
                OrigSplitLineNbr=1,
                OrigPlanType="60",
                Operation = SOOperation.Issue,
                InvtMult = -1,
                LineType = "GI",
                IsIntercompany = false,
                PlanType = "61"
            };

            shipmentGraph.splits.Insert(shipLineSplit);
        }
        shipmentGraph.Save.Press();
       

        PXTrace.WriteInformation("step 6");

        foreach (var group in detailsList.GroupBy(d => new { d.InventoryID, d.SubItem, d.Warehouse, d.Location }))
        {

        

            SOShipLine dataInsertShip = new SOShipLine
            {
                ShipmentNbr = shipment.ShipmentNbr,
                SiteID = group.First().Warehouse,
                InventoryID = group.First().InventoryID,
                SubItemID = group.First().SubItem,
                Qty = group.First().ShipQty,
                UOM = group.First().Uom,
                LocationID = group.First().Location,
                LotSerialNbr = group.First().LotNbr,
                OrigOrderType = "SO",
                OrigOrderNbr = rilise.Sonbr,
                LineNbr = 1,
                OrigLineNbr = 1,
                OrigSplitLineNbr = 1,
                OrigPlanType = "60",
                Operation = SOOperation.Issue,
                InvtMult = -1,
                LineType = "GI",
                IsIntercompany = false,
                PlanType = "61"
            };
            
            shipmentGraph.Transactions.Insert(dataInsertShip);
            shipmentGraph.Save.Press();

        }

      

        PXTrace.WriteInformation("step 7");
        rilise.Status = "Released";
        rilise.ShipmentNbr = shipment.ShipmentNbr;
        MasterView.Cache.Update(rilise);
        MasterView.Cache.Persist(PXDBOperation.Update);

        //SOOrderEntry soOrderGraph = PXGraph.CreateInstance<SOOrderEntry>();

        //SOShipmentEntry soShipmentGraph = PXGraph.CreateInstance<SOShipmentEntry>();
        //soShipmentGraph.Clear();

        ////--------Create Shipment------------
        //DocumentList<SOShipment> created = new DocumentList<SOShipment>(soShipmentGraph);
        //soShipmentGraph.CreateShipment(soOrderGraph.Document.Current, siteId, soOrderGraph.Document.Current.OrderDate, false, SOOperation.Issue, created);

    }
    return adapter.Get();
}

Please Help me


Forum|alt.badge.img

@Febri 

I have made some adjustments to your code to avoid nulls errors. Try with below code

foreach (var group in detailsList
             .Where(d => d.InventoryID != null && d.SubItem != null && d.Warehouse != null && d.Location != null)
             .GroupBy(d => new { d.InventoryID, d.SubItem, d.Warehouse, d.Location }))
{
    var firstItem = group.FirstOrDefault();

    if (firstItem == null)
    {
        PXTrace.WriteWarning("Skipping group due to null values.");
        continue;
    }

    SOShipLine dataInsertShip = new SOShipLine
    {
        ShipmentNbr = shipment.ShipmentNbr,
        SiteID = firstItem.Warehouse,
        InventoryID = firstItem.InventoryID,
        SubItemID = firstItem.SubItem,
        Qty = firstItem.ShipQty,
        UOM = firstItem.Uom,
        LocationID = firstItem.Location,
        LotSerialNbr = firstItem.LotNbr,
        OrigOrderType = "SO",
        OrigOrderNbr = rilise.Sonbr,
        LineNbr = 1,
        OrigLineNbr = 1,
        OrigSplitLineNbr = 1,
        OrigPlanType = "60",
        Operation = SOOperation.Issue,
        InvtMult = -1,
        LineType = "GI",
        IsIntercompany = false,
        PlanType = "61"
    };

    shipmentGraph.Transactions.Insert(dataInsertShip);
    shipmentGraph.Save.Press();
}

Thanks


Forum|alt.badge.img
  • Author
  • Freshman I
  • 25 replies
  • March 25, 2025

ok, i will try first.

i get same eorr bro


Forum|alt.badge.img
  • Author
  • Freshman I
  • 25 replies
  • March 25, 2025

Like This
 

 


davidnavasardyan
Jr Varsity I
Forum|alt.badge.img+3


Hi @Febri ! Acumatica often expects you to insert the parent record, mark it as Current, and then insert child records. Additionally, letting Acumatica handle line numbering (LineNbr) helps avoid mismatches between parent and child.

Below is a cleaned‐up version of your code that should work more reliably. The main difference is that I insert the SOShipment and set it to Document.Current right away, then insert the lines in shipmentGraph.Transactions, save, and only do additional split/lot adjustments afterward if needed.

Try out this code and see if it resolves the null reference error for you!

 

public PXAction<ITMarking> Release;
[PXUIField(DisplayName = "RELEASE", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false)]
[PXButton(SpecialType = PXSpecialButtonType.Process, Connotation = PX.Data.WorkflowAPI.ActionConnotation.Success)]
public virtual IEnumerable release(PXAdapter adapter)
{
    PXTrace.WriteInformation("Begin Release Action");

    ITMarking rilise = MasterView.Current;

    // Validate that we have a valid MarkingNbr
    if (rilise?.MarkingNbr != null 
        && rilise.MarkingNbr != "" 
        && rilise.MarkingNbr != "[DocumentID]" 
        && rilise.MarkingNbr != "<NEW>")
    {
        // Create graph for SOShipmentEntry
        SOShipmentEntry shipmentGraph = PXGraph.CreateInstance<SOShipmentEntry>();

        // Look up CustomerID and Location
        var soOrder = SelectFrom<SOOrder>
            .Where<SOOrder.orderNbr.IsEqual<P.AsString>>
            .View.Select(this, rilise.Sonbr).TopFirst;

        int? customerID = soOrder?.CustomerID;
        int? customerLocationID = soOrder?.CustomerLocationID;

        PXTrace.WriteInformation("Creating new Shipment record...");

        // Insert a new SOShipment record
        SOShipment shipment = new SOShipment
        {
            ShipDate          = rilise.DocumentDate,
            ShipmentType      = SOShipmentType.Issue,
            ....
        };
        shipment = shipmentGraph.Document.Insert(shipment);

        // Make sure the newly inserted shipment is set as the Current document
        shipmentGraph.Document.Current = shipment;

        // Save so the shipment is fully created in the database
        shipmentGraph.Save.Press();
        PXTrace.WriteInformation("Shipment record created: " + shipment.ShipmentNbr);


        SOOrderShipment shipmentOrder = new SOOrderShipment
        {
            OrderType   = "SO",
            OrderNbr    = rilise.Sonbr,
            ShipmentNbr = shipment.ShipmentNbr,
            Operation   = SOOperation.Issue
        };
        shipmentOrder = shipmentGraph.OrderList.Insert(shipmentOrder);
        shipmentGraph.Save.Press();

        PXTrace.WriteInformation("Adding shipment lines...");

        // Grab the details from your ITMarkingDetail lines
        var detailsList = DetailsView.Select().RowCast<ITMarkingDetail>().ToList();
        if (detailsList == null || !detailsList.Any())
        {
            throw new PXException("your error msg");
        }

        // Insert an SOShipLine for each item in details
        // Acumatica will handle the LineNbr automatically
        foreach (ITMarkingDetail detail in detailsList)
        {
            var shipLine = new SOShipLine
            {
                ShipmentNbr     = shipment.ShipmentNbr,
                SiteID          = detail.Warehouse,
                InventoryID     = detail.InventoryID,
                SubItemID       = detail.SubItem,
                ... 
            };
            shipmentGraph.Transactions.Insert(shipLine);
        }
        // Save after lines are inserted
        shipmentGraph.Save.Press();

        // If you need to manually modify splits (e.g., lot/serial management),
        // you can do so here by selecting the splits from shipmentGraph.splits
        // But in many cases, Acumatica auto-generates them for you.

        PXTrace.WriteInformation("All lines added; finalizing shipment...");

        // Update ITMarking record to indicate success
        rilise.Status = "Released";
        rilise.ShipmentNbr = shipment.ShipmentNbr;
        MasterView.Cache.Update(rilise);
        MasterView.Cache.Persist(PXDBOperation.Update);

        PXTrace.WriteInformation("Release action complete.");
    }

    return adapter.Get();
}

 


harutyungevorgyan
Jr Varsity I
Forum|alt.badge.img+1

Hello ​@Febri,

I completely agree with the points raised by ​@davidnavasardyan, and I'd like to contribute a few additional suggestions that might help clarify and improve the logic.

First, regarding the initial conditional check — for improved readability and maintainability, I recommend simplifying it to:

!string.IsNullOrEmpty(rilise?.MarkingNbr)

This eliminates the need for multiple separate null or empty checks while conveying the same logic more clearly.

Regarding the hardcoded value [DocumentID], be cautious unless you are certain that this placeholder cannot be changed via the UI. As for the <NEW> value, this is typically tied to Acumatica’s numbering sequences. If you are relying on automatic numbering, it's important not to hardcode <NEW> when checking for unsaved records. Users can change the New Number Symbol on the Numbering Sequences screen, and if that happens, hardcoded values may lead to incorrect behavior. A better approach is to retrieve the associated Numbering and access the Numbering.NewSymbol property to ensure your code always reflects the current configuration.

Lastly, on the topic of line splits: as ​@davidnavasardyan already mentioned, Acumatica handles most split generations automatically. However, if you do need to insert splits manually, make sure to set the correct Current record in the Transactions view before performing any insert into the splits view. This is important because the splits view is configured to use the Current SOShipLine record as its parent reference. Inserting a split without a properly set context may result in unintended behavior or errors.
As your method currently has more than 100 lines, I would also recommend separating it into smaller, more focused methods. This will improve readability, make maintenance easier, and allow for better testability in the future.

I hope these insights help prevent potential issues down the line. Please feel free to reach out if you have any questions or need further clarification.


Forum|alt.badge.img
  • Author
  • Freshman I
  • 25 replies
  • April 9, 2025

 

I have successfully entered data on Shipment but failed on ShipLine. because of any block added on the shipping screen


harutyungevorgyan
Jr Varsity I
Forum|alt.badge.img+1
Febri wrote:

 

I have successfully entered data on Shipment but failed on ShipLine. because of any block added on the shipping screen

 

Hello ​@Febri ,

It's great to hear that you made progress by successfully entering data for the Shipment. Could you please clarify what you mean by "block" on the shipping screen?


Forum|alt.badge.img
  • Author
  • Freshman I
  • 25 replies
  • April 9, 2025

This is detail of ShipLine

 

Is this a default feature of Acumatica, or is there a setting that can open it ?


harutyungevorgyan
Jr Varsity I
Forum|alt.badge.img+1
Febri wrote:

This is detail of ShipLine

 

Is this a default feature of Acumatica, or is there a setting that can open it ?

Hi ​@Febri ,
Although this is disabled in the UI for users, it's still possible to insert lines programmatically.
However, you're touching a core part of the Sales Order module logic here, and customizing this area can easily conflict with Acumatica’s internal processes if not done carefully.

To avoid introducing custom batch cycles or re-implementing complex logic, I strongly recommend using the same method Acumatica uses internally when the user clicks the "Add Order" button on the Shipment screen. This approach allows you to insert Sales Order lines into the Details tab of a shipment without bypassing important features.
Here’s an example method that achieves the same behavior programmatically after creation of the Shipment:

private static void AddSOLinesToShipment(SOShipmentEntry sOShipmentEntry, SOOrder sOOrder, int?[] lineNbrs)
{
    //Be sure you have correct values you will need later
    if (lineNbrs == null || lineNbrs.Length == 0)
    {
        return;
    }

    if (sOShipmentEntry.addsofilter.Current is not AddSOFilter filter)
    {
        return;
    }

    //Set the filter values to have the list of lines you want to add
    filter.OrderType = sOOrder.OrderType;
    filter.OrderNbr = sOOrder.OrderNbr;
    filter.AddAllLines = false;
    filter.Operation = SOOperation.Issue;
    sOShipmentEntry.addsofilter.Update(filter);

    //Take the list of lines and select the required ones to be added to the shipment
    foreach (PXResult<SOShipmentPlan, SOLineSplit, SOLine> shipmentPlan in sOShipmentEntry.soshipmentplan.Select())
    {
        SOLineSplit lineSplit = shipmentPlan.GetItem<SOLineSplit>();
        SOShipmentPlan plan = shipmentPlan.GetItem<SOShipmentPlan>();

        if (lineSplit.OrderNbr == sOOrder.OrderNbr &&
            lineSplit.OrderType == sOOrder.OrderType &&
            lineNbrs.Contains(lineSplit.LineNbr))
        {
            plan.Selected = true;
            sOShipmentEntry.soshipmentplan.Update(plan);
        }
    }
    //Press the Add SO button to add the lines to the shipment
    sOShipmentEntry.addSO.Press();
    //Press the Save button to save the shipment
    sOShipmentEntry.Save.Press();
}

You can certainly separate this into smaller methods for better reusability. I kept it together here to make the logic clear for the community.

Let me know if you have any questions.


Forum|alt.badge.img
  • Author
  • Freshman I
  • 25 replies
  • April 10, 2025

Can this method include lot number field ?
 

or if the goods have the same inventory, subitem, warehouse and location but the lot number is different, the details must be entered in Line Details ?


please help me


harutyungevorgyan
Jr Varsity I
Forum|alt.badge.img+1
Febri wrote:

Can this method include lot number field ?
 

or if the goods have the same inventory, subitem, warehouse and location but the lot number is different, the details must be entered in Line Details ?


please help me

Hi ​@Febri ,

The method I gave you uses OrderLineNbr, which means the system will automatically pull the data from the SOOrderLine into your shipment line.

However, when it comes to Line Details (commonly referred to as line splitting or allocation), that logic needs to be handled separately. If you want to control splits manually, you’ll need to explicitly add the required allocations yourself. To do this correctly, I strongly recommend first understanding how the allocation process works—especially its impact on Qty. On Hand, Qty. Available, and related inventory quantities. Also, make sure that the lot/serial number you’re trying to use is available in the exact warehouse and location you're assigning it to.

At this point, the discussion is moving into more advanced customization, and it’s no longer related to the original error you reported. If the issue with adding lines from the Sales Order is now resolved, I’d suggest closing this topic. You can open a new thread specifically focused on handling splits or allocation logic when you're ready to explore that further.

Hope this helps!


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings