I'd like to add a custom button to the header of the Bills and Adjustments screen that will contain custom actions in a dropdown, ala the 'Actions' button that's already there (I don't want to add these actions to the existing 'Actions' button - I want my own dropdown containing custom actions).
I know how to add actions to the existing 'Actions' button, but is there a way to do what I'm looking to do?
It is the same step just using your own drop button. You need to add your "Actions" button and then do the same steps to the other buttons to add them to your main drop down button.
Here is a quick example below. I created a MyDropMenu action button which all of my other buttons live under:
//within initialize or graph constructor...
MyDropMenu.AddMenuAction(MyAction1);
MyDropMenu.AddMenuAction(MyAction2);
MyDropMenu.AddMenuAction(MyAction3);
//...
public PXAction<PrimaryDac> MyDropMenu;
[PXUIField(DisplayName = "My Drop Menu", MapEnableRights = PXCacheRights.Select)]
[PXButton(MenuAutoOpen = true)]
protected IEnumerable myDropMenu(PXAdapter adapter)
{
return adapter.Get();
}
public PXAction<PrimaryDac> MyAction1;
[PXUIField(DisplayName = "My Action 1", MapEnableRights = PXCacheRights.Select)]
[PXButton]
protected IEnumerable myAction1(PXAdapter adapter)
{
return adapter.Get();
}
public PXAction<PrimaryDac> MyAction2;
[PXUIField(DisplayName = "My Action 2", MapEnableRights = PXCacheRights.Select)]
[PXButton]
protected IEnumerable myAction2(PXAdapter adapter)
{
return adapter.Get();
}
public PXAction<PrimaryDac> MyAction3;
[PXUIField(DisplayName = "My Action 3", MapEnableRights = PXCacheRights.Select)]
[PXButton]
protected IEnumerable myAction3(PXAdapter adapter)
{
return adapter.Get();
}
You also need to add the callback command for the drop menu action to the page like this...
<px:PXDSCallbackCommand Name="MyDropMenu" Visible="True" CommitChanges="true" StartNewGroup="true" ></px:PXDSCallbackCommand>
I tested this on a Sales Order Extension replacing PrimaryDac to SOOrder and shows up as:
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
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)
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();
}
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();
}