Friday, 24 March 2023

How to Create or copy product attributes using X++ code

 The post is about copying the product attributes from one product to another, you can use it to create new attributes as well.

/// <summary>

    /// Copy the product categories

    /// </summary>

    /// <param name = "_origProduct">Origin product</param>

    /// <param name = "_newProduct">New product</param>

    public void updateProductCategories(EcoResProduct _origProduct, EcoResProduct _newProduct)

    {

        EcoResProductCategory   ecoResProductCategory, ecoResProductCategoryOrig;

        EcoResProductRecId      newEcoResProductRecId = _newProduct.RecId;


        delete_from ecoResProductCategory

            where ecoResProductCategory.Product == newEcoResProductRecId;


        RefRecId  origProductRecId, newProductRecId,     productInstanceRecIdNew, ecoResTextValueRecId_AfterInsert;        

        

        EcoResCategory                     ecoResCategory;

        EcoResCategoryAttributeLookup      ecoResCategoryAttributeLookup;

        

        EcoResAttribute                    ecoResAttribute;

        EcoResAttributeValue               ecoResAttributeValue, ecoResAttributeValue_ForInsert;

        EcoResProductInstanceValue         ecoResProductInstanceValue, ecoResProductInstanceValueNew;

        EcoResTextValue                    ecoResTextValue, ecoResTextValue_ForInsert;

        

        if (_origProduct && _newProduct)        

        {            

            origProductRecId = _origProduct.RecId;

            newProductRecId = _newProduct.RecId;

            

            if (origProductRecId != newProductRecId)            

            {              

                ttsBegin;


                ecoResProductInstanceValueNew.Product = newProductRecId;


                new OverwriteSystemFieldsPermission().assert();


                ecoResProductInstanceValueNew.overwriteSystemfields(true);

                ecoResProductInstanceValueNew.(fieldNum(EcoResProductInstanceValue, InstanceRelationType)) = tableName2id(tableStr(EcoResProductInstanceValue));

                ecoResProductInstanceValueNew.insert();


                ecoResProductInstanceValueNew.overwriteSystemfields(false);

                CodeAccessPermission::revertAssert();

                ttsCommit;

                

                if (ecoResProductInstanceValueNew)                

                {

                    productInstanceRecIdNew = ecoResProductInstanceValueNew.RecId;

                    

                    while select ecoResProductCategoryOrig

                            where ecoResProductCategoryOrig.Product == origProductRecId

                        join ecoResCategory 

                            where ecoResCategory.RecId == ecoResProductCategoryOrig.Category

                    {

                        ttsbegin;

                        ecoResProductCategory.Product           = newProductRecId;                   

                        ecoResProductCategory.Category          = ecoResProductCategoryOrig.Category;

                        ecoResProductCategory.CategoryHierarchy = ecoResProductCategoryOrig.CategoryHierarchy;

                        ecoResProductCategory.insert();                       

                        ttscommit;

                        if (ecoResProductCategory)                        

                        {

                            while select ecoResCategoryAttributeLookup where ecoResCategoryAttributeLookup.Category == ecoResCategory.RecId  

                                        join ecoResAttribute where ecoResAttribute.RecId == ecoResCategoryAttributeLookup.Attribute

                            

                            {

                                select firstonly ecoResAttributeValue 

                                        where ecoResAttributeValue.Attribute == ecoResAttribute.RecId

                                    join ecoResProductInstanceValue 

                                        where ecoResProductInstanceValue.RecId == ecoResAttributeValue.InstanceValue 

                                        && ecoResProductInstanceValue.Product == origProductRecId

                                    join ecoResTextValue 

                                        where ecoResTextValue.RecId == ecoResAttributeValue.Value;

                                

                                if (ecoResAttributeValue.Attribute > 0)                                 

                                {

                                    ecoResTextValue_ForInsert.TextValue = ecoResTextValue.TextValue;

                                    new OverwriteSystemFieldsPermission().assert();

                                    ecoResTextValue_ForInsert.overwriteSystemfields(true);

                                    ecoResTextValue_ForInsert.(fieldNum(EcoResTextValue, InstanceRelationType)) = tableName2id(tableStr(EcoResTextValue));

                                    ecoResTextValue_ForInsert.insert();

                                    ecoResTextValue_ForInsert.overwriteSystemfields(false);

                                    CodeAccessPermission::revertAssert();

                                   

                                }

                                

                                if (ecoResTextValue_ForInsert)                                

                                {

                                    ecoResTextValueRecId_AfterInsert = ecoResTextValue_ForInsert.RecId;  

                                                                       

                                    ecoResAttributeValue_ForInsert.Attribute     = ecoResAttributeValue.Attribute;    

                                    ecoResAttributeValue_ForInsert.InstanceValue = productInstanceRecIdNew;      

                                    ecoResAttributeValue_ForInsert.Value         = ecoResTextValueRecId_AfterInsert;     

                                    ecoResAttributeValue_ForInsert.insert();

                                    

                                    

                                }

                            }  

                        }

                    }   

                }                

            }                       

        }

        

    }

Thursday, 23 March 2023

How to Create or Copy product using X++?

In this post I would like to show you how to create a Released product using X++. I have used the EcoResProductV2Entity to create the product. The reason for this is, by using the Entity default validations will be triggered and the references will be created automatically. If you want to use the table directly use EcoResProductMaster and create the product. Dont use EcoResDistinctProduct. If you use EcoResDistinctProduct latter it will difficult to create the product variants. It will check for Product master.


The hierarchy is, 

EcoResProductMaster,

EcoResProduct,

EcoResDistinctProduct.


internal final class ReleasedProductCopy

{

    /// <summary>

    /// Copy the selected product

    /// </summary>

    /// <param name = "_inventTable">Old product InventTable buffer</param>

    /// <param name = "_prodNameCon">Product name and search name container</param>

    public void copyProduct(InventTable _inventTable, container _prodNameCon)

    {        

        EcoResProduct                               product, origProduct;

        EcoResDescription                           productDesciption;

        EcoResDistinctProductVariant                ecoResDistinctProductVariant;

        EcoResProductName                           productName = conPeek(_prodNameCon, 1);

        

        if (_inventTable.RecId)

        {

            origProduct                             = _inventTable.Product();

            productDesciption                       = origProduct.productDescription();


            ttsbegin;

                   

            product = this.createNewProduct(origProduct, _prodNameCon);

        

            if (product)

            {

                //Create or update all language translations

                this.createOrUpdateTranslation(origProduct, product, productName, productDesciption);


                //Release the created master prodcut

                this.releaseProduct(product); 

               

                if (origProduct.productSubtype() == EcoResProductSubtype::ProductMaster)

                {

                    


                    //Create product variants

                    ecoResDistinctProductVariant = this.createProductVariants(origProduct, product);

                }


                //Update the released prodcut information

                this.createRetailKit(origProduct, product, ecoResDistinctProductVariant);

               

                Info(strFmt("@ItemCopy:NewProductInfo", product.DisplayProductNumber));

            }


            ttscommit;

        }

        

    }


    /// <summary>

    /// Create a new product from the exiting product

    /// </summary>

    /// <param name = "_origProduct">Origin product buffer</param>

    /// <param name = "_prodNameSearchName">Product name and Search name buffer</param>

    /// <returns>New product buffer</returns>

    public EcoResProduct createNewProduct(EcoResProduct _origProduct, container _prodNameSearchName)

    {

        EcoResProductV2Entity                       ecoResProductEntity;

        EcoResProductDimensionGroup                 ecoResProductDimensionGroup;

        EcoResStorageDimensionGroup                 ecoResStorageDimensionGroup;

        EcoResTrackingDimensionGroup                ecoResTrackingDimensionGroup;

        EcoResProductDimensionGroupProduct          ecoResProductDimensionGroupProduct;

        EcoResStorageDimensionGroupProduct          ecoResStorageDimensionGroupProduct;

        EcoResTrackingDimensionGroupProduct         ecoResTrackingDimensionGroupProduct;

        EcoResProductMasterModelingPolicy           ecoResProductMasterModelingPolicy;

        EcoResCategory                              ecoResCategory;

        EcoResProductCategory                       ecoResProductCategory;

        EcoResProduct                                origProduct;

        EcoResProductMaster                         ecoResProductMaster;

        WHSEcoResProductTransportationCodes         wHSEcoResProductTransportationCodes;

        EcoResProductServiceWarranty                ecoResProductServiceWarranty;

        EcoResDescription                           productDesciption;

        

        NumberSequenceReference                     numberSequenceReference = EcoResProductParameters::numRefProductNumber();

        NumberSequenceTable                         numberSequenceTable = numberSequenceReference.numberSequenceTable();

        NumberSeq                                   numberSeq   = NumberSeq::newGetNumFromId(numberSequenceTable.RecId);



        origProduct                             = _origProduct;

        productDesciption                       = origProduct.productDescription();


        select firstonly Name, RecId from ecoResProductDimensionGroup

            join ecoResProductDimensionGroupProduct

             where ecoResProductDimensionGroupProduct.ProductDimensionGroup == ecoResProductDimensionGroup.RecId

                && ecoResProductDimensionGroupProduct.Product == origProduct.RecId;


        select firstonly Name, RecId from ecoResStorageDimensionGroup

            join ecoResStorageDimensionGroupProduct

             where ecoResStorageDimensionGroupProduct.StorageDimensionGroup == ecoResStorageDimensionGroup.RecId

                && ecoResStorageDimensionGroupProduct.Product == origProduct.RecId;


        select firstonly Name, RecId from ecoResTrackingDimensionGroup

            join ecoResTrackingDimensionGroupProduct

             where ecoResTrackingDimensionGroupProduct.TrackingDimensionGroup == ecoResTrackingDimensionGroup.RecId

                && ecoResTrackingDimensionGroupProduct.Product == origProduct.RecId;


        select firstonly ecoResProductMaster

            where ecoResProductMaster.RecId == origProduct.RecId;


        select firstonly ecoResProductMasterModelingPolicy

            where ecoResProductMasterModelingPolicy.ProductMaster == ecoResProductMaster.RecId;


        select firstonly Name from ecoResCategory

            join ecoResProductCategory

            where ecoResProductCategory.Product == origProduct.RecId;


        select firstonly STCCCode, HarmonizedCode, NMFCCode from wHSEcoResProductTransportationCodes

            where wHSEcoResProductTransportationCodes.Product == origProduct.RecId;


        select firstonly ecoResProductServiceWarranty

            where ecoResProductServiceWarranty.DistinctProduct == origProduct.RecId;


        ecoResProductEntity.ProductNumber                           = numberSeq.num();

        ecoResProductEntity.ProductName                             = conPeek(_prodNameSearchName, 1);

        ecoResProductEntity.ProductSearchName                       = conPeek(_prodNameSearchName, 2);

        ecoResProductEntity.ProductDescription                      = productDesciption;

        ecoResProductEntity.ProductType                             = origProduct.ProductType;

        ecoResProductEntity.ProductSubType                          = origProduct.productSubtype();

        ecoResProductEntity.VariantConfigurationTechnology          = ecoResProductMaster.VariantConfigurationTechnology;

        ecoResProductEntity.ProductDimensionGroupName               = ecoResProductDimensionGroup.Name;

        ecoResProductEntitY.StorageDimensionGroupName               = ecoResStorageDimensionGroup.Name;

        ecoResProductEntity.TrackingDimensionGroupName              = ecoResTrackingDimensionGroup.Name;

        ecoResProductEntity.ServiceType                             = origProduct.ServiceType;

        ecoResProductEntity.IsCatchWeightProduct                    = origProduct.PdsCWProduct;

        ecoResProductEntity.IsProductVariantUnitConversionEnabled   = ecoResProductMaster.IsProductVariantUnitConversionEnabled;

        ecoResProductEntity.ProductColorGroupId                     = ecoResProductMaster.RetailColorGroupId;

        ecoResProductEntity.ProductSizeGroupId                      = ecoResProductMaster.RetailSizeGroupId;

        ecoResProductEntity.ProductStyleGroupId                     = ecoResProductMaster.RetailStyleGroupId;

        ecoResProductEntity.AreIdenticalConfigurationsAllowed       = ecoResProductMasterModelingPolicy.IsReuseConfigurationEnabled;

        ecoResProductEntity.IsAutomaticVariantGenerationEnabled     = ecoResProductMasterModelingPolicy.IsVariantGenerationEnabled;

        ecoResProductEntity.RetailProductCategoryName               = ecoResCategory.Name;

        ecoResProductEntity.STCCCode                                = wHSEcoResProductTransportationCodes.STCCCode;

        ecoResProductEntity.HarmonizedSystemCode                    = wHSEcoResProductTransportationCodes.HarmonizedCode;

        ecoResProductEntity.NMFCCode                                = wHSEcoResProductTransportationCodes.NMFCCode;

        ecoResProductEntity.WarrantyDurationTime                    = ecoResProductServiceWarranty.DurationTime;

        ecoResProductEntity.WarrantyDurationTimeUnit                = ecoResProductServiceWarranty.DurationTimeUnit;

        

        ecoResProductEntity.insert();


        EcoResProductNumber productNumber = ecoResProductEntity.ProductNumber;

        

        return EcoResProduct::findByProductNumber(productNumber);

    }


    /// <summary>

    /// Create new product variant

    /// </summary>

    /// <param name = "_oldProduct">source product</param>

    /// <param name = "_newProduct">Destination product</param>

    /// <returns>New variant buffer</returns>

    public EcoResDistinctProductVariant createProductVariants(EcoResProduct _oldProduct, EcoResProduct _newProduct)

    {

        EcoResConfiguration                     ecoResConfiguration;

        EcoResProductMasterConfiguration        ecoResProductMasterConfiguration;

        EcoResDistinctProductVariant            ecoResDistinctProductVariant;

        EcoResProductVariantConfiguration       ecoResProductVariantConfiguration;

        EcoResProductMasterColor                ecoResProductMasterColor, ecoResProductMasterColorOld;

        EcoResProductMasterStyle                ecoResProductMasterStyle, ecoResProductMasterStyleOld;

        EcoResProductMasterSize                 ecoResProductMasterSize, ecoResProductMasterSizeOld;        

        

        RefRecId                            ecoResDistinctProductVariantRecId;

        EcoResProductReleaseManagerBase     releaseManager;

        container productDimensions;


        select firstonly RecId from ecoResConfiguration

            where ecoResConfiguration.Name == _newProduct.DisplayProductNumber;


        if (!ecoResConfiguration.RecId)

        {

            ecoResConfiguration.Name = _newProduct.DisplayProductNumber;

            ecoResConfiguration.insert();

        }


        select firstonly RecId from ecoResProductMasterConfiguration

            where ecoResProductMasterConfiguration.ConfigProductMaster == _newProduct.RecId

                && ecoResProductMasterConfiguration.Configuration == ecoResConfiguration.RecId;


        if (!ecoResProductMasterConfiguration.RecId)

        {

            ecoResProductMasterConfiguration.ConfigProductMaster = _newProduct.RecId;

            ecoResProductMasterConfiguration.Configuration = ecoResConfiguration.RecId;

            ecoResProductMasterConfiguration.ConfigProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, ConfigId));

            ecoResProductMasterConfiguration.insert();

        }

        

        select firstonly ecoResProductMasterColorOlD

            where ecoResProductMasterColorOld.ColorProductMaster == _oldProduct.RecId;

        

        //Color assigned to product master

        ecoResProductMasterColor.clear();

        ecoResProductMasterColor.initValue();

        ecoResProductMasterColor.Color = ecoResProductMasterColorOld.Color;

        ecoResProductMasterColor.ColorProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventColorId));

        ecoResProductMasterColor.ColorProductMaster = _newProduct.RecId;

        ecoResProductMasterColor.insert();


        select firstonly ecoResProductMasterStyleOld

            where ecoResProductMasterStyleOld.StyleProductMaster == _oldProduct.RecId;


        //Style assigned to product master

        ecoResProductMasterStyle.clear();

        ecoResProductMasterStyle.initValue();

        ecoResProductMasterStyle.Style = ecoResProductMasterStyleOld.Style;

        ecoResProductMasterStyle.StyleProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventStyleId));

        ecoResProductMasterStyle.StyleProductMaster = _newProduct.RecId;

        ecoResProductMasterStyle.insert();


        select firstonly ecoResProductMasterSizeOld

            where ecoResProductMasterSizeOld.SizeProductMaster == _oldProduct.RecId;


        //Size assigned to product master

        ecoResProductMasterSize.clear();

        ecoResProductMasterSize.initValue();

        ecoResProductMasterSize.Size = ecoResProductMasterSizeOld.Size;

        ecoResProductMasterSize.SizeProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, InventSizeId));

        ecoResProductMasterSize.SizeProductMaster = _newProduct.RecId;

        ecoResProductMasterSize.insert();


        EcoResDistinctProduct ecoResDistinctProduct;


        select firstonly ecoResDistinctProduct

            where ecoResDistinctProduct.RecId == _oldProduct.RecId;


        productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainerForConfiguration(ecoResConfiguration.Name);


        //Product variant

        ecoResDistinctProductVariant.clear();

        ecoResDistinctProductVariant.initValue();

        ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(

                                                            _newProduct.productNumber(),

                                                            productDimensions);

        

        ecoResDistinctProductVariant.ProductType    = _newProduct.ProductType;

        ecoResDistinctProductVariant.ProductMaster  = _newProduct.RecId; 


        //Product variant configuration

        ecoResProductVariantConfiguration.clear();

        ecoResProductVariantConfiguration.initValue();

        ecoResProductVariantConfiguration.initFromDistinctProductVariant(ecoResDistinctProductVariant);

        ecoResProductVariantConfiguration.ProductDimensionAttribute = EcoResProductDimensionAttribute::inventDimFieldId2DimensionAttributeRecId(fieldNum(InventDim, ConfigId));

        ecoResProductVariantConfiguration.Configuration = ecoResConfiguration.RecId;

        

        ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(_newProduct.RecId, ecoResDistinctProductVariant.DisplayProductNumber, productDimensions);


        //Find newly created Product Variant

        ecoResDistinctProductVariant = ecoResDistinctProductVariant::find(ecoResDistinctProductVariantRecId);


        //Now release the Product variant

        releaseManager = EcoResProductReleaseManagerBase::newFromProduct(ecoResDistinctProductVariant);

        releaseManager.release();


        return ecoResDistinctProductVariant;

    }


    /// <summary>

    /// Copy or update translation

    /// </summary>

    /// <param name = "_ecoResProdcutSource">Source product</param>

    /// <param name = "_ecoResProdcutDestination">Destination product</param>

    /// <param name = "_productName">Product name</param>

    /// <param name = "_productDesciption">Product description</param>

    public void createOrUpdateTranslation(EcoResProduct         _ecoResProdcutSource, 

                                            EcoResProduct       _ecoResProdcutDestination,

                                            EcoResProductName   _productName,

                                            EcoResDescription   _productDesciption)

    {

        //Create one or more translations

        EcoResProductTranslation::createOrUpdateTranslation(_ecoResProdcutDestination.RecId, _productName, _productDesciption);


        EcoResProductRecId          newproductRecId = _ecoResProdcutDestination.RecId;

        EcoResProductTranslation    ecoResProductTranslation, ecoResProductTranslationOld;

        LanguageId                  systemLanguageId = SystemParameters::getSystemLanguageId();

       

        insert_recordset ecoResProductTranslation(Description,LanguageId ,Name ,Product)

            select Description,LanguageId ,Name , newproductRecId from ecoResProductTranslationOld

                where ecoResProductTranslationOld.LanguageId != systemLanguageId

                    && ecoResProductTranslationOld.Product == _ecoResProdcutSource.RecId;

    }


    /// <summary>

    /// Release the new product in current company

    /// </summary>

    /// <param name = "_ecoResProdcut">new Ecoresporduct buffer</param>

    public void releaseProduct(EcoResProduct _ecoResProdcut)

    {

        EcoResProductReleaseSessionManager          productReleaseSessionManager;

        EcoResReleaseSessionRecId                   releaseSessionRecId;

        Args                                        args;

        CompanyInfo                                 companyInfo = CompanyInfo::find();


        // Release the master product for the current company

        productReleaseSessionManager    = EcoResProductReleaseSessionManager::newReleaseSession();

        releaseSessionRecId             = productReleaseSessionManager.parmReleaseSessionRecId();


        productReleaseSessionManager.addProduct(_ecoResProdcut.RecId);

        productReleaseSessionManager.addLegalEntityForProduct(companyInfo.RecId, _ecoResProdcut.RecId);


        args = new Args(formStr(EcoResProductRelease));

        args.record(EcoResReleaseSession::find(releaseSessionRecId));


        // the first boolean parameter is for showing a log for errors

        // the second boolean parameter is for executing the release with a batch

        if (EcoResProductReleaseSessionBatch::runJob(args, true, false))

        {

            productReleaseSessionManager.cleanUp();

        }

    }


/// <summary>

    /// Create retail kit

    /// </summary>

    /// <param name = "_origProduct">Origin item number</param>

    /// <param name = "_newProduct">New item number</param>

    /// <param name = "_ecoResDistinctProductVariant">Product variant</param>

    public void createRetailKit(EcoResProduct _origProduct, EcoResProduct _newProduct, EcoResDistinctProductVariant _ecoResDistinctProductVariant)

    {

        RetailKit                       retailKit, retailKitOld;

        RetailKitComponent              retailKitComponent, retailKitComponentOrig;

        RetailKitVariantComponent       retailKitVariantComponent, retailKitVariantComponentOld;

        EcoResDistinctProductRecId      newKitVariant;


        newKitVariant = _newProduct.RecId;   

        

        select firstonly retailKitOld

                    where retailKitOld.ProductMaster == _origProduct.RecId;


        if (retailKitOld)

        {

            retailKit.data(retailKitOld);

            retailKit.ProductMaster = _newProduct.RecId;

            retailKit.insert();


            if (retailKit)

            {

                while select retailKitComponentOrig

                    join retailKitVariantComponentOld

                        where retailKitComponentOrig.Kit == retailKitOld.RecId

                        && retailKitVariantComponentOld.ComponentRecId == retailKitComponentOrig.RecId

                {       

                    buf2Buf(retailKitComponentOrig, retailKitComponent);

                    retailKitComponent.Kit = retailKit.RecId;

                    retailKitComponent.insert();


                    if (retailKitComponent)

                    {

                        buf2Buf(retailKitVariantComponentOld, retailKitVariantComponent);

                        retailKitVariantComponent.ComponentRecId = retailKitComponent.RecId;

                        retailKitVariantComponent.KitVariant = _ecoResDistinctProductVariant.RecId;

                        retailKitVariantComponent.insert();

                    }

                }

            }

        }


    }

}