Wednesday, July 24, 2013

Playing with controller class

SysOperation framework relies on SysOperationServiceController class for passing the args argument from the menu item to the framework. Overriding some of the methods on this class gives you more control over its functioning. Same way when you want to modify the user interface of a SysOperation service, UI Builder classes are the way to go. Two methods of particular interest to me are:
showQueryValues When a query is used and this method returns true, then the fields with ranges and a Select button will be shown on the dialog. Return false in this method to hide them.
showQuerySelectButton This method does the same as the showQueryValues method, but only affects the Select button.

Some cases we want to create a batchable job, which a user can use but don't want to give him the option to 'select' any particular records or its meaningless to show the query fields on dialog. Overriding the above two methods to return false can solve the purpose.

You will also need to override main and construct methods in this case, like below.

 public static void main(args _args)  
 {  
   MMSPriceUpdatePublishDataController  controller = MMSPriceUpdatePublishDataController::construct();  
   controller.startOperation();  
 }  
 private static MMSPriceUpdatePublishDataController construct(SysOperationExecutionMode _mode = SysOperationExecutionMode::ReliableAsynchronous)  
 {  
   MMSPriceUpdatePublishDataController  controller = new MMSPriceUpdatePublishDataController(classStr(MMSPriceUpdatePublishData),methodStr(MMSPriceUpdatePublishData, run), _mode);  
   return controller;  
 }  
 public boolean showQuerySelectButton(str parameterName)  
 {  
   return false;  
 }  
Also set the Object property on the menu item as the name of your controller class.

Wednesday, July 17, 2013

Posting trade agreements

Posting trade agreements is not a straightforward thing and i found it during a recent assignment. Trade agreements broadly revolve around three main tables, PriceDiscAdmTable, PriceDiscAdmTrans and PriceDiscTable and posting is handled via class PriceDiscAdmCheckPost.

So i create a journal header and fill the journal lines (details in another blog maybe) and call the below method to do the posting.

 void postTradeAgreement(PriceDiscAdmTable  _priceJourHeader)  
 {  
   PriceDiscAdmCheckPost    jourPost;  
   PriceDiscTable            tradeTable;  
   InfologData               infologData;  
   //Post  
   jourPost = new PriceDiscAdmCheckPost(false);  
   infologData = infolog.infologData();          // store infolog data  
   infolog.clear();                    // if you don't clear the infolog, posting errors out.  
   jourPost.initJournalNum(_priceJourHeader.JournalNum);  
   jourPost.run();  
   infolog.import(infologData);              // import infolog data  
 }  

See anything strange?
I do three things related to Infolog.
1. Store the contents. I am storing the contents of infolog (my logic needs to show info to user later) in a data type InfologData, which is a container.

2. Clear the infolog. If i dont clear the infolog just before i hit run() method to post, i get an error which makes no sense.

3. Import the infolog contents again.

Anybody knows a better way?

Default unit on a Product

While writing logic to create new products through code, there was a discussion to have the Purch/Invent/Sales unit id on a Product to be defaulted to ‘Each’. And idea was to hardcode it.
This unit id is required by AX for trade agreements creation.

While trying to code this, we found a parameter setting on Inventory parameters form that lets the user parameterise it instead of harcoding.


Wednesday, July 3, 2013

List page controls design

This would be a quick post. More so for my remembrance than for enlightening public in general :)

Controlling the visibility of a form's controls and action pane buttons is something very common.
But doing so for a list page is not so common.

For a normal form, to make a field invisible you would write something like below in form's init() method.

 VendTable_ds.object(fieldNum(VendTable, yourField)).visible(false);  

For a list page, you would write something like below in that list page's interaction class's initialized() method.

 this.listPage().listPageFieldVisible(formControlStr(VendTableListPage, VendTable_YourField), false);  

More features
this.listPage().listPageArgs().menuItemName() - would let you control the list page's behavior depending on which menu item is your page getting called from.

this.listPage().actionPaneControlVisible and this.listPage().actionPaneControlEnabled - for controlling action panes behavior.

I refered VendTableListPageInteraction class for this post. Cheers.

Cross company traversing

Today's discussion is around traversing a table across companies. In our example, a record sits in a custom parameters table, which needs to be updated. Instinctively first thing to check would be  the SaveDataPerCompany property of the table, which in our case is set to Yes. So this table stores records per company and for implementing the feature in discussion we will forcefully update the record across all companies by overriding the table's update method.

Logic centers around
1. Traversing DataArea table, which is a system table containing all legal entities
2. Using keyword changeCompany which swaps the companies one by one and
3. Clearing the table object after each change, failing to do so makes the logic not work.

 public void update()   
 {   
   YourTable yourtable;  
   DataArea DataArea;   
   super();   
   while select DataArea where !DataArea.isVirtual   
   {   
     changecompany (DataArea.Id)   
     {   
       yourtable= null;   
       ttsBegin;   
       yourtable= Yourtable::find(true);        
       if (yourtable.RecId)   
       {   
         yourtable.Field = "";   
         yourtable.update();   
       }   
       ttsCommit;   
     }   
   }   
 }