Search This Blog

Wednesday, November 30, 2011

how to use Set class in AX

The Set class is used for the storage and retrieval of data from a collection in which the values of the elements contained are unique and serve as the key values according to which the data is automatically ordered.
Scenario:
I have this requirement to track the records that are modified by user and  i  need to take action on mofdied records
Solution with SetsDeclare set in Form\class declaration
Set                         setChangedRecord;
Initialize set on Form\DataSource\init as follows:
setChangedRecord     = new Set(Types::Record);
Store records in set on Write method of the data source as follows
 if (!setChangedRecord.in(purchReqLine))
    {
        setChangedRecord.add(purchReqLine);
    }
Traversing of records in Set:
Following is the way of traversing records from Set
SetEnumerator   setEnumerator    = setChangedRecord.getEnumerator();
 while (setEnumerator.moveNext())
            {
                reqLine = setEnumerator.current();
                if (!reqLine.IsSaved)
                {
                    purchReqLineLocal = PurchReqLine::findRecId(reqLine.RecId,true);
                    purchReqLineLocal.IsSaved = true;
                    purchReqLineLocal.update();
                }

            }

Difference between Container, List, Map and set

Containers:Containers are dynamic and have no limits. They can contain elements of
almost all data types: boolean, integer, real, date, string, container,
arrays, tables, and extended data types. However, objects may not be stored
in containers.
Containers in AX are used very often. It’s easy to work with them. But…
data in containers are stored sequentially, and thus retrieved sequentially.
This means that containers provide slower data access if you are working with
_large numbers_ of records. In case of large numbers of records use temporary
tables.
List:
Lists are structures that may contain any number of elements that are
accessed sequentially. Lists may contain values of any X++ type. All the
values in the list must be of __the same__(this is the main difference
between lists and containers) type, given in the creation of the list. The
implementation of lists is such that traversal of the list elements is __very
fast.
Take a look for example at class Dialog addControl() method.
There controls are stored in ctrls List.
Map:
A map is a data type that associates one (key) value with another value [An
analog - a small table in memory with two fields: Keys, Values]. Both the key
and value values may be of any valid X++ type, including objects. The types
of the key and the value are given in the declaration of the map. The
implementation of maps is such that access to the values is _very fast_.
Don’t confuse map X++ types with Map objects in AOT, wich are used for
mapping tables with similar structures of fields
-
Set:
The functionality of Sets is similar with list.  A Set is just an unordered list of items, while a list of items held by a Map
are indexed via via a key.
Take look at
\Classes\sysLabel\LabelModuleId().

Get system Date and AX session Date

How to get session date time using preferred time zone in x ++
DateTimeUtil::date(DateTimeUtil::applyTimeZoneOffset(
DateTimeUtil::getSystemDateTime(), DateTimeUtil::getUserPreferredTimeZone())))


How to get system date in x++
systemDateGet();

Server and Client execution Process

What does server and client keywords do?
Many of the new x++ developers, when they start coding in x++ they really find hard to understand the usage of “Server” and “Client” keyword or server and client properties, Like when they should use the server method or the class and when the client keyword come into play. So I thought I should compose a post on this.
There are many books which throws light on this keyword, however they are more theoretical than practical and I think for a developer it is really necessary they are taught by live example by scenario so through the post below, I will try to be less theoretical and will try to be more practical and conceptual. Through my overall experience, I found that there are two ways to learn things

1. Fall and get stuck into the problem and try everything before you go through the book or search net (that who else fall into this problem and how he resolved it) and then use that solution. When you do that, you will understand the thinking behind the invention of the technique. You will get more clearer concept and you will have the Eagle’s eye view of the problems
2. Go through the book, copy paste the example and learn. But in this technique, it is hard to recall when you actually get into the problem.
Anyways let’s move to server client approach, I will try to keep it short and will post an example.
Ok so what does server keyword do?
Consider a scenario, where you as a developer or a technical consultant given a job to copy some files to the server through when someone setups something.
For instance, take an example of interest code in Account Receivable –> Collections –> Interest code. The scenario is, On the setting of interest code, you are setting something in file system, specific to the interest code and those file system settings will be used later by the interest calculation job for some calculation. Now, the requirement is there will be other web service that will be consuming those file settings.
What does the above scenario mean?
It means you need to do some setting in the code to copy the file system setting on the server as well. Now you if you see from top view, you need to do two things
1. Create Files on the client (Use the client class or client method for it)
2. Create files on the server because copy is not allowed between client and server normally.(Use the server keyword or server class for it)
How can I make server and client methods?
It is easy just put the server or client keyword before the method or class name and method should be static for Server. Client does not have this limitation.
We also have keyword Server Client for the method and class, what does it mean?
The server client method works as the Called from property of the AOT Object, which means the object execution will be dependent on the caller. If the client method or class is calling the server client class, the class or method will be executed on the client machine and vice versa.

Friday, November 4, 2011

AX2009 Send Mail using Mail Template in X++ code.

void krishh_UseMailTemplateAndSendMail(PurchTable _purchTable)
         {
             str                                 LIQ_message;
             Map                                 LIQ_emailParamMap;
             SysMailer     LIQ_Mailer;
       
             SysMailerAddressField               LIQ_tos;
             PurchtotalsForm                     LIQ_totalsForm;
             Amount                              LIQ_totalAmount;
             SysEmailId                           _emailId;
             SysEmailMessageTable                message;
             SysEmailTable                       Emailtable;
            
             ;
        
        
             //Get the Mail Template and Get the Message body

             _emailId = SysEmailTable::find(VendParameters::find().LIQ_DefaultMinPOTemplate).EmailId;

             Emailtable= SysEmailTable::find(_emailId);
             message=SysEmailMessageTable::find(_emailId,Emailtable.DefaultLanguage);
        
             LIQ_totalsForm   = PurchtotalsForm::newPurchTotalsForm(_purchTable, PurchUpdate::All);
             LIQ_totalsForm.calctotals();
             LIQ_totalAmount=LIQ_totalsForm.invoiceAmountValue();
        
            if (message.LayoutType == SysEmailLayoutType::StaticLayout)
            {
                     LIQ_message = message.Mail;
            }
           
            //Set the variable values for the email template.
            LIQ_emailParamMap    = new Map(Types::String,Types::String);
            LIQ_emailParamMap.insert('PurchId', _purchTable.PurchId);
            LIQ_emailParamMap.insert('Total amount',num2str(abs(LIQ_totalAmount), 0, 2, 1, 0));
            LIQ_emailParamMap.insert('currecncy',CompanyInfo::find().CurrencyCode);
            LIQ_emailParamMap.insert('PurchName',_purchTable.PurchName);
            LIQ_message=SysEmailMessage::stringExpand(LIQ_message,LIQ_emailParamMap);

//Get the Mail parameters ex:mailserver.
           if(!LIQ_mailInitialized)
           {
               this.LIQ_initMail();
           }
 //validate the Mail ID before sending the mail.
           if (LIQ_mailer != null && SysEmailDistributor::validateEmail(RCMStoreTable::find
                                                                                                       (_purchTable.InventSiteId).Email))
          {
        
          LIQ_mailer.fromAddress(SysEmailTable::find("POminvalue").SenderAddr, "@SYS115063");
          LIQ_mailer.subject('Minimum PO value');
          LIQ_tos=LIQ_mailer.tos();
          LIQ_tos.clear();
          LIQ_tos.appendAddress(RCMStoreTable::find(_purchTable.InventSiteId).Email);
          LIQ_mailer.priority(1);
          LIQ_mailer.htmlBody(strReplace(LIQ_message, '\r\n', '<br>'));
          LIQ_mailer.sendMail();
          }
}/Method Close

         void LIQ_initMail()
         {
             SysEmailParameters parameters = SysEmailParameters::find();
             InteropPermission interopPermission;
             ;
             //initialize mailer class
             interopPermission = new InteropPermission(InteropKind::ComInterop);
             interopPermission.assert();
             LIQ_mailer = new SysMailer();
             if(parameters.smtpRelayServerName)
             {
                 LIQ_mailer.SMTPRelayServer(parameters.smtpRelayServerName,
                 parameters.smtpPortNumber,
                 parameters.smtpUserName,
                 SysEmailParameters::password(),
                 parameters.ntlm);
             }
             else
             {
                 LIQ_mailer.SMTPRelayServer(parameters.smtpServerIPAddress,
                 parameters.smtpPortNumber,
                 parameters.smtpUserName,
                 SysEmailParameters::password(),
                 parameters.ntlm);
             }
             LIQ_mailInitialized = true;
        
         }

How to get the AIF XML for OutBound interface using X++

static void krish_OutboundXMLAifProcess(Args _args)
    {
        AIFQueryCriteria   QueryCriteria=AIFQueryCriteria::construct();
        AIFCriteriaElement   criteriaElement1,criteriaElement2;
         EDSACRMOrderReturnService   CRMOrderReturnService;
         AIFXml  aifXMl;
        ;
        CRMOrderReturnService=EDSACRMOrderReturnService::construct();
        criteriaElement1=AIFCriteriaElement::newCriteriaElement(tablestr(EDSACRMSyncLog),fieldstr
                                   (EDSACRMSyncLog,CRMOrderId),AIFCriteriaOperator::Equal,'10345');
        criteriaElement2=AIFCriteriaElement::newCriteriaElement(tablestr(EDSACRMSyncLog),fieldstr 
                                  (EDSACRMSyncLog,DocReturn),AIFCriteriaOperator::Equal,Enum2str
                                  (NoYes::No));
      QueryCriteria.addCriteriaElement(criteriaElement1);
      QueryCriteria.addCriteriaElement(criteriaElement2);

      aifXMl=CRMOrderReturnService.find(QueryCriteria).serialize();

    }

Tuesday, November 1, 2011

Call File Outbound AIF Service using Query in X++

The following code is used to execute the AIF File outbound  Service using Query  for AIF find Operation.
ex:= Sales Table-salesid,another field and call AIF find to execute query criteria.

static void krish_OutboundAifQueryProcess(Args _args)
    {
        AxdSendContext          axdSendContext      = AxdSendContext::construct();
        AifAction               aifAction ;
        AifConstraint           aifConstraint       = new AifConstraint();
        AifConstraintList       aifConstraintList   = new AifConstraintList();
        AifOutboundProcessingService AifOutboundProcessingService =
                                                  new AifOutboundProcessingService();
        AifGatewaySendService   AifGatewaySendService = new AifGatewaySendService();
         AifActionId                 actionId;
         AifEndpointList             endpointList;
         Query                               query;
         QueryBuildDataSource      queryBuildDataSource;
        ;

        query = new Query(queryStr(AIFCRMOrderReturn));

        queryBuildDataSource = query.dataSourceTable(tablenum(EDSACRMSyncLog));
        queryBuildDataSource.addRange(fieldnum(EDSACRMSyncLog,CRMOrderId)).
                                                                                    value(QueryValue('2500591'));
        queryBuildDataSource.addRange(fieldnum(EDSACRMSyncLog,DocReturn)).
                                                                             value(QueryValue(NoYes::No));

       aifAction = AifAction::find(AifSendService::getDefaultSendAction(classnum
               (EDSACRMOrderReturnService),AifSendActionType::SendByQuery)) ;

        axdSendContext.parmXMLDocPurpose(XMLDocPurpose::Original);
        axdSendContext.parmSecurity(false);

        aifConstraint.parmType(AifConstraintType::NoConstraint);
        aifConstraintList.addConstraint(aifConstraint) ;

        endPointList=AifSendService::getEligibleEndpoints(aifAction.ActionId,aifConstraintList);

        AifSendService::submitFromQuery(aifAction.ActionId, endpointList, query, AifSendMode::Sync);

        AifGatewaySendService.run();
        AifOutboundProcessingService.run();
    }