Search This Blog

Friday, December 5, 2014

Release products to the legal entities using X++ [Dynamics AX 2012]

In this post, I would like to share X++ Code that will help to release products to the legal entities from product master.
In Microsoft Dynamics AX 2012, Microsoft has enhanced the item-product data management framework to provide flexibility and sustainability across the organization.In Microsoft Dynamics AX 2012, all product master data is shared across all companies, and the virtual table collection concept is no longer available for product master data management. The old item representation (InventTable) still exists[msdn]
I will be using 2 legal entities – CEU and newly created legal entity ‘RAX’
[If you want to create new legal entity – Organization administration >> setup >> Organization >> Legal entities >> New]
Let me show you the product master data [a particular product] which I am trying to release using code.

EcoResProductReleaseManagerBase class will help to release products to the legal entities. static method -releaseproduct will release products.

static void SR_ReleaseProducts(Args _args)
{
EcoResProduct ecoResProduct;
;
select firstOnly ecoResProduct where EcoResProduct.DisplayProductNumber == “20003”; //Audio system
EcoResProductReleaseManagerBase::releaseProduct(ecoResProduct.RecId,
CompanyInfo::findDataArea(‘RAX’).RecId);
}

After running the above job, you will see that 20003 product number has been released to legal entity ‘RAX’ as shown below.

I know most of us are very familiar of creating items using code in AX 2009. Now, let me walk through with the equavalent code in AX 2012 [Hope I got it right, please note: This code is an attempt to findout the way it is in AX 2012. Request to test the code in dev environments before using them in live]

static void SR_ReleaseProducts_detailed(Args _args)
{
EcoResProduct ecoResProduct;
InventTable inventTable;
InventTableModule inventTableModule;
NumberSequenceTable numberSequenceTable;
ItemId itemId;
InventItemSetupSupplyType inventItemSetupSupplyType;
EcoResStorageDimensionGroupProduct ecoResStorageDimensionGroupProduct;
EcoResTrackingDimensionGroupProduct ecoResTrackingDimensionGroupProduct;
EcoResStorageDimensionGroupItem ecoResStorageDimensionGroupItem;
EcoResTrackingDimensionGroupItem ecoResTrackingDimensionGroupItem;
;
select firstOnly ecoResProduct where EcoResProduct.DisplayProductNumber == “20003”; //Audio system
changecompany (‘RAX’)
{
ttsBegin;
inventTable = null;
inventTableModule = null;
inventItemSetupSupplyType = null;
ecoResStorageDimensionGroupProduct = null;
ecoResTrackingDimensionGroupProduct = null;
ecoResStorageDimensionGroupItem = null;
ecoResTrackingDimensionGroupItem = null;
numberSequenceTable = InventParameters::numRefItemId().numberSequenceTable();
//get item id from:
//1. Product number if number seq for item ID is not set up or manual or return blank value
if (!numberSequenceTable.RecId || numberSequenceTable.Manual)
{
itemId = ecoResProduct.productNumber();
}
else //number sequence auto, get a number
{
itemId = NumberSeq::newGetNumFromId(numberSequenceTable.RecId).num();
}
inventTable.initValue();
inventTable.initFromEcoResProduct(ecoResProduct);
inventTable.ItemId = ItemId;
inventTable.NameAlias = ecoResProduct.SearchName;
inventTable.insert(true);
// Create inventTableModules
inventTableModule.initValue();
inventTableModule.ItemId = inventTable.ItemId;
inventTableModule.ModuleType = ModuleInventPurchSales::Invent;
inventTableModule.insert();
inventTableModule.initValue();
inventTableModule.ItemId = inventTable.ItemId;
inventTableModule.ModuleType = ModuleInventPurchSales::Purch;
inventTableModule.insert();
inventTableModule.initValue();
inventTableModule.ItemId = inventTable.ItemId;
inventTableModule.ModuleType = ModuleInventPurchSales::Sales;
inventTableModule.insert();
//Create inventItemLocation
InventItemLocation::createDefault(inventTable.ItemId);
// Creates a new item default order type for the product that is released.
inventItemSetupSupplyType.initValue();
inventItemSetupSupplyType.ItemId = inventTable.ItemId;
inventItemSetupSupplyType.ItemDataAreaId = inventTable.DataAreaId;
inventItemSetupSupplyType.insert();
//create relationship tables to dimension groups.
ecoResStorageDimensionGroupProduct = EcoResStorageDimensionGroupProduct::findByProduct(ecoResProduct.RecId);
ecoResTrackingDimensionGroupProduct = EcoResTrackingDimensionGroupProduct::findByProduct(ecoResProduct.RecId);
if (ecoResStorageDimensionGroupProduct.RecId)
{ // mandatory storage dimension group for the product
ecoResStorageDimensionGroupItem.ItemDataAreaId = inventTable.DataAreaId;
ecoResStorageDimensionGroupItem.ItemId = inventTable.ItemId;
ecoResStorageDimensionGroupItem.StorageDimensionGroup = ecoResStorageDimensionGroupProduct.StorageDimensionGroup;
ecoResStorageDimensionGroupItem.insert();
}
if (ecoResTrackingDimensionGroupProduct.RecId)
{ // mandatory tracking dimension group for the product
ecoResTrackingDimensionGroupItem.ItemDataAreaId = inventTable.DataAreaId;
ecoResTrackingDimensionGroupItem.ItemId = inventTable.ItemId;
ecoResTrackingDimensionGroupItem.TrackingDimensionGroup = ecoResTrackingDimensionGroupProduct.TrackingDimensionGroup;
ecoResTrackingDimensionGroupItem.insert();
}
ttsCommit;
info(strfmt(“Product successfully released to ‘RAX’ legal entity”));
}
}

In Microsoft Dynamics AX 2012 inventory dimensions have been divided into the following three categories:
Product dimensions:These correspond to the old item dimensions.
Storage dimensions:These are Site, Warehouse, Location, and Pallet.
Tracking dimensions:These are Batch number and Serial number.

Export to Excel - Dynamics AX Form With Multiple Data Sources

AX 2012 now makes it really easy to output to Excel from a form. Quite simply all you need to do is add a Command button to the form and link it to the command Export to Microsoft Excel. This is great for list pages or any form with a single data source.
However you will find that when several data sources are used on a single form then Ax will output the data from the first data source on the form rather than from the specific data source  that the user is selecting when the Export to Microsoft Excel button is clicked.
Even if you add multiple Export to Microsoft Excel buttons and set the data source individually on the button groups you will still find that the output to Excel is from the first data source of the form.
Now the user can get around this by using CTRL – T from any given grid to export that datasource to Excel but a lot of users may not find it easy to remember which hot key to use.
After a bit of hunting around I have found an easy solution to this issue.
Simply override the Clicked method of the Command button control by calling element.selectControl as shown below: -
void clicked()
{
    element.selectControl(Grid); // The "Grid" argument is the name of the grid
                                 // that you want to export from
 
    super();
}
By keeping track of which grid the user is selecting (override the form datasource Active() methods for example) you can control which grid is exported to Excel.

 

Creating Product or Product Master through X++

static void CreateEcoResProduct(Args _args)
{
    EcoResEcoResProduct_TrackingDimGroup        tracDimGroup;
    EcoResEcoResProduct_Product_Master          productMaster;
    EcoResEcoResProduct_Product_Distinct        distMaster;
    EcoResEcoResProduct_ProductDimGroup         prodDimGroup;
    EcoResEcoResProduct_StorageDimGroup         storDimGroup;
    EcoResEcoResProduct_translation             translation;
    EcoResEcoResProduct_Identifier              identifier;
    EcoResProductService                        ecoProdSvc;
    EcoResProductNumber                         lEcoResProductNumber;
    NumberSequenceTable                         numberSequenceTable;
    EcoResEcoResProduct                         ecoResProd;
    EcoResProductType                           ecoResProductType;
    boolean                                     isMaster = false;
    EcoResProductSearchName                     _ecmProductName;
    EcoResProductSubtype                        prodSubType;
    ;
    prodSubType = EcoResProductSubtype::ProductMaster;
    _ecmProductName = " IDB test 09";
    lEcoResProductNumber = "IDB -099";
    try
    {
        // create product by initializing the Service object
        ecoProdSvc = EcoResProductService::construct();
        // initialize the EcoResEcoResProduct object
        ecoResProd = new EcoResEcoResProduct();
       // numberSequenceTable = EcoResProductParameters::numRefProductNumber().numberSequenceTable(); // Automated
      //  lEcoResProductNumber = NumberSeq::newGetNumFromId(numberSequenceTable.RecId).num(); // Automated
       
       
        ecoResProductType = EcoResProductType::Item;
        if(prodSubType == EcoResProductSubtype::ProductMaster)
        {
            isMaster = true;
            //Create a new product master
            productMaster = new EcoResEcoResProduct_Product_Master();
            //initialize product master
            productMaster.parmDisplayProductNumber(lEcoResProductNumber);
            productMaster.parmProductType(ecoResProductType);
            productMaster.parmSearchName(_ecmProductName);
            productMaster.parmProductType(EcoResProductType::Service);
            productMaster.parmVariantConfigurationTechnology(EcoResVariantConfigurationTechnologyType::PredefinedVariants);
            //create a product master Translation Object
            translation = productMaster.createTranslation().addNew();
            // create a new identifier object
            Identifier = productMaster.createIdentifier().AddNew();
            // Create the ProductDimensionGroup
            prodDimGroup = productMaster.createProductDimGroup().addNew();
            prodDimGroup.parmProduct(lEcoResProductNumber);
            prodDimGroup.parmProductDimensionGroup('Con-Dim');
            // Create the StorageDimgroup object
            storDimGroup = productMaster.createStorageDimGroup().addNew();
            storDimGroup.parmProduct(lEcoResProductNumber);
            storDimGroup.parmStorageDimensionGroup("Con-Dim"); // Storage dimension group
            // Create the TrackingDimGroup object
            tracDimGroup = productMaster.createTrackingDimGroup().addNew();
            tracDimGroup.parmProduct(lEcoResProductNumber);
            tracDimGroup.parmTrackingDimensionGroup("Con-Dim"); // Tracking dimension group
        }
        else
        {
            // Create a new product distinct master
            distMaster = new EcoResEcoResProduct_Product_Distinct();
            // Take the newly created and initialize ProdMaster - variable and fill with product data
            distMaster.parmDisplayProductNumber(lEcoResProductNumber);
            distMaster.parmProductType(ecoResProductType);
            distMaster.parmSearchName(_ecmProductName);
            // Create a translation object
            translation = distMaster.createTranslation().addNew();
            // Create a new identifier object
            Identifier = distMaster.createIdentifier().addNew();
            // Create the StorageDimgroup object
            storDimGroup = distMaster.createStorageDimGroup().addNew();
            storDimGroup.parmProduct(lEcoResProductNumber);
            storDimGroup.parmStorageDimensionGroup("Con-Dim");
            // Create the TrackingDimGroup object
            tracDimGroup = distMaster.createTrackingDimGroup().addNew();
            tracDimGroup.parmProduct(lEcoResProductNumber);
            tracDimGroup.parmTrackingDimensionGroup("Con-Dim");
        }
        // fill the translation object
        translation.parmDescription(_ecmProductName);
        translation.parmLanguageId('en-us');
        //translati
        translation.parmName(_ecmProductName);
        // fill the identifier
        identifier.parmProductNumber(lEcoResProductNumber);
        // add the product to ecoResProd
        if(isMaster)
            ecoResProd.createProduct().add(productMaster);
        else
            ecoResProd.createProduct().add(distMaster);
        // create the product using service
        ecoProdSvc.create(ecoResProd);
    }
    catch(Exception::Error)
    {
        throw Exception::Error;
    }
    catch(Exception::Deadlock)
    {
        retry;
    }
    catch(Exception::UpdateConflict)
    {
        if(appl.ttsLevel() == 0)
        {
            if(xSession::currentRetryCount() >= 4)
            {
                throw Exception::UpdateConflictNotRecovered;
            }
            else
            {
                retry;
            }
        }
        else
        {
            throw Exception::UpdateConflict;
        }
    }
}

Above code creates the record for product in EcoResProduct Table and Once you get the data in product form(EcoResProduct -Table) you can easily release those product in specified company in a single go, by selecting multiple products. It doesn't take much time as well. Release product will be saved in InventTable. 

 Else use the below method. Pass all the required parameters and get the required result

public container createProduct(str60 _product,
                            str60 _productname,
                            str60 _searchname,                           
                            str60 _desc,
                            str60 _color,
                            str60  _size,
                            str60  _style,
                            str60  _site,
                            str60  _warehouse,
                            Str60  _vendorId,
                            str60  _externalDesc,
                            str60 _countingGroup,
                            str60 _defaultReceipt,
                            str60 _defaultIssue,
                            str60 _defaultLocation,
                            str60 _productDimension,
                            str60  _sizeGrpId,
                            str60  _styleGrpId,
                            str60  _approveStatus,
                            str60  _category)
{
    EcoResProductService erProdSvc;
    EcoResEcoResProduct EcoResProd;
    EcoResEcoResProduct_Product_Master ProdMast;
    EcoResEcoResProduct_Translation Translation;
    EcoResEcoResProduct_Identifier Identifier;
    EcoResEcoResProduct_ProductDimGroup ProdDimGroup;
    boolean                         isVariantExist = false;
    InventDim                       inventDim;
    InventDimCombination            inventDimCombination;
    container productDimensions,displayNumber,ret,sizeColorStyle;
    EcoResDistinctProductVariant        ecoResDistinctProductVariant;
    EcoResProductVariantDimensionValue  EcoResProductVariantDimensionValue;
    RefRecId                                   ecoResDistinctProductVariantRecId;
    EcoResProductReleaseManagerBase     releaseManager;
    CompanyInfo                         companyInfo;
    EcoResProductTranslation            productTranslation;
    RecId           color,size,style;
    Inventtable     inventtable;
    PdsVendorCheckItem vendorCheckItem;
    EcoResCategory          ecoResCategory;
    RetailAttributesGlobalLookup       retailAttributesGlobalLookup;
    CreateProducMaster productMaste = new CreateProducMaster();
    ttsBegin;
    if(!EcoResProduct::findByDisplayProductNumber(_product).RecId)
    {
        //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(_product);
        ProdMast.parmProductType(EcoResProductType::Item);
        ProdMast.parmSearchName(_searchname);
        //Create a new translation object:
        Translation = ProdMast.createTranslation().addNew();
        Translation.parmDescription(_desc);
        Translation.parmLanguageId('en-us');
        Translation.parmName(_productname);
        Identifier = ProdMast.createIdentifier().addNew();
        Identifier.parmProductNumber(_product);
        ProdDimGroup = ProdMast.createProductDimGroup().addNew();
        ProdDimGroup.parmProduct(_product);
        ProdDimGroup.parmProductDimensionGroup(_productDimension);
        ProdMast.parmVariantConfigurationTechnology(EcoResVariantConfigurationTechnologyType::PredefinedVariants);
        EcoResProd.createProduct().add(ProdMast);
        erProdSvc.create(EcoResProd);
    }
    select * from ecoResCategory where ecoResCategory.Name == _category;
    select * from retailAttributesGlobalLookup where retailAttributesGlobalLookup.Category == ecoResCategory.RecId;
    sizeColorStyle = productMaste.insertProductDimension(_product,_color,_size,_style,retailAttributesGlobalLookup.VariantColorGroup
                                                    ,retailAttributesGlobalLookup.VariantSizeGroup,retailAttributesGlobalLookup.VariantStyleGroup);
    color = conPeek(sizeColorStyle,1);
    size  = conPeek(sizeColorStyle,2);
    style = conPeek(sizeColorStyle,3);
    if(!color)
        _color = '';
    if(!size)
        _size = '';
    if(!style)
        _style ='';
    productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer('',_size,_color,_style);
    //if(EcoResProductVariantManager::checkNotExistDistinctProductVariant(EcoResProduct::findByDisplayProductNumber(_product).RecId,
                        //productDimensions) && color && size && style)
    if(!EcoResProductVariantManager::findDistinctProductVariant(EcoResProduct::findByDisplayProductNumber(_product).RecId, productDimensions).RecId && color && size && style)
    {
        ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(
                                                                        _product,
                                                                        productDimensions);
        ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(EcoResProduct::findByDisplayProductNumber(_product).RecId
                                                                ,ecoResDistinctProductVariant.DisplayProductNumber,productDimensions);
    }
    if(!InventTable::find(_product).RecId)
    {
         EcoResProductReleaseManagerBase::releaseProduct(EcoResProduct::findByDisplayProductNumber(_product).RecId
                                                      ,CompanyInfo::findDataArea(curext()).RecId);
    }
    select inventtable where inventtable.ItemId == _product;
    if(inventtable)
    {
        inventtable.selectForUpdate(true);
        inventtable.PdsVendorCheckItem = str2enum(vendorCheckItem,_approveStatus);
        inventtable.doUpdate();
    }
    if(size && color && style)
    {
        inventDim.InventSizeId  = _size;
        inventDim.InventColorId = _color;
        inventDim.InventStyleId = _style;
        isVariantExist = true;
    }
        inventDim.InventSiteId  = _site;
        inventDim.InventLocationId = _warehouse;
        inventDim               = InventDim::findOrCreate(inventDim);
    if(!InventDimCombination::find(_product,inventDim.InventDimId).RecId && ecoResDistinctProductVariantRecId)
    {
        // create InventDimCombination
        inventDimCombination.DistinctProductVariant = ecoResDistinctProductVariantRecId;
        inventDimCombination.ItemId                 = _product;
        inventDimCombination.InventDimId            = inventDim.InventDimId;
        inventDimCombination.Insert();
    }
    ttsCommit;
    ret  = [inventDim.InventDimId,ecoResDistinctProductVariantRecId,isVariantExist];
    return ret;
}
 

Thursday, November 27, 2014

Dynamics AX 2012 Optimization – Product Configurator

Dynamics AX 2012 Optimization – Product Configurator
Purpose: The purpose of this document is to illustrate how Product Configurator can be used in Dynamics AX 2012 to configure products and services. In this document the emphasis will be put on how to build rules base or constraints base for particular business scenario to ensure that valid combination of modeling variables values is selected.
Challenge: In Dynamics AX 2012 new Product Configurator was introduced which will ultimately replace Product Builder in the next release. Product Configurator is a new Configurator solution which leverages Solver Foundation engine. One of the reasons to introduce Product Configurator was to eliminate a need for Developer license in order to use Configurator capabilities of Dynamics AX 2012, so functional users will be able to use Configurator efficiently. The challenge is to understand how Product Configurator can be effectively used to implement real world rules-based and constraint-based configuration scenarios.
Solution: Example of start-to-end Car configuration using Product Configurator in Dynamics AX 2012 will be described in this document. We start with definition of the problem and its formalization, and then continue with translating this knowledge into Dynamics AX 2012 terms and setting up the system appropriately, and end with working solution and the result.
Configuration Model:
Modeling Variable Name
Modeling Variable Value(s)
Type
"Sport Car", "Family Car"
Package
"Deluxe", "Luxury", "Standard"
Frame
"Convertible", "Hatchback", "Sedan"
Engine
"A", "B"
Transmission
"Manual", "HalfAutomatic", "Automatic"
In this example Car is configured using 5 modeling variables such as Type, Package, Frame, Engine and Transmission. Each modeling variable has a set of possible values as depicted in the table above. The task is to build rules base or constraints base for Car configuration scenario to ensure that valid combination of modeling variables values is selected.
Configuration Model Diagram:
image
In the configuration process client initially is supposed to provide input regarding Type of Car which he/she needs and what Package will have to be included. After that other Car specifications will be determined such as Frame, Engine and Transmission based on Configuration rules.
For example, Client says: "I need Deluxe Sport Car" and the system will have to ensure that valid combination of Car specifications is selected as the result of configuration.
On the Configuration Model Diagram you can see that certain modeling variables drive the selection of other modeling variables. For example, Type of Car is used to determine Transmission. Please see the full list of Configuration rules which were composed with knowledge of business domain (Automotive industry in this example).
Configuration Rules:
Rule 1: IF Package = "Deluxe" AND Frame = "Convertible" THEN Engine = "A"
Rule 2: IF Package = "Deluxe" AND Frame = "Hatchback" THEN Engine = "B"
Rule 3: IF Package = "Standard" AND Frame = "Convertible" THEN Engine = "A"
Rule 4: IF Engine = "A" THEN Transmission = "Manual"
Rule 5: IF Engine = "B" THEN Transmission = "Automatic"
Rule 6: IF Type = "Sport Car" THEN Frame = "Convertible"
Rule 7: IF Type = "Family Car" THEN Frame = "Sedan"
Rule 8: IF Type = "Sport Car" THEN Transmission = "Manual"
Rules 1, 2 and 3 use Package and Frame to determine Engine. Rules 4 and 5 make decision about Transmission based on Engine. Rules 6 and 7 decide on Frame taking into account Type. And Rule 8 uses Type to determine Transmission.
Please note that certain modeling variable selection may be a result of different combinations of other modeling variables selections which is the case in complex business domains (such as Automotive industry).
Next step: We will define Product Configuration Model, Attributes and Attribute types, and design User Interface for Product Configuration Model in Dynamics AX 2012
Attribute types
Attribute Type Name
Base Type
Attribute Type Fixed List
CarType
Text
"Sport Car", "Family Car"
CarPackage
Text
"Deluxe", "Luxury", "Standard"
CarFrame
Text
"Convertible", "Hatchback", "Sedan"
CarEngine
Text
"A", "B"
CarTransmission
Text
"Manual", "HalfAutomatic", "Automatic"
Attribute Type = "CarType"
Attribute Type = "CarPackage"
Attribute Type = "CarFrame"
Attribute Type = "CarEngine"
Attribute Type = "CarTransmission"
Product Configuration Model
Attributes
Attribute Name
Attribute Type
Type
CarType
Package
CarPackage
Frame
CarFrame
Engine
CarEngine
Transmission
CarTransmission
User interface
Attribute Group
Attribute Name
Preferences
Type
Preferences
Package
Specifications
Frame
Specifications
Engine
Specifications
Transmission
To better organize configuration process all modeling variables will be divided into 2 groups: Preferences and Specifications. Preferences will represent client's initial requirements regarding Type of Car and Package to be included. Specifications group will represent physical characteristics of Car such as Frame, Engine and Transmission which will be defined based on initial client's requirements.
Next step: We will implement 2 options to illustrate Rules-based and Constraints-based approach in order to structure knowledge base. Option 1 implements Rules-based approach and Option 2 implements Constraints-based approach.
Option 1: Constraints (Rules base)
Using Rules-based approach all Rules can be represented as Expression constraints in Dynamics AX 2012. Please see all Expression constraints in relation to the original rule below
Rule 1: IF Package = "Deluxe" AND Frame = "Convertible" THEN Engine = "A"
Rule 2: IF Package = "Deluxe" AND Frame = "Hatchback" THEN Engine = "B"
Rule 3: IF Package = "Standard" AND Frame = "Convertible" THEN Engine = "A"
Rule 4: IF Engine = "A" THEN Transmission = "Manual"
Rule 5: IF Engine = "B" THEN Transmission = "Automatic"
Rule 6: IF Type = "Sport Car" THEN Frame = "Convertible"
Rule 7: IF Type = "Family Car" THEN Frame = "Sedan"
Rule 8: IF Type = "Sport Car" THEN Transmission = "Manual"
Option 1: Result
Please note that when you just open Configuration screen and you don't have any particular selections for modeling variables yet, almost all selections for all modeling variables will be available
Type
Package
Frame
Engine
Transmission
The exceptions are Frame = "Hatchback" and Transmission = "Half-automatic" which were filtered out because of lack of relevant rules.
However when you specify client's requirements "Deluxe Sport Car" the system will automatically filter out all inappropriate selections and the final result will look like the following
Please note that after you have selected Type = "Sport Car" and Package = "Deluxe" the only one selection for each modeling variable will remain available based on existing rules
Type
Package
Frame
Engine
Transmission
Please note that every time you change selection for particular modeling variable the system sends current configuration to Solver for analysis and then adjusts selections for all related modeling variables in real time. Red circle is your indication that particular selection for modeling variable is not available within current configuration.
Also please note that using Rules-based approach the system implements deduction principle based on existing rules. For example, when you specify Transmission = "Manual" the system will know that Engine = "A" based on Rule 4
Rule 4: IF Engine = "A" THEN Transmission = "Manual" (forward chaining)
Type
Package
Frame
Engine
Transmission
And vice versa when you specify Engine = "A" the system will know that Transmission = "Manual" based on Rule 4
Rule 4*: IF Transmission = "Manual" THEN Engine = "A" (backward chaining)
Type
Package
Frame
Engine
Transmission
Option 2: Table Constraints
In order to use Constraints-based approach we will have to represent Rules differently by grouping them into 4 groups. Rules 1, 2 and 3 will fall into 1st group which represents all valid combinations of Package, Frame and Engine. Rules 4 and 5 will form 2nd group which represents all valid combinations of Engine and Transmission. Rules 6 and 7 will be basis for 3rd group which represents all valid combinations of Type and Frame. And Rule 8 will represent 4th group with the only one valid combination of Type and Transmission defined at the moment.
Group 1: Package-Frame-Engine
Rule 1: IF Package = "Deluxe" AND Frame = "Convertible" THEN Engine = "A"
Rule 2: IF Package = "Deluxe" AND Frame = "Hatchback" THEN Engine = "B"
Rule 3: IF Package = "Standard" AND Frame = "Convertible" THEN Engine = "A"
Package
Frame
Engine
Deluxe
Convertible
A
Deluxe
Hatchback
B
Standard
Convertible
A
Please note that I substituted Rules 1, 2 and 3 with Group 1 Table representing all valid combinations of Package-Frame-Engine
Group 2: Engine-Transmission
Rule 4: IF Engine = "A" THEN Transmission = "Manual"
Rule 5: IF Engine = "B" THEN Transmission = "Automatic"
Engine
Transmission
A
Manual
B
Automatic
Please note that I substituted Rules 4 and 5 with Group 2 Table representing all valid combinations of Engine-Transmission
Group 3: Type-Frame
Rule 6: IF Type = "Sport Car" THEN Frame = "Convertible"
Rule 7: IF Type = "Family Car" THEN Frame = "Sedan"
Type
Frame
Sport Car
Convertible
Family Car
Sedan
Please note that I substituted Rules 6 and 7 with Group 3 Table representing all valid combinations of Type-Frame
Group 4: Type-Transmission
Rule 8: IF Type = "Sport Car" THEN Transmission = "Manual"
Type
Transmission
Sport Car
Manual
Please note that I substituted Rule 8 with Group 4 Table representing valid combination of Type-Transmission
The difference between Rules-based approach and Constraints-based approach is that instead of expressing the rules in form of conditions and conclusions (Rules-based approach) I'm expressing relations between modeling variables and valid modeling variables value combinations (Constraints-based approach).
Using Constraints-based approach all Rules can be represented as Table constraints (User defined) in Dynamics AX 2012. Please see all Table constraints in relation to the original rules group below
Group1: PackageFrameEngine
Group2: Engine-Transmission
Group3: Type-Frame
Group4: Type-Transmission
Option 2: Constraints (Constraints base)
After we set up Table constraints we can link them to our Product Configuration Model
For all Product Configuration Model Table constraints we have to define the relation between Column name in the original Table constraint and Product Configuration Model Attribute name.
Group1: Package-Frame-Engine
Group2: Engine-Transmission
Group3: Type-Frame
Group4: Type-Transmission
Option 2: Result
Please note that when you just open Configuration screen you have particular selections for almost all modeling variables already in place, this is because the system took into account valid combinations of modeling variables specified in Table constraints. Moreover based on current Table constraints the only 2 combinations of 5 modeling variables are available. They are {Type = "Sport Car", Package = "Deluxe", Frame = "Convertible", Engine = "A", Transmission = "Manual"} and {Type = "Sport Car", Package = "Standard", Frame = "Convertible", Engine = "A", Transmission = "Manual"}.
Type
Package
Frame
Engine
Transmission
Let's explain why the only 2 combinations of 5 modeling variables are available based on current Table constraints at the moment. In order to explain this I will get back to 4 groups defined earlier which represent knowledge base.
Group 1: Package-Frame-Engine
Package
Frame
Engine
Deluxe
Convertible
A
Deluxe
Hatchback
B
Standard
Convertible
A
Group 2: Engine-Transmission
Engine
Transmission
A
Manual
B
Automatic
Group 3: Type-Frame
Type
Frame
Sport Car
Convertible
Family Car
Sedan
Group 4: Type-Transmission
Type
Transmission
Sport Car
Manual
Please note that each Group represents valid combinations of modeling variables. Please also note that certain modeling variables are used multiple times in different groups which means that we can reduce number of groups by combining them together and making sure that selections of "shared" modeling variables in different groups will be the same as we add a combination into new "super" group.
Iteration 1: Combine Group 1 and Group 2 into Group 1-2 by "shared" modeling variable "Engine"
Group 1-2: Package-Frame-Engine-Transmission
Package
Frame
Engine
Transmission
Deluxe
Convertible
A
Manual
Deluxe
Hatchback
B
Automatic
Standard
Convertible
A
Manual
Iteration 2: Combine Group 1-2 and Group 3 into Group 1-2-3 by "shared" modeling variable "Frame"
Group 1-2-3: Package-Frame-Engine-Transmission-Type
Package
Frame
Engine
Transmission
Type
Deluxe
Convertible
A
Manual
SportCar
Standard
Convertible
A
Manual
SportCar
Iteration 3: Combine Group 1-2-3 and Group 4 into Group 1-2-3-4 by "shared" modeling variables "Type" and "Transmission"
Group 1-2-3-4: Package-Frame-Engine-Transmission-Type
Package
Frame
Engine
Transmission
Type
Deluxe
Convertible
A
Manual
SportCar
Standard
Convertible
A
Manual
SportCar
Group 1-2-3-4 Table represents all valid combinations of 5 modeling variables
As the result we have only 2 valid combinations of 5 modeling variables which is exactly what was available on Configuration screen
You can download XML file for Constraints-based configuration (PC-AlexCar-Constraints) here: https://skydrive.live.com/redir.aspx?cid=9c660ef56a3ba3f7&resid=9C660EF56A3BA3F7!110&parid=9C660EF56A3BA3F7!101&authkey=!ALJ3y9wD7_Ir8TE
Summary: Product Configurator is a very powerful solution which can be used in Dynamics AX 2012 for configuring products and services. Product Configurator allows you to implement Rules-based approach and Constraints-based approach for Product Configuration Models. In similar walkthrough I will also explain how Product Builder in Dynamics AX 2012 allows you to implement Rules-based approach and Constraints-based approach for Product Models.
Author: Alex Anikiev, PhD, MCP
Tags: Dynamics ERP, Dynamics AX 2012, Solver Foundation, Product Configurator, Rules-based Configurator, Constraints-based Configurator.
Note: This document is intended for information purposes only, presented as it is with no warranties from the author. This document may be updated with more content to better outline the concepts and describe the examples.
Reference: "Constraint-based knowledge representation for configuration systems" by Boi Faltings and Rainer Weigel

PS: http://ax2012solveroptimization.blogspot.in/2012/03/dynamics-ax-2012-optimization-product.html