- Ecoresproduct -------> contains all products details
- EcoResDistinctProduct ----> abstract table which support inheretance for EcoresproductTable
- EcoResProductIdentifier ----> containes identification numbers for the products
- ecoResProductTranslation-----> global Languge details for product
- EcoResProductMaster --->stores product masters details
- EcoResStorageDimensionGroup---> containes storgae dimensions LIke site,Sitewh
- EcoResProductDimensionGroupProduct ---> stores the association recids of produts and its storage dimensions.
- ecoResStorageDimensionGroupProduct ---> stores product storge dimension
- ecoResTrackingDimensionGroupProduct---> stroes tracking dimensions of products
- inventTable ---> stores all relaesed products as items.
- inventModelGroupItem ----> stores item model group in association with item id
- inventItemGroupItem ----> stores group of the item like audio,parts,electronics etc...
- inventTableModule----> which stores the items for different modules like purch,sales,inventory.
- InventItemLocation ---> information about the location setup for an item...like warehouse.
- InventItemSetupSupplyType --> information about supply type wheather it is purchased or production type and stores the company of the item.
- ecoResTrackingDimensionGroupItem ---> after relasing the products the tracking dimension of the item stored based on the inventtable.
- ecoResStorageDimensionGroupItem --->storge dimennsion details for item.
Product and Product Master Tables in Ax2012.
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:
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++
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 userwhere 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);}}