July 26, 2012

How to split a Form in two window

hi Friends,
WE a going to create a new form and want to show this form in two interrelated windows, like the following form
Untitled
on the basis of the header the line level information will update,
so for get this type of design in your form you have to write three methods in from design.
1.
int mouseDown(int x, int y, int button, boolean ctrl, boolean shift)
{
    int ret;
    ret = super(x, y, button, ctrl, shift);
    return _formSplitterVertical.mouseDown(x, y, button, ctrl, shift);
}

2.
int mouseMove(int x, int y, int button, boolean ctrl, boolean shift)
{
    int ret;
    ret = super(x, y, button, ctrl, shift);
    return _formSplitterVertical.mouseMove(x,y,button,ctrl,shift);
}

3.
int mouseUp(int x, int y, int button, boolean ctrl, boolean shift)
{
    int ret;
    ret = super(x, y, button, ctrl, shift);
    return _formSplitterVertical.mouseUp(x, y, button, ctrl, shift);
}

after adding these three methods in your form design it will spilt  into two windows, now write your code for validation what ever is your requirement.

- Harry

Top 5 AIF Development Tips and Tricks

Top 5 AIF Development Tips and Tricks
1. Enable the debugger
You will notice, if you put a breakpoint into your document class, that when you run the associated action, the breakpoint will get ignored – leaving you in the dark. This is because the action is called using a ‘runas’ function call  to change the user executing the code.
To workaround this replace the runas method calls with direct calls in\Classes\AifOutboundProcessingService\ and \Classes\AifInboundProcessingService, eg:
1 /*
2 runas(message.sourceEndpointAxUserId(),
3 classnum(AifInboundProcessingService),
4 staticmethodstr(AifInboundProcessingService, processAsUser),
5 [message.pack(), messageId]);
6 */
7 AifInboundProcessingService::processAsUser([message.pack(), messageId]);

2. Run jobs instead of waiting for batch processing
The usual way for the AIF to run is using the batch processing framework, where you setup an interval for the inbound and outbound processing  to run.  This minute or so can feel like an age when you are in the middle of developing:
clip_image002
AIF batch processing
So use a custom job to have the AIF run instantly at the click of a button, here is an example of the receive job:
01 static void runAIFReceive(Args _args)
02 {
03 AifGatewayReceiveService aifGatewayReceiveService;
04 AifInboundProcessingService aifInboundProcessingService;
05 ;
06
07 aifGatewayReceiveService = new AifGatewayReceiveService();
08 aifGatewayReceiveService.run();
09 aifInboundProcessingService = new AifInboundProcessingService();
10 aifInboundProcessingService.run(true);  // pass true for debug mode
11 }

3. Use file adapters
clip_image004
When using the AIF, you will most likely be using a Biztalk, Web service or MSMQ adapter. Testing actions using one of these adapters can be a pain as you will most likely require another program to send or receive the message.
To get around this you can use a file adapter during testing, so that you can just write the message in plain XML and drop the file into a directory on your file system to be processed.
Then when you are finished testing / developing you can easily swap the file adapter out.
4. Compose messages with the Visual Studio XML editor
During development (when you use a file adapter), you can create the message using notepad or any other text editor. I recommend using the Visual Studio XML editor to quickly compose these to take advantage of intellisense, schema validation and other useful features (like inserting a guid):
clip_image006
5. Use the pipeline
It is unlikely (if you are integrating with a third party) that the XML schemas  of the external system match those in AX.
To transform the message into the format AX can handle you can use the pipeline to add a component to run an xslt on the inbound XML:
clip_image008


Enjoy...
Harry

July 25, 2012

How to fetch Values from WorkFlow Tables

How to fetch Values from WorkFlow Tables

Hi friends,
   I am facing a problem since many days and now i got the logic to fetch values from a workflow table, but still it’s for only PO and PR and i am working on the GL transaction also, here is the Code, Use copy and paste it in a job and run.

static void theaxapta_WorkflowHisory()
{
    WorkflowTrackingTable           workflowTrackingTable;
    WorkflowStepTable               workflowstepTable;
    WorkflowTrackingStatusTable     workflowTrackingStatusTable;
    WorkflowTrackingCommentTable    workflowTrackingCommentTable;

    utcdatetime     dt[];
    string100     Comment;
    int i;
    ;
    i = 1;
   select workflowtrackingtable join workflowsteptable
    where workflowsteptable.StepId == workflowtrackingtable.StepId
    &&    workflowtrackingtable.ContextRecId == PurchTable::find('NBH1112_PO000025').RecId;

   while select workflowtrackingtable
            where  workflowtrackingtable.ContextRecId == PurchTable::find('NBH1112_PO000025').RecId
    {

        dt[i] = workflowtrackingtable.createdDateTime;
        i ++;
        info(strfmt("Step Name == %1......  user Code: %2", workflowsteptable.Name,  workflowtrackingtable.User));
    }
    info(strfmt('User Approved: %1 - %2.....%3......%4.......%5..........', dt[1], dt[2],dt[3],dt[4]));

    select workflowTrackingCommentTable  where workflowTrackingCommentTable.TrackingId == workflowTrackingTable.TrackingId;
    while select workflowTrackingCommentTable  where workflowTrackingCommentTable.TrackingId == workflowTrackingTable.TrackingId
    {
        info(strfmt("Comment...=  %1",workflowTrackingCommentTable.TrackingMessage));
    }


//    select workflowTrackingCommentTable
//    where workflowTrackingCommentTable.TrackingId == workflowTrackingTable.TrackingId;
//
//    info(strfmt('Date Approved: %1', workflowTrackingCommentTable.TrackingMessage, DateTimeUtil::applyTimeZoneOffset(workflowTrackingCommentTable.createdDateTime, DateTimeUtil::getUserPreferredTimeZone())));
//

}

Note: This is rough code, you may need to update it as per your requirement.
Enjoy,
Harry.

Add a button to go to Main Transaction

Add a button to go to Main Transaction

Hi guys,

The following code for adding a button on your forms to go to the main transaction form/table, to do this type of magic you have to add a button on you form and copy paste the following code in the click method of that button.

void clicked()
{
    Common buffer;
    selectableDataArea company = curExt();
    Args args = new Args();
    SysDictTable dictTable;
    FormRun formRun;
    WorkflowTrackingStatusTable trackingStatus;
    ;
    trackingStatus = WorkflowTrackingStatusTable::findByCorrelation(WorkflowTrackingStatusTable.CorrelationId);
    if (trackingStatus.RecId)
    {
        changecompany(trackingStatus.ContextCompanyId)
        {
            dictTable = new SysDictTable(trackingStatus.ContextTableId);
            buffer = dictTable.makeRecord();
            select buffer where buffer.RecId == trackingStatus.ContextRecId;
            if (! buffer)
            {
                 info('You cannot go to the origin of the workflow instance. The record no longer exists or you do not have sufficient access.');
return;
            }
            dictTable.formRef();
            args.lookupRecord(buffer);

            args.name(dictTable.formRef());
            formRun = ClassFactory.formRunClass(args);
            formRun.init();
            formRun.run();
            formRun.detach();
        }
    }
}

This a very simple code to go to main Transaction Table, in above methods you can add your comment also to make it more user friendly, this a good practice to give error or empty records messages to End user to make your coding efficient and more user friendly.
-Harry