Wednesday, October 17, 2012

Manupulating forms from code - continued...

After publishing a post about manipulating the Marking form from code, I got some feedback (special thanks to Maxim Gorbunov).

I would like my readers to remember, that forms should never be used like that in business logic executed on a daily basis. If this is something that should be run more often than once, this logic should preferably be run on the server, and in the case with the Marking form, it should rather be TmpInventTransMark::updateTmpMark() method called directly. You will need to prepare parameters for it, though, so you will first need to figure out how the form does that.

In other words, please use out-of-the-box solutions you find on the Internet with care.

Thursday, October 11, 2012

Manipulating the Marking form from code

Businesses buy AX, because they would like to automate their processes. Sometimes they would like to automate more, than standard AX allows. And if business logic is built into forms, it is sort of hard to automate.

One of our clients had to migrate open sales and purchase orders to AX, and mark their lines against each other afterwards. Apparently, calling InventTransOrigin::updateMarking method was not enough, as sales and purchase lines were still not pointing to each other in the reference fields. So, I tried to use the standard Marking form for that ad-hoc task.

Below is the code sample that takes a purchase line lot ID, opens the Marking form, selects the target sales order line and marks it (or unmarks, if it was marked before). Just like you do it by hand.

static void main(Args _args)
{
    #define.TmpInventTransMarkDsNo(2)
    #define.InventTransOriginDsNo(4)
    #define.InventTransOriginMarkDsNo(5)
    #define.MarkNowControlName('markNow')
 
    #define.PurchLineLotId("GSC-000983")
    #define.SalesLineLotId("GSC-000982")
 
    FormRun formRun;
    Args args;
    TmpInventTransMark tmpInventTransMark;
    SalesLine salesLine;
    InventTransOrigin salesLineOrigin;
    PurchLine purchLine;
    InventTransOrigin inventTransOriginMark;
    FormCheckBoxControl markNowCheckBox;
 
    purchLine = PurchLine::findInventTransId(#PurchLineLotId);
 
    args = new Args();
    args.name(formStr(InventMarking));
    args.record(purchLine);
 
    // Work-around: first if-statement in
    // Classes\ReqCalc\argsItemId method expects a caller
    args.caller(new InventMarkingEmulator());
 
    formRun = classfactory.formRunClass(args);
    formRun.init();
    formRun.run();
 
    // The temp table is filled in when this active() is called
    formRun.dataSource(#InventTransOriginDsNo).active();
 
    tmpInventTransMark = 
        formRun.dataSource(#TmpInventTransMarkDsNo).cursor();
    inventTransOriginMark = 
        formRun.dataSource(#InventTransOriginMarkDsNo).cursor();
 
    ttsbegin;
 
    // Find the required reference and mark it    
    formRun.dataSource(#TmpInventTransMarkDsNo).first();
    Debug::assert(tmpInventTransMark.RecId != 0);
    do
    {
        if (inventTransOriginMark.InventTransId == #SalesLineLotId)
        {
            markNowCheckBox = 
                formRun.design().controlName(#MarkNowControlName);
            markNowCheckBox.value(1);
            markNowCheckBox.clicked();
 
            formRun.closeOk();
            break;
        }
    } while (formRun.dataSource(#TmpInventTransMarkDsNo).next());
 
    ttscommit;
}