Skip to main content

It looks like there has been a major refactoring of how line splitting works in Acumatica, which is great news because this moves us away from the old kvstore approach, which was not performant at scale.

However, there seem to be zero practical examples of how to implement this functionality. For example, let’s say I want to add a field to POReceiptLineSplit, and then pull that field back in a SOSalesOrderLineSplittingExtension. How might I do that?

@Dmitrii Naumov Do you think we could get some practical examples of how to work with the new line splitting code? It looks like there have been other requests also for this, which so far have gone unanswered...

 

@Dmitrii Naumov I’ve figured most of this out now. I wlil post a formal how-to in the coming weeks as I get my own project into more solid form.

I have some feedback for the development team, however. I think it was very smart to nuke the kvstore idea, and to go with these line split tables instead. For example, we now have POReceiptLineSplit instead of POReceiptLineKvExt. That’s all great.

But the UI for working with Inventory Receipts and Sales Order Line allocations hasn’t adapted to this new approach. In the screenshot below, this is an example of an Inventory Receipt transaction, where we already entered the purchase receipt of 100 units of material as two, 50 and 50 lots with different lot numbers. When we go to enter the inventory receipt, the system auto-populates the correct lot/serial number entered into the Purchase Receipt, which is good. But it is placed into a selector field, where you can then choose some other lot/serial number if you want to. This is just non-sensical. You wouldn’t ever choose a different lot of material than the one you just received in the Purchase Receipt, since the Purchase Receipt and Inventory Receipt are linked together. You might only put some of what you received into inventory, but you wouldn’t put some different lot of material than what you received into inventory. 

It also looks like we’re storing information about our lot/serialized inventory in INSiteLotSerial, and here is where you lose me completely.

If we can track inventory receipts in POReceiptLineSplit, and we can consume inventory in SOLineSplit and SOShipLineSplit, then what is on hand should always be the net of what we received and what we consumed. If we want to have a rollup table to calculate this stuff on a continuous basis for easy querying, I get that. But it looks like we are still using INLotSerialStatus as the single source of truth for which serial numbers are located in which locations. This is bad and unnecessary. We already have a way to track split inventory. Use the uniqueness of the line splits throughout the system, and then you can always track inventory back to its original receipt. By subquerying the inventory id, subitem id, and location to get lot/serial information using the INLotSerialStatus table, we are breaking the chain of custody of the inventory through the system, and we don’t have to do that anymore now that inventory is tracked at the split level.

This is a pretty nuanced point, but hopefully your core devs will understand. I think this is really close to being great, but is still missing the boat for tracking lot/serial information in a robust way.

 

 


hI @Dmitrii Naumov -

Sure. I will just run you through what I’m working on right now, and hopefully that will illustrate where some of the questions are coming up.

We are in the metals industry, which means for every receipt of material, we need to track certain things on a per lot basis. One of these would be a Lot Number (already built into Acumatica). But there is also something called a Heat Number (which is related to Lot Number but generally distinct from it). And then we usually have a document called a Test Report which gives specific details about that lot of material, and which needs to be tracked with each lot of material we receive.

So, when we receive material, we need to record this information against each lot received. It also needs to be tracked in INTran, so that it is logged against the actual receipt of material. Likewise, this needs to be selectable in SOLineSplit, so that if a salesperson wants to sell a specific lot of that material, they can see what is available and review the test report document attached to each lot of material.I have already extended POReceiptLineSplit, and added the two fields I want. Code is below. This part works!

 

Extension of POReceiptLineSplit:

	public class POReceiptLineSplitExt : PXCacheExtension<POReceiptLineSplit>
{
#region Heat Number
public abstract class heatNumber : PX.Data.BQL.BqlString.Field<heatNumber> { }
rPXDBString(255)]
rPXUIField(DisplayName = "Heat Nbr")]
public virtual string HeatNumber
{
get;
set;
}
#endregion
#region Test Report Document
public abstract class testReport : PX.Data.BQL.BqlString.Field<testReport> { }
rPXDBString(255)]
rPXUIField(DisplayName = "Test Report")]
public virtual string TestReport
{
get;
set;
}
#endregion
}

Now, when we receive material, we can fill out these fields and they will be stored along with the Lot/Serial in the database (confirmed by looking in the database). Great!

But...how do we extend the graph logic for these fields? Or have these fields flow to the INTran and SOLineSplit DACs when we allocate this material downstream of the Purchase Receipt process?

 

Let’s say we want these fields to flow through to INTran (material receipt process), and SOLineSplit (allocate inventory to specific sales order), and then SOShipLineSplit. Just for example purposes, let’s say we also want to manipulate some of the data inbetween pulling it into the SOLineSplit line.

The only documentation I’ve seen at all about extending the graph for the new LineSplitting extensions is a small reference on Yuriy Zaletskyy’s blog. He posted this screenshot:

https://blog.zaletskyy.com/image.axd?picture=/LSSelect/21R2Override.png

 

Here is the full blog post: https://blog.zaletskyy.com/post/2022/04/08/lsselect-view-in-acumatica

 

So put yourselves in the shoes of a programmer who has to create an extension of the Line Splitting logic, and how it will flow from Purchase Receipt, to Inventory Receipt, to Sales Order and to Shipment. The data is linked up through all these processes, so how do we step into the middle of the line splitting logic when, for example, there is a field updating event on the SOLineSplit field in the Sales Order inventory allocation screen?

I have tried implementing this the way Yuriyy laid out in the screenshot on his blog, and it doesn't throw any errors, but at least for now I can’t hit breakpoints in that code. Below is a stub implementation of the approach on Yuriyy’s blog for the SalesOrderLineSplittingExtension. Can we get some examples of what can be down here, and whether this is in fact the correct approach to extending the graph of these SOLineSplits?

 

	public class SOOrderEntry : PXGraph<SOOrderEntry, SOOrder>
{
public SOSalesOrderLineSplittingExtension SOOrderLineSplitExt =>
FindImplementation<SOSalesOrderLineSplittingExtension>();

public SOSalesOrderLineSplittingAllocatedExtension SOOrderLineAllocExt =>
FindImplementation<SOSalesOrderLineSplittingAllocatedExtension>();
}
public class SOSalesOrderLineSplittingExtension : PX.Objects.SO.GraphExtensions.SOOrderEntryExt.SOOrderLineSplittingExtension
{

//WHAT DO WE DO HERE? CAN WE CHANGE THE BEHAVIOR OF WHAT HAPPENS WHEN WE CHOOSE
//INVENTORY FOR ALLOCATION IN A SALES ORDER? WHAT WOULD THAT LOOK LIKE?

//HOW DO WE PROPERLY GRAB DATA FROM POReceiptLineSplit AND PULL IT INTO SOSalesOrderLineSplit?
}

public class SOSalesOrderLineSplittingAllocatedExtension : PX.Objects.SO.GraphExtensions.SOOrderEntryExt.SOOrderLineSplittingExtension
{
//WHAT DO WE DO HERE? CAN WE CHANGE THE BEHAVIOR OF WHAT HAPPENS WHEN WE CHOOSE
//INVENTORY FOR ALLOCATION IN A SALES ORDER? WHAT WOULD THAT LOOK LIKE?
}

 


Good idea, thanks for the suggestion. 

I think it is a good idea to have some examples. 

 

Could you suggest some example scenarios that we can implement? Could you explain the scenario with a custom field on POReceiptLineSplit a little bit more?

 

 


Reply