Product and Product Master Tables in Ax2012.

 Here The following Tables are used while creating and relaesing of a product and product master  in ax 2012.


  1. Ecoresproduct -------> contains all products details
  2. EcoResDistinctProduct ----> abstract table which support inheretance for EcoresproductTable
  3. EcoResProductIdentifier ----> containes identification numbers for the products
  4. ecoResProductTranslation-----> global Languge details for product 
  5. EcoResProductMaster --->stores product masters details
  6. EcoResStorageDimensionGroup---> containes storgae dimensions LIke site,Sitewh
  7. EcoResProductDimensionGroupProduct ---> stores the association recids of produts and its storage dimensions.
  8. ecoResStorageDimensionGroupProduct ---> stores product storge dimension
  9. ecoResTrackingDimensionGroupProduct---> stroes tracking dimensions of products
  10. inventTable ---> stores all relaesed products as items.
  11. inventModelGroupItem ----> stores item model group in association with item id
  12. inventItemGroupItem ----> stores group of the item like audio,parts,electronics etc...
  13. inventTableModule----> which stores the items for different modules like purch,sales,inventory.
  14. InventItemLocation ---> information about the location setup for an item...like warehouse.
  15. InventItemSetupSupplyType --> information about supply type wheather it is purchased or production type and stores the company of the item.
  16. ecoResTrackingDimensionGroupItem ---> after relasing the products the tracking dimension of the item stored based on the inventtable.
  17. ecoResStorageDimensionGroupItem --->storge dimennsion details for item.

Filter Records based On the MenuitemCaller

  For filtering the records in a form based on the menuitem caller we have to follow following steps

  For Example ;

 we have ledgerJournalTable form which is presented in the modules like AP, AR,GL   

  but if we observe that form, whenever we open from one module it will show only respected details

because ledgerjournaltable form called from the respected menuitems.

if u observe in the menuitem properties the specifed 2 proporties

based on this properties our form will be called.

to know the initilizing process

Check

\Forms\LedgerJournalTable\Methods\init

go to line ;      journalFormTable = new LedgerJournalFormTable(element);

Then Go to  \Classes\LedgerJournalFormTable   which is extend from JournalformTable class

and check  \Classes\JournalFormTable\initJournalTypeFromCaller.

   Now U can Find the entire proccess 

same I have a requirment to apply the entire process in my customized tables 

for that i have created one form and a base enum and MenuItems as below

in the form datasource init method add below code for filteration

public void init()

{



    //anytype LedgerJournalType;

    ;

    super();

    if (element.args().parmEnumType())

     {

        LedgerJournalType = element.args().parmEnum();

     }

     if (LedgerJournalType)///If found

    {

        this.query().dataSourceTable(tableNum(DaxLedgerJournal)).addRange(fieldnum(DaxLedgerJournal,DaxJournalType)).value(QueryValue(LedgerJournalType));


    }


}


Passing Multiple Values Using Args Concept

 Here the code snippet,  For passing the multiple selected records from one to another form by using args.

    here im using multiselctionhelper class to get the selected records . 

   To pass the records from one form to another form based on the button click.add below code in the clicked method of parent form button control.

Parent form :

void clicked()

{


     //int recordsCount;

     DAXVendor vendorLoc;

     container con;

     Args args= new Args();

     str multiSelectString;

    MultiSelectionHelper helper = MultiSelectionHelper::construct();

    helper.parmDatasource(DAXVendor_ds);

    vendorLoc = helper.getFirst();


     while (vendorLoc)

     {

     // storing recid of selected field in container

      con = conIns(con,1,vendorLoc.VendorNumber);

     //// converting container to string with comma separated

      multiSelectString = con2Str(con,',');

      vendorLoc = helper.getNext();

     }

     //// passing string

     args.parm(multiSelectString);

     //// calling menu item

     new MenuFunction(menuitemDisplayStr(DAXVendorDetailstest), MenuItemType::Display).run(args);


}

       after getting the values we should pass the values to the child form.for that we have wright the code in child form init method

 child form:

public void init()

{

    container   con;

    int         i;

    str         multipleRecords;

    super();

// getting string value from caller

    multipleRecords = element.args().parm();


// string to container

    con = str2con(multipleRecords,",");


// for sorting

    for(i = 1;i<= conLen(con) ;i++)

    {                   DAXVendorDetails_ds.query().dataSourceTable(Tablenum(DAXVendorDetails)).addRange(fieldNum(DAXVendorDetails,VendorNumber)).value(SysQuery::value(conPeek(con,i)));

    }


}

       






 

Date functions in AX2012

    Different  types of date functions that are available in ax2012.

static void Datefunctions(Args _args)

{


    str          s;

    int          i,noOfMonths,noOfMonthsBetweenYears;

    date         c;

    Date         dob;

    Date         _LastDateOfMonth;

    Int          month_number;

    Int          years_numbers;

    Int          day_number;

    TransDate    d1,d2;

    date         d3 =18\04\1998;

    date         d4 = 17\8\2020;

    int          daydiff,yrdiff,monthdiff;

    date         inputDate = str2Date("4/18/1998", 213);

    date         refDate = str2Date("8/17/2020", 213);

    TransDate    k,    now = today();

    date         maximumdate;

    //Gives name of day

    s= dayName(12);

    info(strFmt(" day  is %1",s));



    //Gives Date

    i=dayOfMth(today());

    info(strFmt('todays date of the month is %1',i));



    //Gives Day no of a week

    i=dayofwk(today());

    info(strFmt('todays day of the week is %1',i));


    i=dayOfYr(today());

    //info(strFmt('todays day of the year is %1',i));

    info(strFmt( 'todays day of year is ' +int2str(i)));


    i=wkOfYr(today());

    info(strFmt('todays week of a year is' +int2str(i)));


    i=year(30\05\2098);

    info(strFmt(' year is' +int2str(i)));



    //mkdate

    Day_number=18;

    Month_number=4 ;

    years_numbers=1998;

    dob =mkdate(Day_number, Month_number, years_numbers);

    info(strFmt('%1',dob));


    //name of month

    s=mthName(11);

    info(s);


    //next month

    c=nextMth(today());

    info(strFmt('%1',c));

    c=nextMth(22\12\2020);

    info(strFmt('%1',c));


     //previous month

    c = prevMth(today());

    info(strFmt("%1",c));




    //quater

    c=nextqtr(1\1\2020);

    info(strFmt('%1',c));

    c=nextqtr(today());

    info(strFmt('%1',c));


    //prevqtr

    c = prevqtr(17\1\2020);

    info(strFmt("%1",c));




    //next year

    c = nextYr(today());

    info(strFmt("%1",c));


    // prev year

    c= prevyr(8\6\2019);

    info(strFmt("%1",c));



    //today

     c= today();

     info(strFmt("%1",c));


    //timenow

    i= timeNow();

    info(strFmt("%1",i));


    c=dateEndWk(Today());

    info(strFmt("%1",C));

    C=dateStartWk(today());

    info(strFmt("%1",C));


    //date start and end of years and month

    c = dateStartMth(today());

    info(strFmt("%1", c));

    c=dateEndMth(today());

    info(strFmt("%1", c));

    C=dateStartYr(today());

    info(strFmt("%1", c));

    c=dateEndYr(today());

    info(strFmt("%1", c));


    //fowrd & bckwrd months

    C=today();

    info(strFmt('%1',dateMthFwd(systemdateget(),5)));

    C=today();

    info(strFmt('%1',dateMthFwd(systemdateget(),-5)));

    //DateDifference

    d1  = 16\8\2021;

    d2  = today();

    i = d2 - d1;

    info(strfmt("%1",i));

    daydiff=dayOfMth(d4)-dayOfMth(d3);

    yrdiff=year(d4)-year(d3);

    monthdiff=mthOfYr(d4)-mthOfYr(d3);

    info(strFmt("%1",daydiff));

    info(strFmt("%1",yrdiff));

    info(strFmt("%1",monthdiff));


    //months dif btwn years

    noOfMonths = intvNo(refDate, inputDate, intvScale::Month);

    noOfMonthsBetweenYears = intvNo(refDate, inputDate, intvScale::YearMonth);

    info("noOfMonths  :"+int2str(noOfMonths) + "  ,noOfMonthsBetweenYears  :"+int2str(noOfMonthsBetweenYears));


      k = DateTimeUtil::Date(DateTimeUtil::addMonths(DateTimeUtil::newDateTime(now, 0, DateTimeUtil::getCompanyTimeZone()),-6));

       info(strFmt("%1",k));

    maximumdate=maxDate();

    info(strFmt("%1",maximumdate));

}


SysOperation frame work in ax2012

            Sysoperation frame work in ax2012  is used for run our business logic inter actively or   periodically by scheduling batch jobs. in ax batch server.  

Sysoperation framework follows MVC pattern which is model view and controller 

Model ; model  is a member which intarct with view to get the input parameters and it is also co-ordinate with controller for execte the busines logic.

view; view is for display purpose.Ui builder class is worked as view in ax 2012

controller; Controller is used for execute  our busines logic.

    apart from that in sysoperation framwork  we have some classes which are exactly worked as mvc pattern

those are 

1.sysopeartion contarct class 

2.sysopeartion serviece class

3.sysopeartioncontroller class

4.sysopeartion uibuilder class

  here i have a requirement that i want to insert lines for price/disc agrement journal by using existing posted journals.

For that i have created a contract class having parameters current journals and posted journals.

here the code for sysopeartion 


Data Contract class :

          To create  Datacontarct class we have to use DataContractAttribiute on the top of the class and 

and we have to mention DatamemberAttribute on the top of the Methods.

Additionally we can use UiBuilder class for forther refferences like lookups,validations,modifications etc.

  Code snippet:

1.declaring Datacpontract class

                         [DataContractAttribute,

                             SysOperationContractProcessingAttribute(classstr(DaxPricediscUiBuilder))]

                    class DaxPriceDiscContract

                    {

                           str  CurrentJournal;           //for unbond controls we mention datatype 

                           str  PostedJournals;             // for bonded edts

                     }

2.declaring Parm Methods for user input. These methods will create parmaetrs of dailoge form for user interactions.

                                    [DataMemberAttribute,

                                SysOperationLabelAttribute(literalStr(" current journal")), -------> label

                                SysOperationHelpTextAttribute(literalStr("for current journal lines")),---->helptext

                                SysOperationDisplayOrderAttribute('1')] 


                            public str parmCurrentJournal(str _currentJournal = currentJournal)

                            {

                             currentJournal =_currentJournal;

                            return currentJournal;

                           }

           And one more parmmethod

[DataMemberAttribute,

SysOperationLabelAttribute(literalStr(" Posted journal")),

SysOperationHelpTextAttribute(literalStr("for insert journal lines")),

SysOperationDisplayOrderAttribute('2')]

public str parmPostedJournals(str _postedJournals = postedJournals)

{

    postedJournals =_postedJournals;

    return postedJournals;

}

UI BUILDER CLASS: 

   my requiermnt is I want lookup for posted journal field in dailoge box.so that i have used uibuilder class.
 Uibuilder class is extented from SysOperationAutomaticUibuilder;

1.create UiBuilder class and declare Contract class.
              

class DaxPricediscUiBuilder extends SysOperationAutomaticUIBuilder
{
    DaxPriceDiscContract DaxPriceDiscContractloc;
}

2. Build method for perfom operatiopn on Contract class

 

   Public void build()
{
    DaxPriceDiscContractloc = this.dataContractObject();
    this.addDialogField(methodStr(DaxPriceDiscContract,parmCurrentJournal),DaxPriceDiscContractloc);
    this.addDialogField(methodStr(DaxPriceDiscContract,parmPostedJournals),DaxPriceDiscContractloc);

}

3. Normal lookup method.

                                Public void lookupPostJour(FormStringControl _formStringControl)

{

    Query query = new Query();

    QueryBuildDataSource qbds;

    QueryBuildRange qbr;

    SysTableLookup lookup;

    lookup = SysTableLookup::newParameters(tableNum(PriceDiscAdmTable),_formStringControl);

    qbds=query.addDataSource(tableNum(PriceDiscAdmTable));

    qbr=qbds.addRange(fieldNum(PriceDiscAdmTable,Posted));

    qbr.value(SysQuery::value(NoYes::Yes));

    lookup.parmQuery(query);


    lookup.addLookupfield(fieldNum(PriceDiscAdmTable,JournalNum));

    lookup.addLookupfield(fieldNum(PriceDiscAdmTable,JournalName));

    lookup.performFormLookup();

4. We will create a PostBuild Method.


Public void PostBuild()

{

    DialogField dgpostedJour;

    dgpostedJour=this.bindInfo().getDialogField(this.dataContractObject(),

    methodStr(DaxPriceDiscContract,parmPostedJournals));

    dgpostedJour.registerOverrideMethod(methodStr(FormStringControl,lookup),

    methodStr(DaxPricediscUiBuilder,lookupPostJour),this);

}

 So now we will apply this Uibuilder class on the top of the Contract Class. So that it will extract the Uibuilder class methods.

SERVICE CLASS:

 Now Iam Creating service class which  used to write our busines logic to perform our operation.

Note; Service class is optional class.we can also use controller class to run our business logic.But for the better performnce, as to reduce the overloading in contarct class we wil use service class.

1. class declaration 

class DaxPricdiscService extends SysOperationServiceBase

{

}

2.add one method to perform our logic


[SysEntryPointAttribute]        // mandotary to get the values from dailoge

public  void testContract(DaxPriceDiscContract _daxPriceDiscContract)

{

    PriceDiscAdmTrans priceDiscAdmTrans,priceDiscAdmTransLOC;

    RecordInsertList insertRecords;

    insertRecords = new RecordInsertList(tableNum(PriceDiscAdmTrans));

    while select priceDiscAdmTransLOC

        where priceDiscAdmTransLOC.JournalNum==_daxPriceDiscContract.parmPostedJournals()

    {

        if (priceDiscAdmTransLOC)

        {

         // for traditional insert follow this one. here im using RecordInsertList 

            //priceDiscAdmTrans.JournalNum=_daxPriceDiscContract.parmCurrentJournal();

            //priceDiscAdmTrans.inventdimid=priceDiscAdmTransLOC.inventdimid;

            //priceDiscAdmTrans.itemrelation=priceDiscAdmTransLOC.itemrelation;

            //priceDiscAdmTrans.itemcode=priceDiscAdmTransLOC.itemcode;

            //priceDiscAdmTrans.amount=priceDiscAdmTransLOC.amount;

            //priceDiscAdmTrans.fromdate=priceDiscAdmTransLOC.fromdate;

            //priceDiscAdmTrans.accountcode=priceDiscAdmTransLOC.accountcode;

            //priceDiscAdmTrans.relation=priceDiscAdmTransLOC.relation;

            //priceDiscAdmTrans.currency=priceDiscAdmTransLOC.currency;

            insertRecords.add(priceDiscAdmTransLOC);

            info('inserted');

        }

    }

    insertRecords.insertDatabase();

    info('parm dailoge test');

}

 CONTROLLER CLASS:

          Controller is the main class to execute our business logic.Controller class must have one main method, new method,Construct method.

Here code snippet.

1.Class Declartion

[    SysOperationJournaledParametersAttribute(true) ]

class DaxPricediscController extends SysOperationServiceController

{

                         //declare all variables which will use in your  opeartion 

     Common                  callerrecord;

    DaxPricediscController           controller;

    DaxPriceDiscContract    daxPriceDiscContract;

    PriceDiscAdmTable       priceDiscAdmTable;

    PriceDiscAdmTrans       priceDiscAdmTrans;

   }

2. My requiremnt is i want to pic the current record from a form and insert its line details.

So that im using args Parameters and methods./

   1.add parmCallerRecord

  public Common parmCallerRecord(Common _callerRecord = callerRecord)

{

                        //used to get the selected record table 

    callerRecord = _callerRecord;


    return callerRecord;

2  add initFromCaller

.private void initFromCaller()

{

                        // getting object of contract class 

    daxPriceDiscContract = this.getDataContractObject();

    switch (this.parmCallerRecord().TableId)

    {

                            // initilizing parmcallerrecord 

        case tableNum(PriceDiscAdmTrans) :

           priceDiscAdmTrans = this.parmCallerRecord() as PriceDiscAdmTrans;

            daxPriceDiscContract.parmCurrentJournal(priceDiscAdmTrans.journalnum);

            break;

    }

}

3.  newFromArgs

public static DaxPricediscController newFromArgs(Args _args)

{

                                // pasing args   to the controller class

    DaxPricediscController           controller;

    IdentifierName                  className;

    IdentifierName                  methodName;

    SysOperationExecutionMode       executionMode;


    [className, methodName, executionMode] = SysOperationServiceController::parseServiceInfo(_args);

    if (_args.record())

    {

        executionMode = SysOperationExecutionMode::Synchronous;

    }

    controller = new DaxPricediscController(className, methodName, executionMode);

    controller.parmArgs(_args);

    controller.parmCallerRecord(_args.record());

    return controller;

}

4.refreshCallerRecord

protected void refreshCallerRecord()

{

                                // used to refresh the caller record 

    FormDataSource callerDataSource;

    if (this.parmCallerRecord() && this.parmCallerRecord().dataSource())

    {

        callerDataSource = this.parmCallerRecord().dataSource();

        callerDataSource.research(true);

    }

}

5.new method

            // in the paranthesis declare classes and methods and execution mode as parameters

void new(IdentifierName _className = classStr(DaxPricdiscService),

IdentifierName _methodName = methodStr(DaxPricdiscService, testContract),

SysOperationExecutionMode _executionMode = SysOperationExecutionMode::Synchronous

)

{

    super(_className, _methodName, _executionMode);

// by passing service class in these methods we will creating reference for our contract class as well so that when we running our controller class it will show us dailoge

   this.parmClassName(classStr(DaxPricdiscService));

   this.parmMethodName(methodStr(DaxPricdiscService,testContract));


 5.Main Method.

    as we know main method used for creating  instance object of the class and opertion will execute or starts from Main method only.

  Public static void Main(Args _args)

{

        DaxPricediscController daxPricediscController= new DaxPricediscController();

     daxPricediscController = DaxPricediscController ::newFromArgs(_args);

         //daxPricediscController.parmArgs(_args);

        daxPricediscController.initFromCaller();

        daxPricediscController.refreshCallerRecord();

      // manodtary  to start our controller class operations

        daxPricediscController.startOperation();

}

6.Create a instance of Data contract class. so that it is easy to access Data Contract class.

     public DaxPriceDiscContract parmDaxPriceDiscContract(DaxPriceDiscContract _DaxPriceDiscContract = daxPriceDiscContract)

{

    daxPriceDiscContract = _DaxPriceDiscContract;

    return daxPriceDiscContract;

}

So its done for creating classes and methods.. so now we will going to add our controller class to a Action Menu iterm.

 in the action menu item properties we have to mention following properties 

    

    And then compile your project and open the menu item

   U will Get a dailoge like this  

    


      Keep Daxing.....!








 




   

To Create login credentials for ax2012 application using X++

        to create login credentials for our ax application we have wright code in the classes, which are executed while openinmg the application.
 
So we will wright our code in Application class and also Info Class.
And put the following code in StartupPost method.
Now im using the Info Class. 

Path:- \Classes\Info\startupPost

put the following code in startuppost Method

    Dialog                dialog;
    Dialogfield         dName,dPassword;
    Userinfo              user;
    boolean                ret;
    SysClientSessions   sysClientSessions;
    AxaptaUserManager   axUserManager;

   dialog      = new dialog("User login");
    dialog.formBuildDesign().height(170);
    dialog.formBuildDesign().width(400);

    dName      = dialog.addField(ExtendedTypestr(userid),"User name");
    dPassword   = dialog.addField(ExtendedTypestr(Password),"Password");
    dName.enabled(false);

    dName.value(curuserid());

     select firstOnly id from user
            where user.id == dName.value();

    if (user.id != "Admin")
    {
    dPassword.passwordStyle(true);
    dialog.parmIsModal(true);


        axUserManager = new AxaptaUserManager();
        if (dialog.run())
        {
            if (!axUserManager.validatePassword(user.networkAlias , user.NetworkDomain, dPassword.value()))
            {
                infolog.shutDown(true);
            }
            else
            {
                Box::info("Access granted.","AX Group","ERP");
                ret = true;
            }
        }

        if (ret == false && user.RecId)
        {
            infolog.shutDown(true);
        }
 }