Search This Blog

Wednesday, August 8, 2012

AX2012 Methods on Queries and Forms Cannot Compile to CIL


Classes, tables, and enums are types in the X++ language. X++ types can be compiled to CIL. The queries and forms in the AOT are not X++ types, and they cannot be compiled to CIL. This means there are a few minor cases where calls from CIL to X++ p-code can cause an exception.

Suppose a method that is running as CIL calls a method on a query. The query method calls the ClassFactory system class of Microsoft Dynamics AX. This case causes an exception to be thrown. The problem is that the CIL session does not have access to all the system classes, yet the query method makes a call to a system class.


X++ Functions that are Not Supported in CIL
X++ language functions that run strings of dynamically written X++ code are not supported when compiled to CIL. The following X++ functions are not supported when compiled to CIL:
  • evalbuf
  • runbuf


Thursday, August 2, 2012

Dynamics AX2012 Terms and Explanation about Models

Dynamics AX2012 Terms and Explanations for each term.
Term
Definition
Metadata
Information about the properties or structure of data in the Application Object Tree (AOT) that is not part of the data values. Everything in the AOT is metadata.
Application layer
A single layer of the Microsoft Dynamics AX 2012 application within a model store. Elements in higher layers override elements in lower layers.
Model
A named set of elements in a given application layer. Each layer consists of one or more models, of which one is a system-generated layer model.
Model element
A single piece of metadata. For instance, a table definition is a model element. Any one element in a layer belongs to exactly one model; that is, no element can belong to two different models nor can it belong to any model.
Model file (.axmodel)
A model that has been exported from a model store. This file is the chief vehicle of metadata deployment in Microsoft Dynamics AX 2012.
Model store file (.axmodelstore)
A complete model store that has been exported from the database. The file includes all metadata, compiled artifacts, CIL code, and security artifacts. The file is used for moving consistent metadata between environments with minimum downtime.
Model store
A collection of tables in the Microsoft Dynamics AX 2012 database that house the application metadata. The model store is analogous to the AOD file share in Microsoft Dynamics AX 2009.
Generated data
Data that is generated by Microsoft Dynamics AX during development.
Transactional data
Data that describes business transactions and the state of the business.
Configuration data
Data concerning how Microsoft Dynamics AX 2012 is configured. This data includes the following subcategories:
Environment: Computer-environment–specific data. An example of environment data is the list of servers running Microsoft SQL Server® Reporting Services that Microsoft Dynamics AX 2012 is configured to use. If this data is moved, it needs to be corrected to account for new server locations.
System: Parameter settings for the Application Object Server (AOS) such as which database to connect to, or for Enterprise Portal forms.
Application: Number sequences, invoicing profiles, or other data that relates directly to the application.
Reference data
Data that is characterized by shared read operations and infrequent changes. Examples of reference data include flight schedules and product catalogs. Windows Server® AppFabric offers the local cache feature for storing this type of data.
Master data
The critical data of a business, such as customer, product, location, employee, and asset. Master data falls generally into four groupings: people, things, places, and concepts. It also can be further categorized. For example, within people, there are customer, employee, and salesperson categories. Within things, there are product, part, store, and asset categories. Within concepts, there are categories like contract, warrantee, and licenses. Finally, within places, there are office location and geographic division categories.
Definition group
A collection of tables that defines what will be exported by using the data export feature.
Common Intermediate Language (CIL)
The Common Intermediate Language instruction set is part of the specification of the Common Language Infrastructure from Microsoft and is more widely known as .NET. An older name for CIL was Microsoft intermediate language (MSIL).

Wednesday, August 1, 2012

Create multiple items using EcoresproductService in AX2012


creating multiple items using the ecoresecoresproduct service by calling one time create Function. This code was written by my friend Jesper Clausen, I personally thanks hims for providing this code.

static void ImportProducts(Args _args)
{
    EcoResEcoResProduct                     ecoResEcoResProduct;
    EcoResEcoResProduct_Product_Distinct    ProdDist;   
    EcoResEcoResProduct_translation         translation;
    EcoResEcoResProduct_Identifier          identifier;
    EcoResEcoResProduct_ProductDimGroup     prodDimGroup;
    EcoResEcoResProduct_StorageDimGroup     storDimGroup;
    EcoResEcoResProduct_TrackingDimGroup    tracDimGroup;

    EcoResProductService                    ecoresPRoductService;

    CommaIo                                 file;
    container                               readCon;

    Dialog                                  d;
    DialogField                             df1, df2;
    EcoResProductDisplayProductNumber       ProductDisplayProductNumber;
    // Create a comma separated file as input with col1 = product and col2 = description
     and remaining fields.
    ;
    d = new Dialog("Import items");
    df1 = d.addField(ExtendedTypeStr("FilenameOpen"));
    ecoresPRoductService=EcoResProductService::construct();
    ecoResEcoResProduct= new EcoResEcoResProduct();
    if (d.run())
    {
        file = new CommaIo(df1.value(), 'r');
        file.inFieldDelimiter(';');
        while (file.status() == IO_Status::Ok)
        {
            readCon = file.read();
            ProdDist = new EcoResEcoResProduct_Product_Distinct();
            ProdDist.parmDisplayProductNumber(strLRTrim(conPeek(readCon,1)));
            ProdDist.parmProductType(EcoResProductType::Item);
            ProdDist.parmSearchName(strLRTrim(conPeek(readCon,2)));

            // Create the translation object
            translation = ProdDist.createTranslation().addNew();
            translation.parmDescription(strLRTrim(conPeek(readCon,2)));
            translation.parmLanguageId("en-us");
            translation.parmName(strLRTrim(conPeek(readCon,1)));
           
            // Create the identifier object
            Identifier = ProdDist.createIdentifier().addNew();
            identifier.parmProductNumber(strLRTrim(conPeek(readCon,1)));
           
            // Create the StorageDimgroup object
            storDimGroup = ProdDist.createStorageDimGroup().addNew();
            storDimGroup.parmProduct(strLRTrim(conPeek(readCon,1)));
            storDimGroup.parmStorageDimensionGroup("Con-Dim");

            // Create the TrackingDimGroup object
            tracDimGroup = ProdDist.createTrackingDimGroup().addNew();
            tracDimGroup.parmProduct(strLRTrim(conPeek(readCon,1)));
            tracDimGroup.parmTrackingDimensionGroup("Lean-Dim1");

            // checking this product is already Exists or not .
            if(ecoResEcoResProduct.existsProduct())
            {
                ecoResEcoResProduct.parmProduct().add(ProdDist);
            }
            else
            {
                ecoResEcoResProduct.createProduct().add(ProdDist);
            }
        }
        // call create function to create products.
        ecoresPRoductService.create(ecoResEcoResProduct);
    }

}

Thursday, July 26, 2012

Data Migration Framework for AX2012 was released.


Data Migration Framework beta for AX2012  was released.

Please go through about this in the following link and you can download the setup


Tuesday, July 24, 2012

Import Ax2012 Routes from CSV

We are importing route  from CSV.
We are dealing with the following tables for importing routes.

 RouteTable; RouteVersion,  Route,   RouteOpr .

For any item there must be only one RouteVersion record per item.So before importing we have to find whether routeversion exists or not.

There is 1:1 relation between RouteTable and RouteVersion records during the import.

If the RouteVersion record exists, then the RouteTable record must exist as well and we should not be created.

Class declaration


class krishh_ImportRoute 
{
    //Define your csv file column name with positions
    #define.RouteTable_Name_ColumnNum(1)
    #define.RouteVersion_ItemId_ColumnNum(2)
    #define.Route_OprId_ColumnNum(3)
    #define.Route_OprNum_ColumnNum(4)
    #define.Route_OprNumNext_ColumnNum(5)
    #define.RouteOpr_ProcessTime_ColumnNum(6)
    #define.RouteOpr_RouteGroupId_ColumnNum(7)
    #define.RouteOpr_RouteType_ColumnNum(8)
    #define.RouteOpr_SetupTime_ColumnNum(9)
    #define.RouteOpr_ToHours_ColumnNum(10)
    #define.RouteOpr_WrkCtrIdCost_ColumnNum(11)
    #define.WrkCtrActivityResourceRequirement_WrkCtrId_ColumnNum(12)

    RouteTable      routeTable;
    RouteVersion    routeVersion;
    Route           route;
    RouteOpr        routeOpr;
    ItemId          itemIdRouteVersion;
    NumberSeq       numberSeq;
}
// execute the route imports here container is the values that we read from CSV file.

public void run(container _item)
{
    ttsBegin;
    this.initRouteVersion(_item);
    this.createRouteTable(_item);
    this.createRoute(_item);
    this.createRouteOpr(_item);
    this.createWrkCtrActivity(_item);
    ttsCommit;
}
protected void new()
{
    ;
    numberSeq       =   RouteTable::numberSeq(false,true);
}

protected void initRouteVersion(container _conLine)
{
    itemIdRouteVersion  =   conPeek(_conLine,
                                              #RouteVersion_ItemId_ColumnNum);

    // There must be only one RouteVersion record per item
    select firstOnly routeVersion
        where routeVersion.ItemId == itemIdRouteVersion;
}
protected void createRouteTable(container _conLine)
{
    ;
    if(routeVersion.RecId)
    {
        routeTable  =   RouteTable::find(routeVersion.RouteId);
        // There is always 1:1 relation betwean RouteTable and RouteVersion records during the import.
        // If the RouteVersion record exists, then the RouteTable record must exist as well and should not be created.
        return;
    }
    // If it is a new route, then update the last one.
    if(routeTable.RecId     &&
       !routeVersion.RecId)
    {
        this.updateLastRoute();
    }
    routeTable.clear();
    routeTable.initValue();
    routeTable.CheckRoute   =   NoYes::Yes;
    // Approved
    routeTable.Approved     =   NoYes::Yes;
    // Approver
    routeTable.Approver     =   "krishh"
    // Name
    routeTable.Name         =   conPeek(_conLine,
                                                  #RouteTable_Name_ColumnNum);
    // RouteId
    routeTable.RouteId      =   numberSeq.num();
    routeTable.insert();
}
protected void createRouteVersion(container _conLine)
{
    InventDim           inventDim;

    if(routeVersion.RecId)
    {
        return;
    }
    routeVersion.clear();
    routeVersion.initValue();
    // Active
    routeVersion.Active         =   NoYes::Yes;
    // Approved
    routeVersion.Approved       =   NoYes::Yes;
    // Approver
    routeVersion.Approver       =   "Krishh";
    // FromDate
    routeVersion.FromDate       =   dateNull();
    // ItemId
    routeVersion.ItemId         =   itemIdRouteVersion;
    // RouteId
    routeVersion.RouteId        =   routeTable.RouteId;
    // InventDimId
    inventDim.clear();
    inventDim.InventSiteId      =   InventTable::find(routeVersion.ItemId).inventInventSiteId();
    routeVersion.InventDimId    =   InventDim::findOrCreate(inventDim).inventDimId;
    routeVersion.insert();
}


protected void createRoute(container _conLine)
{
   Route routeFieldList;
   ;
   route.clear();
   route.initValue();
   route.RouteId = routeTable.RouteId;
   route.OprId =Conpeek(_conLine,#Route_OprId_ColumnNum);
   route.OprNum = Conpeek(_conLine,#Route_OprNum_ColumnNum);
   route.OprNumNext = Conpeek(_conLine,#Route_OprNumNext_ColumnNum);

   select RecId from routeFieldList where routeFieldList.RouteId == route.RouteId &&                routeFieldList.OprNum == route.OprNum && routeFieldList.OprPriority == route.OprPriority;

        if(routeFieldList.RecId)         {

              // Do not create if it already exists.
                     return;          }
   route.insert();
}


protected void createRouteOpr(container _conLine)
{
    ;
    routeOpr.clear();

    routeOpr.initValue();

    routeOpr.WrkCtrIdCost   =  Conpeek(_conLine,
                                                  #RouteOpr_WrkCtrIdCost_ColumnNum);

    routeOpr.initFromWrkCtrId(routeOpr.WrkCtrIdCost);
    routeOpr.ProcessTime    =   str2num( Conpeek (_conLine,
                                                  #RouteOpr_ProcessTime_ColumnNum));
    routeOpr.RouteGroupId   =    Conpeek (_conLine,
                                                  #RouteOpr_RouteGroupId_ColumnNum);
    routeOpr.RouteType      =    Conpeek (_conLine,
                                                  #RouteOpr_RouteType_ColumnNum) == "Standard" ?
    RouteOprType::Standard : RouteOprType::Vendor;
    routeOpr.SetupTime      =   str2num( Conpeek (_conLine
                                                                          , #RouteOpr_SetupTime_ColumnNum));
    routeOpr.ToHours        =   Conpeek (_conLine,
                                                  #RouteOpr_ToHours_ColumnNum);

    routeOpr.OprId          =   route.OprId;

    routeOpr.ItemCode       =   TableGroupAll::Table;
    routeOpr.ItemRelation   =   routeVersion.ItemId;
    routeOpr.RouteCode      =   RouteAll::Route;
    routeOpr.RouteRelation  =   route.RouteId;
    routeOpr.SiteId         =   routeVersion.inventSiteId();
    if(RouteOpr::exist(routeOpr.OprId,
                       routeOpr.ItemCode,
                       routeOpr.ItemRelation,
                       routeOpr.ConfigId,
                       routeOpr.RouteCode,
                       routeOpr.RouteRelation,
                       routeOpr.SiteId))
    {
        return;
    }
    routeOpr.insert();
}


protected void createWrkCtrActivity(container _conLine)
{
    WrkCtrActivityRequirement           wrkCtrActivityRequirement;
    WrkCtrActivityResourceRequirement   wrkCtrActivityResourceRequirement;
    ;
    wrkCtrActivityRequirement.clear();

    wrkCtrActivityRequirement.ActivityRequirementSet    =   routeOpr.activityRequirementSet().RecId;

    wrkCtrActivityRequirement.RelationshipType          =   WrkCtrActivityRequirementType::Resource;
    wrkCtrActivityRequirement.UsedForJobScheduling      =   NoYes::Yes;

    wrkCtrActivityRequirement.insert();


    wrkCtrActivityResourceRequirement.clear();

    wrkCtrActivityResourceRequirement.setActivityRequirement(wrkCtrActivityRequirement.RecId);

    wrkCtrActivityResourceRequirement.ResourceDataAreaId    =   curExt2dataareaid(tableNum(WrkCtrTable));
    wrkCtrActivityResourceRequirement.WrkCtrId              =  Conpeek(_conLine,
                                                                                  #WrkCtrActivityResourceRequirement_WrkCtrId_ColumnNum);

    wrkCtrActivityResourceRequirement.insert();
}


protected void updateLastRoute()
{
    if(routeTable.RecId)
    {
        routeTable.updateRoute(false);
    }
}










Wednesday, July 18, 2012

Ax2012 Table Keys.

We are going to see the concept of keys on Tables in Ax2012.
These all following keys that we are going though appears in the AOT Table properties window.

Primary Key
The primary key is usually the type of key that other tables, called child tables, refer to when a foreign key field in those other tables need a relational identifier.
When we create a new table in AX2012 the Primary key was enforced by an index that has one field, this field should be unique, by default the primary key is based on Recid field. This is represented as surrogateKey in the table properties primary index.
By default the CreateRecIdIndex property was true and ClusterIndex as surrogateKey.


The ClusterIndex value is given to the underlying Microsoft SQL Server database system as a performance tuning choice. This choice generally controls the physical sequence in which the records are stored in the underlying database.


ReplacementKey
This key is used to define the replacement fields to display in your design when you referred  to some relation using the Recid.
for ex:-
Table B is referring to Table A where the TableB have the Refrecid from Table A, but when you open the form for TableB We cant show the Recid of the TableA in the Presentation,So whatever the field that you want to display, you will define one index on TableA with the fields that you want to show and and index alternateKey property to Yes. define the Replacement key property for the table A as this index.


If a ReplacementKey is chosen, its fields can appear on forms to helpfully identify each record.The ReplacementKey should be a set of fields that represent the natural key.


In AX2012 Relation represents a foreign key.


In Ax2012 we will use different Terms that used to describe the keys, These terms we wont see anywhere in AX physically in property names.


Foriegn Key-In Microsoft Dynamics AX, an AOT node under MyTable > Relations represents a foreign key. 
natural key-A key whose value has meaning to people. Most replacement keys are natural keys.(ReplacementKey).
unique key-this applies to primary keys and to alternate keys. It does not apply to foreign keys. This term emphasizes that all values for a given key must be unique within one table. All fields in a unique key must be not-nullable.

Thursday, July 12, 2012

Perform Lookup on 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;

Monday, July 9, 2012

AX2012 Import Vendors from CSV using VENDVendTableService part2

To use this class method I have created all parmmethods in this class where i am using all those fields in this method to create vendor.
Before seeing this post please read the post That i posted earlier for creating the vendors.

http://krishhdax.blogspot.dk/2012/03/ax2012-import-vendors-from-csv-using.html

This post is just upgrade of my earlier logic to create vendor,multiple contacts informations.


public static void CreateVendor()
{

    VendVendTableService                        vendVendTableService;
    VendVendTable                               vendVendTable;
    VendVendTable_VendTable                     vendTable;
    VendVendTable_DirPartyPostalAddressView     adresss;
    VendVendTable_DirPartyTable_DirOrganiza1    dirPartyTable;
    VendVendTable_DirPartyContactInfoView       contactInfoPhone, contactInfoFax, contactInfoEmail,
                                                                             contactInfoWeb;
    VendVendTable_OrganizationName              organizationName;

    DirContactPersonsService                    dirContactPersonsService;
    DirContactPersons                           dirContactPersons;
    DirContactPersons_ContactPerson             dirContactPersons_ContactPerson;
    DirContactPersons_Person                    dirContactPersons_Person;
    DirContactPersons_PersonName                dirContactPersons_PersonName;

    TaxVATNumTable                              taxVATNumTable;
    LogisticsLocationRole                       logisticsLocationRole =
    LogisticsLocationRole::findBytype(LogisticsLocationRoleType::Business);

    AifDimensionAttributeValueSet               aifDimensionAttributeValueSet;
    AifDimensionAttributeValue                  aifDimensionAttributeValue;

    AifEntityKeyList                            aifEntityKeyList, aifEntityKeyList_DirContactPerson;

    str                                         fName, mName, lName;
    ;

    vendVendTableService = vendVendTableService::construct();

    vendVendTable = new VendVendTable();
    vendTable = vendVendTable.createVendTable().addNew();

    vendTable.parmAccountNum(vendorAccount);
    vendTable.parmItemBuyerGroupId(buyerGroup);
 
    vendTable.parmVendGroup(credGroup);
    vendTable.parmCurrency(currency);
    vendTable.parmName(name);
    vendTable.parmVATNum(vATNum);
    vendTable.parmPaymTermId(PaymTerms);
 
   //This is validated and not found in Ax so update vendor after create or leave empty
    vendTable.parmInvoiceAccount(InvoiceAccount);
    vendTable.parmDlvTerm(deliveryTerms);

    // Create dimension
    if (defDimProject)
    {
        if (!aifDimensionAttributeValueSet)
        {
            aifDimensionAttributeValueSet   = vendTable.createDefaultDimension();
            aifDimensionAttributeValue      = aifDimensionAttributeValueSet.createValues().addNew();
        }
        else
        {
            aifDimensionAttributeValue = aifDimensionAttributeValueSet.parmValues().addNew();
        }

        aifDimensionAttributeValue.parmName("Project");
        aifDimensionAttributeValue.parmValue(defDimProject);
    }

    if (defDimDepartment)
    {
        if (!aifDimensionAttributeValueSet)
        {
            aifDimensionAttributeValueSet   = vendTable.createDefaultDimension();
            aifDimensionAttributeValue      = aifDimensionAttributeValueSet.createValues().addNew();
        }
        else
        {
            aifDimensionAttributeValue = aifDimensionAttributeValueSet.parmValues().addNew();
        }

        aifDimensionAttributeValue.parmName("Department");
        aifDimensionAttributeValue.parmValue(defDimDepartment);
    }


    if (vATNum && !TaxVATNumTable::exist(vendTable.parmVATNum(), countryRegionId))
    {
        taxVATNumTable.VATNum = vendTable.parmVATNum();
        taxVATNumTable.CountryRegionId = countryRegionId;
        taxVATNumTable.insert();
    }



    dirPartyTable = new VendVendTable_DirPartyTable_DirOrganiza1();
    vendTable.createDirPartyTable().add(dirPartyTable);
    dirPartyTable.parmLanguageId(language);

    organizationName = dirPartyTable.createOrganizationName().addNew();
    organizationName.parmName(name);

    adresss = dirPartyTable.createDirPartyPostalAddressView().addNew();
    adresss.parmCity(city);
    adresss.parmCountryRegionId(countryRegionId);
    adresss.parmStreet(street);
    adresss.parmZipCode(zipCode);
    adresss.parmRoles(logisticsLocationRole.Name);

    contactInfoPhone = dirPartyTable.createDirPartyContactInfoView().addNew();
    contactInfoPhone.parmLocationName(name);
    contactInfoPhone.parmIsPrimary(NoYes::Yes);
    contactInfoPhone.parmLocator(phone);
    contactInfoPhone.parmType(LogisticsElectronicAddressMethodType::Phone);
    contactInfoPhone.parmRoles(logisticsLocationRole.Name);
    contactInfoPhone.parmIsLocationOwner(1);


    contactInfoFax = dirPartyTable.parmDirPartyContactInfoView().addNew();
    contactInfoFax.parmLocationName(name);
    contactInfoFax.parmIsPrimary(NoYes::Yes);
    contactInfoFax.parmLocator(fax);
    contactInfoFax.parmType(LogisticsElectronicAddressMethodType::Fax);
    contactInfoFax.parmRoles(logisticsLocationRole.Name);
    contactInfoFax.parmIsLocationOwner(1);

    contactInfoEmail = dirPartyTable.parmDirPartyContactInfoView().addNew();
    contactInfoEmail.parmLocationName(name);
    contactInfoEmail.parmIsPrimary(NoYes::Yes);
    contactInfoEmail.parmLocator(email);
    contactInfoEmail.parmType(LogisticsElectronicAddressMethodType::Email);
    contactInfoEmail.parmRoles(logisticsLocationRole.Name);
    contactInfoEmail.parmIsLocationOwner(1);

    contactInfoWeb = dirPartyTable.parmDirPartyContactInfoView().addNew();
    contactInfoWeb.parmLocationName(name);
    contactInfoWeb.parmIsPrimary(NoYes::Yes);
    contactInfoWeb.parmLocator(web);
    contactInfoWeb.parmType(LogisticsElectronicAddressMethodType::URL);
    contactInfoWeb.parmRoles(logisticsLocationRole.Name);
    contactInfoWeb.parmIsLocationOwner(1);

    aifEntityKeyList = vendVendTableService.create(vendVendTable);


    dirContactPersonsService        = DirContactPersonsService::construct();
    dirContactPersons               = new DirContactPersons();

    if (contactId)
    {
        dirContactPersons_ContactPerson = dirContactPersons.createContactPerson().addNew();
        dirContactPersons_ContactPerson.parmContactForPartyVendAccount(vendorAccount);

        dirContactPersons_Person        = dirContactPersons_ContactPerson.createPerson().addNew();
        dirContactPersons_Person.parmNameAlias(contactId);

        dirContactPersons_PersonName    = dirContactPersons_Person.createPersonName().addNew();
        [fName, mName, lName]           = DirPerson::splitNameParts(contactId);
        dirContactPersons_PersonName.parmFirstName(fName);
        dirContactPersons_PersonName.parmMiddleName(mName);
        dirContactPersons_PersonName.parmLastName(lName);

        aifEntityKeyList_DirContactPerson = dirContactPersonsService.create(dirContactPersons);
    }

  }

Friday, July 6, 2012

AX2012 Import BOM from CSV


Sample code used to import BOM lines from CSV


//Create the BomTable
protected void createBOMTable(container _conLine)
{
    BOMId           bomId;
    BOMTable        bomTable;
    InventTable     inventTable;
 
  bomId       =   this.getLineValue(_conLine,
                                      #BOMTable_BomId_ColumnNum);

    bomTable    =   BOMTable::find(bomId,
                                   true);

    if(bomTable.RecId)
    {
        axBOMTable = AxBOMTable::newBOMTable(bomTable);

        // Avoid update for better performance.
        return;
    }
    else
    {
        axBOMTable = AxBOMTable::construct();
    }

    // BOMId
    axBOMTable.parmBOMId(bomId);

    // Name
    axBOMTable.parmName(this.getLineValue(_conLine,
                                           #BOMTable_Name_ColumnNum));

    inventTable =   InventTable::find(axBOMTable.parmBOMId());

    // ItemGroupId
    axBOMTable.parmItemGroupId(inventTable.itemGroupId());

    // SiteId
    axBOMTable.parmSiteId(inventTable.inventInventSiteId());

 
    // Approver
    AxBOMTable.parmApprover(gnDTDestAxBOM.parmApprover());

    // Approved
    axBOMTable.parmApproved(NoYes::Yes);

    axBOMTable.save();
}

// create the BOM

protected void createBOM(container _conLine)
{
    BOMId   bomId;
    ItemId  itemId;
    LineNum lineNum;

    BOM     bom;

    bomId   =   axBOMTable.parmBOMId();

    itemId  =   this.getLineValue(_conLine,
                                  #BOM_ItemId_ColumnNum);

    lineNum =   this.getLineValue(_conLine,
                                  #BOM_LineNum_ColumnNum);

    select firstOnly forupdate bom
        where   bom.BOMId   ==  bomId   &&
                bom.ItemId  ==  itemId  &&
                bom.LineNum ==  lineNum;

    if(bom.RecId)
    {
        axBOM = AxBOM::newBOM(bom);

        // Avoid update for better performance.
        return;
    }
    else
    {
        axBOM = AxBOM::construct();
    }

    // LineNum
    axBOM.parmLineNum(lineNum);

    // BOMType
    axBOM.parmBOMType(this.getLineValue(_conLine,
                                        #BOM_BOMType_ColumnNum));

    // BOMConsump
    axBOM.parmBOMConsump(this.getLineValue(_conLine,
                                           #BOM_BOMConsump_ColumnNum));

    // ItemId
    axBOM.parmItemId(itemId);

    // BOMQty
    axBOM.parmBOMQty(this.getLineValue(_conLine,
                                       #BOM_BOMQty_ColumnNum));

    // RoundUpQty
    axBOM.parmRoundUpQty(this.getLineValue(_conLine,
                                           #BOM_RoundUpQty_ColumnNum));

    // Position
    axBOM.parmPosition(this.getLineValue(_conLine,
                                         #BOM_Position_ColumnNum));

    // UnitId
    axBOM.parmUnitId(this.getLineValue(_conLine,
                                       #BOM_UnitId_ColumnNum));

    // BOMId
    axBOM.parmBOMId(bomId);

    // BOMQtySerie
    axBOM.parmBOMQtySerie(1);

    // ProdFlushingPrincip
    axBOM.parmProdFlushingPrincip(ProdFlushingPrincipBOM::Blank);

    axBOM.save();
}

// Create the BOM Version

protected void createBOMVersion(container _conLine)
{
    ItemId              itemId;
    BOMId               bomId;
    BOMVersionActive    active;
    FromQty             fromQty;
 

    BOMVersion          bomVersion;

    itemId      =   this.getLineValue(_conLine,
                                      #BOMVersion_ItemId_ColumnNum);

    bomId       =   axBOMTable.parmBOMId();

    active      =   NoYes::Yes;

    fromQty     =   1;

    bomVersion  =   BOMVersion::find(itemId,
                                     bomId,
                                     active,
                                     dateNull(),
                                     dateNull(),
                                     fromQty,
                                     true);

    if(bomVersion.RecId)
    {
        axBOMVersion = AxBOMVersion::newBOMVersion(bomVersion);

        // Avoid update for better performance.
        return;
    }
    else
    {
        axBOMVersion = AxBOMVersion::construct();
    }

    // ItemId
    axBOMVersion.parmItemId(itemId);
    axBOMVersion.parmInventDimId(bomVersion.InventDimId);

    // BOMId
    axBOMVersion.parmBOMId(bomId);

    // Name
    axBOMVersion.parmName(axBOMTable.parmName());

    // Active
    axBOMVersion.parmActive(active);

    // FromQty
    axBOMVersion.parmFromQty(fromQty);

    // Approver
    axBOMVersion.parmApprover(GNDTDestAxBOM.parmApprover());

    // Approved
    axBOMVersion.parmApproved(NoYes::Yes);

    axBOMVersion.save();
}

public void run()
{

    this.createBOMTable(container);
    this.createBOM( container );
    this.createBOMVersion( container );

}