I have to adjust how an action works. I know that I cannot adjust the code that runs the action itself, so is there any way to execute extra code when a specific action has been executed?
You simply declare the Action in your extension the same as the base action to "override"
Here is an example overriding the View Source Document action on GL Journal Entry:
public class JournalEntryMyExtension : PXGraphExtension<JournalEntry>
{
public PXAction<Batch> viewDocument;
[PXLookupButton]
[PXUIField(DisplayName = "View Source Document", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
public virtual IEnumerable ViewDocument(PXAdapter adapter)
{
// Logic Before Base Action
Base.viewDocument.Press(adapter);
// Logic After Base Action
return adapter.Get();
}
}
Here is the action direct from the base graph for comparison:
public PXAction<Batch> viewDocument;
[PXUIField(DisplayName = Messages.ViewSourceDocument, MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
[PXLookupButton()]
public virtual IEnumerable ViewDocument(PXAdapter adapter)
{
if (this.GLTranModuleBatNbr.Current != null)
{
GLTran tran = (GLTran) this.GLTranModuleBatNbr.Current;
OpenDocumentByTran(tran, BatchModule.Current);
}
return adapter.Get();
}
Related
I have the following code to override the "Email Purchase Order" action on the PO entry screen.
The code compiles and the message is displayed, but after selecting Yes Or No the message is displayed again and again until I click the X. Any idea what would cause that?
public delegate IEnumerable NotificationDelegate(PXAdapter adapter, String notificationCD);
[PXOverride]
public IEnumerable Notification(PXAdapter adapter, String notificationCD, NotificationDelegate baseMethod)
{
if(Base.Document.Ask("Are you sure you want to Email the PO?", MessageButtons.YesNo)
!= WebDialogResult.Yes) return adapter.Get();
return baseMethod(adapter, notificationCD);
}
UPDATE:
Here's my latest attempt, that's still not working. The code compiles, but I never get the message box. Added a trace message to confirm it's hitting the code:
public PXAction<POOrder> notification;
[PXUIField(DisplayName = "Notifications", Visible = false)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntryF)]
protected virtual IEnumerable Notification(PXAdapter adapter,
[PXString] string notificationCD)
{
PXTrace.WriteInformation("Reached Notification Action - Notification CD = " + notificationCD + '|');
if (notificationCD == "PURCHASE ORDER")
{
PXTrace.WriteInformation("Notification Action - If reached");
if(Base.Document.Ask("Are you sure you want to Email the PO?", MessageButtons.YesNo)
!= WebDialogResult.Yes) return adapter.Get();
}
return Base.notification.Press(adapter);
}
This happens if the message dialog request is in a place where the framework cant handle a message box.
Try overriding the action itself (21R1):
public PXAction<POOrder> emailPurchaseOrder;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Email Purchase Order", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
public virtual IEnumerable EmailPurchaseOrder(
PXAdapter adapter,
[PXString]
string notificationCD = null)
{
if(Base.Document.Ask("Are you sure you want to Email the PO?", MessageButtons.YesNo)
!= WebDialogResult.Yes) return adapter.Get();
return Base.emailPurchaseOrder.Press(adapter);
}
Or for 20R2
public PXAction<POOrder> notification;
[PXUIField(DisplayName = "Notifications", Visible = false)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntryF)]
protected virtual IEnumerable Notification(PXAdapter adapter,
[PXString] string notificationCD)
{
if (notificationCD == "EM")
{
if(Base.Document.Ask("Are you sure you want to Email the PO?", MessageButtons.YesNo)
!= WebDialogResult.Yes) return adapter.Get();
}
return Base.emailPurchaseOrder.Press(adapter);
}
I would like to see the code behind the grid actions button. let say buttons in the grid sectoin of Bills and Adjustment Screen are marked with orange boxes.
I would like to see how the code is configured behind the buttons.
Where can I find the file or code in the Acumatica website folder?
Especially I want code behind the "ADD SUBCONTRACT" button.
The code for the buttons/actions looks like it comes from the construction edition found in PX.Objects.CN.Subcontracts.AP.GraphExtensions.ApInvoiceEntryAddSubcontractsExtension (PX.Objects.CN.dll)
Snippets of related code:
[PXButton]
[PXUIField(DisplayName = "Add Subcontracts", FieldClass = "DISTR", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
public virtual IEnumerable addSubcontracts(PXAdapter adapter)
{
this.Base.checkTaxCalcMode();
if (!this.ShouldAddSubcontracts())
return adapter.Get();
this.Base.updateTaxCalcMode();
return this.addSubcontract(adapter);
}
[PXButton]
[PXUIField(DisplayName = "Add Subcontract", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false)]
public virtual IEnumerable addSubcontract(PXAdapter adapter)
{
return ApInvoiceEntryAddSubcontractsExtension.AddLines(new Func<PXAdapter, IEnumerable>(this.Base1.AddPOOrder2), adapter);
}
[PXButton]
[PXUIField(DisplayName = "Add Subcontract Line", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
public virtual IEnumerable addSubcontractLines(PXAdapter adapter)
{
this.Base.checkTaxCalcMode();
return this.ShouldAddSubcontractLines() ? this.addSubcontractLine(adapter) : adapter.Get();
}
[PXButton]
[PXUIField(DisplayName = "Add Subcontract Line", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false)]
public virtual IEnumerable addSubcontractLine(PXAdapter adapter)
{
return ApInvoiceEntryAddSubcontractsExtension.AddLines(new Func<PXAdapter, IEnumerable>(this.Base2.AddPOOrderLine2), adapter);
}
private static IEnumerable AddLines(
Func<PXAdapter, IEnumerable> addLine,
PXAdapter adapter)
{
try
{
return addLine(adapter);
}
catch (PXException ex) when (ex.MessageNoPrefix == "Failed to add one or more lines from the PO order. Please check the Trace for details.")
{
throw new Exception("SC Error: Failed to add one or more lines from the Subcontract. Please check the Trace for details.");
}
}
Looking at this code we can see it will use AddPOOrder2 from PX.Objects.PO.GraphExtensions.APInvoiceSmartPanel.AddPOOrderExtension from PX.Objects.dll
This code is found in the source availabine in Acumatica as:
[PXUIField(DisplayName = Messages.AddPOOrder, MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false)]
[PXLookupButton]
[APMigrationModeDependentActionRestriction(
restrictInMigrationMode: true,
restrictForRegularDocumentInMigrationMode: true,
restrictForUnreleasedMigratedDocumentInNormalMode: true)]
public virtual IEnumerable AddPOOrder2(PXAdapter adapter)
{
bool isInvoice = (Base.Document.Current.DocType == APDocType.Invoice),
isPrepayment = (Base.Document.Current.DocType == APDocType.Prepayment);
if (Base.Document.Current != null &&
isInvoice &&
Base.Document.Current.Released == false &&
Base.Document.Current.Prebooked == false)
{
List<POOrder> orders = poorderslist.Cache.Updated.RowCast<POOrder>().Where(rc => rc.Selected == true).ToList();
foreach (POOrder rc in orders)
{
Base.InvoicePOOrder(rc, false);
}
Base.AttachPrepayment(orders);
}
return adapter.Get();
}
The Base call here is referring to APInvoiceEntry
when you decompile the PX.Objects.dll file we can find code for "ADD PO"
PX.Objects.PO.GraphExtensions.APInvoiceSmartPanel.AddPOOrderExtension
but, I need code for ADD Subcontracts
If I have an Action button added on a Graph, how can I programmatically control whether it is enabled or disabled? For example, if I want to disable the button, related to a particular field in my Main DAC, how should I do that?
Within the DACs row selected you can call on your action SetEnabled to indicate if the button is enabled or not.
Example:
protected virtual void MyDac_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
myButtonAction.SetEnabled(true /*false*/);
}
public PXAction<MyDac> myButtonAction;
[PXUIField(DisplayName = "My Button", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select, Visible = false)]
[PXButton]
public virtual IEnumerable MyButtonAction(PXAdapter adapter)
{
reteurn adapter.Get();
}
I have to copy the custom field values from opportunity to sales order while converting the opportunity to sales order.
I have come across a sample code to pass custom field from sales order to shipment and I have tried to use the code for overriding the “create sales order” action.
The following code snippet I have used in OpportunityMaint extension class
public PXAction action;
[PXButton]
[PXUIField(DisplayName="Actions",MapEnableRights=PXCacheRights.Select,MapViewRights=PXCacheRights.Select)]
protected IEnumerable Action( PXAdapter adapter,
[PXIntList(new int[] {1,2,3}, new string[] {"Create Account","Create Sales order","Create Invoice"}),PXInt]
int? actionId,
[PXString]
string ActionName)
{
if(actionId == 2)
{
// Implement So Order row insert handler
}
return Base.Action.Press(adapter);
}
The piece of code is not triggering.
Looking forward for better solution to implement this option
Regards,
R.Muralidharan
You will need to override the CreateSalesOrder action. Below is a snippet of code where I had to push the opportunity down to the sales order.
public class OpportunityMaint_Extension : PXGraphExtension<OpportunityMaint>
{
public PXAction<CROpportunity> createSalesOrder;
[PXUIField(DisplayName = Messages.CreateSalesOrder, MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Select)]
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntry)]
public virtual IEnumerable CreateSalesOrder(PXAdapter adapter)
{
PXGraph.InstanceCreated.AddHandler<SOOrderEntry>((graph) =>
{
graph.RowInserted.AddHandler<SOOrder>((cache, args) =>
{
var soOrder = (SOOrder)args.Row;
var soOrderExt = PXCache<SOOrder>.GetExtension<SOOrderExt>(soOrder);
foreach (CROpportunity opportunity in adapter.Get())
{
soOrderExt.UsrOpportunityID = opportunity.OpportunityID;
}
});
});
return Base.createSalesOrder.Press(adapter);
}
}
Hi I am trying to extend the ARPaymentEntry graph so I can do some extra stuff when the user releases the payment.
I have extended the paymententry graph and copied the Release action over like so
public PXAction<ARPayment> release;
[PXUIField(DisplayName = "Release", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXProcessButton]
public virtual IEnumerable Release(PXAdapter adapter)
{
PXCache cache = Base.Document.Cache;
List<ARRegister> list = new List<ARRegister>();
foreach (ARPayment ardoc in adapter.Get<ARPayment>())
{
if (!(bool)ardoc.Hold)
{
cache.Update(ardoc);
list.Add(ardoc);
}
}
if (list.Count == 0)
{
throw new PXException(Messages.Document_Status_Invalid);
}
Base.Save.Press();
PXLongOperation.StartOperation(this, delegate()
{
if (SyncPaymentToRex(list))
{
ARDocumentRelease.ReleaseDoc(list, false);
}
});
return list;
}
If you look at the PXLongOperation I have a my own method I want to pass before it goes and releases the document.
Now this works for me but there is no user feedback on the screen (e.g. the controls arent disabled, no processing icon appears while its performing the operation etc) and also the screen doesnt reload, I have to manually reload the page before I can see the payment has been release etc
Can I get some help so I can get the page updating and reacting like it usually does on release but with my code in there as well?
Try this
public PXAction<ARPayment> release;
[PXUIField(DisplayName = "Release", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXProcessButton]
[PXOverride]
public virtual IEnumerable Release(PXAdapter adapter)
{
PXCache cache = Base.Document.Cache;
List<ARRegister> list = new List<ARRegister>();
foreach (ARPayment ardoc in adapter.Get<ARPayment>())
{
if (!(bool)ardoc.Hold)
{
cache.Update(ardoc);
list.Add(ardoc);
}
}
if (list.Count == 0)
{
throw new PXException(Messages.Document_Status_Invalid);
}
Base.Save.Press();
PXLongOperation.StartOperation(this.Base, delegate()
{
if (SyncPaymentToRex(list))
{
ARDocumentRelease.ReleaseDoc(list, false);
}
});
return list;
}