Hi,
We are working on customizations to the Sales Order screen. I have added several new fields and overridden a few methods, such as PrepareInvoice
and CreateShipment
, to ensure that some of the custom fields flow through to shipments and invoices
However, we are encountering an error with the following message:
Error: Inserting 'Billing Address' record raised at least one error. Please review the errors. Error: 'RevisionID' cannot be empty.

We are unable to pinpoint exactly when this error occurs. Sometimes, it happens when adding a non-stock item, and at other times, it occurs when saving values in the new custom fields. The error disappears after refreshing the page, but this is not a practical solution as all entered data is lost upon refresh.
I have attached the SOOrderEntry
code and the Customization Projectfor your reference. Could you help identify what we might be doing wrong or missing?
Any help would be greatly appreciated.
Thank you.
Ramitha Manathunga.
SOOrderEntry Code
#region Event Handlers
// Overriding PreapareInvoice Method to Pass values from sales order to Invoices Upon Preaparing the Invoice
public delegate IEnumerable PrepareInvoiceDelegate(PXAdapter adapter);
;PXOverride]
public IEnumerable PrepareInvoice(PXAdapter adapter, PrepareInvoiceDelegate baseMethod)
{
PXGraph.InstanceCreated.AddHandler<SOInvoiceEntry>((invoiceGraph) =>
{
invoiceGraph.RowPersisting.AddHandler<ARRegister>((sender, e) =>
{
ARRegister currentInvoice = (ARRegister)e.Row;
ARRegisterExt registerExt = currentInvoice.GetExtension<ARRegisterExt>();
SOOrderExt orderExt = Base.Document.Cache.GetExtension<SOOrderExt>(Base.Document.Current);
// Update ARRegisterExt fields
registerExt.UsrVesselName = orderExt.UsrVesselName;
registerExt.UsrVesselETADate = orderExt.UsrVesselETADate;
registerExt.UsrVesselETA = orderExt.UsrVesselETA;
registerExt.UsrVesselType = orderExt.UsrVesselType;
registerExt.UsrSalesType = orderExt.UsrSalesType;
registerExt.UsrContainerNumber = orderExt.UsrContainerNumber;
registerExt.UsrCustomerPONumber = orderExt.UsrCustomerPONumber;
registerExt.UsrTerminalName = orderExt.UsrTerminalName;
registerExt.UsrJobNumber = orderExt.UsrJobNumber;
// Update ARTranExt fields
PXResultset<ARTran> arTrans = PXSelect<ARTran,
Where<ARTran.refNbr, Equal<Required<ARTran.refNbr>>,
And<ARTran.tranType, Equal<Required<ARTran.tranType>>>>>
.Select(invoiceGraph, currentInvoice.RefNbr, currentInvoice.DocType);
foreach (ARTran arTran in arTrans)
{
ARTranExt arTranExt = arTran.GetExtension<ARTranExt>();
arTranExt.UsrContainerNumber = orderExt.UsrContainerNumber;
invoiceGraph.Caches<ARTran>().Update(arTran);
}
});
});
return baseMethod(adapter);
}
// Overriding CreateShipment Method to Pass values from sales order to Shipment Upon Creating the Shipment
public delegate IEnumerable CreateShipmentDelegate(PXAdapter adapter, DateTime? shipDate, int? siteID, DateTime? endDate, string operation);
// Acuminator disable once PX1096 PXOverrideSignatureMismatch tJustification]
cPXOverride]
public IEnumerable CreateShipment(PXAdapter adapter, DateTime? shipDate, int? siteID, DateTime? endDate, string operation, CreateShipmentDelegate baseMethod)
{
PXGraph.InstanceCreated.AddHandler<SOShipmentEntry>((graphShipmentEntry) =>
{
graphShipmentEntry.RowPersisting.AddHandler<SOShipment>((sender, e) =>
{
SOShipment currentShipment = (SOShipment)e.Row;
SOShipmentExt shipmentExt = currentShipment.GetExtension<SOShipmentExt>();
SOOrderExt orderExt = Base.Document.Cache.GetExtension<SOOrderExt>(Base.Document.Current);
// Copy custom fields from SOOrderExt to SOShipmentExt
shipmentExt.UsrVesselName = orderExt.UsrVesselName;
shipmentExt.UsrVesselETADate = orderExt.UsrVesselETADate;
shipmentExt.UsrVesselETA = orderExt.UsrVesselETA;
shipmentExt.UsrVesselType = orderExt.UsrVesselType;
shipmentExt.UsrSalesType = orderExt.UsrSalesType;
shipmentExt.UsrContainerNumber = orderExt.UsrContainerNumber;
shipmentExt.UsrCustomerPONumber = orderExt.UsrCustomerPONumber;
shipmentExt.UsrTerminalName = orderExt.UsrTerminalName;
shipmentExt.UsrJobNumber = orderExt.UsrJobNumber;
});
});
return baseMethod(adapter, shipDate, siteID, endDate, operation);
}
}Obsolete]
protected void SOOrder_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
var salesOrder = (SOOrder)e.Row;
if (salesOrder == null) return;
// Only apply for Order Type SO and during Insert or Update
if (salesOrder.OrderType != "ST" ||
(e.Operation != PXDBOperation.Insert && e.Operation != PXDBOperation.Update))
return;
// Retrieve the custom field value from the SOOrder extension
string newContainerNumber = PXCache<SOOrder>.GetExtension<SOOrderExt>(salesOrder)?.UsrContainerNumber;
if (!string.IsNullOrEmpty(newContainerNumber))
{
// Check if the same container number is assigned to another sales order
SOOrder existingOrder = SelectFrom<SOOrder>
.Where<SOOrderExt.usrContainerNumber.IsEqual<@P.AsString>
.And<SOOrder.orderNbr.IsNotEqual<@P.AsString>>
.And<SOOrder.orderType.IsEqual<@P.AsString>>>
.View.Select(Base, newContainerNumber, salesOrder.OrderNbr, "ST");
if (existingOrder != null)
{
// Change to Warning level instead of Error
// Acuminator disable once PX1050 HardcodedStringInLocalizationMethod zJustification]
cache.RaiseExceptionHandling<SOOrderExt.usrContainerNumber>(
salesOrder,
newContainerNumber,
new PXSetPropertyException("This Container Number is already assigned to another sales order.", PXErrorLevel.Warning));
}
}
}
protected virtual void SOOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected InvokeBaseHandler)
{
InvokeBaseHandler?.Invoke(cache, e);
SOOrder row = e.Row as SOOrder;
if (row != null)
{
//Allowing caches to update with below code
Base.Document.Cache.AllowUpdate = true;
Base.Transactions.Cache.AllowUpdate = true;
PXUIFieldAttribute.SetEnabled(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrActualHours>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrAverageCost>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrCustomerPOReceivedDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrDurationDates>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrEWOReceivedDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrHandoverToFinanceDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrInquiryReceivedDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrInquiryReceivedTime>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrLastUpdatedDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrQuotationcofirmedDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrTargetCompletionDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrWorkCompletionDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrWorkDoneSignedDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrWorkStartDate>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrYardSuperviserIncharge>(cache, row, true);
PXUIFieldAttribute.SetEnabled<SOOrderExt.usrAverageCost>(cache, row, true);
}
}
#endregion