I'm trying to override the Cancel Order button in Purchase Order screen, but I didn't found the Acumatica existing source code in POOrderEntry.
Can anyone help me on this. Thanks in advance.
Technically you can do the following:
public class POOrderEntryExt : PXGraphExtension<POOrderEntry>
{
public MyCancelButton<POOrder> Cancel;
}
public sealed class MyCancelButton<TNode> : PXCancel<TNode> where TNode : class, IBqlTable, new()
{
public MyCancelButton(PXGraph graph, string name) : base(graph, name)
{
}
public MyCancelButton(PXGraph graph, Delegate handler) : base(graph, handler)
{
}
[PXUIField(DisplayName = "Cancel", MapEnableRights = PXCacheRights.Select)]
[PXCancelButton]
protected override IEnumerable Handler(PXAdapter adapter)
{
//DO SOME STAFF HERE
throw new PXException("Very bad idea");
return base.Handler(adapter);
}
}
But I DON'T RECOMMEND you doing that because the "Cancel" action is doing a lot of very important staff and messing it up is pretty easy.
I recommend considering other ways to do what you want to do. May be to place the logic in the Persisting or Verifying handlers.
Related
Good day
I am looking for a way to override the function ProcessItemBarcode(string Barcode) inside public class INScanReceive : WMSBase
The idea is to extend the INScanReceiveHost graph and manipulate the barcode before it is processed. This is to change how the Scan and Receive page scan'sa barcodes so that I can read and manipulate QR codes
namespace PX.Objects.IN
{
// Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
public class INScanReceiveHost_Extension : PXGraphExtension<INScanReceive>
{
#region Event Handlers
[PXOverride]
public virtual void ProcessItemBarcode(string barcode)
{
//change barcode
Base.ProcessItemBarcode.Invoke(barcode);
}
#endregion
}
}
But It telling me i can't access the function?
Update 2021/06/15
Thanks Sean Prouty for your help so far. I am getting very close to a solution.
I have a follow-up question.
I have overridden the ProcessItemBarcode function and ProcessLotSerialBarcode
Question: Can I call ProcessLotSerialBarcode from ProcessItemBarcode
because I have the location from the QR code I can set it from the first scan:
#region Overrides ProcessItemBarcode
//ProcessItemBarcode
public delegate void ProcessItemBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessItemBarcode(string barcode, ProcessItemBarcodeDelegate baseMethod)
{
try
{
string inventoryBC = barcode;
//...//get InvetoryID using Barcode
baseMethod?.Invoke(inventoryBC);
//how do you call the ProcessLotSerialBarcode function?
ProcessLotSerialBarcode(barcode, ProcessLotSerialBarcodeDelegate);
}
catch (Exception ex)
{//TODO: check if not a QR code
PXTrace.WriteError("ProcessItemBarcode Override: " + ex.Message);
baseMethod?.Invoke(barcode);
}
}
#endregion
#region Overrides ProcessLotSerialBarcode
//ProcessLotSerialBarcode
public delegate void ProcessLotSerialBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessLotSerialBarcode(string barcode, ProcessLotSerialBarcodeDelegate baseMethod)
{
try
{
string inventoryBC = "LOgic";
baseMethod?.Invoke(inventoryBC);
}
catch (Exception)
{
//TODO: check if not a QR code
baseMethod?.Invoke(barcode);
}
}
#endregion
[PXProtectedAccess]
public abstract class INScanReceiveHostExtProtectedAccess : PXGraphExtension<INScanReceiveHostExtCustomPackage, INScanReceive, INScanReceiveHost>
{
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessItemBarcode(string barcode);
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ApplyState(string state);
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessLotSerialBarcode(string barcode);
}
I was also thinking of setting the state from the first method but then I need to call
Base.ApplyState(INScanIssue.ScanStates.Confirm);
Then I can set the Header and just keep resetting the scanner to the Confirm state. What do you think?
Because the method you are trying to override is protected, and not public, you will need to override the logic in a different way using the PXProtectedAccess attribute and an abstract graph extension.
namespace MyCustomPackage.Graph.Extension
{
public class INScanReceiveHostExtCustomPackage : PXGraphExtension<INScanReceive, INScanReceiveHost>
{
public static bool IsActive() => true;
#region Overrides
public delegate void ProcessItemBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessItemBarcode(string barcode, ProcessItemBarcodeDelegate baseMethod)
{
PXTrace.WriteInformation("Running abstract override");
baseMethod?.Invoke(barcode);
}
#endregion
}
[PXProtectedAccess]
public abstract class INScanReceiveHostExtProtectedAccess : PXGraphExtension<INScanReceiveHostExtCustomPackage, INScanReceive, INScanReceiveHost>
{
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessItemBarcode(string barcode);
}
}
I didn't have a good way to test this unfortunately, so you may need to tweak the type that is being passed to the PXProtectedAccess attribute above the abstract method. If this doesn't work, try passing the INScanReceiveHost type to the attribute and see if that works for you.
I think this is probably just something stupid, but I'm trying to add a custom menu to the Customer form. I've used this code:
public override void Initialize()
{
base.Initialize();
this.SpeedyActions.AddMenuAction(BtnCreateMenu1);
this.SpeedyActions.AddMenuAction(BtnCreateMenu2);
}
public PXAction<PX.Objects.AR.Customer> BtnCreateMenu1;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Menu Item 1")]
protected void btnCreateMenu1()
{
// Logic
}
public PXAction<PX.Objects.AR.Customer> BtnCreateMenu2;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Menu Item 2")]
protected void btnCreateMenu2()
{
// Logic
}
public PXAction<PX.Objects.AR.Customer> SpeedyActions;
[PXButton(SpecialType = PXSpecialButtonType.Report, MenuAutoOpen =true)]
[PXUIField(DisplayName = "Speedy Actions")]
protected void speedyActions()
{
//code logic here
}
I've got basically the same code on the sales order form and it works perfectly. I suspect that I'm maybe using the wrong code here PX.Objects.AR.Customer and I've also tried CR.BAccount, but can't seem to make it work. Anyone have some thoughts?
I would try
Base.report.AddMenuAction(BtnCreateMenu1)
so I'm trying to add a small bool field to the SOInvoiceEntry graph, so it can be exposed to the API. It needs to remain editable even after the document has been closed and released. I've set up the DAC field as:
public class ARRegisterExt : PXCacheExtension<PX.Objects.AR.ARRegister>
{
[PXDBBool]
[PXUIField(DisplayName="Has been integrated", Visibility = PXUIVisibility.Visible, Enabled = true)]
public virtual bool? UsrIsIntegrated { get; set; }
public abstract class usrIsIntegrated : IBqlField { }
}
And added RowSelected events which should, in theory, be setting the field to enabled:
public class SOInvoiceEntry_Extensions : PXGraphExtension<SOInvoiceEntry>
{
[PXOverride]
public void SOInvoice_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected baseMethod)
{
baseMethod?.Invoke(sender, e);
if (e.Row == null) return;
PXUIFieldAttribute.SetEnabled<ARRegisterExt.usrIsIntegrated>(sender, e.Row, true);
}
}
However the field remains readonly on closed invoices. I've tested this on the ARInvoiceEntry graph, and exposed that to the api, and it works fine. I've been testing different methods of setting the field as enabled, but no luck so far.
Any help would be awesome.
Thanks
Issue was caused by an automation step on the SOInvoiceEntry screen setting the ARInvoice table as disabled, which was overriding the logic I was adding.
I was asked to make what I thought would be a very simple customization, hide the Promised On field on the PO Order Entry page. I opened the PO301000 screen in the customization editor, highlighted Promised On, clicked Attributes and clicked Override on Screen Level. I changed the resulting code on POOrderEntry to:
namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
#region Event Handlers
[PXDBDate()]
[PXDefault(typeof(POOrder.orderDate), PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Promised On", Visibility = PXUIVisibility.Visible, Visible = false)]
protected virtual void POOrder_ExpectedDate_CacheAttached(PXCache cache)
{
}
#endregion
}
}
To my surprise, it did not work, the Promised On field is still visible and I do not know why. The version is 18.100.0062.
It looks like there is a RowSelected event in POOrderEntry that sets the visibility based on if it is a blanket PO. Since this is later in the chain of events it overrides the CacheAttached event.
You can get what you want by adding your own RowSelected event. Here's an example.
protected void POOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
PXUIFieldAttribute.SetVisible<POOrder.expectedDate>(cache, null, false);
}
GeorgeM use the code below. The trick is to call baseMethod before making changes to the visible state of the field.
namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
[PXOverride]
protected virtual void POOrder_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected baseMethod)
{
baseMethod(cache, e);
PXUIFieldAttribute.SetVisible<POOrder.expectedDate>(cache, null, false);
}
}
}
I want to execute some code (to change the shipment date) upon the 'Confirm Shipment' action on the Shipments screen (SO302000).
I was thinking that this would be the way to do it:
public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
{
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder)
{
Base.ConfirmShipment(docgraph, shiporder);
//Add my code to do something here...
}
}
When I try this, I get a shipment counter error. Is there a better way to do this?
From a similar case:
How to add custom business logic to Acumatica framework's Actions?
public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
{
public PXAction<SOShipment> action;
[PXButton]
[PXUIField(DisplayName = "Actions", MapEnableRights = PXCacheRights.Select)]
protected IEnumerable Action(PXAdapter adapter
,[PXIntList(new int[] { 1 }
,new string[] { "Confirm Shipment" })
,PXInt] int? actionID)
{
//actionID = 1 means the Confirm Shipment action was the one invoked
if (actionID == 1)
{
Base.Document.Current.ShipDate = Base.Accessinfo.BusinessDate;
Base.Document.Update(Base.Document.Current);
}
//calls the basic action that was invoked
return Base.action.Press(adapter);
}
}