We are in to acumatica 20 r2 and when we publish the custom package, the default report menu print salesorder/quote option disappears.
We have custom reports which are added by overriding the initialize method of salesorderentry graph in my extension.
public override void Initialize()
{
base.Initialize();
base.Base.report.AddMenuAction(embroideryreport);
base.Base.report.AddMenuAction(embroiderysoreport);
base.Base.report.AddMenuAction(screenprintreport);
base.Base.report.AddMenuAction(screenprintsoreport);
}
I am not able to figure out the reason for missing report. I have upgraded the workflow to latest version and still having the issue.
UPDATE
I did not call base.Initialize() initially and since the default report is not coming, I thought it may be due to not invoking the base method.
I have tried bahaa-zantout suggestion and the base report is already tagged to the report menu and when I commented on the code in Initialize method for adding the report the default report appeared again under-report menu.
It looks like there is conflict in the workflow and I am not able to figure it out.
I have tried to add those report in the workflow action section and tagged them to Report and the entire report menu disappeared
Change you initialization method to....
public override void Initialize()
{
base.Base.report.AddMenuAction(embroideryreport);
base.Base.report.AddMenuAction(embroiderysoreport);
base.Base.report.AddMenuAction(screenprintreport);
base.Base.report.AddMenuAction(screenprintsoreport);
}
From Acumatica DEV documentation portal
You do not need to explicitly invoke the Initialize() method on the previous extension levels; these methods are called automatically. Invoking base.Initialize() makes no sense, because the base variable points to the base class, which is PXGraphExtension (not the base graph). The PXGraphExtension class defines Initialize() as an empty method.
You could attempt the following in attempt to restore the toolbar menu item.
Navigate to the Sales Order screen in the customization project
Go to the Actions
Locate the missing print options (ie. printSalesOrder) and place the Toolbar folder in the original folder in this case "Reports". If it doesn't work try moving to "Actions" and see if it appears.
See example screenshot.
I am not sure it is due to this statement or not but when I changed the following statement it fixed the issue
[PXButton(SpecialType = PXSpecialButtonType.ReportsFolder)]
to
[PXButton]
for Report action
public PXAction<SOOrder> embroideryreport;
[PXUIField(DisplayName = "Embroidery Production Report", MapEnableRights = PXCacheRights.Select)]
//[PXButton(SpecialType = PXSpecialButtonType.ReportsFolder)]
[PXButton]
Related
I am Unable to Open Cash Sale Screen in Customization Editor of Acumatica, after I have added a new tab control with a Grid inside. I have assigned a custom DataView in the data member property of the Grid Control.
It Gives up the following error "The Customization Project Must Be Published before the screen can be edited. Error : The View CommissionCalcView does not exist".
Here "CommissionCalcView" is the name of my custom view, and it is Present in ARCashSaleEntry Extension of my project.
My Code Goes here....
using COMMISSIONMAPPING;
using PX.Objects.AR.Standalone;
namespace PX.Objects.AR
{
public class ARCashSaleEntry_Extension : PXGraphExtension<ARCashSaleEntry>
{
public PXSelect<CommissionCalculation,
Where<CommissionCalculation.cashSaleDocType,
Equal<ARCashSale.docType>,
And<CommissionCalculation.cashSaleRefNbr,
Equal<ARCashSale.refNbr>>>> CommissionCalcView;
#region Event Handlers
#endregion
}
}
Error Image
I have experienced this many times as well. The problem for me tends to be an error in how I define fields in a DAC extension or in improperly defining the view in the form.
In this case, you have BQL that is trying to compare CommissionCalculation (table selected in the BQL) to ARCashSale (table not selected in the BQL). Try adding Current<> on the ARCashSale references in the view so that it pulls the current value from the cache for ARCashSale in the base graph.
using COMMISSIONMAPPING;
using PX.Objects.AR.Standalone;
namespace PX.Objects.AR
{
public class ARCashSaleEntry_Extension : PXGraphExtension<ARCashSaleEntry>
{
public PXSelect<CommissionCalculation,
Where<CommissionCalculation.cashSaleDocType,
Equal<Current<ARCashSale.docType>>,
And<CommissionCalculation.cashSaleRefNbr,
Equal<Current<ARCashSale.refNbr>>>>> CommissionCalcView;
#region Event Handlers
#endregion
}
}
This was an issue with the development process and missing dlls, i removed the dll from the bin folder of my website and removed any key fields from my DAC, and rebuilt the project,
The problem was resolved
Is it possible to display error in toolbar without using [PXProcessButton] and the delegate? I've overridden a Process Button in acumatica, but before it executes I have underlying codes to check a condition and fire an error if it find any.
There's not a lot of valid scenario where you have a PXProcessButton without a PXProcessing or PXFilteredProcessing data view. I would expect a PXButton to be used when there is no PXProcessing data view instead of a PXProcessButton.
With a PXProcessing view in the process screen you would do:
PXProcessing<DAC>.SetError(new PXException("Test));
There is no method that I know of that allows to directly set an error in the toolbar. You'll notice that these error are tied with a PXLongOperation. In the main toolbar you'll see the hourglass icon of the long operation and it can change to a success or error icon.
Process action does this but also Save action amongst others. Unless you require a long operation I would advise to avoid displaying error in the main toolbar because it's not a behavior found in the base Acumatica product.
That said you can replicate that functionality pretty much everywhere by throwing a PXExceptionfrom within a PXLongOperation inside an PXAction event handler like this:
public class SOOrderEntry_Extension : PXGraphExtension<SOOrderEntry>
{
public PXAction<SOOrder> test;
[PXUIField(DisplayName = "Test")]
[PXButton]
protected virtual IEnumerable Test(PXAdapter adapter)
{
PXLongOperation.StartOperation(Base, delegate {
throw new PXException("Test");
});
return adapter.Get();
}
}
I have created a new CREATE QUOTE button on Requisition screen that replace the standard button which located at Action menu. After trying to hide it on RQRequisition_RowSelected event, the button still appear and able to click when the requisition is on Pending Quote Status. Kindly need advice how to hide it.
Customized Requisition Screen
To hide or show an action button, you should redefine the Visible parameter of the PXUIField attribute for the button.
You can change attributes of an action button by using one of the following approaches:
Dynamically at run time, in the Initialize() method of the graph
extension
Statically, by overriding the action attributes in the
graph extension
To Hide an Action Button at Run Time
In the graph extension, add the following code.
public override void Initialize()
{
base.Initialize();
Base.MyAction.SetVisible(false);
}
In the added code, replace MyAction with the action name.
To Hide or Show an Action Button Statically
To override action attributes in a graph extension statically, you should declare both the graph member of the PXAction type and the delegate. You should attach a new set of attributes to the action delegate, declared within the graph extension. Also, you need to invoke the Press() method on the base graph action. Having redeclared the member of PXAction, you prevent the action delegate execution from infinite loops.
Explore the original action declaration and copy the declaration to the graph extension.
In the action declaration, set to false the Visible parameter of the PXUIField attribute, as the following code snippet shows.
...
[PXUIField(…, Visible = false)]
...
Replace the action delegate with the following code template.
public virtual IEnumerable myAction(PXAdapter adapter)
{
return Base.MyAction.Press(adapter);
}
In the code template, replace myAction and MyAction with the appropriate names.
In the template, redefine the action delegate arguments and return type according to the signature of the base action delegate.
If you have a customization that replaces an original action
declaration statically, after upgrading Acumatica ERP to a new
version, a new functionality of the same action may became
unavailable.
Also, if a callback command for the button is declared in the PXDataSource control, you can hide the button by customizing the ASPX code. To do this, in the Layout Editor, expand the PXDataSource control, select the appropriate PXDSCallbackCommand element, and set to False the Visible property of the element.
CREATE QUOTE button on the Requisition screen is implemented like a normal action in the RQRequisitionEntry BLC:
public class RQRequisitionEntry : PXGraph<RQRequisitionEntry>
{
...
public PXAction<RQRequisition> createQTOrder;
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntry)]
[PXUIField(DisplayName = Messages.CreateQuotation)]
public virtual IEnumerable CreateQTOrder(PXAdapter adapter)
{
...
}
...
}
However, CREATE QUOTE button is added into the Actions drop down via Automation Steps:
With that said, the best way to customize the CREATE QUOTE button is by re-declaring the action within the RQRequisitionEntry BLC extension following sample below. I would be happy to come up with a more specific sample, if you provide additional details regarding your request.
public class RQRequisitionEntryExt : PXGraphExtension<RQRequisitionEntry>
{
public PXAction<RQRequisition> createQTOrder;
[PXButton(ImageKey = PX.Web.UI.Sprite.Main.DataEntry)]
[PXUIField(DisplayName = RQ.Messages.CreateQuotation)]
public virtual IEnumerable CreateQTOrder(PXAdapter adapter)
{
return Base.createQTOrder.Press(adapter);
}
}
I'm trying to write some code for a customization with an action button, AddFollowUp to Leads. I want to:
update a custom field called UsrNextFollwup -> how do I access the custom field in the object?
I can update objects I find with PXSelect<> but how I can insert new objects? eg if I create Contact myContact=new Contact(); //set properties, etc -> how do I insert it?
How can I find the current user's ID? I can get the current lead from Contact curLead=Base.LeadCurrent.SelectSingle() but I also want something like #me function.
My code:
public class LeadMaint_Extension:PXGraphExtension<LeadMaint>
{
public PXAction<PX.Objects.CR.Contact> AddFollowUp;
public PXSelect<CRActivity> Task;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Add FollowUp")]
public void addFollowUp()
{
Contact curLead=Base.LeadCurrent.SelectSingle();
DateTime dueDate = DateTime.Now;
curLead.CreatedDateTime = dueDate.AddDays(14); //works great
curLead.UsrNextFollwup = dueDate.AddDays(14); //doesn't work
}
}
In Acumatica custom fields are declared via DAC extensions. To access the DAC extension object, you can use the following methods:
The GetExtension() generic method available for each DAC instance:
ContactExt contactExt = curLead.GetExtension<ContactExt>();
The GetExtension(object) generic method declared within the non-generic PXCache class
ContactExt contactExt = Base.LeadCurrent.Cache.GetExtension<ContactExt>(curLead);
or
ContactExt contactExt = Base.Caches[typeof(Contact)].GetExtension<ContactExt>(curLead);
The GetExtension(object) static generic method of the PXCache generic class
ContactExt contactExt = PXCache<Contact>.GetExtension<ContactExt>(curLead);
To insert, update or delete a DAC record, one should invoke Insert, Update or Delete method on appropriate PXCache instance (or a data view, which simply redirects the call to PXCache -> ShipmentLines.Insert(line) is an equivalent to ShipmentLines.Cache.Insert(line) statement). For instance, to insert a data record into the cache in code, you invoke the Insert() method of a data view as follows:
ShipmentLine line = new ShipmentLine();
line.ProductID = card.ProductID;
...
ShipmentLines.Insert(line);
Some application settings, such as BranchID, UserID and UserName are accessible via Accessinfo property of the PXGraph class. The Accessinfo property returns an instance of the AccessInfo DAC - AccessInfo.UserID will return ID for the current user. To access the Accessinfo property from a BLC extension, use Base.Accessinfo statement
Starting ver. 5 Acumatica introduced runtime compilation, which allowed to publish customizations without a mandatory restart of IIS app pool when there are no dlls included with any of currently applied customization projects. Before runtime compilation was released, customization manager created all code files in App_Code\Caches folder of the website. Asp.Net runtime takes care of any code files created in App_Code\Caches folder, immediately compiles them and restarts IIS app pool to also immediately bring all changes on your Acumatica website. The beauty of this approach is that all classes declared in any file located under App_Code\Caches folder, are available with VS IntelliSense and never highlighted with red underlines as potential issue. The only drawback - every time you make any change inside App_Code\Caches folder, IIS app pool restarts (same thing as if you re-compiled a dll located in Bin folder) and it takes some time for your website to reboot so you can test your changes.
With runtime compilation in place, Acumatica created all code files in App_RuntimeCode folder of the website. Now it's Acumatica's responsibility to compile all code files from App_RuntimeCode folder into an assembly and load it at runtime without a restart of IIS app pool. With this approach you don't need to wait for your website to reboot every time you make some changes in your customization. On the other hand, sometimes runtime complication doesn't always properly clear up what was done in your previous code files and time to time, it might be necessary to manually recycle app pool or restart IIS on your developer machine to make sure Acumatica loads only actual code from the App_RuntimeCode folder. Another drawback is lack of support by VS IntelliSense: all classes declared in any file located under App_RuntimeCode folder is never suggested by IntelliSense and always highlighted with red underlines as potential issue, though both yourself and Acumatica are confident, that everything is fine and all files will compile with mo issues.
To have all customization files automatically created in App_Code\Caches folder, just disable runtime compilation on your development website by adding following key to appSettings in web.config file:
<add key="UseRuntimeCompilation" value="false" />
I'm using the BTProgressHUD Xamarin component in an app that is built using MvvmCross. I'm currently working on the iOS version of the app. My ViewModels make several web service calls and expose an 'IsBusy' property, which the associated views are binding to, in order to show or hide the progress spinner. This is pretty much the way things are set up in the N=34 MvvmCross sample (https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/tree/master/N-34-Progress) as well.
The problem is that in some cases a ViewModel must automatically call a service as soon as it is created. I tried to make the call in the Start() function of the ViewModel, but I noticed that the BTProgressHUD spinner does not show up on top of the view. I suspect that the problem is that BTProgressHUD must be displayed only after a view has been made visible, and probably this is not the case when ViewModel.Start() runs.
Has anyone encountered this before? Is there a simple way to run code in the ViewModel after the view has been made visible?
Thanks.
Is there a simple way to run code in the ViewModel after the view has been made visible?
The N=42 video - http://slodge.blogspot.co.uk/2013/11/n42-is-my-viewmodel-visible-can-i-kill.html - introduces an IVisible interface that you can add to your ViewModel - it's your job to call this from your View - but this is easy to do on each platform. For example,, on iOS it is done using ViewDidAppear/ViewDidDisappear in https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/blob/master/N-42-Lifecycles/Lifecycle.Touch/Views/FirstView.cs
protected IVisible VisibleViewModel
{
get { return base.ViewModel as IVisible; }
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
VisibleViewModel.IsVisible(true);
}
public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
VisibleViewModel.IsVisible(false);
}