Intro
Copy pasting data in different software has became a must have quality of life functionality over the years. So, in Acumatica ERP there is of course a built-in mechanism for copy-pasting documents. However, since different documents have different business rules, copy-pasting functionality is not that straight forward and may be a little bit tricky at times. Let’s see how a developer can control the copy-paste behavior and troubleshoot it in case of incorrect behavior.
Functionality Description
First I’d like to quickly overview the Copy-paste functionality in Acumatica ERP. Copy paste button presents on many forms in the system. It usually looks like that:
Let’s see what each button does:
- Copy. Well, it’s just a copy button. It copies currently opened document to the current user session. If the user logs out, the copied data is erased.
- Paste. Allows a user to paste previously copied document. That button is not active if there is no copied data. It’s also important to note that the date is not pasted to the disabled fields.
- Save as Template. This button allows a user to save some document as a template and use it later to paste from that template. The template is saved to the database, so it persists until user explicitly deletes it. A user can save as many templates as they want. We’ll take a closer look at the template functionality later in this post.
- Reset to Default. That button is not present on majority of documents. It only appears on the documents that may be populated by the system during deployment. For instance, that button presents on Generic Inquiries form. The button allows a user to reset a document to its initial state. E.g. it resets a Generic Inquiry to the system default. If you’d like to know the technical details, the button redefaults the document to the state that is saved in the System Tenant (CompanyID=1 in the database).
- Import & Export as XML. Those buttons are not visible on most of the screens. However, on some system screens you can find them. The buttons allow to export copied data into an xml file and import it in a different instance of Acumatica ERP. One should be careful about versions compatibility though, as the xml structure of a document may vary from version to version. The section is visible if there is an xml file with Import/Export structure definition in the \App_Data\XmlExportDefinitions folder of the site. The name of the file with the structure definition must be equal to the screenID of the screen.
- Lastly, we have a section containing list of templates that are available for pasting.
Majority of these buttons are pretty obvious. However, the ‘Save as Template’ button needs a bit more detailed description.
When a user clicks the ‘Save as Template’ button, they are being redirected to a new form containing the template details.
On that form we see the screen where the template has been copied from, description of the template, and the list of copied values.
Usually, after getting to this form a user fills the description of the template and saves it. However, not everyone realizes that the template itself is actually editable. A user can change some values in the template, activate or deactivate some lines of copied data, even remove or add new portions of data manually.
Customizing Copy-Paste
Now let’s see what a developer can use to control the copy paste behavior.
First things first. How to add the Copy-Paste buttons on a custom form?
To add the Copy-paste menu a developer only needs to define a PXCopyPaste action in the graph or just derive the graph from PXGraph<TGraph, TPrimaryDAC>. If there is an xml schema definition in the App_Data\XmlExportDefinitions folder the ‘Import from XML’ and Export to XML’ buttons will also appear.
public class SomeGraph : PXGraph<SomeGraph> { public PXCopyPasteAction<SomeDAC> CopyPaste; //... } //or public class SomeGraph : PXGraph<SomeGraph, SomeDAC> { //... }
After adding the copy paste functionality to a form a developer may want to fine tune the behavior by disabling copy-pasting of some specific fields of views. For instance, when copy-pasting a payment it probably makes sense to not copy details of the related credit card transaction. In order to disable a field from being copied one can put a PXCopyPasteHiddenFields attribute on the view that the field belongs to. If the entire view should not be copied, there is a PXCopyPasteHiddenView attribute for that. Finally, if some event should not be executed in a graph when pasting a data, the logic in the event may be conditionally turned off with the help of IsCopyPasteContext falg. See the examples below.
public class SomeGraph : PXGraph<SomeGraph, SomeDAC> { [PXCopyPasteHiddenFields( typeof(SomeDAC.fieldThatShouldNotBeCopied), typeof(SomeDAC.anotherFieldThatShouldNotBeCopied))] public PXSelect<SomeDAC> ViewThatShouldBeCopied; [PXCopyPasteHiddenView] public PXSelect<OtherDAC> ViewThatShouldNotBeCopied; protected virtual void _(Events.RowInserted<SomeDAC> e) { if (!this.IsCopyPasteContext) { //some code that should not be triggered //during pasting of a document } } }
Troubleshooting
Sometimes a developer faces a situation where some field or view is not copy-pasted. To investigate the root cause of that behavior and fix it we need to clearly understand what exactly goes wrong. Usually the first step of any type of troubleshooting is decomposing the situation into smaller pieces. For copy-pasting that means that it is crucial to understand whether the field is not copied or if it is not pasted.
To understand that we can use previously mentioned Templates functionality. In the template we can clearly see what data has been copied. Thus, by clicking ‘Save as Template’ button and reviewing the data in the template a developer can determine which step of the process is not working as expected.
If the field is not copied, there may be several reasons for that:
- The field is not visible on the screen.
- The field is hidden from the copy process by PXCopyPasteHiddenView or PXCopyPasteHiddenFields attribute.
- There is some tricky code in one of the events in the graph. E.g. an event may change the field visibility dynamically and during copying the field becomes invisible for the copy process.
If the field is copied successfully but not pasted, there is a different set of possible root causes for that:
- The field is disabled when Pasting happens. The disabled fields are not populated by the Paste process.
- There is some data validation or defaulting logic in one of the events that overrides the field value.
I am looking to override the default behaviour when copying and pasting a Stock Item. It is not copying the ItemCost since upgrading from 22R2 to 23R2.
The code that I think is stopping that happening is in StockItemMaint.cs:
[PXCopyPasteHiddenFields(typeof(INItemCost.lastCost))]
public
SelectFrom.
Where<INItemCost.inventoryID.IsEqual.
And<INItemCost.curyID.IsEqual>>.
View ItemCosts;
Is there a way to override this to enable copying/pasting of the last cost value?