Wednesday, May 19, 2010

Enable grid filter in a form via X++

Form task() method is executed, when the user performs some task in a form e.g. using the toolbar, the menu, or the keyboard.

For example, if the user has activated the grid filter after opening the form, its called with task() with 2855 as parameter. Like this we can automate any user actions in toolbar, menu or keyboard by knowing the taskId for each action. That can be found by adding a break point in task().  By adding the following code in form run() after super will enable grid filter automatically.

public void run()
{
    super();
    this.task(2855);
}

Need to call  this.task(2855); at canClose() so that the grid filter is released, and will reapply on form run (need to explore a bit how to handle the same effect by reading sysLastValue table).

But by default its needed in all the form, it can be set globally in Tools > Options > Details > Filter by grid on by default check box enabled.









Saturday, April 17, 2010

Create RLS via X++

// Sample code of how to create RLS via X++
static void mydSXP_TestInsertRLS(Args _args)
{
    Query                   q;
    SysQueryRun             queryRun;
    sysRecordLevelSecurity  sysRecordLevelSecurity,sysRecordLevelSecurity_old;
    ;

    q = new Query();

    q.addDataSource(tablenum(CustTable));
    SysQuery::findOrCreateRange(q.dataSourceNo(1),fieldnum(CustTable,CustGroup)).value(queryValue(10) +','+queryValue(20)+','+queryValue(30));

    queryRun    =   new SysQueryRun(q);

    // Need to have a RecordSortList and insert will happen for one time only, loop of companies is needed
    sysRecordLevelSecurity.clear();
    sysRecordLevelSecurity.TabId        =   77;
    sysRecordLevelSecurity.companyId    =   'SJH';
    sysRecordLevelSecurity.groupId      =   'SJH_TEST';
    sysRecordLevelSecurity.restriction  =   queryRun.pack();

    // TODO - Check how to update
    // Need to check for the primark key combination
    // TabId,groupId,companyId
    if(sysRecordLevelSecurity.validateWrite())
    {
        select firstonly sysRecordLevelSecurity_old
        where sysRecordLevelSecurity_old.tabId  ==  sysRecordLevelSecurity.tabId    &&
        sysRecordLevelSecurity_old.companyId    ==  sysRecordLevelSecurity.companyId    &&
        sysRecordLevelSecurity_old.groupId      ==  sysRecordLevelSecurity.groupId;

        if(sysRecordLevelSecurity_old)
        {
            ttsbegin;
            sysRecordLevelSecurity_old.selectForUpdate(true);
            sysRecordLevelSecurity_old.restriction  =   sysRecordLevelSecurity.restriction;
            sysRecordLevelSecurity_old.write();
            ttscommit;
        }
        else
        {
            sysRecordLevelSecurity.selectForUpdate(true);
            sysRecordLevelSecurity.write();
        }
    }

}

Friday, April 16, 2010

RLS - Record level security

Record level security (RLS) is automatically handled by the kernel when a form or report is opened
RLS need to be configured for each company

RLS - Works
- RLS on any table
- RLS also restricts the information that is sent from Application Integration Framework (AIF) to external by default
- Excel export will follow RLS
- Report Builder (based on AOT Perspective -> Report Model)
- Visio Studio Reporting tool for AX (based on AOT queries)
- RLS for "save data per company" No
- In shared Tables (virtual company)
- Document handling - If a person have access to a record, then he will able to see the documents attached to it also?

RLS - won't works In
- In display and edit methods
- In FormListControl, FormTreeControl or TableListControl
- In temporary table as a data source
- Table joins won't work
- Any code level calculation by default won't follow the RLS unless un-till it is specified explicitly
- In Table View does not follow RLS

10 MorphX tricks in 10 minutes

Click here

Monday, April 5, 2010

Sales Order posting via X++

static void SalesOrderPosting(Args _args)
{
SalesFormletter SalesFormletter;
SalesTable SalesTable;
;

SalesFormletter = SalesFormletter::construct(DocumentStatus::Confirmation,true); // Needed status

SalesTable.clear();
SalesTable = SalesTable::find('');
SalesFormletter.update(SalesTable, systemDateGet(), SalesUpdate::All, AccountOrder::None, false, false);
}