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 Unit Test

Acumatica unit test

Hello readers of mine blog.

Today I want to share with everybody who wants to make unit test of Acumatica how I achieved it.

For unit testing I use NUnit. In order to start my work with Acumatica Unit testing I wrote the following class:

    [TestFixture]
    public class CATranEntryExtTest
    {
        [Test]
        public void TestAutonumber()
        {
            var gr = PXGraph.CreateInstance<CATranEntry>();
        }
    }

Now with help of Resharper let's start debugging:

And here we go, the first error message:

PX.Data.PXProviderException : Provider cannot be instantiated.

   at PX.Data.PXDatabase.get_Provider() in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Database\Provider.cs: line 388

   at PX.Data.PXDatabase.GetSlot(String key, Type[] tables) in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Database\Provider.cs: line 802

   at PX.Data.PXGraph.a(Type A_0) in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Graph\Graph.cs: line 2684

   at PX.Data.PXGraph.CreateInstance(Type graphType) in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Graph\Graph.cs: line 112

   at PX.Data.PXGraph.CreateInstance() in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Graph\Graph.cs: line 57

So, it means we need to add some connection string to the site.  How to add it exactly? What proper way? I tried two next options:

1.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <remove name="ProjectX" />
    <add name="ProjectX" providerName="System.Data.SqlClient" connectionString="Data Source=DIO222\DIO195;Initial Catalog=Ac20140117;Integrated Security=False;User ID=sa;Password=1234" />
  </connectionStrings>
</configuration>



This way also:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionString value="Data Source=DIO222\DIO195;Initial Catalog=Ac20140117;Integrated Security=False;User ID=sa;Password=1234"></connectionString>
</configuration>

and if you suppose, that error message changed, you are wrong. It didn't go away.

Then I addressed support of Acumatica, and here is the answer:

 you just need this config. That is not necessary to create and use real database. You just need connectionString specified.

In case if with answer you know how to add connectionString to app.config for unit test and it will work, let me congratulate you. For me you are genious. Sadly to admit, I'm not. After a while, I decided to do crazy idea - copy/paste web.config into App.config. Imagine scale of my surprise when I noticed, that error went away!!!!!!

Now I got the next error message:

PX.Data.PXNotLoggedInException : You are not currently logged in.

Do you have any idea how to log in? 

In order to understand this idea lets go to Login.aspx.cs, maybe we can locate there something. For example method NormalLogin:

    private void NormalLogin(string[] companies)
    {
        if (companies != null && companies.Length == 1)
        {
            cmbCompany.Items.Clear();
            cmbCompany.Items.Add(companies[0]);
        }

        string loginText = txtUser.Text.Trim();
        string userName = PXDatabase.Companies.Length > 0 ? loginText + "@" +
            (cmbCompany.SelectedIndex != -1 ? cmbCompany.SelectedItem.Value : PXDatabase.Companies[0]) : loginText;

        if (!PXLogin.LoginUser(ref userName, txtPass.Text))
        {
            // we will change password during next round-trip
            PXContext.Session.SetString("ChangingPassword", txtPass.Text);

            DisablingUserPassword();
            EnablingChangingPassword();

            this.Master.Message = string.Empty;
        }
        else
        {
            PXLogin.InitUserEnvironment(userName, cmbLang.SelectedValue);
        }
    }

I'm considered about mehtod PXLogin.LoginUser. Lets use reflector in order to look there:

 

using (PXLoginScope pxLoginScope = new PXLoginScope(userName, new string[0]))using (PXLoginScope pxLoginScope = new PXLoginScope(userName, new string[0]))

I just think what can mean PXLoginScope. But maybe name is self-explanatory. Some scope where some login considered as working?

Lets write code similar to what reflector showed:

[Test]
public void TestAutonumber()
{
     using (var pxLoginScope = new PXLoginScope("someuserName", new string[0]))
     {
          var gr = PXGraph.CreateInstance<CATranEntry>();
     }
}

and now error message is 

PX.Data.PXUndefinedCompanyException : Unable determine proper company id for the request.

At least we can see, that error message changes during our thinking process :). 

All other conclusions were built on this code:

        MembershipUser membershipUser = (MembershipUser) null;
        try
        {
          if (Membership.ValidateUser(pxLoginScope.UserName, password))
          {
            membershipUser = Membership.GetUser(pxLoginScope.UserName);
            if (membershipUser != null)
            {
              pxLoginScope.UserName = membershipUser.UserName;
              userName = PXContext.PXIdentity.User.Identity.Name;
              if (pxLoginScope.CompanyName != null)
              {
                string[] rolesForUser = System.Web.Security.Roles.GetRolesForUser(pxLoginScope.UserName);
                if (rolesForUser == null || rolesForUser.Length == 0)
                  throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                  {
                    (object) pxLoginScope.CompanyName
                  });
                else if (!Enumerable.Contains<string>((IEnumerable<string>) PXDatabase.AvailableCompanies, pxLoginScope.CompanyName))
                  throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                  {
                    (object) pxLoginScope.CompanyName
                  });
              }
              if (PXLogin.c(pxLoginScope.UserName))
                return false;
              PXLogin.a(pxLoginScope.UserName, false);
              PXLogin.SetBranchID(pxLoginScope.UserName, pxLoginScope.CompanyName, pxLoginScope.Branch);
              PXSessionContextFactory.AuthenticateRequest();
              PXLicenseHelper.OnAuthenticate();
              return true;
            }

The function which has name a if to trust to reflector just updates some info in audit journal, and updates some info in db, which IMHO is not usable for unit test.

So, code, which I use now for initiating Unit test now looks like this:

    [TestFixture]
    public class CATranEntryExtTest
    {
        [Test]
        public void TestAutonumber()
        {
            string userName = "some user name in db";
            using (var pxLoginScope = new PXLoginScope(userName, new string[0]))
            {
                var membershipUser = (MembershipUser) null;
                // Membership.ValidateUser(pxLoginScope.UserName, "123");

                membershipUser = Membership.GetUser(pxLoginScope.UserName);
                if (membershipUser != null)
                {
                    pxLoginScope.UserName = membershipUser.UserName;
                    userName = PXContext.PXIdentity.User.Identity.Name;
                    if (pxLoginScope.CompanyName != null)
                    {
                        string[] rolesForUser = System.Web.Security.Roles.GetRolesForUser(pxLoginScope.UserName);
                        if (rolesForUser == null || rolesForUser.Length == 0)
                            throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                                {
                                    (object) pxLoginScope.CompanyName
                                });
                        else if (
                            !Enumerable.Contains<string>((IEnumerable<string>) PXDatabase.AvailableCompanies,
                                                         pxLoginScope.CompanyName))
                            throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                                {
                                    (object) pxLoginScope.CompanyName
                                });
                    }
                    PXLogin.SetBranchID(pxLoginScope.UserName, pxLoginScope.CompanyName, pxLoginScope.Branch);
                    var gr = PXGraph.CreateInstance<CATranEntry>();
                }
            }
          }
    }

At the end of execution gr looks like this:

Lets continue our way of unit testing for creating instance of our extension. This can be achieved via following way:

var accountsManager = gr.GetExtension<CATranEntryExt>();

Screenshot shows that we created instance of extension successfully:

Now I can test methods, which are inside of the extension CATranEntryExt.

I think it's enough for this article. If you have any comments, requests, wishes, critics, you are wormly welcome to express them.

Acumatica Unit Test

 

Hello readers of mine blog.

Today I want to share with everybody who wants to make unit test of Acumatica how I achieved it.

For unit testing I use NUnit. In order to start my work with Acumatica Unit testing I wrote the following class:

    [TestFixture]
    public class CATranEntryExtTest
    {
        [Test]
        public void TestAutonumber()
        {
            var gr = PXGraph.CreateInstance<CATranEntry>();
        }
    }

Now with help of Resharper let's start debugging.

And here we go, the first error message:

PX.Data.PXProviderException : Provider cannot be instantiated.

   at PX.Data.PXDatabase.get_Provider() in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Database\Provider.cs: line 388

   at PX.Data.PXDatabase.GetSlot(String key, Type[] tables) in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Database\Provider.cs: line 802

   at PX.Data.PXGraph.a(Type A_0) in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Graph\Graph.cs: line 2684

   at PX.Data.PXGraph.CreateInstance(Type graphType) in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Graph\Graph.cs: line 112

   at PX.Data.PXGraph.CreateInstance() in c:\Builders\4_10-2013_12_16-23_17_15-Full\Scripts\BuildTemp\NetTools\PX.Data\Graph\Graph.cs: line 57

So, it means we need to add some connection string to the site.  How to add it exactly? What proper way? I tried two next options:

1.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <remove name="ProjectX" />
    <add name="ProjectX" providerName="System.Data.SqlClient" connectionString="Data Source=DIO222\DIO195;Initial Catalog=Ac20140117;Integrated Security=False;User ID=sa;Password=1234" />
  </connectionStrings>
</configuration>



This way also:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionString value="Data Source=DIO222\DIO195;Initial Catalog=Ac20140117;Integrated Security=False;User ID=sa;Password=1234"></connectionString>
</configuration>

and if you suppose, that error message changed, you are wrong. It didn't go away.

Then I addressed support of Acumatica, and here is the answer:

 you just need this config. That is not necessary to create and use real database. You just need connectionString specified.

In case if with answer you know how to add connectionString to app.config for unit test and it will work, let me congratulate you. For me you are genious. Sadly to admit, I'm not. After a while, I decided to do crazy idea - copy/paste web.config into App.config. Imagine scale of my surprise when I noticed, that error went away!!!!!!

Now I got the next error message:

PX.Data.PXNotLoggedInException : You are not currently logged in.

Do you have any idea how to log in? 

In order to understand this idea lets go to Login.aspx.cs, maybe we can locate there something. For example method NormalLogin:

    private void NormalLogin(string[] companies)
    {
        if (companies != null && companies.Length == 1)
        {
            cmbCompany.Items.Clear();
            cmbCompany.Items.Add(companies[0]);
        }

        string loginText = txtUser.Text.Trim();
        string userName = PXDatabase.Companies.Length > 0 ? loginText + "@" +
            (cmbCompany.SelectedIndex != -1 ? cmbCompany.SelectedItem.Value : PXDatabase.Companies[0]) : loginText;

        if (!PXLogin.LoginUser(ref userName, txtPass.Text))
        {
            // we will change password during next round-trip
            PXContext.Session.SetString("ChangingPassword", txtPass.Text);

            DisablingUserPassword();
            EnablingChangingPassword();

            this.Master.Message = string.Empty;
        }
        else
        {
            PXLogin.InitUserEnvironment(userName, cmbLang.SelectedValue);
        }
    }

I'm considered about mehtod PXLogin.LoginUser. Lets use reflector in order to look there:

using (PXLoginScope pxLoginScope = new PXLoginScope(userName, new string[0]))using (PXLoginScope pxLoginScope = new PXLoginScope(userName, new string[0]))

I just think what can mean PXLoginScope. But maybe name is self-explanatory. Some scope where some login considered as working?

Lets write code similar to what reflector showed:

[Test]
public void TestAutonumber()
{
     using (var pxLoginScope = new PXLoginScope("someuserName", new string[0]))
     {
          var gr = PXGraph.CreateInstance<CATranEntry>();
     }
}

and now error message is 

PX.Data.PXUndefinedCompanyException : Unable determine proper company id for the request.

At least we can see, that error message changes during our thinking process :). 

All other conclusions were built on this code:

        MembershipUser membershipUser = (MembershipUser) null;
        try
        {
          if (Membership.ValidateUser(pxLoginScope.UserName, password))
          {
            membershipUser = Membership.GetUser(pxLoginScope.UserName);
            if (membershipUser != null)
            {
              pxLoginScope.UserName = membershipUser.UserName;
              userName = PXContext.PXIdentity.User.Identity.Name;
              if (pxLoginScope.CompanyName != null)
              {
                string[] rolesForUser = System.Web.Security.Roles.GetRolesForUser(pxLoginScope.UserName);
                if (rolesForUser == null || rolesForUser.Length == 0)
                  throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                  {
                    (object) pxLoginScope.CompanyName
                  });
                else if (!Enumerable.Contains<string>((IEnumerable<string>) PXDatabase.AvailableCompanies, pxLoginScope.CompanyName))
                  throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                  {
                    (object) pxLoginScope.CompanyName
                  });
              }
              if (PXLogin.c(pxLoginScope.UserName))
                return false;
              PXLogin.a(pxLoginScope.UserName, false);
              PXLogin.SetBranchID(pxLoginScope.UserName, pxLoginScope.CompanyName, pxLoginScope.Branch);
              PXSessionContextFactory.AuthenticateRequest();
              PXLicenseHelper.OnAuthenticate();
              return true;
            }

The function which has name a if to trust to reflector just updates some info in audit journal, and updates some info in db, which IMHO is not usable for unit test.

So, code, which I use now for initiating Unit test now looks like this:

    [TestFixture]
    public class CATranEntryExtTest
    {
        [Test]
        public void TestAutonumber()
        {
            string userName = "some user name in db";
            using (var pxLoginScope = new PXLoginScope(userName, new string[0]))
            {
                var membershipUser = (MembershipUser) null;
                // Membership.ValidateUser(pxLoginScope.UserName, "123");

                membershipUser = Membership.GetUser(pxLoginScope.UserName);
                if (membershipUser != null)
                {
                    pxLoginScope.UserName = membershipUser.UserName;
                    userName = PXContext.PXIdentity.User.Identity.Name;
                    if (pxLoginScope.CompanyName != null)
                    {
                        string[] rolesForUser = System.Web.Security.Roles.GetRolesForUser(pxLoginScope.UserName);
                        if (rolesForUser == null || rolesForUser.Length == 0)
                            throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                                {
                                    (object) pxLoginScope.CompanyName
                                });
                        else if (
                            !Enumerable.Contains<string>((IEnumerable<string>) PXDatabase.AvailableCompanies,
                                                         pxLoginScope.CompanyName))
                            throw new PXException("You are not allowed to login to the company {0}.", new object[1]
                                {
                                    (object) pxLoginScope.CompanyName
                                });
                    }
                    PXLogin.SetBranchID(pxLoginScope.UserName, pxLoginScope.CompanyName, pxLoginScope.Branch);
                    var gr = PXGraph.CreateInstance<CATranEntry>();
                }
            }
          }
    }

At the end of execution gr looks like this:

Lets continue our way of unit testing for creating instance of our extension. This can be achieved via following way:

var accountsManager = gr.GetExtension<CATranEntryExt>();

Screenshot shows that we created instance of extension successfully:

Now I can test methods, which are inside of the extension CATranEntryExt.

I think it's enough for this article. If you have any comments, requests, wishes, critics, you are wormly welcome to express them.

14 Comments

  • Steven said 

    Acumatica is horrible. It's just bad.

  • docotor said 

    Partially agree with you, it has a lot of surprises :). But from my experience with ERP, all of big ERPs had surprises. Starting from Micrsofot Dynamics, SAP. All of them require to be good developer, which can critically apply what he finds in documentation

  • Tim Rodman said

    ERP products definitely aren't "one size fits all". Acumatica isn't for everyone, but I think it can be a good fit for a lot of companies.

    Of course, most of the headaches associated with ERP implementations aren't even related to the specific ERP product chosen:
    http://panorama-consulting.com/who-needs-help-managing-an-erp-implementation/

    So I'm sure that Acumatica become the scapegoat for some failed ERP implementations, but it's the same with every ERP product.

  • docotor said 

    Tim, I can't say better then you. I just want to add that depending from task or set of tasks company or person can need totally different product. For somebody will be enough nopcommerce, for somebody just simple web site.

  • Ray Ban 5226 Kolor 2034 said 

    Please dont think Im just trying to copy you, but I really like the formatof this site. Could you let me know which theme are you using? Or was it custom made?

  • docotor said 

    Hi Ray Ban 5226 Kolor 2034,
    I'm using Orchard, Classig Blog Them

  • Buy Ray Ban Glasses Online In Pakistan said 

    Please, can you Mail me and tell me few more thinks about this, I am really fan of your bloggets solved properly asap.

  • docotor said 

    http://www.orchard.org/

  • anonymous said 

    I really like your writing style, excellent info

  • chaussures said 

    This actually answered my problem, thanks!

  • Tony said 

    Hi again, great article about starting a unit testing in Acumatica, I tried to apply it to my test project but it fails =(
    it says "Test 'M:---.---.UnitTests.MyFirstTestClass.TestAutonumber' failed:
    The type initializer for 'PX.Data.PXCache`1' threw an exception."
    Not sure what I'm missing here (I set an valid user and uncommented the line "Membership.ValidateUser..." and added the password of that user). Thanks in advance.

    -Regards.

  • docotor said 

    Hi Tony, mentioned error message I seen, when passwords were hashed. Maybe you have the same. If you wish, I can send you source code of my test project.

  • Tony said 

    Well, in my db the passwords are not hashed... =/
    In visual Studio I had to add some references because they were not set by default (maybe some reference in particular I'm missing?). I will appreciate if you send to my email (____) your source code, thanks in advance.

    Keep with the great blog and feedback... =)

  • docotor said 

    Just send you with additional comments

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.

 

 

Copy Entry Types Via Web Services In Acumatica From One Instance Into Another

Hello everybody.

Today I want to share how to copy Entty Types items in acumaticca from one instance into another instance.

The first step was to create import export settings in both instances of acumatica as described in acumatica manual similar to this screenshot:

The second step was to create project, which I decided to make as windows forms application with the following input fields:

For the button click at entry types write the following:

           var context = new ImportEt.Screen
                {
                    CookieContainer = new CookieContainer(), AllowAutoRedirect = true, EnableDecompression = true, Timeout = 1000000, Url = txtFrom.Text
                };

           var lgRes = context.Login(txtUserName.Text, txtPassword.Text);
           if (lgRes.Code == ErrorCode.OK)
           {
                var ca203000 = context.CA203000GetSchema();
                context.CA203000Clear();


                var export = context.CA203000Export(
                    new Command[]
                        {
                            ca203000.EntryType.EntryTypeID, ca203000.EntryType.DisbReceipt, ca203000.EntryType.EntryTypeDescription, ca203000.EntryType.Module, 
ca203000.EntryType.BusinessAccount, ca203000.EntryType.DefaultOffsetAccount, ca203000.EntryType.UseForPaymentsReclassification,
ca203000.EntryType.ReclassificationAccount, ca203000.EntryType.DeductFromPayment }, null, 0, false, false); context.Url = txtTo.Text; var lgRes2 = context.Login(txtUserName.Text, txtPassword.Text); if (lgRes2.Code == ErrorCode.OK) { ca203000 = context.CA203000GetSchema(); context.CA203000Clear(); foreach (var et in export) { var ca203000ImportResults = context.CA203000Submit( new Command[] { new Value { Value = et[0], LinkedCommand = ca203000.EntryType.EntryTypeID}, new Value { Value = et[1], LinkedCommand = ca203000.EntryType.DisbReceipt }, new Value { Value = et[2], LinkedCommand = ca203000.EntryType.EntryTypeDescription }, new Value { Value = et[3], LinkedCommand = ca203000.EntryType.Module }, new Value { Value = et[4], LinkedCommand = ca203000.EntryType.BusinessAccount }, new Value { Value = et[5], LinkedCommand = ca203000.EntryType.DefaultOffsetAccount }, new Value { Value = et[6], LinkedCommand = ca203000.EntryType.UseForPaymentsReclassification }, new Value { Value = et[7], LinkedCommand = ca203000.EntryType.ReclassificationAccount }, new Value { Value = et[8], LinkedCommand = ca203000.EntryType.DeductFromPayment }, ca203000.Actions.Save }); } } }

 

All activities in Acumatica are done via interface context, whic is of type screen. 

As for me, the easiest way to get some data is via command "screenID" + export. In my code you can see construction CA203000Export. Inside of it you can point to id of screen, data of which you want to receive. For example CA203000Export.

The simplest way to send something to acumatica another instance is function "screen id" + "Submit". In my code you can see method CA203000Submit. Fields Value is self-explanatory as for me. The most important and hard to understand for me was LinkedCommand. It can be name of the field. That means values has to be putted into a field. It can be action name to push on and etc. 

Another important facet of mentioned code is Actions.Save. If it is not mentioned, than code will post data to web services, but they wil not be saved.

 

Autonumbering In Acumatica

 

Today I want to share with you how I implemented autonumbering feature in acumatica for page CA304000.

My task originally was the following: add autonumbering feature to the "Document Ref" field with following rules:

  a. step of incrementing is 1

  b. length of field should be six characters. For example 000001, 000002, ... ,  000223,  001024, ..., and so on

First of all I want to state that my way of adding much simpler then "canonical" ( according to acumatica manuals ) way of adding autonumbering.  If you wish to use standard way you should accomplish so many steps that I should admit that my brain wasn't able to boil them in one project. 

Instead of this I used the following steps.

1. In the page CA304000 I found class, which provides data for the page. It looks like this:

<px:PXDataSource ID="ds" runat="server" Visible="True" Width="100%" PrimaryView="CAAdjRecords" TypeName="PX.Objects.CA.CATranEntry">

2. Created extention of class in the following way:

public class CATranEntryExt : PXGraphExtension<CATranEntry>
    {

3. Located method which returns list of records for the page CA304000, it was the method: CAAdjRecords.

4. According to rules of acumatica, if I want to modify behaviour of method CAAdjRecords I should implement method caadjrecords.

5. 

protected virtual IEnumerable caadjrecords()
        {

6. Implemented method which digs in DB, and returns needed number in string format:

protected string GetExtRefNbr()
        {
            var maxNbr = 1;
            foreach (var cAddjRec in PXSelect<CAAdj>.Select(Base, new byte[0]))
            {
                var extRefNbr = ((CAAdj) cAddjRec).ExtRefNbr;
                int curNbr = 0;
                if (int.TryParse(extRefNbr, out curNbr))
                {
                    maxNbr = curNbr + 1;
                }
            }
            var result = maxNbr.ToString(CultureInfo.InvariantCulture).PadLeft(defaultLength, '0');
            return result;
        }

7. Used GetExtRefNbr in the method caadjrecords in the following way:

protected virtual IEnumerable caadjrecords()
        {
            var res = new List<CAAdj>();
            var availableCashAccounts = GetAvailableCashAccounts();

            foreach (
                var doc in
                    PXSelect<CAAdj, Where<CAAdj.draft, Equal<False>>>.Select(Base, new byte[0]))
            {
                
                if (((CAAdj)doc).RefNbr.Contains("NEW"))
                {
                    ((CAAdj) doc).ExtRefNbr = GetExtRefNbr();
                }
                    
            }
            return res;
        }

8. Enjoyed results:

the field Document Ref.: was inserted automatically.

4 Comments

  • Angie Osorno said

    Hi,

    It's me, again hahaha

    I read your articule

    I read your article but I get it ... in my case I have a custom screen that I want to generate the automatic numerical value, but I do not know how.

    could you it teach me how you do?

  • docotor said 

    Describe a bit more what kind of autonumbering you need?

  • angie said 

    Hi,


    I have selector that it have to search registers about your numbering

    for example, how invoice screen it do...

    I sent an email to you

  • docotor said 

    I can't say that I understood what you mean.

 

Acumatica Active Directory

 

Hello,

today I want to share just simple record of how to join acumatica and your Active Directory.

For example you have the following data:

Active directory url:LDAP://RT1:389

User name yura_zale@dot.com, password: 123

For cases like this you need the following record in your web.config file:

<activeDirectory enabled="true" path="RT1:389" user="dot\yura_zale" password="123" />

 

Acumatica Certificate

 

Hello everybody,

this will be the first post in December. I want to boast that I got T101 certificate from acumatica univercity which proves that I'm certified developer for acumatica!!!!

you can download it from  Download

The screenshot of it: