Hello everyone,
I'm having the following scenario: I’m having the following code related with the Shipments screen in which I’m supposed to have 2 grids a separate tab called “Truck Information”, the grids are one for the Truck Information and the other is for Related Purchase Receipt Information. What I’m trying to achieve is when there’s an existing truck information data, when the user selects that row, the linked PR;s with this truck should be automatically displayed (reloading the graph or better updating the cache if possible). At the moment it’s almost working but the user has to automatically refresh the Related PR’s grid using the actions refresh button and the idea is that to be automated. There’s an existing functionality made by Acumatica in another screen (Complete Bidding) and the tab with the same functionality is called Bidding Results. The idea is the same but I’m not able to automatically refresh or update visually the cache. The selection does work. I’m open for any advice’s. I have tried updating the cache in the event handler for the selected row but it’s incorrectly to use cache manipulation there or at least that’s what the error was saying. The version of Acumatica I’m using is 2025 r2
Here’s the code I’m having at the moment:
public class SOShipmentEntryExt_TruckInfo : PXGraphExtension<SOShipmentEntry>
{
public static bool IsActive() => true;
#region Views
[PXCopyPasteHiddenView]
public PXSelect<SOShipmentTruckInfo,
Where<SOShipmentTruckInfo.shipmentNbr, Equal<Current<SOShipment.shipmentNbr>>>> TruckInformation;
public PXSelectJoin<SOShipmentTruckPRLink,
LeftJoin<POReceipt,
On<POReceipt.receiptNbr, Equal<SOShipmentTruckPRLink.receiptNbr>>>,
Where<SOShipmentTruckPRLink.truckInfoID, Equal<Argument<int?>>>>
RelatedPRInfo;
#endregion
#region Delegate Methods
public virtual IEnumerable relatedPRInfo(
[PXInt]
int? truckInfoID)
{
int? currentTruckInfoID = truckInfoID ?? (TruckInformation.Current != null ? TruckInformation.Current.TruckInfoID : null);
foreach (PXResult<SOShipmentTruckPRLink, POReceipt> item in
PXSelectJoin<SOShipmentTruckPRLink,
LeftJoin<POReceipt,
On<POReceipt.receiptNbr, Equal<SOShipmentTruckPRLink.receiptNbr>>>,
Where<SOShipmentTruckPRLink.truckInfoID, Equal<Required<SOShipmentTruckPRLink.truckInfoID>>>>
.Select(this.Base, currentTruckInfoID))
{
yield return item;
}
}
#endregion
#region Event Handlers - SOShipmentTruckInfo
protected virtual void _(Events.RowSelected<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment == null) return;
bool isEditable = shipment.Status != SOShipmentStatus.Completed;
PXUIFieldAttribute.SetEnabled(e.Cache, e.Row, isEditable);
RelatedPRInfo.View.RequestRefresh();
}
protected virtual void _(Events.RowInserted<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
protected virtual void _(Events.RowUpdated<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
protected virtual void _(Events.RowDeleted<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
#endregion
#region Event Handlers - SOShipmentTruckPRLink
protected virtual void _(Events.RowSelected<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment == null) return;
bool isEditable = shipment.Status != SOShipmentStatus.Completed;
PXUIFieldAttribute.SetEnabled<SOShipmentTruckPRLink.receiptNbr>(e.Cache, e.Row, isEditable);
}
protected virtual void _(Events.FieldSelecting<SOShipmentTruckPRLink.pONbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null || string.IsNullOrEmpty(row.ReceiptNbr))
return;
// Query POReceiptLine to get PO Number
POReceiptLine firstLine = PXSelectReadonly<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>
.SelectSingleBound(Base, null, row.ReceiptNbr);
if (firstLine != null)
{
e.ReturnValue = firstLine.PONbr;
}
}
protected virtual void _(Events.FieldSelecting<SOShipmentTruckPRLink.pOLineNbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null || string.IsNullOrEmpty(row.ReceiptNbr))
return;
// Query POReceiptLine to get PO Line Number
POReceiptLine firstLine = PXSelectReadonly<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>
.SelectSingleBound(Base, null, row.ReceiptNbr);
if (firstLine != null)
{
e.ReturnValue = firstLine.LineNbr;
}
}
protected virtual void _(Events.FieldSelecting<SOShipmentTruckPRLink.contractNbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null || string.IsNullOrEmpty(row.ReceiptNbr))
return;
// Query POReceiptLine to get PO information first
POReceiptLine firstLine = PXSelectReadonly<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>
.SelectSingleBound(Base, null, row.ReceiptNbr);
if (firstLine != null)
{
// Query POLine to get Contract Number
POLine poLine = PXSelectReadonly<POLine,
Where<POLine.orderType, Equal<Required<POLine.orderType>>,
And<POLine.orderNbr, Equal<Required<POLine.orderNbr>>,
And<POLine.lineNbr, Equal<Required<POLine.lineNbr>>>>>>
.SelectSingleBound(Base, null, firstLine.POType, firstLine.PONbr, firstLine.LineNbr);
if (poLine != null)
{
var poLineExt = poLine.GetExtension<POLineExt>();
e.ReturnValue = poLineExt?.UsrContractNbr;
}
}
}
protected virtual void _(Events.FieldUpdated<SOShipmentTruckPRLink.receiptNbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null) return;
// Force FieldSelecting events to fire for unbound fields to refresh UI
object fieldValue = null;
e.Cache.RaiseFieldSelecting<SOShipmentTruckPRLink.pONbr>(row, ref fieldValue, false);
e.Cache.RaiseFieldSelecting<SOShipmentTruckPRLink.pOLineNbr>(row, ref fieldValue, false);
e.Cache.RaiseFieldSelecting<SOShipmentTruckPRLink.contractNbr>(row, ref fieldValue, false);
// Mark shipment as updated to enable Save button
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
protected virtual void _(Events.RowInserted<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
protected virtual void _(Events.RowUpdated<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
protected virtual void _(Events.RowDeleted<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}
#endregion
#region Event Handlers - SOShipment
protected virtual void _(Events.RowSelected<SOShipment> e)
{
if (e.Row == null) return;
bool isEditable = e.Row.Status != SOShipmentStatus.Completed;
TruckInformation.AllowInsert = isEditable;
TruckInformation.AllowDelete = isEditable;
TruckInformation.AllowUpdate = isEditable;
TruckInformation.Cache.AllowInsert = isEditable;
TruckInformation.Cache.AllowDelete = isEditable;
TruckInformation.Cache.AllowUpdate = isEditable;
RelatedPRInfo.AllowInsert = isEditable;
RelatedPRInfo.AllowDelete = isEditable;
RelatedPRInfo.AllowUpdate = isEditable;
RelatedPRInfo.Cache.AllowInsert = isEditable;
RelatedPRInfo.Cache.AllowDelete = isEditable;
RelatedPRInfo.Cache.AllowUpdate = isEditable;
var linkedPRsInvalidStatus = PXSelectJoin<POReceipt,
InnerJoin<SOShipmentTruckPRLink,
On<SOShipmentTruckPRLink.receiptNbr, Equal<POReceipt.receiptNbr>>,
InnerJoin<SOShipmentTruckInfo,
On<SOShipmentTruckInfo.truckInfoID, Equal<SOShipmentTruckPRLink.truckInfoID>>>>,
Where<SOShipmentTruckInfo.shipmentNbr, Equal<Required<SOShipmentTruckInfo.shipmentNbr>>,
And<POReceipt.status, NotEqual<POReceiptStatus.released>>>>
.Select(Base, e.Row.ShipmentNbr);
bool hasLinkedPRsInvalidStatus = linkedPRsInvalidStatus.Count > 0;
if (hasLinkedPRsInvalidStatus)
{
PXUIFieldAttribute.SetWarning<SOShipment.shipmentNbr>(e.Cache, e.Row,
TruckInfo.Messages.CannotConfirmShipmentPRInvalidStatus);
}
// Disable Confirm Shipment action when there are linked PRs with invalid status
PXAction confirmAction = Base.Actions["ConfirmShipment"];
if (confirmAction != null)
{
confirmAction.SetEnabled(!hasLinkedPRsInvalidStatus);
}
}
