Use Case
This article demonstrates how to update fields in a Sales Order upon confirmation on its shipment.
In this example, we will add the "Expected Delivery Date" field to a Sales Order header,
and will calculate it as adding some constant days number (7 here) to the shipment confirmation date.
Prerequisites
The attached customization adds the "Expected Delivery Date" field to Sales Order header (SOOrder database table, DAC, and aspx). It should be used as a starting point for implementing the logic described in the Use Case section.
Solution
The described solution uses the structure of the Confirm Shipment action delegate:
protected virtual IEnumerable ConfirmShipmentAction(PXAdapter adapter)
{
PXLongOperation.StartOperation(this, delegate ()
{
SOShipmentEntry docgraph = PXGraph.CreateInstance<SOShipmentEntry>();
SOOrderEntry orderentry = PXGraph.CreateInstance<SOOrderEntry>();
foreach (SOShipment shipment in list)
{
docgraph.PrepareShipmentForConfirmation(shipment);
docgraph.ShipPackages(shipment);
docgraph.ConfirmShipment(orderentry, shipment); -- here, the Sales Order is saved through the orderentry graph instance
...
It is possible to attach the RowPersisting handler to the orderentry graph instance in the ConfirmShipment method extension and implement the update of the custom field there. In order to pass the target value of the custom field, we can create a public property in the orderentry graph extension and assign this property in the ConfirmShipment method extension.
This, as well as the calculation of the "Expected Delivery Date" field on shipment confirmation, is implemented by the provided blocks of the code extending SOOrderEntry and SOShipmentEntry graphs, respectively:
public class SOOrderEntryAssignFieldOnPersistExtension : PXGraphExtension<SOOrderEntry>
{
public DateTime? CalculatedExpectedDeliveryDate;
public virtual void SOOrderFieldUpdateonRowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
if (CalculatedExpectedDeliveryDate != null)
{
SOOrder doc = (SOOrder)e.Row;
SOOrderExpectedDeliveryDateExt soorderExt =
doc.GetExtension<SOOrderExpectedDeliveryDateExt>();
if (soorderExt != null)
{
soorderExt.UsrExpectedDeliveryDate = CalculatedExpectedDeliveryDate;
}
}
}
}
public class SOShipmentEntryAssignFieldOnPersistExtension : PXGraphExtension<SOShipmentEntry>
{
private DateTime CalculateExpectedDeliveryDate(DateTime inputdate)
{
return inputdate.AddDays(7);
}
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder, Action<SOOrderEntry, SOShipment> baseMethod)
{
SOOrderEntryAssignFieldOnPersistExtension soorderentryExt =
docgraph.GetExtension<SOOrderEntryAssignFieldOnPersistExtension>();
if (soorderentryExt != null )
{
soorderentryExt.CalculatedExpectedDeliveryDate = CalculateExpectedDeliveryDate(DateTime.Now);
docgraph.RowPersisting.AddHandler<SOOrder>(soorderentryExt.SOOrderFieldUpdateonRowPersisting);
}
try
{
baseMethod(docgraph, shiporder);
}
finally
{
if (CalculatedExpectedDeliveryDate != null && soorderentryExt != null)
{
docgraph.RowPersisting.RemoveHandler<SOOrder>(soorderentryExt.SOOrderFieldUpdateonRowPersisting);
}
}
}
}
These code fragments use the cache extension defined in the customization provided in the Prerequisites section
Remarks
- Values to be assigned to a sales order should be calculated from a shipment at the state preceding the main confirmation procedure (ConfirmShipment method) . However, it is possible to calculate this value from shipment packages processed on confirmation (by overriding the ShipPackages method)
- This approach can be used for updating not only a sales order header (SOOrder), but also for any cache that can be persisted through the SOOrderEntry graph, such as lines (SOLine) or links to related shipments (SOOrderShipment). The latter is more appropriate when a sales order can have multiple shipments.