Tuesday, 8 August 2017

Difference between view and table

Difference between a view and a base relation: -

Views:
1. This is one type of relation which is not a part of the physical
database.
2. It has no direct or physical relation with the database.
3. Views can be used to provide security mechanism.
4. Modification through a view (e.g. insert, update, delete) generally
not permitted

Base Relation:
1. A base relation is a relation that is not a derived relation.
2. While it can manipulate the conceptual or physical relations stored
in the data.
3. It does not provide security.
4. Modification may be done with a base relation.
We can assign the view, a name & relate it the query expression as
Create View <View Name> as <Query Expression>
Let EMPLOYEE be the relation. We create the table EMPLOYEE as follows:-

Create table EMPLOYEE
(Emp_No integer of null,
Name char (20),
Skill chars (20),
Sal_Rate decimal (10, 2),
DOB date,
Address char (100),)
For a very personal or confidential matter, every user is not
permitted to see the Sal_Rate of an EMPLOYEE. For such users, DBA can
create a view, for example, EMP_VIEW defined as:-

Create view EMP_VIEW as
(Select Emp_No, Name, Skill, DOB, Address
         From EMPLOYEE)

refresh, reread, research, executeQuery - which one to use?

X++ developers seem to be having a lot of trouble with these 4 datasource methods, no matter how senior they are in AX.

1. Common mistakes
Often, developers call 2 of the mentioned methods in the following order:

formDataSource.refresh()
formDataSource.research()

or

formDataSource.reread()
formDataSource.research()

or

formDataSource.research()
formDataSource.executeQuery()

or

formDataSource.research()
formDataSource.refresh() / formDataSource.reread()

All of these are wrong, or at least partially redundant.
Hopefully, after reading the full post, there will be no questions as to why they are wrong. Leave a comment to this post if one of them is still unclear, and I will try to explain in more detail.


2. Refresh
This method basically refreshes the data displayed in the form controls with whatever is stored in the form cache for that particular datasource record. Calling refresh() method will NOT reread the record from the database. So if changes happened to the record in another process, these will not be shown after executing refresh().


refreshEx
Does a redraw of the grid rows, depending on the optional argment for specifying the number of the record to refresh (and this means the actual row number in the grid, which is less useful for AX devs). Special argument values include -1, which means that all records will be redrawn, and -2, which redraws all marked records and records with displayOptions. Default argument value is -2.
This method should be used sparingly, in cases where multiple rows from the grid are updated, resulting in changes in their displayOptions, as an example. So you should avoid using it as a replacement for refresh(), since they actually have completely different implementations in the kernel.
Also, note, that refreshEx() only redraws the grid, so the controls not in the grid might still contain outdated values. Refresh() updates everything, since this is its intention.


3. Reread
Calling reread() will query the database and re-read the current record contents into the datasource form cache. This will not display the changes on the form until a redraw of the grid contents happens (for example, when you navigate away from the row or re-open the form).
You should not use it to refresh the form data if you have through code added or removed records. For this, you would use a different method described below.


How are these 2 methods commonly used?
Usually, when you change some values in the current record through some code (for example, when the user clicks on a button), and update the database by calling update method on the table buffer, you would want to show the user the changes that happened.
In this case, you would call reread() method to update the datasource form cache with the values from the database (this will not update the screen), and then call refresh() to actually redraw the grid and show the changes to the user.


Clicking buttons with SaveRecord == Yes
Each button has a property SaveRecord, which is by default set to Yes. Whenever you click a button, the changes you have done in the current record are saved to the database. So calling reread will not restore the original record values, as some expect. If that is the user expectation, you as a developer should set the property to No.


4. Research
Calling research() will rerun the existing form query against the database, therefore updating the list with new/removed records as well as updating all existing rows. This will honor any existing filters and sorting on the form, that were set by the user.


Research(true)
The research method starting with AX 2009 accepts an optional boolean argument _retainPosition. If you call research(true), the cursor position in the grid will be preserved after the data has been refreshed. This is an extremely useful addition, which solves most of the problems with cursor positioning (findRecord method is the alternative, but this method is very slow).


5. ExecuteQuery
Calling executeQuery() will also rerun the query and update/add/delete the rows in the grid. The difference in behavior from research is described below.
ExecuteQuery should be used if you have modified the query in your code and need to refresh the form to display the data based on the updated query.


formDataSource.queryRun().query() vs formDataSource.query()
An important thing to mention here is that the form has 2 instances of the query object - one is the original datasource query (stored in formDataSource.query()), and the other is the currently used query with any user filters applied (stored in formDataSource.queryRun().query()).
When the research method is called, a new instance of the queryRun is created, using the formDataSource.queryRun().query() as the basis. Therefore, if the user has set up some filters on the displayed data, those will be preserved.
This is useful, for example, when multiple users work with a certain form, each user has his own filters set up for displaying only relevant data, and rows get inserted into the underlying table externally (for example, through AIF).
Calling executeQuery, on the other hand, will use the original query as the basis, therefore removing any user filters.
This is a distinction that everyone should understand when using research/executeQuery methods in order to prevent possible collisions with the user filters when updating the query.

Why you should be using Team Foundation Server for Dynamics AX lifecycle management?

If you already use Team Foundation Server in your Dynamics AX projects, providing all benefits it can give to your teams, or if you are already convinced to use it soon, then this article is not for you.
You may not be convinced or, even worst, you may disagree about it to be beneficial to your methodologies and team behaviors. You can try to challenge my points with your project's circumstances that make TFS unacceptable. That’s fine. I'm only asking you to read the full article first ðŸ™‚

Team Foundation Server (or Visual Studio Team Services*) is a tool, and as such, it will allow you to achieve the same tasks faster and with less effort. Furthermore, TFS will also give the ability to execute crucial tasks that are only available by using this kind of tools. Those tasks are mostly related to development work and source code management, what makes developer’s life easier, but some of them also help project managers and consultants, and support Quality Assurance guidance and validations, testing and all the rest of Application Lifecycle Management steps, whichever methodology is used to manage our projects: Microsoft SureStep, Agile, Scrum, …
Not to mention that using TFS is mandatory in the new Dynamics 365 for Operations, so including it in our lifecycle processes today will ease the transition and will put in place a set of Best Practices than will improve your team since day one.
Let’s have a look at the benefits of TFS in the three main categories of Application Lifecycle Management:
  1. Work
  2. Code
  3. Build & Release

1. WORK

WORK module is meant to support project management tasks, but we can get much more from it if we make it part of our team toolbox.
It is a simple, generic, but effective Work Item manager that can be used effectively depending on the methodology used to manage each project. By default, the system creates Work Item Types like Epic, User Story, Task, Test Case, Bug, and so on, but what is more important is that these items are here to support our needs, so use them accordingly.
Work Item Details
It is not mandatory to manage tasks and requirements but it will help you improve Project Management traceability across the team (you can even create those items from Microsoft Project Server). It allows linking code and metadata changes done by one developer, with a comprehensive description that anyone can understand. Thus, at any time everybody will know why a change was done and can provide information about testing and deployment status of every single request received from users, customers or whoever our stakeholders are.
Here are a few examples of critical questions that can only be answered when Work Items are used:
  • Who made this change? Was something else changed at the same time?
  • Why was this object modified? Is this change related to any business requirement, a bug fix, a compliance change request?
  • When was this object modified the last time?
  • How many times has this object been modified? What were the motivations for each change?
  • Which was the application version at the time this change or bug fix was introduced? (Hotfix servicing and upgrades will be a blog post by itself)
  • Which are the differences between the current status of the application and the one when this change was made?
  • Estimate hotfix potential conflicts or code upgrades based on the changes you can see in source control.
Check-In changes to TFS from Dynamics AX 2012
This is a small set of questions you can answer with the most basic use of source control integration with Work Items. The list grows when you start using Branches and a proper build practice as we will see in upcoming blog posts.
Furthermore, you can map your BPM processes from Lifecycle Services with TFS Work Items to synchronize elements between and make easier to the team to access their information using their preferred tool.

2. CODE

This is the TFS module used by developers during code and metadata (AOT changes) changes, and where “versions” of the application are stored.
Source Control system provided by TFS makes developer’s life easier and safer and therefore, more profitable for their companies. It is unlikely to see a developer actively refusing to use any source control system. Those advantages are significantly more important when talking about development teams, and amazingly better when talking about distributed teams working in different locations, different countries, different companies (partners) or even different time zones. The more complex the team, the more benefits they will get from any source control mechanism in place.
You may argue that TFS causes extra work to developers. And that is true in theory, but let's explain how this "extra" work is quickly amortized. Extra steps for developers using a source control system
  1. Check-Out: Before modifying an object, the developer needs to indicate the system that this objects is going to be modified. The system will download the last version from the server, just in case any other developer has modified it, so we can work with the latest version.
  2. Check-In: After changes are done and validated by a developer, a check-in will send those changes to the server so other developers can see our modified version, and will release the previous Check-Out made to this object.
  3. Merge: As many developers may be working with different versions of the same object on their isolated development environments at the same time, making changes to the same piece of code without knowing each other work-in-progress, the final version of the object may need to be manually merged. During merge process, a developer push his version into the server and will needs to take decisions about the final, consolidated version of the object if there are conflicts. Those conflicts can happen if somebody else has made changes to the server version since the current developer downloaded the last version during the Check-Out. All source control systems have tools to make the merging process easy and secure, even automatic if the changes are simple enough.
It doesn't seem like a lot of extra work. Now let's analyze what we get in exchange and it will get even better:
  • Check-In/Check-Out mechanism allows several developers to work on the same object without disturbing each other. While modifying an object, a developer needs to save and execute it many times until the final version is ready. It won't be until the developer checks-in this finished version than the rest of developers will even see those changes. When a developer synchronizes changes from a colleague, it will always get a complete change set, so he won't be disturbed with unexpected errors due to unfinished changes, something common in shared development environments.
  • Merging changes can be annoying in some cases. But following a good methodology will always be easier than importing XPO files, as the Visual Studio merging tool is way more sophisticated, powerful and quick than the MorphX Compare Tool (it’s fair to say that performance has been really improved in last versions). Anyway, the result of this merging process will always be saved to the server as a new change set. If something goes wrong, one can always see exactly what has been merged, fix it, or rollback to a previous version. Neither of this is available when we are asked to import an XPO file. After we import the file we can’t undo any change or even know what was the previous state.
  • Every Check-In is saved to the server as a change set. This change set links all changes done at the same time to code and metadata to multiple objects, and can be linked to a Work Item or more than one as we mentioned earlier. With minimum effort (like providing a Work Item code during the check-in process, see the previous screenshot), we are creating a fully descriptive change set containing new, modified and deleted objects, and the Task/Bug/Requirement that motivated those changes. This will provide full traceability for every change made and can be even better if we follow some easy rules to merge between Branches allowing, for example, to make code reviews using those Branching change sets.
  • Saving all change sets to the server allows everybody in the project to inspect the change history of any single object in the application, comparing different versions to see what has been the changed over time and, if linked to Work Items, who and why was it changed.
As an example, in the image below we have a full change set as shown by the VSTS portal (it can be accessed from Visual Studio too), showing new and modified objects, the link with 2 work items, and detailed code and metadata changes highlighted in different colors:
Change Set Details
As this view is pure TFS tooling, any member of the team, regardless of knowledge or access to a Dynamics AX instance (of course TFS have its own access and security system), will be able to see and review this change history forever, as this is stored in the source control server regardless of what happens with the Dynamics AX test or development instances. A Dynamics AX 2012 development system based on any version stored in TFS server (including any Branch) can be deployed at any time, as we will see when talking about the BUILD & RELEASE module.
Same example as seen above, but this time from a Dynamics AX 2012 development environment perspective is shown below:
Change History in Dynamics AX 2012
This is an invaluable tool for developers to be able to quickly see the change history of any object and navigate to this version in the AOT, compare with the current or any other version of the object and see what has been changed, or even reverse the current status to a previous version to undo any involuntary or mistaken change. Any developer will love that, there is not much discussion here.
All this code traceability is only possible when TFS is used to track changes. Dynamics AX is such a business-critical application that any code change should be described, controlled and traced. Who, when and why any change is done needs to be clear and easy to access. Customers without such traceability put themselves in dangerous path for regression problems and code instability.
We are still not considering the concept of Branching, closely related with any source control system, which roughly represents different versions of the entire application that we can manage independently. It allows to maintain a detailed version history (What was the status of my application at a specific point of time) that goes in line, but way more in deep of Dev/Test/UAT typical granularity. Branching is an interesting but extensive topic, so we will dedicate a full blog post in the future if our readers are interested on the subject.

3. BUILD AND RELEASE

I must admit, build module is my favorite topic: it is where development lifecycle gets closed and the benefits of using a full Application Lifecycle Management (ALM) process can be appreciated in a clear and obvious way by all the team. But it is quite a big topic too, so I will let the details for an upcoming post.
To sum up: In Dynamics AX 2012, we can work with a source control system to develop code and metadata changes, and then export them as a model (I don’t consider XPO files a valid promotion artifact). That works out of the box, but we can go a step further and put in place some automatic tooling to make our deployments quicker, easier and more predictable. The more predictable is a process, the easier to automate it. The more automatic, the stronger and error proof.
Imagine all changes done by our distributed development team are compiled, packed and deployed every night to a consolidated test AOS, so every change finished by our developers the previous day is available to the Testers every morning: That's the kind of automation we can do with the BUILD AND RELEASE capability.
There is plenty to talk about BUILD AND RELEASE automation and its possibilities, but this post is getting longer than expected. Let's follow up on the next ones.

If you still want to prove me wrong about TFS usage, I will be happy to discuss individual cases with you. I worked myself as a developer and development team lead using TFS, so I am very aware of some limitations regarding physical infrastructure needed for isolated environments, for instance. But, please, always consider that actively avoiding the use of a Version Control System on software projects (and a Dynamics AX implementation is such a project) has a prize that somebody will need to pay for.
Give it a try**. Start simple and evolve as you discover potential improvements to your ALM cycle. Analyze pros and cons, always trying to get the most of the tools, and of course, ask us for advice on the specific case!


* I use TFS acronym regardless of the version we are talking about, either on premise (called Team Foundation Server) or cloud (called Visual Studio Team Services, or VSTS) as they are pretty much equivalent with minor differences in the meantime the continuous changes deployed to the cloud version are finally released as a new version to the on-premise flavor. Dynamics AX 2012 is compatible with both flavors but some specific versions or hotfixes are needed for some combinations. See Dynamics AX Prerequisites for specific details.
** Testing TFS is never been easier. From an implementation perspective, by using VSTS you don't need to install nor deploy any component yourself as it works as a service; Cost-wise, VSTS is free up to 5 users, more than enough to test with a pilot team, and overall cost has been greatly reduced even if you need to buy more licenses. Furthermore, license is included in Visual Studio Subscriptions (former MSDN subscriptions) so you may have it licensed already!

Importing a General Journal using Data Import/Export Framework AX 2012

Here is a tutorial on how to configure Dynamics AX 2012 to import a general journal from a CSV file. The steps below are using Contoso demo data.
  1. Create a new folder on the root of the C: Drive and name it “DIEF”:
  2. Navigate to Data import export framework | Setup | Data import export framework parameters. Click “Browse” next to “Shared working directory” and select the “DIEF” folder we created. Once selected, click “Validate”.
  3. Close the “Data import export framework parameters” form.
  4. Go to Data import export framework | Setup | Source data formats. Enter “GLJOURNAL” for the “Source name” and “Type” = “File. In the parameters on the right side, enter “File format” = “Delimited”, “First row header” = TRUE, “Row delimiter” = “{CR}{LF}”, “Column delimiter” = “Comma {,}”, “Text Qualifier” = “*”, and “Role separator” = “;”. Click “Application”, and then select “CostCenter”, “Department”, and “ExpensePurpose”. Enter “CostCenter-Department-ExpensePurpose” for the “Dimension format” value.

  5. Go to Data import export framework | Setup | Target entities. Click “New” and enter “Entity type” = “Entity”, “Entity” = “Custom”, “Entity name” = “GLJOURNAL”, “Staging table” = “DMFLedgerJournalEntity”, “Entity class” = “DMFLedgerBalanceEntityClass”, and “Target entity” = “DMFLedgerJournalTransEntity”. Close the “Target entites” form.
  6. Go to Data import export framework | Common | Processing group. Type “GLJOURNAL” for the “Group name”, Ctrl+S to save, and click “Entities”. 
  7. On the “Select entities for processing group” form, enter “GLJOURNAL” for both the “Entity name” and the “Source data format”. Click “Generate source file”.
  8. On the “Wizard” form, click “Next”. For the “Display data” fields, select the following and put them in the following sequence: JournalName, JournalNum, LineNum, CurrencyCode, TransDate, Voucher, AccountType, LedgerDimension, AmountCurDebit, AmountCurCredit, OffsetAccountType, OffsetLedgerDimension. Click “Generate sample file”.
  9. A .txt file should open, and save it to the root of the C: drive.
  10. Click “Finish” on the “Wizard” form. Close the “Select entities for processing group” form. Close the “Processing group” form.
  11. Go to General ledger | Setup | General ledger parameters. Click “Number sequences”. Right-click “Gene_10” next to “Journal batch number” and click “View details”.
  12. Click “Edit”, change the “_010” to “JN”, and click “Move up”. Click the “General” fast tab and note the “Next” value, in my case “JN000421”.
  13. Close the “Number sequences” form and the “General ledger parameters” form.
  14. Navigate to General ledger | Setup | Journals | Journal names. Select “GenJrn” and right-click the “Acco_18” next to “Voucher series”, and then click “View details”.
  15. On the “Number sequences” form, click “Edit”. In the “Segments” fast tab, click “Add”, select “Constant” for the “Segment”, and type “VN” for “Value”. Move this new segment to the top by clicking “Move up”. Note the next number in the series. In my case, “VN00000038”.
  16. Close all forms.
  17. Open Excel. Click File | Open. Navigate to the C: drive and select the “GLJOURNAL.txt” file (You may need to change the drop menu to “All Files (*.*)”)
  18. On the “Text Import Wizard” form, click “Delimited” and click “Next”. Check the box for “Comma” and click “Finish”.
  19. In line 2, enter the following values for each header:
    1. JournalName = GenJrn
    2. JournalNum = JN000421 (Value from step 12)
    3. LineNum = 1
    4. CurrencyCode = USD
    5. TransDate = 8/19/2013
    6. Voucher = VN00000038 (Value from step 16)
    7. AccountType = Ledger
    8. LedgerDimension = 110180-OU_1-OU_3566-Training
    9. AmountCurDebit = 10
    10. OffsetAccountType = Ledger
    11. OffsetLedgerDimension = 110101-OU_1-OU_3566-Training
  20. Click File | Save As. Click “CSV (Comma delimited)” for the “Save as type” drop-menu.
  21. Close Excel.
  22. Go to Data import export framework | Common | Processing group. Select the line for “GLJOURNAL” and click “Entities”.
  23. Click the folder icon next to “Sample file path”, and select the .csv file from step 20. Click “Generate source mapping”. Close the infolog.
  24. Close the “Select entities for processing group” form.
  25. On the “Processing group” form, select the line for “GLJOURNAL” and click “Get staging data”.
  26. A form for “Create a job ID for the staging data job” should open and populate with a “Job ID”. Click “OK”.
  27. On the “Staging data execution” form, click “Preview”. Verify the columns are correct, and then click “Run”.
  28. Close the infolog.
  29. On the “Processing group” form, click “Copy data to target”. Select the “Job ID” created earlier, and click “OK”. On the “Target data execution” form, click “Run”, then click “OK”.
  30. Close the Infolog.
  31. Go to General ledger | Journals | General journal. Locate the imported journal, and click “Lines”.
  32. Notice the values imported properly, and click Post | Post. The journal posts successfully.

Create Product Master with Product Varients Using X++

Public void Create_ProductMaster(ItemId _itemid,ItemName _itemname,Name _searchname,Name _name,ProductType _ProductType)
{
 EcoResProductMaster                    ecoResProductMaster;
 EcoResProductIdentifier                ecoResProductIdentifier;
 EcoResProductDimensionGroupProduct     ecoResProductDimensionGroupProduct;
 EcoResProductMasterModelingPolicy      ecoResProductMasterModelingPolicy;

 EcoResStorageDimensionGroupProduct     ecoResStorageDimensionGroupProduct;
 EcoResTrackingDimensionGroupProduct    ecoResTrackingDimensionGroupProduct;

 EcoResConfiguration                    ecoResConfiguration;
 EcoResProductMasterConfiguration       ecoResProductMasterConfiguration;

 EcoResSize                             ecoResSize;
 EcoResProductMasterSize                ecoResProductMasterSize;

 EcoResColor                            ecoResColor;
 EcoResProductMasterColor               ecoResProductMasterColor;

 EcoResDistinctProductVariant           ecoResDistinctProductVariant;
 EcoResProductVariantConfiguration      ecoResProductVariantConfiguration;
 EcoResProductVariantColor              ecoResProductVariantColor;
 EcoResProductVariantSize               ecoResProductVariantSize;

 InventTable                            inventTable;
 InventTableModule                      inventTableModule;
 InventItemSetupSupplyType              inventItemSetupSupplyType;

 EcoResStorageDimensionGroupItem        ecoResStorageDimensionGroupItem;
 EcoResTrackingDimensionGroupItem       ecoResTrackingDimensionGroupItem;

 InventModelGroupItem                   inventModelGroupItem;
 InventItemGroupItem                    inventItemGroupItem;

 InventDim                              inventDim;
 InventDimCombination                   inventDimCombination;

try
 {
     //ProductMaster
         ecoResProductMaster.clear();
         ecoResProductMaster.initValue();
         ecoResProductMaster.ProductType                    = EcoResProductType::Item;
         ecoResProductMaster.DisplayProductNumber           = _itemid;
         ecoResProductMaster.SearchName                     = _searchname;
         ecoResProductMaster.VariantConfigurationTechnology = EcoResVariantConfigurationTechnologyType::PredefinedVariants;
         if (ecoResProductMaster.validateWrite())
         {
            ecoResProductMaster.insert();
         }

     //Product Identifer
        ecoResProductIdentifier.clear();
        ecoResProductIdentifier.initValue();
        ecoResProductIdentifier.ProductNumber = _itemid;
        ecoResProductIdentifier.Product       = ecoResProductMaster.RecId;
        ecoResProductIdentifier.insert();

    //Product dimension group
        ecoResProductDimensionGroupProduct.clear();
        ecoResProductDimensionGroupProduct.initValue();
        ecoResProductDimensionGroupProduct.initFromProduct(ecoResProductMaster);
        ecoResProductDimensionGroupProduct.ProductDimensionGroup = EcoResProductDimensionGroup::findByDimensionGroupName("SizeColCon").RecId;
        if(ecoResProductDimensionGroupProduct.validateWrite())
        {
            ecoResProductDimensionGroupProduct.insert();
        }

    //Storage dimension group
        ecoResStorageDimensionGroupProduct.clear();
        ecoResStorageDimensionGroupProduct.initValue();
        ecoResStorageDimensionGroupProduct.Product               = ecoResProductMaster.RecId;
        ecoResStorageDimensionGroupProduct.StorageDimensionGroup = EcoResStorageDimensionGroup::findByDimensionGroupName("Site").RecId;
        if (ecoResStorageDimensionGroupProduct.validateWrite())
        {
            ecoResStorageDimensionGroupProduct.insert();
        }

    //Tracking dimension group
        ecoResTrackingDimensionGroupProduct.clear();
        ecoResTrackingDimensionGroupProduct.initValue();
        ecoResTrackingDimensionGroupProduct.Product                = ecoResProductMaster.RecId;
        ecoResTrackingDimensionGroupProduct.TrackingDimensionGroup = EcoResTrackingDimensionGroup::findByDimensionGroupName("Serial").RecId;
        if (ecoResTrackingDimensionGroupProduct.validateWrite())
        {
            ecoResTrackingDimensionGroupProduct.insert();
        }

    //Product modeling policy
        ecoResProductMasterModelingPolicy.clear();
        ecoResProductMasterModelingPolicy.initValue();
        ecoResProductMasterModelingPolicy.ProductMaster = ecoResProductMaster.RecId;
        if (ecoResProductMasterModelingPolicy.validateWrite())
        {
            ecoResProductMasterModelingPolicy.insert();
        }

    //Product translation
       EcoResProductTranslation::createOrUpdateTranslation(ecoResProductMaster.RecId, _itemname, _searchname);

    //Configuration
         ecoResConfiguration = EcoResConfiguration::findByName("NoteBook");
         if (!ecoResConfiguration)
         {
             ecoResConfiguration.clear();
             ecoResConfiguration.initValue();
             ecoResConfiguration.Name = "NoteBook ";
             ecoResConfiguration.insert();
         }

    //Size
         ecoResSize = EcoResSize::findByName("1");
         if(!ecoResSize)
         {
             ecoResSize.clear();
             ecoResSize.initValue();
             ecoResSize.Name = "1 ";
             ecoResSize.insert();
         }
    //color
        ecoResColor = EcoResColor::findByName("Black");
        if(!ecoResColor)
        {
            ecoResColor.clear();
            ecoResColor.initValue();
            ecoResColor.Name = "Black";
            ecoResColor.insert();
        }

    //InventDimId Creating
        inventDim.clear();
        inventDim.ConfigId = "NoteBook";/*ConfigId*/
        inventDim.InventSizeId =  "1";  //size
        inventDim.InventColorId = "Black"; // name
        inventDim = InventDim::findOrCreate(inventDim);

    //Configuration assigned to product master
        ecoResProductMasterConfiguration.clear();
        ecoResProductMasterConfiguration.initValue();
        ecoResProductMasterConfiguration.Configuration = ecoResConfiguration.RecId;
        ecoResProductMasterConfiguration.ConfigProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, ConfigId));
        ecoResProductMasterConfiguration.ConfigProductMaster = ecoResProductMaster.RecId;
        ecoResProductMasterConfiguration.insert();

    //Size assigned to product master
        ecoResProductMasterSize.clear();
        ecoResProductMasterSize.initValue();
        ecoResProductMasterSize.Size = ecoResSize.RecId;
        ecoResProductMasterSize.SizeProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventSizeId));
        ecoResProductMasterSize.SizeProductMaster    = ecoResProductMaster.RecId;

    //color assigned to product master
        ecoResProductMasterColor.clear();
        ecoResProductMasterColor.initValue();
        ecoResProductMasterColor.Color = ecoResColor.RecId;
        ecoResProductMasterColor.ColorProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventColorId));
        ecoResProductMasterColor.ColorProductMaster = ecoResProductMaster.RecId;

    //Product variant
        ecoResDistinctProductVariant.clear();
        ecoResDistinctProductVariant.initValue();
        ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(
        ecoResProductMaster.productNumber(),
        EcoResProductVariantDimValue::getDimensionValuesContainer(_itemname, "1", "Black",""));
        ecoResDistinctProductVariant.SearchName = ecoResProductMaster.SearchName /*ConfigId*/;
        ecoResDistinctProductVariant.ProductType = ecoResProductMaster.ProductType;
        ecoResDistinctProductVariant.ProductMaster = ecoResProductMaster.RecId;
        ecoResDistinctProductVariant.insert();

    //Product variant configuration
        ecoResProductVariantConfiguration.clear();
        ecoResProductVariantConfiguration.initValue();
        ecoResProductVariantConfiguration.initFromDistinctProductVariant(ecoResDistinctProductVariant);
        ecoResProductVariantConfiguration.ProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, ConfigId));
        ecoResProductVariantConfiguration.Configuration = ecoResConfiguration.RecId;
        ecoResProductVariantConfiguration.insert();

    //product variant size
        ecoResProductVariantSize.clear();
        ecoResProductVariantSize.initValue();
        ecoResProductVariantSize.initFromDistinctProductVariant(ecoResDistinctProductVariant);
        ecoResProductVariantSize.ProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventSizeId));
        ecoResProductVariantSize.Size                      = ecoResSize.RecId;
        ecoResProductVariantSize.insert();

    //product variant color
        ecoResProductVariantColor.clear();
        ecoResProductVariantColor.initValue();
        ecoResProductVariantColor.initFromDistinctProductVariant(ecoResDistinctProductVariant);
        ecoResProductVariantColor.ProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventColorId));
        ecoResProductVariantColor.Color                     = ecoResColor.RecId;
        ecoResProductVariantColor.insert();


    //Product variant translation
         EcoResProductTranslation::createOrUpdateTranslation(ecoResDistinctProductVariant.RecId, _itemname, _searchname);

    //Released product
        inventTable.clear();
        inventTable.initValue();
        inventTable.initFromEcoResProduct(ecoResProductMaster);
        inventTable.ItemId    =_itemid;
        inventTable.NameAlias =_searchname;
        if(inventTable.validateWrite())
        {
            inventTable.insert();
        }

    //Inventory model group
        inventModelGroupItem.clear();
        inventModelGroupItem.initValue();
        inventModelGroupItem.ItemDataAreaId = inventTable.dataAreaId;
        inventModelGroupItem.ItemId         = inventTable.ItemId;
        inventModelGroupItem.ModelGroupId   = "FIFO";
        inventModelGroupItem.ModelGroupDataAreaId = curext();
        inventModelGroupItem.insert();

    //Item group
        inventItemGroupItem.clear();
        inventItemGroupItem.initValue();
        inventItemGroupItem.ItemDataAreaId = inventTable.dataAreaId;
        inventItemGroupItem.ItemId         = inventTable.ItemId;
        inventItemGroupItem.ItemGroupId    = "Parts";
        inventItemGroupItem.ItemGroupDataAreaId = curext();
        inventItemGroupItem.insert();

    //Extended product details – Inventory
        inventTableModule.clear();
        inventTableModule.initValue();
        inventTableModule.ItemId     = inventTable.ItemId;
        inventTableModule.ModuleType = ModuleInventPurchSales::Invent;
        inventTableModule.insert();

    //Extended product details – Purchase
        inventTableModule.clear();
        inventTableModule.initValue();
        inventTableModule.ItemId     = inventTable.ItemId;
        inventTableModule.ModuleType = ModuleInventPurchSales::Purch;
        inventTableModule.insert();

    //Extended product details – Sales
        inventTableModule.clear();
        inventTableModule.initValue();
        inventTableModule.ItemId     = inventTable.ItemId;
        inventTableModule.ModuleType = ModuleInventPurchSales::Sales;
        inventTableModule.insert();

    //Warehouse items
        InventItemLocation::createDefault(inventTable.ItemId);

    //Supply type setup
        inventItemSetupSupplyType.clear();
        inventItemSetupSupplyType.initValue();
        inventItemSetupSupplyType.ItemId         = inventTable.ItemId;
        inventItemSetupSupplyType.ItemDataAreaId = inventTable.DataAreaId;
        inventItemSetupSupplyType.insert();

    //Product storage dimension group
        ecoResStorageDimensionGroupProduct = EcoResStorageDimensionGroupProduct::findByProduct(ecoResProductMaster.RecId);
        if (ecoResStorageDimensionGroupProduct.RecId)
        {
            ecoResStorageDimensionGroupItem.clear();
            ecoResStorageDimensionGroupItem.initValue();
            ecoResStorageDimensionGroupItem.ItemDataAreaId        = inventTable.DataAreaId;
            ecoResStorageDimensionGroupItem.ItemId                = inventTable.ItemId;
            ecoResStorageDimensionGroupItem.StorageDimensionGroup = ecoResStorageDimensionGroupProduct.StorageDimensionGroup;
            ecoResStorageDimensionGroupItem.insert();
        }

    //Product tracking dimension group
        ecoResTrackingDimensionGroupProduct = EcoResTrackingDimensionGroupProduct::findByProduct(ecoResProductMaster.RecId);
        if (ecoResTrackingDimensionGroupProduct.RecId)
        {
            ecoResTrackingDimensionGroupItem.clear();
            ecoResTrackingDimensionGroupItem.initValue();
            ecoResTrackingDimensionGroupItem.ItemDataAreaId         = inventTable.DataAreaId;
            ecoResTrackingDimensionGroupItem.ItemId                 = inventTable.ItemId;
            ecoResTrackingDimensionGroupItem.TrackingDimensionGroup = ecoResTrackingDimensionGroupProduct.TrackingDimensionGroup;
            ecoResTrackingDimensionGroupItem.insert();
        }

    //Released product variant
        inventDimCombination.clear();
        inventDimCombination.initValue();
        inventDimCombination.DistinctProductVariant = ecoResDistinctProductVariant.RecId;
        inventDimCombination.ItemId                 = inventTable.ItemId;
        inventDimCombination.InventDimId            = inventDim.InventDimId;
        inventDimCombination.insert();
        info("Done!");
    }
   catch
   {
      error("Error!");
      return;
   }
}