Hopefully I am missing something easy. This is on 2019R2.
I've added a custom button to my SO form with the idea that it's similar to the Quick Process button. The steps I need to take on the current SO are:
- Create a shipment containing all lines on the order
- Confirm Shipment
- Update IN
- Create Invoice
- Release Invoice
I'm not having a lot of luck getting it to finish properly. I've gotten steps 1 and 2 to work, step 3 seems to work (I don't get an error), but I never get an invoice for the shipment from step 4 (just the error below). Haven't even added step 5 yet.
Error: Another process has updated the 'SOShipment' record. Your changes will be lost.
Here's the implementation code:
public PXAction<PX.Objects.SO.SOOrder> AIquickProcess;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Phone Quick Process")]
protected void aIquickProcess()
{
SOOrder so = Base.CurrentDocument.Current;
if (so == null) return;
if (so.OrderType != "SO" && so.OrderType != "TR") return;
SOOrder ordercopy = (SOOrder)Base.Caches[typeof(SOOrder)].CreateCopy(so);
SOShipmentEntry shipmentEntryGraph = PXGraph.CreateInstance<SOShipmentEntry>();
DocumentList<SOShipment> shipmentDocs = new DocumentList<SOShipment>(shipmentEntryGraph);
SOLine line = PXSelect<SOLine,
Where<SOLine.orderType, Equal<Required<SOLine.orderType>>,
And<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>>>>
.Select(Base, so.OrderType, so.OrderNbr);
if (line == null) return;
DateTime? shipDate = so.ShipDate == null ? so.OrderDate : so.ShipDate;
try
{
TimeSpan timespan;
Exception ex;
// Create shipment
shipmentEntryGraph.CreateShipment(so, line.SiteID, shipDate, false, line.Operation, shipmentDocs, PXQuickProcess.ActionFlow.NoFlow);
shipmentEntryGraph.CurrentDocument.Current.ControlQty = shipmentEntryGraph.CurrentDocument.Current.ShipmentQty;
shipmentEntryGraph.CurrentDocument.Update(shipmentEntryGraph.CurrentDocument.Current);
shipmentEntryGraph.Save.Press();
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
// Confirm Shipment
PXAutomation.CompleteSimple(shipmentEntryGraph.Document.View);
PXAdapter adapter2 = new PXAdapter(new DummyView(shipmentEntryGraph, shipmentEntryGraph.Document.View.BqlSelect,
new List<object> { shipmentEntryGraph.Document.Current }));
adapter2.Menu = SOShipmentEntryActionsAttribute.Messages.ConfirmShipment;
adapter2.Arguments = new Dictionary<string, object>
{
{"actionID", SOShipmentEntryActionsAttribute.ConfirmShipment}
};
adapter2.Searches = new object[] { shipmentEntryGraph.Document.Current.ShipmentNbr };
adapter2.SortColumns = new[] { "ShipmentNbr" };
shipmentEntryGraph.action.PressButton(adapter2);
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
// Update IN
shipmentEntryGraph.UpdateIN.Press();
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
shipmentEntryGraph.CurrentDocument.UpdateCurrent();
// create invoice
adapter2 = new PXAdapter(new DummyView(shipmentEntryGraph, shipmentEntryGraph.Document.View.BqlSelect,
new List<object> { shipmentEntryGraph.Document.Current }));
adapter2.Menu = SOShipmentEntryActionsAttribute.Messages.CreateInvoice;
adapter2.Arguments = new Dictionary<string, object>
{
{"actionID", SOShipmentEntryActionsAttribute.CreateInvoice}
};
adapter2.Searches = new object[] { shipmentEntryGraph.Document.Current.ShipmentNbr };
adapter2.SortColumns = new[] { "ShipmentNbr" };
shipmentEntryGraph.action.PressButton(adapter2);
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
// getting: Error: Another process has updated the 'SOShipment' record. Your changes will be lost.
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
}
catch (SOShipmentException ex)
{
Base.Caches[typeof(SOOrder)].RestoreCopy(so, ordercopy);
throw;
}
catch (Exception ex)
{
Base.Caches[typeof(SOOrder)].RestoreCopy(so, ordercopy);
shipmentEntryGraph.Clear();
throw;
}
}
Here's the code for the DummyView
public class DummyView : PXView
{
List<object> _Records;
internal DummyView(PXGraph graph, BqlCommand command, List<object> records) : base(graph, true, command)
{
_Records = records;
}
public override List<object> Select(object[] currents, object[] parameters, object[] searches, string[] sortcolumns,
bool[] descendings, PXFilterRow[] filters, ref int startRow, int maximumRows, ref int totalRows)
{
return _Records;
}
}
Here is a version that sometimes works to create and release the invoice, but I still get the same error. I've noticed that I get the error on the UpdateIN.Press() step when the inventory item would go negative (which is allowed).
public PXAction<PX.Objects.SO.SOOrder> AIquickProcess;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Phone Quick Process")]
protected void aIquickProcess()
{
SOOrder so = Base.CurrentDocument.Current;
if (so == null) return;
if (so.OrderType != "SO" && so.OrderType != "TR") return;
SOOrder ordercopy = (SOOrder)Base.Caches[typeof(SOOrder)].CreateCopy(so);
SOShipmentEntry shipmentEntryGraph = PXGraph.CreateInstance<SOShipmentEntry>();
DocumentList<SOShipment> shipmentDocs = new DocumentList<SOShipment>(shipmentEntryGraph);
SOLine line = PXSelect<SOLine,
Where<SOLine.orderType, Equal<Required<SOLine.orderType>>,
And<SOLine.orderNbr, Equal<Required<SOLine.orderNbr>>>>>
.Select(Base, so.OrderType, so.OrderNbr);
if (line == null) return;
DateTime? shipDate = so.ShipDate == null ? so.OrderDate : so.ShipDate;
try
{
TimeSpan timespan;
Exception ex;
// Create shipment
shipmentEntryGraph.CreateShipment(so, line.SiteID, shipDate, false, line.Operation, shipmentDocs, PXQuickProcess.ActionFlow.NoFlow);
shipmentEntryGraph.CurrentDocument.Current.ControlQty = shipmentEntryGraph.CurrentDocument.Current.ShipmentQty;
shipmentEntryGraph.CurrentDocument.Update(shipmentEntryGraph.CurrentDocument.Current);
shipmentEntryGraph.Save.Press();
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
// Confirm Shipment
PXAutomation.CompleteSimple(shipmentEntryGraph.Document.View);
PXAdapter adapter2 = new PXAdapter(new DummyView(shipmentEntryGraph, shipmentEntryGraph.Document.View.BqlSelect,
new List<object> { shipmentEntryGraph.Document.Current }));
adapter2.Menu = SOShipmentEntryActionsAttribute.Messages.ConfirmShipment;
adapter2.Arguments = new Dictionary<string, object>
{
{"actionID", SOShipmentEntryActionsAttribute.ConfirmShipment}
};
adapter2.Searches = new object[] { shipmentEntryGraph.Document.Current.ShipmentNbr };
adapter2.SortColumns = new[] { "ShipmentNbr" };
shipmentEntryGraph.action.PressButton(adapter2);
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
// Update IN
PXAutomation.CompleteSimple(shipmentEntryGraph.Document.View);
shipmentEntryGraph.UpdateIN.Press();
while (PXLongOperation.GetStatus(shipmentEntryGraph.UID, out timespan, out ex) == PXLongRunStatus.InProcess)
{ }
if (ex != null && ex.Message.ToLower() != "nothing in progress" && ex.Message.ToLower() != "the operation has completed.") throw ex;
// Create and release invoice
SOInvoiceEntry invoiceEntryGraph = PXGraph.CreateInstance<SOInvoiceEntry>();
DocumentList<ARInvoice, SOInvoice> created = new ShipmentInvoices(shipmentEntryGraph);
shipmentEntryGraph.SelectTimeStamp();
invoiceEntryGraph.SelectTimeStamp();
PXProcessing<SOShipment>.SetCurrentItem(shipmentEntryGraph.CurrentDocument.Current);
shipmentEntryGraph.InvoiceShipment(invoiceEntryGraph, shipmentEntryGraph.CurrentDocument.Current, Base.Accessinfo.BusinessDate.Value, created, PXQuickProcess.ActionFlow.NoFlow);
invoiceEntryGraph.CurrentDocument.Current.CreditHold = false;
invoiceEntryGraph.Save.Press();
invoiceEntryGraph.release.Press();
}
catch (SOShipmentException ex)
{
Base.Caches[typeof(SOOrder)].RestoreCopy(so, ordercopy);
throw;
}
catch (Exception ex)
{
Base.Caches[typeof(SOOrder)].RestoreCopy(so, ordercopy);
shipmentEntryGraph.Clear();
throw;
}
}