Friday, 23 September 2016

Custom Selector Attribute

Hi All,

Today I want to discuss with you a ways to define selectors and data for them.
Usually you define selectors like this:
[PXSelector(typeof(Search<Carrier.carrierID>))]

In this case system will automatically select value from database Carrier table and show list of Carrier IDs to user.
In this case you have 2 potential problems:

  • you should have a database table, otherwise you will see an error.
  • There is no way to dynamically change or adjust data that is returned to user
  • You can limited configurations to control selector behavior. 

To solve these problem Acumatica has a Custom Selector attributes:
public class CustomerPriceClassAttribute : PXCustomSelectorAttribute
{
    public CustomerPriceClassAttribute()
        : base(typeof(ARPriceClass.priceClassID))
    {
            this.DescriptionField = typeof(ARPriceClass.description);
    }
    protected virtual IEnumerable GetRecords()
    {
        foreach (ARPriceClass pc in PXSelect<ARPriceClass>.Select(this._Graph))
        {
            yield return pc;
        }
    }

}

In this case you see that you have simple attribute, that is really similar to the attribute for first example. Using GetRecords method you can create a custom BQL querry, select any data you want, apply any filter and return it as a IEnumberble collection.
In the user interface you will see exactly data provided by your custom query.

Monday, 19 September 2016

Make compilation of extension library faster

Hi All,

When you develop customization using Microsoft Visual Studio you may notice that compilation process (if you click F6 or Ctrl+Shift+B) is really long - you may wait for 5-10 minutes.

Usually this happens because system compiles full solution that contains DLL and also Web Site. Site has multiple pages that have aspx markup and must be transformed before compilation. But actually this process is required only for validation purpose and does not require for Acumatica functionality, as ASP.NET will compile page any way one more time when you open it in browser.
You may read more about it here.

So as it is optional compilation you may guess that it can be disabled. Just go to web site property pages and deactivate 2 configurations:

  • Build Web site as part of the solution
  • Before run startup page - no build.

After this your compilation process will take just few seconds instead of minutes. And it is absolutely save for your customization development.

But we still highly recommend you to do one full compilation and validation before releasing of final production version of customization to ensure that there is not errors on final pages.

Have a nice development!

Wednesday, 14 September 2016

Acumatica REST API

HI All,

With Acumatica 6 release you can find (and actually use) new type of API - Rest API.

Acumatica Rest API is based on Contract based API, so here you have some important points:

  • You need to use existing or custom endpoint be able to send API calls
  • Field and container is available for REST API only if it is defined in contract. But you may extend existing contracts.
  • With REST API you have the same set of commands that you have with Contract Based API.
  • Acumatica uses Json format for transfer data between client and server
  • You still have to maintain session and authentication cookies.

URL:
http://<InstanceName>/entity/<EndpointName>/<EndpointVersion>/<Entity>
Example: http://acumatica.com/entity/Default/6.00.001/StockItem

Ok, lest try to do some examples. Here I will show you how to call Acumatica REST commands from Browser. By using this approach you can easily test functionality and just feel, how does it work.

Thursday, 8 September 2016

Mass Processing using GI

Hi All,

Lets assume that you have multiple records where you need to mass execute some action or update multiple fields to the new value.
From the I100 Acumatica Integration Services Training course you may know that you can do it with Export or Import scenarios. Integration Scenarios are some sort of the small program inside your ERP where you can update multiple fields, calculate depended values, execute actions and so on.

But what if you want to have more control on records need to be updated. Some sort of semi-manual mass updating tool? In this case Generic Inquiry Mass Update feature can be more interesting and useful.

Lets try to use it.

Monday, 5 September 2016

Disable Discounts Calculation for API Calls

Hi All,

When you creating a multiple AR/SO documents with multiple lines through the API, you may have a nice trick to little-bit optimize system performance.

By default Acumatica business logic is optimized for entering data from UI, so all variables as taxes and discounts must be recalculated on each document line.
But during bulk load you actually can do it just once - before document save.

Here you have extension that will disable automatic discounts calculation if you loading data from API or Integration services.

public class SOOrderEntryExtension : PXGraphExtension<SOOrderEntry>
{
       [PXOverride]
       public virtual void RecalculateDiscounts(PXCache sender,
SOLine line, Action<PXCache, SOLine> del)
       {
              if (!Base.IsImport) del(sender, line);
       }

}

To calculate discounts before saving the record you can manually call RecalculateDiscounts Action from your code. Here is example for Screen-Based API.

List<Command> list = new List<Command>();
list.Add(new Value() { Value = "False", LinkedCommand =
schema.RecalculatePricesAndDiscounts.RecalcUnitPrices });
list.Add(new Value() { Value = "True", LinkedCommand =
schema.RecalculatePricesAndDiscounts.RecalcDiscounts });
list.Add(schema.Actions.ActionRecalculateDiscountsAction);
list.Add(schema.Actions.Save);
list.Add(schema.OrderSummary.OrderNbr);


Content[] result = screen.Submit(list.ToArray());

You can use the similar code for AR invoices as well.

Have a nice integration!

Thursday, 1 September 2016

Custom Integration Services Data Provider

Hi All,

Today I want to share with you one way how you can extend Acumatica data export/import providers or add a new one to integrate with new system.

To accomplish this task you need some development skills as creation of new provider require some code writing. But you can write this code with any possible way:
  • Visual Studio
  • Acumatica Customization browser
  • Notepad or any compatible application

To create a new provider you need create new class that will implement a IPXSYProvider interface:
public interface IPXSYProvider
{
       string ProviderName { get; }
       string DefaultFileExtension { get; }
       //Parameters
       PXSYParameter[] GetParameters();
       void SetParameters(PXSYParameter[] parameters);
       PXStringState[] GetParametersDefenition(); 
       //Schema
       string[] GetSchemaObjects();
       PXFieldState[] GetSchemaFields(string objectName);
       //Import/Export
       void Export(string objectName, PXSYTable table, bool breakOnError,                                    Action<SyProviderRowResult> callback);
       PXSYTable Import(string objectName, string[] fieldNames, PXSYFilterRow[] filters,                              string lastTimeStamp, PXSYSyncTypes syncType);
}

Monday, 29 August 2016

Restriction Groups Architecture

Hi All,

Today I want to share with you some technology information about how Acumatica Restriction groups works inside Acumatica.

For each group system assign one byte in the GroupMask Database column:
Group 1 - 0x8000 = 1000 0000 0000 0000
Group 2 - 0x4000 = 0100 0000 0000 0000
Group 3 - 0x2000 = 0010 0000 0000 0000
Group 4 - 0x1000 = 0001 0000 0000 0000
Group 5 - 0x0800 = 0000 1000 0000 0000
Group 6 - 0x0400 = 0000 0100 0000 0000
.....
and so on


Here you can see that Acumatica numbers groups using bytes. Each group - one unique byte.
To maintain correct security rights fore new and removed groups Acumatica cannot reuse bytes that are already used, that's why you cannot delete existing groups.
Actually it can be changed/reused technically, but it require to update each record in database, that may be quite long on big databases.

When you assign some item to some group it actually sets the flags in the group masks for the item: Lets assume vendor belongs to group 3 and group 6, than mask will be
0010 0100 0000 0000 = 0x2400
Note that we have "1" exactly on position of group where this record belongs.

You can see exactly this configuration based on demo data:
User interface configurations:
And database:

Users are also belongs to groups by the same rule. Than system search for interceptions between groups to which user and entity belongs and than calculate calculate assess rights.
Also do not forget that there are different types of groups that can calculate interception and access rights differently.

Have a nice configuration.

Wednesday, 24 August 2016

Configuring Batch Payments for Custom File Format

Hi All,

Today I want to share with you an configuration way for new bank format. Out of the box Acumatica supports: ACH and GIRO file types.

Support for bank files works through configuration of 3 different components

  1. Batch Payments - Process where multiple payments can be combined to one single document. Exactly this document will be exported to payment file.
  2. Export scenarios - To generate real file from document Acumatica uses export scenarios with special data provider. Scenario is uses as instruction and columns mapping between file and acumatica.
  3. Data Provider - Knows how to generate required file. For different payment standard you may need to create a different providers, but luckily it is highly customization.


Lets start with Batch Payments.
You can setup special payment method that will be configured as "batch payment".

Later you can generate Batch payment document that will combine one or several payments into one batch (Screen ID: AP305000)

If you click "Export" button on this screen, system will generate file and attach it to the current document. But the actual export will be done with export scenario, that you configure for Payment Method on previous image. Here you can see an export scenario that you can copy and customize for your own format.
As I already mention, scenarios are mostly mapping between Acumatica Batch Payment document and file format. You selecting Acumatica and File fields and sometimes can just change some fields using formulas and other data manipulations.

Now we are coming to Provider configuration. Each provider consists of 2 main parts: parameters and fields configuration. Parameters is mostly responsible on some small configurations of the result data format. Sometimes when it is complex to change configuration with single property, you can decide to create own provider.
In Acumatica we have 2 out of the box providers:

  1. ACH Provider - mostly responsible for generation fix-width file format. Also it may be used for files with strict requirements for block size.
  2. GIRO Provider - mostly responsible for generation flexible and less structured file with no limitations on block or line sizes.

File format is defined by schema file, which is a simple text file attached to provider.

Schema file contains:

  • Header/footer information. This is #01 number on the begin of line. Number defines the level of sub group. #01 - is header and footer, #02 can be a group of documents, #03 can be details. For the GIRO provider usually it is enough to have only 2 levels
  • Placeholders for dynamic fields from Acumatica - values like this {H2_Corporate_ID:30}. This field will be visible in Acumatica Export scenario and can be mapped with data. Fields can contain some formation options:
    • ":30" - means that field should be not more that 30 characters in length.
    • ":-10" - means that field value should aligned to right
    • "NotKey|FillOnEnd" - define calculation parameters, like in the reports.
      • NotKey - means that field should not define new group when field is changed
      • FillOnEnd - means that data should be calculated in the end
    • "=TotalCount" - some formulas that can do simple calculations
  • Simple text, that will me stored as is. In my example all character like this "|||||||||||||||" means just a simple text, that should be there in the end file. Of course there are some parameters that can be passed there, but in our continuations it can be empty.

There are some more parameters that can be used when required, but i think it is enough for overview.

You also can create a new provider and inherit it from the base one. For example i'm providing here some simple provide that add new functionality for calculation running total:

public class MyGIROProvider : GIROPaymentProvider
{
       public override string ProviderName
       {
              get return "MyGIROProvider"; }
       }

       private decimal RunningTotal;
       public decimal AppendToTotal(decimal aAmount)
       {
              this.RunningTotal += aAmount;
              return this.RunningTotal;
       }

}

This function (AppendToTotal) we actually can use from Export scenarios.

Also you may note some yellow warnings on Source Objects. This means that we are using Data View that exists in Graph object, but does not exists in the UI, so it is some sort of hidden view. It is totally OK for this scenario and sometimes may be useful for you as well.
The good think for you to know Acumatica Platform and Customization tools - it may help you a lot if you want to define new provider.

This is the actual payment file result of new reconfigured provider:

Have a nice configuration!

Friday, 19 August 2016

Extending Contract-Based API Default Endpoint

Hi All!

Today, I want to speak with you about Contract-Based Web Services API share with you new cool thing that is available in Acumatica 6 - Extensions of Contracts.

Using this feature you can reuse of all benefits of default endpoint that Acumatica provides you out of the box and just extend it with adding couple of fields.

OK, let me show you one simple example with 2 changes:
  • Adding one more entity to default endpoint. In my case it will be Country screen. Country is a standard table but the same way you can add all custom screens as well. 
  • Adding one more column to Journal Transactions grid. In my case I will add Inventory ID field, which is also standard field but it works perfectly for custom fields as well.

On our first step we need to create an extension on default endpoint. To do this you just need to select default, click "Extend Endpoint" buttons and provide name for new one.

When you do so, new Endpoint will be created and it will be inherited from default one. You can see that all inherited entities will be marked with arrow. Custom entities will be with no mark. 
So now you can add new screens and entities to your endpoint. I have created an entity for country screen.

You also can extend fields on any existing entity. I have selected Journal Entry screen, and have added a new row in the details grid.

If you check the services definition schema (WSDL schema), you will see that Acumatica merges all default and custom definitions into one schema.

That's all you need. Now we can use Visual Studio to define our integration code.

Provided code sample:
class Program
{
       static void Main(string[] args)
       {
              DefaultSoapClient client = new DefaultSoapClient();
              client.Login("admin", "123", null, null, null);
              foreach (Country cntr in client.GetList(new Country(), false))
              {
                      Console.WriteLine(cntr.CountryID);
              }

              JournalTransaction batch = client.Get(new JournalTransaction()
              {
                      Module = new StringValue() { Value = "IN" },
                      BatchNumber = new StringSearch() { Condition = 
StringCondition.Contains, Value = "00000046" } }
                      ) as JournalTransaction;

              Console.WriteLine(batch.BatchNumber.Value);
              foreach (JournalTransactionDetail tran in batch.Details)
              {
                      Console.WriteLine(tran.InventoryID);
              };
       }

}

Have a nice integration!

Monday, 15 August 2016

PXViewDetailsButton Attribute for better navigation

Hi All,

Today want to share with you one new way how you can define navigation in Acumatica version 5.3.
From T200 Acumatica Framework Fundamentalist you may know that if you want to map action to any cell in the grid and show it as link you need to define LineCommand:

<px:PXGridColumn DataField="ProductID" Width="140px" LinkCommand="ViewProduct" />

But to be able to use it, you should define action, action handler, throw appropriate exception, hide it in data source and so on. Quite log and boring.

In Acumatica 5.3 there is a PXViewDetailsButtonAttribute that can do all these things for you.

[PXViewDetailsButton(typeof(Contact),typeof(Select<Contact,
    Where<Contact.contactID, Equal<Current<CROpportunity.contactID>>>>))]
[PXViewDetailsButton(typeof(BAccount),typeof(Select<BAccount,
    Where<BAccount.ccbAccountIDEqual<Current<CROpportunity.customerID>>>>))]
public PXSelectReadonly<CROpportunit> Opportunities;

This attribute will do following:

  • Will add dynamic action with name <DataView_Name>_<DAC_Name>_ViewDetails. So in our example it will be Opportunities_BAccount_ViewDetails and Opportunities_Contact_ViewDetails.
  • Will add an action handler where it will search for required entity based on provided BQL and do redirect.
  • Will hide dynamic action in data sources.

So as the result you just can go to aspx file and use it!

<px:PXGridLevel DataMember="Opportunities">
       <Columns>
              <px:PXGridColumn DataField="OpportunityID" />
<px:PXGridColumn DataField="BAccount__AcctCD"
LinkCommand="Opportunities_BAccount_ViewDetails" />
              <px:PXGridColumn DataField="Contact__DisplayName"
LinkCommand="Opportunities_Contact_ViewDetails" />
       </Columns>

</px:PXGridLevel>

In the result you code is cleaner and the result is nicer.

Also note that you may have multiple PXViewDetailsButton attributes that will generate multiple buttons.
As an addition you can configure action behavior with attribute properties:

  • Custom action name by explicitly specifying it
  • Window open mode: popup or window
  • What to do when popup is closed - refresh data for example.

Have a nice Development!