Explore AX.com

Skip to content
  • Home
  • About Me
  • Questions?
  • X++ 101

Approve By Email

Approve your AX 2009 and 2012 Workflows direct from your inbox with Axnosis Email Approver. Works with Outlook, Blackberry, Android, iPad, iPhone etc...

Recent Posts

  • Saving Company Logo to file (X++)
  • Prevent AX Reports from Auto-Sending via Outlook Email
  • Allow non editable table fields to be modified via AIF.
  • Batch Job Updates – The Corresponding AOS Validation Failed
  • AX User 101 – Tips and Tricks for Using AX

Categories

  • AIF
  • AX2012
  • Client
  • Dynamics AX
  • Environment Management
  • Further Reading
  • Integration
  • Jobs
  • Model Management
  • Quick Tips
  • Role Centers
  • Security
  • SQL Scripts
  • SSRS
  • Training
  • Uncategorized
  • Workflow
  • X++

Archives

  • May 2018
  • February 2018
  • January 2018
  • January 2016
  • October 2015
  • September 2015
  • August 2015
  • July 2015
  • June 2015
  • May 2015
  • April 2015
  • March 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

About

Welcome to my blog, a place where I record my thoughts and discoveries as I explore the Dynamics AX landscape.

Subscribe to ExploreAX.com

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Online XPO Reader (Beta)

Online XPO Reader

Explore AX.com

Don’t only practice your art, but force your way into its secrets

Skip to content
  • Home
  • About Me
  • Questions?
  • X++ 101

Approve By Email

Approve your AX 2009 and 2012 Workflows direct from your inbox with Axnosis Email Approver. Works with Outlook, Blackberry, Android, iPad, iPhone etc...

Recent Posts

  • Saving Company Logo to file (X++)
  • Prevent AX Reports from Auto-Sending via Outlook Email
  • Allow non editable table fields to be modified via AIF.
  • Batch Job Updates – The Corresponding AOS Validation Failed
  • AX User 101 – Tips and Tricks for Using AX

Categories

  • AIF
  • AX2012
  • Client
  • Dynamics AX
  • Environment Management
  • Further Reading
  • Integration
  • Jobs
  • Model Management
  • Quick Tips
  • Role Centers
  • Security
  • SQL Scripts
  • SSRS
  • Training
  • Uncategorized
  • Workflow
  • X++

Archives

  • May 2018
  • February 2018
  • January 2018
  • January 2016
  • October 2015
  • September 2015
  • August 2015
  • July 2015
  • June 2015
  • May 2015
  • April 2015
  • March 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org

About

Welcome to my blog, a place where I record my thoughts and discoveries as I explore the Dynamics AX landscape.

Subscribe to ExploreAX.com

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Online XPO Reader (Beta)

Online XPO Reader

User Settings

1 Comment Posted on September 18, 2015 AX2012, Client, Dynamics AX, Quick Tips, X++

Share AX User Form Customizations Between Companies

One of the nifty features of Dynamics AX is to share form personalisations between user. To see how to do so check out Murray Fife’s article over here. However it seems that a distinct restriction is that you cannot effectively share personalisations between companies, even for the same user. This means that you need to perform the same setups for every form that you are working on.

I thought I would share with you today a quick customization that will assist allow you to copy your own customizations from one company to another or copy from a different user’s profile in another company to yours.

Our customization will make a modification to the “SysSetupForm” in AX. This is the form that is displayed when right clicking on a field in AX and clicking “Personalise”

In this post we will basically duplicate the “Retrieve from User” button to provide a “Retrieve from Alternate company” option in addition to the basic functionality. You could also simply customize the standard function as well.

Step 1. Create a new button

  • Navigate in the AOT to the forms node and find “SysSetupForm”
  • Expand the following nodes “SysSetupForm->Designs->Design->Tab:ControlTab->TabPage:LayoutTab-> Group:RightGrp -> ButtonGroup:MainBtnGroup.
  • Right click on ButtonGroup:MainBtnGroup, click “New Control -> Button”
  • Set the button’s “Text” property to “Retrieve from Company”

Step 2. Update button to display profiles from all users and companies

  • Right click on the method’s node of your button, click Override Method -> clicked
  • In the clicked method add the following line of code: element.loadFromUserAll(); 
  • Navigate to the methods node of the SysSetup form, right click and click “New Method”
  • Rename your new method to: loadFromUserAll
  • Modify this method’s code the following (this is basically a modified copy of the loadFromUser method to cater for cross company lookups)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void loadFromUserAll()
{
    SysLastValue sysLastValue;
    userId       userId;
    CompanyId    companyId;
    ;
    if (!loadFromUserMapAll)
    {
        loadFromUserMapAll     = new Map(Types::String, Types::String);
 
        while select sysLastValue
            group by UserId, Company
            where sysLastValue.Company      != this.lastValueDataAreaId()
               && sysLastValue.RecordType   == UtilElementType::Usersetup
               && sysLastValue.ElementName  == this.lastValueElementName()
               && sysLastValue.DesignName
        {
            loadFromUserMapAll.insert(sysLastValue.UserId+"|"+sysLastValue.company, strFmt("%1 (%2)", sysLastValue.UserId, sysLastValue.company));
        }
    }
 
    if (loadFromUserMapAll.elements())
    {
        [userId,companyId] = str2con(pickUser(loadFromUserMapAll, true),"|");
 
        if (userId)
        {
            element.loadSetupCompany(userId,companyId);
        }
    }
    else
    {
        info("@SYS73299");
    }
}

  • Edit SysSetupForm’s Class declaration to  declare a new variable: “Map loadFromUserMapAll;

Step 3: Provide logic to load the setup on selection

  • Navigate to the methods node of the SysSetup form, right click and click “New Method”
  • Rename your new method to:
    public void loadSetupCompany(userId userId, CompanyId _company)
  • Modify this method’s code the following (this is basically a modified copy of the loadSetup method to cater for loading from a selected alternate company setup)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// AosRunMode::Client
public void loadSetupCompany(userId userId, CompanyId _company)
{
    SysLastValue    sysLastValue;
    container       value;
    Name            designName;
    Map             map;
    ;
 
    select firstonly sysLastValue
        where sysLastValue.Company      == _company  &&
              sysLastValue.UserId       == userId                      &&
              sysLastValue.RecordType   == this.lastValueType()  &&
              sysLastValue.ElementName  == this.lastValueElementName() &&
              sysLastValue.DesignName   != '';
 
    if (sysLastValue)
    {
        map = new Map(Types::String, Types::String);
 
        while select designName from sysLastValue
            where sysLastValue.Company      == _company   &&
                  sysLastValue.UserId       == userId                       &&
                  sysLastValue.RecordType   == this.lastValueType()         &&
                  sysLastValue.ElementName  == this.lastValueElementName()  &&
                  sysLastValue.DesignName   != ''
        {
            map.insert(sysLastValue.DesignName, sysLastValue.DesignName);
        }
 
        designName = pickList(map, "@SYS28107","@SYS28107", true);
        if (designName)
        {
            value = xSysLastValue::getValue(
                _company,
                userId,
                this.lastValueType(),
                this.lastValueElementName(),
                designName);
 
 
            xSysLastValue::putValue(
                value,
                this.lastValueDataAreaId(),
                curUserId(),
                this.lastValueType(),
                this.lastValueElementName(),
                '');
 
            element.disableLayoutChanges();
        }
    }
    else
    {
        info(strfmt("@SYS28106", userId));
    }
}

You’re all done! 

Compile your form and access it from anywhere in AX by right clicking on a field and clicking Personalise.

Personalise

You should now have a “Retrieve from Company” button.

2015-09-18_0755

 

When clicking on this button you will see a list of all user profiles for other companies, including your own with the company listed in brackets. Double click on the user name, then double click on the the personalisation name to load it.

I hope this helps make life more efficient and easy!

 

 

 

Development tricks Personalise User Settings
Leave a comment Posted on September 8, 2015September 11, 2015 AX2012, Dynamics AX, Environment Management, SQL Scripts

AX DB Restore Scripts #4 – Reconfigure batch jobs

Last week I embarked on a series of posts on DB restore scripts for Dynamics AX by creating a list of items in your AX database that need to be updated/reconfigured when restoring a database from a production environment to a development or QA one.

This post is closely tied to and relies on my previous post on re-configuring your AOS and Batch AOS instances to work, so ensure you have completed that script before continuing.  Today I will be looking at re-configuring your actual batch jobs and batch groups to function correctly under your new environment.

In the Dynamics AX 2012 client the configurations that we are going to look at are:
1. Batch Groups, accessed via System Administration -> Setup -> Batch Groups

Batch_Groups Batch_Groups2

2. Batch Jobs, accessed via System Administration -> Inquiries -> Batch Jobs -> Batch Jobs
Batch_Jobs

Depending on the configuration of your source system (e.g. Production) you may have multiple AOSs setup as batch servers whereas your DEV and QA would most likely just have a single AOS that functions as the batch AOS. You may also have a number of batch jobs that that you explicitly don’t want to run in a development environment, such as integrations to vendors, automatic ordering etc… Therefore our scripts will need to do the following:

1. For each of our batch groups we want to:
– Delete all but one of their selected/linked “batch servers”
– Re-point the remaining link to the current batch server setup in our previous script.
2. Disable batch jobs that we do not want to run in our development environment.
Before proceeding, please note, these scripts are intended as guidelines and do make various assumptions on the state of your environment. For example I’m assuming that your batch jobs were cleanly shutdown with their status’ either in “Error, ended, or waiting” (not Cancelling or Executing). Please adjust these scripts to suit your environment.

The following SQL code will accomplish the above. I have parameterised the SQL for easier reuse or adjustment.

MySQL
1
2
3
4
5
6
7
8
9
10
11
--Reuse the parameter declared for the SSRS and AOS update script
Declare @AOS varchar(30) =  '[AOSID]' -- Must be in the format '01@SEVERNAME'
 
-- #1.1 Clear out but one link between each batch server group and batch server.
delete from BATCHSERVERGROUP where RecId not in (select min(recId) from BATCHSERVERGROUP group by GROUPID)
-- #1.2 Repoint remaining links to the active aos/batch server.
update BATCHSERVERGROUP set SERVERID=@AOS
  where serverid != @AOS -- Optional to see "affected row count"
-- #2 - Disable batch jobs that should not run in a production environment. Copy the two lines below for each batch job you want to disable.
update batchjob set batchjob.status=4 where batchjob.CAPTION = '[BATCHJOBNAME]'
update batch set batch.STATUS=4 from batch inner join BATCHJOB on BATCHJOBID=BATCHJOB.RECID AND batchjob.CAPTION = '[BATCHJOBNAME]'

2015-09-08_0834

 

I hope this assists you and will be useful in your management of your AX environments.

View Next – AX DB Restore Scripts #5 – Configure Service Accounts and Help Server

View Previous – AX DB Restore Scripts #3 – Configure AX servers and batch servers

Back to List

Database Development tricks Environment Management SQL User Settings
1 Comment Posted on August 4, 2014 AX2012, Client, Dynamics AX, Quick Tips, Uncategorized, X++

Setting Status Bar options in Code and SQL

Problem / Symptom: How to automatically set the status bar options (Under User Options) for all users.

Description: As a developer or functional consultant we quite often receive support requests from users with very little information as to their circumstances under which the issue occurs. E.G. What environment where they working on (Prod, QA, Dev)? What is their userId etc (in order to find out security settings applied)? What currency? and most importantly what AX company they are logged into. All of this information can be set to be displayed in the users status bar by setting enabling it per user under Administration -> Users -> Options -> Status Bar.

Screen Shot 2014-08-04 at 4.29.50 PM

 

It really helps to have it set over there so that screenshots will normally just show this information.

However you may want to set these options globally for all users when initially configuring the system. Doing this manually is quite a tedious process and there is no field per setting to do it in a quick sql script or AX job. Rather AX stores it in a single binary field called “Userinfo.StatusLineInfo” and uses bitwise operators for setting and reading the individual options. This really makes it a bit tricky to set but is very efficient in terms of space and reading speed for the system.

So how do you perform this global setting? My first two options will show you how to set all users to have the same option sets, my last solution will show you how to set only one specific setting for all users.

OPTION 1 (AX Solution): 
1. Login with your AX user and navigate to Administration -> Users -> Options -> Status Bar.
2. Set all the status bar parameters that you would like to display for all users.
3. Create a new Job in the AOT with the following code:

1
2
3
4
5
6
7
static void syncAllUserToCurrentUserStatusBarOptions(Args _args)
{
    UserInfo user, updUser;
    select user where user.id == curUserId();
    
    update_recordSet updUser setting StatusLineInfo = user.StatusLineInfo;
}

OPTION 2 (SQL Solution):
1. Login with your AX user and navigate to Administration -> Users -> Options -> Status Bar.
2. Set all the status bar parameters that you would like to display for all users.
3. Login to your SQL database for AX, locate your user record in the UserInfo table
4. Copy the StatusLineInfo value field value.
5. Execute the following script

1
update userinfo set statuslineinfo=[COPIED VALUE]

e.g.

1
update userinfo set statuslineinfo=-529533

This example will set all users to have the following options: Show help text, Show Utility layer, Show Company accounts, Show currency, Show UserId, Show Alert Status, Show AOS name, Show Current Model, Show Document Attachments button, Show Record Navigation buttons, Show View Edit Record Button, Show details form details/grid view buttons.

Option 3 Set a specific option for all users:
1. Open the AOT, expand forms node, navigate to SysUserSetup Form.
2. Right click, click “View Code”
3. Open the “ClassDeclaration” method.
4. Move down to approx line 57 where there are a whole bunch of macros entitled #LOCALMACRO.FLAG_XXXXXXXX
5. Locate the macro that has the setting that you want to use e.g. #LOCALMACRO.FLAG_StatuslineShowPartition to show the default partition. Take note of the value after the “<<” symbol. E.g. 19

6. Create a new job with the following code:

1
2
3
4
5
6
7
8
9
10
11
static void addStatusBarOptionToAllUsers(Args _args)
{
    UserInfo updUser;
ttsBegin;
while select forUpdate updUser
{
updUser.statuslineInfo = updUser.statuslineInfo | (1 &lt;&lt; [value from step 6]);
updUser.doUpdate();
}
ttsCommit;
}

E.G. To set all users to show default partitions:

1
2
3
4
5
6
7
8
9
10
11
static void addStatusBarOptionToAllUsers(Args _args)
{
    UserInfo updUser;
ttsBegin;
while select forUpdate updUser
{
updUser.statuslineInfo = updUser.statuslineInfo | (1 &lt;&lt; 19);
updUser.doUpdate();
}
ttsCommit;
}

7. Execute the job

NOTE: To remove a setting from all users simply replace the line

1
updUser.statuslineInfo = updUser.statuslineInfo | (1 &lt;&lt; 19);

with

1
updUser.statuslineInfo = updUser.statuslineInfo ^ (1 &lt;&lt; 19);

Simple as that (sortof)

Hope you benefit from this. Drop me any comments if anything is unclear.

Bitwise operators Status bar User Options User Settings UserInfo
Proudly powered by WordPress | Theme: Adaption by Automattic.