Wednesday 19 December 2012

Create and Post Trade agreement using X++ , AX 2012

Hi , below job will create Trade agreement in AX 2012.


static void idbExecutePricPriceDiscJourSvcJob(Args _args)
{
    // PricePrice Vars
    PricePriceDiscJournalService            PriceDiscSvc;
    PricePriceDiscJournal                   PriceDiscJour;
    PricePriceDiscJournal_PriceDiscAdmTrans PriceDiscJourAdmTrans;
    PricePriceDiscJournal_InventDim         PriceDiscJourDim;
   
    // keys return from create process
    AifEntityKeyList                        keys;
 
    PriceDiscSvc = PricePriceDiscJournalService::construct();
    PriceDiscJour = new PricePriceDiscJournal();
    PriceDiscJourAdmTrans = PriceDiscJour.createPriceDiscAdmTrans().addNew();
    PriceDiscJourDim = PriceDiscJourAdmTrans.createInventDim().addNew();

    // Set PriceDiscJourDim
    PriceDiscJourDim.parminventDimId("your dim id");

    // Set PriceDiscJourAdmTrans
   // PriceDiscJourAdmTrans.parmInventDim().add(PriceDiscJourDim);
    PriceDiscJourAdmTrans.parmItemRelation(InventTable::findByProduct( your product).ItemId);
    PriceDiscJourAdmTrans.parmItemCode(TableGroupAll::Table);
    PriceDiscJourAdmTrans.parmAmount(100.00);
    PriceDiscJourAdmTrans.parmFromDate(today());
    PriceDiscJourAdmTrans.parmAccountCode(TableGroupAll::All);
    PriceDiscJourAdmTrans.parmrelation(PriceType::PriceSales);
    PriceDiscJourAdmTrans.parmCurrency("USD");
   

    // Post PriceDiscJour
    keys = PriceDiscSvc.create(PriceDiscJour);
        }
    }
}



How ever , this will only create trade agreement .
If you want to post automatically, then you neeed to modify the "priceDiscAdmCheckPost" method of class


public void priceDiscAdmCheckPost()
{
    PriceDiscAdmCheckPost   priceDiscAdmCheckPost = new PriceDiscAdmCheckPost(false);//To make sure posting is happen

    if (initNoErrorsInInfolog == infolog.num(Exception::Error))
    {
        priceDiscAdmCheckPost.initJournalNum(priceDiscAdmTable.JournalNum);
        priceDiscAdmCheckPost.run();
    }
}


Wednesday 7 November 2012

Create Pull jobs for newly created Tables in AX retail 2012


How To Create Pull  jobs for newly created Tables in AX retail 2012.

For creating Pull  jobs for newely created tables, we need to follow the following steps :

1 . Create a new table  as below :
 2.Add below fields in table other than your normal fields :

RetailTerminalId
RetailStoreId
RetailStatementId
RetailStaffId
ReplicationCounter

3.Add below two methods in your table :



  public RetailReplicationCounter maxReplicationCounterFromOrigin(RetailConnDistributionLocationId _locationId)
{
    RetailPosBatchTable  posBatchTable;
    RetailTerminalTable terminalTable;

    if (_locationId)
    {
        if (RetailStoreTable::find(_locationId))
        {
            select maxof(ReplicationCounter) from posBatchTable
            where posBatchTable.StoreId == _locationId;
        }
        else
        {
            terminalTable = RetailTerminalTable::find(_locationId);
            if (terminalTable)
            {
                select maxof(ReplicationCounter) from posBatchTable
                where posBatchTable.TerminalId == terminalTable.TerminalId;
            }
        }
    }

    return posBatchTable.ReplicationCounter;
}



public void setMaxReplicationCounter(RetailConnDistributionLocationId _locationId, RetailReplicationCounter _counter)
{
    RetailPosBatchTable  posBatchTable;
    RetailTerminalTable terminalTable;

    if (_locationId)
    {
        if (RetailStoreTable::find(_locationId))
        {
            ttsbegin;

            while select forupdate posBatchTable
            where posBatchTable.StoreId == _locationId
            && posBatchTable.ReplicationCounter >= _counter
            {
                posBatchTable.ReplicationCounter = _counter;
                posBatchTable.update();
            }

            ttscommit;
        }
        else
        {
            terminalTable = RetailTerminalTable::find(_locationId);
            if (terminalTable)
            {
                ttsbegin;

                while select forupdate posBatchTable
                where posBatchTable.TerminalId == terminalTable.TerminalId
                && posBatchTable.ReplicationCounter >= _counter
                {
                    posBatchTable.ReplicationCounter = _counter;
                    posBatchTable.update();
                }

                ttscommit;
            }
        }
    }
}



Replace the RetailPosBatchTable   with your table name.

4. Go to Retail ->Setup ->Retail Scheduler -> Distribution Location :
Select your distribution Location and click on Location table , select the table for which you want to pull data,click on Location fields , now you can add fields either Manually or you can use function button provided.
[Make sure to select only those fields which are available in corresponding AX table,else AX will throw error , filed in not available in table]
5. Now go to Retail ->Setup ->Retail Scheduler ->Scheduler subjob
Create a new subjob :

And set the important fields as below :

6.Click on Create TempDBStaging table , which will make a temporary table TableX .
TableX is being used by AX to hold staging data.
7. Now either you can create a new P-job or you can add this sub job in existing P-job.

Run the P-job and data will be pulled to AX from Store
[Off-course you should have retail settings in Place :) ]









Buf2Buf() vs Data() method

Hi all,
while creating a duplicate/replica of a record , generally we use table.data() method , in place of passing each  field one by one. The only issue with data() method is it copies the system fields as well , and hence if we are inserting data across companies , we can not use data() method.

So what should be solution for this, AX also provides one more generic method Buf2Buf(SourceRecord,TargetRecord) , the only difference between Buf2Buf() and data() method is that Buf2Buf() does not copy system fields.

Hence for intercompany insert of data , we should use Buf2Buf() method with changeCompany() method().


thanks,

Wednesday 31 October 2012

Unit of Work

Hi all.

Unit of Work is a new framework , which is being introduced in AX 2012.
Now let us explore what is need of having this framework  :

Suppose we do have Two tables , TableHeader and TableLine.
Now we want to insert bulk data in these two tables , TableLine is linked with TableHeader by RecID.

So first we need to insert the data in TableHeader and then pass the recid of this table to Tableline and insert the record. So there are 2 major issue is : We need to hold recId of Parent table and pass to Tableline and we have to hit database with each insert.

Now Unit of Work framework come into picture and helps us , we dont have to hold the recid of parent table and also we can insert all data in a single trip . How ... Let us Implement this :

1.Create 2 table SKU_Table and SKU_Line.
2.SKU_Line is related to SKU_Table by RecId.
3.Go to relation of table and make sure property CreateNavigationPropertyMethods = true
by making this property true , system will add appropriate methods to table SKU_Line
4 . Now we are ready to go


public void Insert()
{
    SKU_Table                       SKU_Table;
    SKU_Line                        SKU_Line;      
    UnitofWork                      UnitofWork;
 
    UnitofWork                      =  new UnitofWork();
    while select aaaaa
    {
     //insert data in parent table
        SKU_Table.clear();   
        SKU_Table.somefield                 = cccc;      
        UnitofWork.insertonSaveChanges(SKU_Table);
   
        while select bbbb
        {
               //insert data in child table
            SKU_Line.clear();
            SKU_Line.somefield                 = ddddd;
            SKU_Line.SKU_Table(SKU_Table);
            UnitofWork.insertonSaveChanges(SKU_Line);
        }      
    }
//Now insert data in a single trip
    UnitofWork.saveChanges();
}

Thursday 18 October 2012

Create Product Variant using X++


How to create a product variant with Dimensions provided  

ecoResDistinctProductVariant        ecoResDistinctProductVariant;
    EcoResProductVariantDimensionValue  EcoResProductVariantDimensionValue;
    RefRecId                                   ecoResDistinctProductVariantRecId;
    EcoResProductReleaseManagerBase     releaseManager;
    container productDimensions;


//Create a container to hold dimension values
productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer(ConfigurationName,
                                                                                        Size,
                                                                                        ColorId,
                                                                                        InventStyleId);
//Create Product search name

ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(
                                                                   EcoResProduct::find(InventTable.Product).productNumber(),
                                                                    productDimensions);

//Create Product variant with Product and dimensions provided

    ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(InventTable.Product,ecoResDistinctProductVariant.DisplayProductNumber,productDimensions);

//Find newly created Product Variant
    ecoResDistinctProductVariant = ecoResDistinctProductVariant::find(ecoResDistinctProductVariantRecId);
//Now release the Product variant
    releaseManager = EcoResProductReleaseManagerBase::newFromProduct(ecoResDistinctProductVariant);
    releaseManager.release();



Hope this will help u guys :)



Wednesday 10 October 2012

create Product master by using X++ , AX 2012

Following code to create Product master by using X++
static void ProductCreate(Args _args)
{

EcoResProductService erProdSvc;
EcoResEcoResProduct EcoResProd;
EcoResEcoResProduct_Product_Master ProdMast;
EcoResEcoResProduct_Translation Translation;
EcoResEcoResProduct_Identifier Identifier;
EcoResEcoResProduct_ProductDimGroup ProdDimGroup;

//Initialize the service object
erProdSvc = EcoResProductService::construct();
EcoResProd = new EcoResEcoResProduct();
ProdMast = new EcoResEcoResProduct_Product_Master();

//ProdDimGroup = new EcoResEcoResProduct_ProductDimGroup();
//Newly created and initialize prodMast
ProdMast.parmDisplayProductNumber("IDB-PM002");
ProdMast.parmProductType(EcoResProductType::Item);
ProdMast.parmSearchName("IDB Product Master 1");


//Create a new translation object:
Translation = ProdMast.createTranslation().addNew();

Translation.parmDescription("IDB product Master");
Translation.parmLanguageId("en-us");
Translation.parmName("IDB Product Master 1");
Identifier = ProdMast.createIdentifier().addNew();

Identifier.parmProductNumber("IDB-PM002");
ProdDimGroup = ProdMast.createProductDimGroup().addNew();
ProdDimGroup.parmProduct("IDB-PM001");
ProdDimGroup.parmProductDimensionGroup("Col");


ProdMast.parmVariantConfigurationTechnology(EcoResVariantConfigurationTechnologyType::PredefinedVariants);
EcoResProd.createProduct().add(ProdMast);

erProdSvc.create(EcoResProd);

Lookup for RealEdit Control in Ax2012

Lookup for RealEdit Control in Ax2012

we cant build the lookup for RealEdit control by using SysLookup functionality for that we have to customize the SysTableLookup class method performFormLookup()
Add the case for switch for handling the FormRealControl.
FormRealControl     callingRealControl;


 case classNum(FormRealControl):
            callingRealControl = callingControl;
            callingRealControl.performFormLookup(this.formRun());
            break;

Tuesday 4 September 2012

Function DimensionValidation::validateByTree has been incorrectly called.

While Creating General Journal using X++ , we faced this error:
Function DimensionValidation::validateByTree has been incorrectly called.

First let us go through , why we are getting this :

This error is coming because we are passing the account and offset account in wrong manner to LedgerJournalTrans . The field OffsetLedgerDimension and LedgerDimension are of type :
DimensionDynamicAccount , so before passigng the Account to these field , we need to convert the account to correct type . How to do it:

For non ledger account(Bank, customer ..............) , we do have the API :
DimensionStorage::getDynamicAccount(A/cNo ,LedgerJournalACType::Bank);

we need to pass this AS :

LedgerJournalTrans .LedgerDimension  = DimensionStorage::getDynamicAccount(Hedging_table.AccountID,LedgerJournalACType::Bank);

There you go.......

But what to do with Ledger Account , you still can not pass these account directly as well .

Well there is one more API which can help us :

LedgerJournalTrans .getLedgerDimensionForLedgerType(Ledger A/c,jourTrans.Company);
LedgerJournalTrans .LedgerDimension  = 
LedgerJournalTrans .getLedgerDimensionForLedgerType(Ledger A/c,jourTrans.Company);



Please put your comment ,if you find it helpful or looking for some more info......


Thanks,

Monday 27 August 2012

Inventory Dimension enable /disable based upon item selected


Inventory Dimension enable /disable based upon item selected

Hi Friends, Well we have seen a no of times we face the issue to have  the correct Inventory dimension field enabled/disabled based upon Item selected . How to achieve this :
1.       Add below declaration in your class declaration of form

         public class FormRun extends ObjectRun
        {
          InventDimCtrl_Frm       inventDimFormSetup;
        }
2.       Add below piece in form’s Init method :
public void init()
{
    element.updateDesign(InventDimFormDesignUpdate::Init);
}


3.       Add below method :
InventDimCtrl_Frm inventDimSetupObject()
{
    return inventDimFormSetup;
}

4.   Add below method :
void updateDesign(InventDimFormDesignUpdate mode)
{
    inventDimParm   inventDimParmVisible;
    inventDimParm   inventDimParmEnabled;

    switch (mode)
    {
        case InventDimFormDesignUpdate::Init          :
        case InventDimFormDesignUpdate::LinkActive    :
            if (!inventDimFormSetup)
            {
                inventDimFormSetup  = InventDimCtrl::newFromForm(element);
            }
            inventDimFormSetup.parmSkipOnHandLookUp(true);

            if (element.args().dataset() == tableNum(datasource))
            {
                inventDimParmVisible = EcoResProductDimGroupSetup::newItemId(Item_Adjustment.ItemId).inventDimParmActiveDimensions();
            }
            else
            {
                inventDimParmVisible.initProductDimensionsAllGroups();
            }
            inventDimFormSetup.parmDimParmVisibleGrid(inventDimParmVisible);
            break;

        case InventDimFormDesignUpdate::Active        :
            inventDimFormSetup.formActiveSetup();
            inventDimParmEnabled = EcoResProductDimGroupSetup::newItemId(datasource.ItemId).inventDimParmActiveDimensions();
            inventDimParmEnabled.InventLocationIdFlag = true;
            inventDimFormSetup.parmDimParmEnabled(inventDimParmEnabled);
            inventDimFormSetup.formSetControls(true);
            //inventDimFormSetup.

            break;

        case InventDimFormDesignUpdate::FieldChange   :
            inventDimFormSetup.formActiveSetup();
            inventDimParmEnabled = EcoResProductDimGroupSetup::newItemId(datasource.ItemId).inventDimParmActiveDimensions();
            inventDimFormSetup.parmDimParmEnabled(inventDimParmEnabled);
            //inventDimFormSetup.
            inventDimFormSetup.formSetControls(true);
            break;

        default :
            throw error(strfmt("@SYS54195",funcname()));
    }
}


5.       Add below lines in Active method of DS :
public int active()
{
    int ret;
    ret = super();
    element.updateDesign(InventDimFormDesignUpdate::Active);
   
    return ret;
}

6      Add below line in ItemId’s modified method :
element.updateDesign(InventDimFormDesignUpdate::FieldChange);


Well you are ready to go :
 PS : You want to enable\ disable one particular  Dimension field irrespective  of Item selected , how to do : 
Simple put the corresponding flag true or false as
inventDimParmEnabled.InventLocationIdFlag = true;


Hope this will help you guys   J

Hide Enum values in Form Control


Hide Enum values in Form Control :
Well there are various situations where you  want to show only subset of Enum values :
How to do it :
Well add below , In Class declaration of form
public class FormRun extends ObjectRun
{
    SysFormEnumComboBox         sysFormEnumComboBox;
    Set                         enumSet;// = new Set(Types::Enum);
}

Add below piece of code in Form’s init method :
public void init()
{
    enumSet= new Set(Types::Enum);
    enumSet.add(Enum::A);
    enumSet.add(Enum::B);
    enumSet.add(Enum::C);
    enumSet.add(Enum::D);
   
    sysFormEnumComboBox  = sysFormEnumComboBox::newParameters(element,element.controlId(formControlStr(Form,control)),enumNum(enum),enumSet);
    super();
  
}

Well, Please have a deep look on second Argument ,which is control ID.

Friday 24 August 2012

Disable/Enable button based upon records available in List page



Disable/Enable button based upon records available in List page .
I created a new List page , and was surprised that even though there is no record available in List page ,
Edit and Edit in Grid buttons are enabled , which lead to issues:

 
So what is  solution for this :
Simple  set the”NeededRecords”  property of button to “yes”.

Tuesday 21 August 2012

Implement Catch Weight


Implement Catch Weight in New Form 


Before Starting Implementation , Let us have a Quick Look on this functionlaity 
You often use catch weight products in industries where products can vary slightly by weight or size, or both, such as the food industry. Catch weight products use two units of measure – an inventory unit and a catch weight unit. The inventory unit is the unit of measure in which the product is weighed and invoiced. The catch weight unit is the unit in which the inventory transactions are performed, such as sold, received, transferred, picked, and shipped. The nominal quantity represents the conversion between the catch weight unit and the inventory unit. Minimum and maximum quantities represent the allowed interval in which the inventory quantity can vary.

Now go for Implementation :

1 . Create a new class Extend with PdsCWFormCtrl_Std
            Override the method as required.
2. In table create two fields : Qty and PdsCWQty
3. Add display method to table :
public display PdsCWUnitId pdsCWUnitId()
{
    return PdsCatchWeight::cwUnitId(this.ItemId);
}


4.In Classdeclaration of Form   add below line :
PdsCWFormCtrl                       cwFormCtrl;
 5.In init method of Form :
        if (#PdsCatchWeightEnabled)
        {
            cwFormCtrl = yourclass::newFromForm(element);
            cwFormCtrl.initPre();
        }
       
        super();
    if (cwFormCtrl)
    {
        cwFormCtrl.parmBuffer(YourTable);
        cwFormCtrl.initPost();
    }
    6.In init method of Datasource add :

public void init()
{
    super();
    if (cwFormCtrl)
    {
        cwFormCtrl.dataSourceInitPost(YourTable);
    }
   
}
\
7.Override the Validatewrite of DS :
public boolean validateWrite()
{
    boolean ret;

    ret = super();

    if (cwFormCtrl)
    {
        ret = cwFormCtrl.dataSourceValidateWrite() && ret;
    }
   
    return ret;
}
8.Override the Active method of DS
if (cwFormCtrl)
    {
        cwFormCtrl.dataSourceActivePost();
    }

9.Override the modified of ItemId and QTY as
           
  if (cwFormCtrl)
    {
        cwFormCtrl.fieldModified(fieldnum(WO_line, ItemId));
    }

Thursday 26 July 2012

"Error executing code: The field with ID '60001' does not exist in table 'RetailStoreTable'."


error : "Error executing code: The field with ID '60001' does not exist in table 'RetailStoreTable'."

Hi I got this error , when I was trying to update data in RetailStore table.To my surprise this field id was not added to RetailStore Table , then why system was checking for this field id : I debugged further and then found that there is one table : RetailConnCreateActionsByField , which is holding these values together : Table RetailStore mapped with fieldId 60001 , hence system was forced to check this field .

Solution : Remove this entry from Table J.

Will be back 

Friday 20 April 2012

Open AX 2012 in dev environment

Every time , when you open AX 2012 , you need to press CTRL +D , to open the development work space, 
what if you want to open the Development work space directly , Its very simple ,Just go to properties of shortcut of AX 2012 and update the Target values by adding -development , :) 

Monday 6 February 2012

Get all dimensions available in AX for any given Environment


How to get all dimensions available in any environment , the below job will help us
static void getAllDimension(Args _args)
{
    Counter         idx;
    Dimension       dimension;
    DimensionCode   dimensionCode;
    str             name;
    ;
    for (idx = 1; idx <= dimof(dimension); idx++)
    {
        dimensionCode = Dimensions::arrayIdx2Code(idx);
        name = enum2str(dimensionCode);
        // if (name == 'B') ...
        info(strfmt("%1: %2", idx, name));
    }
}

Request for the permission of type 'SqlStatementExecutePermission' failed.

While running one Job , where I was trying to execute one SQL statement in AX, I got the below stack trace :


Request for the permission of type 'SqlStatementExecutePermission' failed.
(S)\Classes\SqlStatementExecutePermission\demand
(S)\Classes\Statement\executeQuery
(C)\Jobs\test - line 21


So what is the solution for this , Very simple , we need to run this job on Server , So now how to do it :
here is solution , create a menu item of type action, give the object type as Job ,and object name , and set the property Run on as" Server ".

There you go , Problem solved  :) 

Get Database size using X++

How to get size of Database being used by AX ,below job can help you :



static void GetDBSize(Args _args)
{
LoginProperty loginProp;
ODBCConnection conn;
Resultset resultSet, resultSetCount;
Statement statement1, statement2;
str test;
real s;
SysSQLSystemInfo   systemInfo =  SysSQLSystemInfo::construct();

;

 test = strfmt( "SELECT size FROM sys.master_files where name = '%1'",systemInfo.getloginDatabase()  );
loginProp = new LoginProperty();

loginProp.setServer(systemInfo.getLoginServer());
loginProp.setDatabase(systemInfo.getloginDatabase());

conn = new ODBCConnection(loginProp);

statement1 = conn.createStatement();
resultSet = statement1.executeQuery(test);

while (resultSet.next())
{
s = str2int(resultSet.getString(1));
s = s*8 /1024;
info(strfmt("%1  MB",s));
}
}

Wednesday 18 January 2012

Get all objects from a Project


If you want to get all objects for a given project , the below job will help .

static void listAllObjectosFromProject(Args _args)
{

  ProjName        projName = "Your Project Name";

  ProjectListNode   list = infolog.projectRootNode().AOTfindChild("Shared");

  TreeNodeIterator  ir = list.AOTiterator();
  ProjectNode      pnProj;
  ProjectNode      pn = list.AOTfindChild(projName);

  void searchAllObj(projectNode rootNode)
  {
    #TreeNodeSysNodeType

    TreeNode          childNode;
    TreeNodeIterator      rootNodeIterator;
    ;

    if (rootNode)
    {
      rootNodeIterator = rootNode.AOTiterator();
      childNode = rootNodeIterator.next();
      while (childnode)
      {

        if (childNode.AOTgetNodeType() == #NT_PROJECT_GROUP)
         searchAllObj(childNode);

        else
          info(strfmt("Group :%1 - Object: %2", rootNode.AOTname(), childNode.AOTname()));

        childNode = rootNodeIterator.next();
      }
    }
  }
  ;

  if (pn)
  {
    info(strFmt("Project %1:", projName));
    pnProj = pn.loadForInspection();
    searchAllObj(pnProj);
    pnproj.treeNodeRelease();
  }
  else
    info("Projet objects");
}

Tuesday 3 January 2012

Filter automatically on Form

Hi , There may be some requirement that we need to have Filter by grid on form available.
One way of achieving this is , Go to Tools -> Options and Mark Filed by grid on default .
The disadvantage of this , all form will have this functionality and System will slow down.
Then , how to enforce this on only selected forms :
Here you go , place the below line of code in Run method of form after Super();

 this.task(2855);

;
 you will have Filter on only that particular form.

Thanks

Logo for New module created in AX


Hi! I have received the following task: Create new module in Dynamics AX and assign image or logo to this module.
Module is created very easy:Go to the AOT > Menus and create new menu.  For example TestMenu.
1.    Add menu item. For example CustTable menu item.
2.    Then create new menu reference in the MainMenu menu:
o    On the MainMenu menu clicks the right mouse button and select New > Menu reference. TheSelect: Menus windows opens.
o    Drag and drop the TestMenu menu from Select:Menus window to the MainMenu.

This is all. The new module have been added. Reopen Dynamics AX application.
The new modules appears without image (to move module on the top position clicks the Microsoft Dynamics AX >View > Navigate Pane Options…):


 Select the TestMenu menu in the AOT, click right mouse button and selectProperties. There are two properties NoramlImage and NormalResource.


In the NormalImage property the file path to the logo could be specified. But if we create product for sell then we can not specify the exact file path because each Customer will have own path.
In the NormalResource property the image id could be specified. It is suitable for our requirements. Let’s add image in Dynamics AX:
1.    Go to the AOT > Resources. Click right mouse button and select Create form file.
2.    Specify the file path and click Open.
The new image resource will be created:


But this resource doesn’t have the resource id or image id property. Even more in the NormalResourceproperty only the resource id of standard image can be specified. Standard image could be review here AOTForms > SysImageResources.
Trick: we will use the NormalImage property and Logo_image_png resource.
Create the following static method:
static client void addImageToModule()
{
TreeNode treeNodeMenu;
;
treeNodeMenu = SysDictMenu::newMenuName(menustr(TestMenu)).parmTreeNode();
if (treeNodeMenu)
{
treeNodeMenu.AOTsetProperty(identifierstr(NormalImage), SysResource::getImagePath(resourcestr(Logo_image_png)));
treeNodeMenu.AOTsave();
}
}
Call this method in the \Classes\Application\startupPost method:

// No SYS code must exist in this method
// If you need the startup command, look in the class SysStartupCmd
void startupPost()
{
;
Class1::addImageToModule();
}

Reopen application.


All the best Description: ;)