Thursday, 16 March 2017

Launch Multiple Reports with one Exception

Hi All

Today I want to share with you an example how you can launch multiple unrelated reports with one single PXReportRequiredException.

PXReportRequiredException has a helper method - CombineReport(..), where you can pass multiple ReportRequiredExceptions and Acumatica will process them together.

Acumatica will extract each separate report from extension and can open it with following rules:

  • Print all report as a single PDF file - ex.SeparateWindows = false;
  • Open each separate report in a new tab - ex.SeparateWindows = true;

There same rule as with other Pop-ups we can open it with new tab, window or the same window as well - ex.Mode = PXBaseRedirectException.WindowMode.New;

Also note that you should pass report parameters to all reports separately.



Full Code Snippet:

Have a nice development!

Tuesday, 14 March 2017

Copy notes from AP/AR Invoice to GL Batch

Hi All,

Just want to share with you short example of how you can copy Notes and Files from AP/AR invoices directly to General Ledger Batch.

For archive it we are doing following steps:
  1. Define extension for (AP/AR)ReleaseProcess graph. Exactly this graph is responsible for releasing operation.
  2. On the Initialize method we are trying to subscribe on InstanceCreated event for JournalEntry graph, where we can catch exact graph instance used for saving batch. 
    1. InstanceCreated even is very useful for customization purposes. Here you can subscribe events and pass parameters between different graphs.
  3. Subscribe to ARRegister_BatchNbr_FieldUpdated to catch moment when batch is saved and linked to our invoice.
  4. Using graph and batch number we can find exact batch.
  5. Using PXNoteAttribute.CopyNoteAndFiles we can copy notes and files from one object to another.
Full Code Snippet:

Have a nice development!

Monday, 27 February 2017

Hide Action from Datasource

Hi All,

When you new create action in the PXGraphExtensions, it is automatically getting visible in in the data-source actions bar, even if you have not customized ASPX.
public class JournalEntry_Extension:PXGraphExtension<JournalEntry>
{
    public PXAction<PX.Objects.GL.BatchNewAction;  
    [PXButton(CommitChanges true)]
    [PXUIField(DisplayName "New Action")]
    protected void newAction()
    {
    }
}
It looks like here:

But if you want to hide that button, it is very easy to do it with Customization Browser. Just drag and drop button to the data-source in page editor:

Than just set the Name to your action name and Visible to false.

That is all. Now Action is not visible anymore.

Have a nice development!

Thursday, 23 February 2017

Customization and Source Control

Hi All,

I'm sure you know that Acumatica customization project is just a big XML file that has some links on external files. You can easily export ZIP archive with all linked files and store it on the file system. Unfortunately is not really good for tracking changes.

But do you know that Acumatica has very easy-to-use integration with source control where you can export project as set of text files? Let me show you how to use it:

As I said customization project is big zip file, but it can be split by items, that you can see using File -Edit Project Items menu:

All of these items we can export to some folder as a separate files, so it will be much easier to store them and track changes.
To export them click on Source Control -> Save To Folder

Monday, 20 February 2017

Override Static Method

Hi All,

Unfortunately sometimes during customization you may need to override some logic in static methods and that is really bad task, as it requires to copy a lot of code.
Here I will show you few examples that can give you idea how you can fix it.

In general there is no way to really override static method, the only one way how you can replace it's logic is just define a new one and replace all places where it is called.

3 different scenarios will be based on Acumatica Fixed Assets module:
  • Not so good - static method on event
    • AssetMaint.LiveUpdateMaskedSubs(PXGraph graph, PXCache facache, FALocationHistory lochist);
  • Bad - static method on dynamically subscribed event
    • AssetMaint.MakeSubID<MaskField, SubIDField>(PXCache sender, FixedAsset asset);
  • Very Bad - static method on Persist
    • AssetProces.TransferAsset(PXGraph graph, FixedAsset asset, FALocationHistory location, ref FARegister register);
Lets start:

Thursday, 9 February 2017

Multi-Company Reports

Hi All,

Today I want to share with you a way how you can print multi-company (multi-tenancy) reports.
You know that Acumatica tenants are completely separated and there is no way to make a report or generic inquiry for multiple tenants.

So first of all want to share with you the technical details - Acumatica stores all tenants in one database, but separate it by CompanyID column, that is a part of primary key. You can read more about it here.

Acumatica Framework automatically detects CompanyID column in the table and adds "WHERE CompanyID = {Something}" to every query. Unfortunately you cannot change anything here.
But good thing is - if you have table without CompanyID column, it will be also supported and Acumatica will work with that table as a global for all tenants.

So if we create a view without CompanyID column, we can use it for global reporting. The only one thing that lefts is to create a DAC for that view and use it in Acumatica.

However views and DACs are not really protected from updates - if you update Acumatica and there are changes in database, you have to recreate views and DACs.
So here I want to show you few tricks, how you can keep it update protected with minimum changes.

Welcome in the article for more details.

Monday, 6 February 2017

Dynamically Activate Extensions

Hi All,

Today I want to share with the way how you can enable and disable extensions dynamically.

You know that when you have published extension as a DLL or a Code file it will be automatically discovered by Acumatica Framework and used.
However there is a hidden way to stop Acumatica from usage of that extension. Do do that you just need add static method IsActive() to your extension.
  public class GL_Batch_Ext PXCacheExtension<PX.Objects.GL.Batch>
  {    
      public static bool IsActive()
      {
        return false;
      }
  }
Acumatica will automatically call that method by signature (you need to have correct name, public, static and return bool) and if it returns False, extensions will be ignored.
That works the same way for Graph and Cache extensions.
Also note, that if method rise an exception extension will be loaded any way.

Good thing about it that you really can decide dynamically what extension should be loaded based on database value or current company.So that is a way how you can have different business logic customization for different companies.

So in that example I have renamed one of fields on Journal Entry screen based on current company id:
Have a nice development!

Wednesday, 1 February 2017

Approval Workflow Customization

Hi Everyone,

Today I want to share with you one important point about customization of automation approval workflow.

Firs of all please read this article on Stack Overflow to understand how Acumatica Approval works.
But here I would take Purchase Orders screen as example, because there we already have automation workflow configured.

In the article below, you may notices that all approval logic is encapsulated into the special Data View - EPApprovalAutomation. On the Purchase Orders form it is designed like this:
[PXViewName(Messages.Approval)]
public EPApprovalAutomation<POOrder, POOrder.approved, POOrder.rejected, POOrder.hold, POSetupApproval> Approval;

EPApprovalAutomation is just a class with multiple virtual methods that you can override and customize. 
So we can create our own approval workflow and define it in the graph or graph extension.
public class MyAppprovalAutomation
: EPApprovalAutomation<POOrder, POOrder.approved, POOrder.rejected, POOrder.hold,
       POSetupApproval>
{ }

public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
       #region DataViews
       [PXViewName(Messages.Approval)]
       public MyApprovalAutomation Approval;
       #endregion
}

However, here we have one issue.

Thursday, 19 January 2017

Volume Based Prices In Contracts

Hi All,

Quite recently I have discovered that Acumatica Contracts Module support different types of prices agreements:

  • Fixed price - In this case you setup specific price (that can be standard or specially agreed) inside Contract Item
  • Volume Based Prices - In this case final price of one item will depend on customer usage, like a standard volume based prices in Acumatica.

Fixed Price

Fixed price is configured thought Contract Item
Than you can setup contract with this contract item and start to use it
When you bill contract and check invoice you can see that Acumatica use exact price from Contract Item.

You also can set-up extra usage price that can be bigger or lower, but only one level. But the problem is that you have only one level of different prices. That means that you cannot setup 3 or more different prices depend on usage.

Volume Based Prices
In case you want more flexible process you can try different setup approach. First of all we configure standard volume base prices (Remember that it is a separate feature that you should activate).
But then you should not include that idem in the contract itself.
You still can tract contract usage, however it will not be shown in the contract.
When you bill contract and issue invoices, system will get all used items and apply all standard prices and discount rules, so you will see that contracts have used your volume based prices.

Have a nice Configuration!

Tuesday, 10 January 2017

Manual Mass Notifications

Hi All,

Lets imagine scenario where you want to send multiple notifications about multiple documents from the system. It might be quite complicated if you decide to do it manually.
Today I want to show you one trick how you can trigger standard notification on multiple documents at once. For this task we will use Automation Notifications, Custom Field and Generic Inquiry.

My scenario would be to update my customers about quotes that are expiring soon. I want to review them before sending notifications, but do not want to do it one by one.

General idea is - to have a special not visible but editable field that will trigger notification. If we have field, that we can easily update it using Generic Inquiry Mass update operation.

Welcome in the article if you want to see configuration and testing steps.