How To Use F Bql View Instead Of Pxselect

 

Hello everybody,

today I want to leave a short note on how to use F-BQL version of PXSelect in Acumatica.

In past it was common to have this line of code in your graph:

public PXSelect<Student1> Students;

In new F-BQL introduced new construction, SeleftFrom. Proper way of using it is this:

public SelectFrom<Student2>.View Students;

Take notice of suffix .View. Without that suffix you'll not get proper F-BQL view. And Acuminator will give you this warning:

So if to summarize, don't forget to add suffix .View 

How To Download Dac Schema Browser

 

Hello everybody,

here is just short post on how to download DAC Schema browser which I recently opensourced.

You'll need two steps:

1. Navigate in your browser to link https://github.com/YuriyZaletskyy/DacSchemaBrowser 2. Click on Star as displayed on screenshot (this is optional step):

       4. Right mouse click AcumaticaTablesFixed19x100x0122.zip

       5. Save customization wherever you wish

       6. Publish on your local instance

That particular file is intended for Acumatica version 2019 R1 build 0122, but it should work on higher versions as well. Later on I'll add lower versions as well.

How To Get List Of All Acumatica Tables

 

Hello everybody,

today I want to share single line of code, which I found recently while digging Acumatica source code with reflector. Sometime you may need to know if there is some or antoher Acumatica table available. For example if you create some customization plugin. How to find out if there is some table? You can use following line of code for this purpose:

using PX.Api.Soap.Screen;

............

var acumaticaTables = ServiceManager.Tables;

Variable acumaticaTables will have a list of Acumatica tables.

Configuration Error For Acumatica T100 Training

 

Hello everybody,

once upon a time Acumatica requires for certified developers to pass over certification again. 

As obedient person I decided to install T100 sample application over Acumatica Framework Configuration ( don't mix with Acumatica ERP Configuration ). Then I navigated to just installed application, and here is what I've seen:

Server Error in '/T100a' Application.


Configuration Error

Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: The connection string name is missing for the MySqlSiteMapProvider

Source Error:

Line 283:    <siteMap>
Line 284:      <providers>
Line 285:        <add name="MySqlSiteMapProvider" type="MySql.Web.SiteMap.MySqlSiteMapProvider, MySql.Web, Version=8.0.13.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" connectionStringName="LocalMySqlServer" applicationName="/" />
Line 286:      </providers>
Line 287:    </siteMap>

Source File: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config    Line: 285


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.3282.0

 

 

Very puzzling honestly speaking. You've just installed something, and right from the start it doesn't work. 

After some Research I have found, that following some additions should be added to node siteMap section providers:

			<siteMap enabled="true" defaultProvider="PXDatabaseSiteMapProvider">
				<providers>
			            <remove name="MySqlSiteMapProvider" /> <!-- add this line --> 
			            <remove name="PXWikiProvider" />

 

After those additions I was able to open Training sample T100.

 

How To Call Action Cancel In Acumatica

 

Hello everybody,

Today I want to leave a short notice on how to call Cancel button of Acumatica from inside C# code:

graph.Clear();

That is it, Clear method is binded to button Cancel in Acumatica. Besides that Clear method will reload current data record from database and rolls back changes of Cache objects. 

Pxuirequired Attribute Usage In Acumatica

 

Hello everybody,

today I want to say a bit more about usage of attribute PXUIRequired as previous article on my blog wasn't very easy to follow by some of my readers.

Take a look on presented code sample:

public class sOOrderType : Constant<string>
{
	public const string SOOrderType = "SO";
	public sOOrderType() : base(SOOrderType)
	{	
	}
}
 
public class SOOrderExt : PXCacheExtension<SOOrder>
{
	[PXMergeAttributes(Method = MergeMethod.Append)]
	[PXDefault]
	[PXUIRequired(typeof(Where<SOOrder.orderTypeEqual<sOOrderType>>))]
	public virtual string CustomerOrderNbr { getset; }
}

As you can see, besides attribute PXUIRequired it has declaration of constant value "SO". With that declaration before class you may get validation only for SO Order type "SO".

And now as you see on screenshot, field Customer Order got it's star. Take notice that color of that star is also differnet, it become red.

One more point which I want to underline, attribute PXUIRequired will work in connection with PXDefault attriubute. Without PXDefault attribute you'll get another error message, so as as summary, use PXUIRequired attribute with PXDefault.

 

Acumatica Customization Without Acumatica GUI

 

Hello.

Today I want to share some information about Acumatica customization.

Suppose, you want to change your pages not via Acumatica UI, but via Visual Studio. Reasons why you can have such desire can be the following:

1. Visual Studio is faster then Acumatica UI

2. You can put your changes under source control

3. You can easily exchange changes with your co-workers

Let's say you have following situation.

1. You need to make changes to pages ar301000.aspx and  pm301000.aspx and pm304000.aspx.

2. You need to add new page AP508000.aspx.

3. You want to include dll, which is named DS.dll.

In order to do this you'll need the following.

1. Create in your Acumatica instance folder CstPublished

2. Inside created folder create folders pages_ar, pages_pm

3. Copy/Paste into folder pages_ar page ar301000.aspx and into pages_pm pages  pm301000.aspx and pm304000.aspx.

4. Create new page AP508000.aspx in folder AP

5. Build your dll file

6. Create following file: project.xml, with the following records:

<Customization level="0" description="">
    <File AppRelativePath="CstPublished\pages_ar\ar301000.aspx" FileID="0849bd3b-c4ce-473e-8c82-c567112aa96b" />
    <File AppRelativePath="CstPublished\pages_ar\ar301000.aspx.cs" FileID="302c4089-6046-4a17-8411-1023315f5535" />
    <File AppRelativePath="Pages\AP\AP508000.aspx" FileID="b9e88968-7f36-4cfc-9383-caed8363c269" />
    <File AppRelativePath="Pages\AP\AP508000.aspx.cs" FileID="a1ce1918-f569-4ced-8a03-b5571dc26abb" />
    <File AppRelativePath="CstPublished\pages_pm\pm301000.aspx" FileID="8c174bf0-3143-4a86-83e9-c82704c9297a" />
    <File AppRelativePath="CstPublished\pages_pm\pm301000.aspx.cs" FileID="c435350a-89dc-455c-a9cb-6356987b2889" />
    <File AppRelativePath="CstPublished\pages_pm\pm304000.aspx" FileID="65b4f056-859f-463c-99cc-32a9cde11c7d" />
    <File AppRelativePath="CstPublished\pages_pm\pm304000.aspx.cs" FileID="46b0d39b-ba12-486a-be7f-6058a37cdca1" />
</Customization>

7. Create folder with the following structure:

   7.1 Folder CstPublished which has inside of it folders pages_ar and pages_pm. And pages_ar has all ar files, and pages_pm has changes related to pm pages

   7.2 Folder Pages, which has inside of it folder AP, and AP inside of it has AP508000.aspx and AP508000.aspx.cs files

   7.3 Put into folder file project.xml

8. Zip it and your deployment is ready.

Some pitfalls which I faced.

1. xml file should be named project.xml

2. FileId is guid, and each FileID should be unique.

3. All file and folder names shouldn't be capital. Not Pages_pm but pages_pm. And not CstPublished\pages_pm\PM304000.aspx but CstPublished\pages_pm\pm304000.aspx 

4. If you find other surprises with customization let me know.

 

11 Comments

  • mazia said 

    Hi
    Do you provide development support to partners?

  • docotor said 

    Hello Mazia,
    for free to some degree yes. And for money definitely yes :)

  • Tony said 

    Hi, I got some questions:

    1) Is there something else to do after adding the file project.xml (I zip it as you said in the /CstPublished folder with the name project.zip)? is this correct or it should go in a sub folder?

    2) The .dll also goes in /CstPublished or in a especific subfolder?

    3) I got embed SQL querys in the project.xml, It will be executed doing this? o I'll have to run in appart.

    The thing is that I added both files "project.xml" and the zipped "project.zip" and in the menu is not showing the pages menu (sitemap), I wonder if it's needed some kind of refresh to get the changes.

    I'm working with Acumatica version 4.20.0935

    Thanks for your help,
    Regards.

  • docotor said 

    Hello Tony,
    Inside the folder for customization following structure should be:
    Three folders: a) "Bin", b) "CstPublished", c) "Pages" and file project.xml.
    1. If you putted file project.xml into CstPublished folder, then move it one folder higher in the hierarchy.
    2. The .dll file goes to folder bin.
    3. It's possible to embed sql into customization, but I personally use two different files ( I mean customization file and project.sql which has all db changes )

  • docotor said

    I attached screenshot of my customization. Let me know if you'll need something else

  • Tony said 

    Hi again, and thanks for your reply It was very helpful. I had issues inserting the dll but I didnt notice that in the project.xml example was missing (I thought It was there xD).

    I have another question, those GUID for the FileID how are obtained? I'm working with powershell and I can't see a way to get those GUID corresponding for each file.

    Thanks...

  • docotor said 

    It can be any new guid, which is not mentioned in project. I used http://createguid.com web site. In case of powershell I can propose either to read from mentioned web site, or as another option to make some simple program which will generate for you guids

  • Fernando said 

    Hi Docotor!

    I have a question somehow related to this thread.
    Is it possible to include a ZIP file in the Projet.xml and then extract its content? Let me explain further:

    <File AppRelativePath="(...)\files.ZIP" FileID="0849bd3b-c4ce-473e-8c82-c567112aa96b" />

    We are facing difficulties in terms of time and path length while publishing our customization projects, so we thought that if we could just copy the ZIP file and then execute a command that would extract its content, then we could solve both problems at once. Is this feasible?

    Thanks for your help :)

  • docotor said 

    I don't think that it's possible. Actually I don't know. I just can propose you workaround. In your destination Acumatica instance locate folder CstPublished, and inside of it put your modified pages. Then you'll not need to include modified aspx pages into zip file. Just keep in mind naming conventions. In CstPublished should be ar301000 not AR301000. As far as I know Acumatica engine will make analysis of this folder and will consider them as active. If to speak about your pages which you made completely by yourself you can put them into Acumatica directory straight away. I also assume that you can put in Bin folder compiled version of your dll.

  • Ronan Masangcay said 

    I need to code on my local machine using Visual Studio (VS) VS2013 but will deploy the DLL on another machine that has an Acumatica ERP instance. Can I code in VS2013 in my PC and see the Acumatica objects (particularly, Data Providers) in my VS2013; my PC has Acumatica Framework already.

    Please let me know how

    TY

  • docotor said 

    You can code locally on your VS2013 and then you'll need to put dll and pages into Acumatica customization and then publish it at your Acumatica instance.

 

Screen Numbering In Acumatica

 

Hello everybody.

Today I want in short share screen numering in Acumatica.

Let's say we have screen number like this: xx.yy.zz.tt

in that case

yy is screen sequential number

zz is screen type: 10 - setup, 20 - Maintenance, 30 - data entry, 40 - inquiry, 50 - processing, 60 - reports.

tt is sub screen sequential number

1 Comment

  • maillot france 2014 said 

    I am really thankful to the owner of this site who has shared this wonderful post at at this place.

Acumatica Security

 

Hello,

this post is dedicated to understanding how security in Acumatica works. If to be precisive security of accounts. 

Let's say you need in some way filter accounts for some user according to configuration at row level security screen ( GL104000 ).

In my case I had following records in database which correspondent to the following numbers:

Relation group mask : 16; 0; 0; 0

User group mask: 159; 96; 0; 0

Account group mask: 16; 0; 0; 0

How to join them? They are joined not by separated table, which has relations between groups and accounts or groups and users, but with usage of bit mask. It's very effective way to join and is much faster then holding adta in db. But the most complicated from viewpoint of understanding. Lets convert already mentioned numbers into bit masks:

Relation group mask :

00010000; 00000000; 00000000; 00000000

User group mask:

10011111; 11000000; 00000000; 00000000

Account group mask:

00010000; 00000000; 00000000; 00000000

From the bit mask you can notice that there is common bit between first byte in Account group mask and User group mask. Also there is common bit between "User group mask" and Relation group mask which means that user belongs to the group, and account belongs to the group. In order to work with them I wrote the following code:

 public List<Account> GetAvailableCashAccounts()
 {
     var result = new List<Account>();
     var userID = PXAccess.GetUserID();
     var user = GetUsers().First(u => u.PKID == userID);
     var allAccounts = GetAccounts();
     var groups = GetGroups();
     foreach (var account in allAccounts)
     {
           foreach (var relationGroup in groups)
           {
             for (var i = 0; i < relationGroup.GroupMask.Length && i < account.GroupMask.Length; i++)
               {
                  if ((relationGroup.GroupMask[i] & account.GroupMask[i]) == 0) continue;
                  if ((account.GroupMask[i] & user.GroupMask[i]) == 0 || result.Find(a => a.AccountCD.Equals(account.AccountCD)) != null) continue;
                  result.Add(account);
                 }
             }
       }
       return result;
}

As usually all your comments are welcomed, considered, premoderated, banned :)

Autonumbering In Acumatica Second Way

 

In one of my previous posts I described how to add autonumbering to acumatica. Described method will work pretty well, if you don't have any pop-ups which also need to have autonumbering. In case if you have such pop-ups, then it is different story.

My next assignment on the job was to add autonumbering to the screen "Fund Transfers" which is marked as "CA301000" to the field Document ref at three places:

There is a saying, that one image is better then thousands of words :).

Here is example of my code for OutExtRefNbr:

        protected void CATransfer_OutExtRefNbr_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
        {
            var row = e.Row as CATransfer;
            if (row == null)
                return;
            var refNbr = "001224";
            e.NewValue = refNbr;
        }

 

If you have a question why on earth code below needed:

                   var row = e.Row as "Class for which we will provide extension";

                   if( row == null )

                      return;

the answer is simple: because Acumatica for some unknown reason calls method FieldDefaulting and for mysterious reason passes into e.Row null. If you have any idea why, you are welcome to share them. I don't have and just used workaround ( don't say it to my boss ).

 

The second part of my task was to add some value to pop-up window. That can be done via the following template:

public class "Class Extention name" : PXGraphExtension<"Class for which we will provide extension">

{

      protected void "Class for which we will provide extension"_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)

      {

             Base.AddFilter.Current."Field in pop-up" = "some default value";

            Base.AddFilter.Update(Base.AddFilter.Current);

       }

"Field in pop-up" you can find also in Design mode of Acumatica forms.

Here is fragment of my source code for changes:

protected void CATransfer_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
     Base.AddFilter.Current.ExtRefNbr = "0012224";
     Base.AddFilter.Update(Base.AddFilter.Current);
}

In case if you have any comments, ideas don't hesitate to share them via comments line.

There is a saying, that one image is better then thousands of words :).

Here is example of my code for OutExtRefNbr:

        protected void CATransfer_OutExtRefNbr_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
        {
            var row = e.Row as CATransfer;
            if (row == null)
                return;
            var refNbr = "001224";
            e.NewValue = refNbr;
        }

 

If you have a question why on earth code below needed:

                   var row = e.Row as "Class for which we will provide extension";

                   if( row == null )

                      return;

the answer is simple: because Acumatica for some unknown reason calls method FieldDefaulting and for mysterious reason passes into e.Row null. If you have any idea why, you are welcome to share them. I don't have and just used workaround ( don't say it to my boss ).

 

The second part of my task was to add some value to pop-up window. That can be done via the following template:

public class "Class Extention name" : PXGraphExtension<"Class for which we will provide extension">

{

protected void "Class for which we will provide extension"_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
      Base.AddFilter.Current."Field in pop-up" = "some default value";
      Base.AddFilter.Update(Base.AddFilter.Current);
}

"Field in pop-up" you can find also in Design mode of Acumatica forms.

Here is fragment of my source code for changes:

protected void CATransfer_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
     Base.AddFilter.Current.ExtRefNbr = "0012224";
     Base.AddFilter.Update(Base.AddFilter.Current);
}

In case if you have any comments, ideas don't hesitate to share them via comments line.