Monday, February 28, 2022

Process multiple selected record

1. Create a button ProcessSelected(Form Button Control , Text( On Hold(All Selected)), MultiSelect - Yes

2. Copy the event handler and remove static, We will be able to use this here.

 [FormControlEventHandler(formControlStr(VendTable, ProcessSelected), FormControlEventType::Clicked)]

    public void ProcessSelected_OnClicked(FormControl sender, FormControlEventArgs e)

    {

        this.processSelected(sender,e);

    }

3. ProcessSelected method

public void processSelected(FormControl sender,FormControlEventArgs e)

    {

        VendTable tmpVendTable, updateVendTable;         

        int recordUpdated;


        for(tmpVendTable = this.VendTable_ds.getFirst(true) ?

            this.VendTable_ds.getFirst(true) :

            this.VendTable_ds.cursor(); tmpVendTable; tmpVendTable =

            this.VendTable_ds.getNext())

        {

            ttsbegin;

            select firstonly forupdate updateVendTable where

                updateVendTable.AccountNum == tmpVendTable.AccountNum;

            updateVendTable.Blocked = CustVendorBlocked::All;

            updateVendTable.update();

            recordUpdated++;

            ttscommit;

        }

        info(strFmt("Total %1 records processed", recordUpdated));

    }


Combo Box selection at Form level and filtering records in D365 form

1. Create Main account Extension

2. Add a group Filter, Auto dec - Yes

3. Within the group add ComboBox control FilterType, Auto decl -Yes, Selection - 10(Profit Loss), Enum Type -  DimensionLedgerAccountType

4. Also Add Filter Name -> Type String, Edt - Account Name

4. Create a class extension MainAccountForm_Extension, Add below methods


    [FormControlEventHandler(formControlStr(MainAccount, FilterName), FormControlEventType::Modified)]

    public static void FilterName_OnModified(FormControl sender, FormControlEventArgs e)

    {

        FormDataSource mainAccount_ds = sender.formRun().dataSource(formdatasourcestr(MainAccount,MainAccount));

        mainAccount_ds.executeQuery();

    }


/// <summary>

    ///

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="e"></param>

    [FormControlEventHandler(formControlStr(MainAccount, FilterType), FormControlEventType::Modified)]

    public static void FilterType_OnModified(FormControl sender, FormControlEventArgs e)

    {

        FormDataSource mainAccount_ds =sender.formRun().dataSource(formdatasourcestr(MainAccount,MainAccount));

        mainAccount_ds.executeQuery();

    }


 [FormDataSourceEventHandler(formDataSourceStr(MainAccount, MainAccount), FormDataSourceEventType::QueryExecuting)]
    public static void MainAccount_OnQueryExecuting(FormDataSource sender, FormDataSourceEventArgs e)
    {
        QueryBuildRange qbrName;
        QueryBuildRange qbrType;

        QueryBuildDataSource qbds = sender.query().dataSourceTable(tableNum(MainAccount));
        MainAccount::updateBalances();

qbrName = SysQuery::findOrCreateRange(qbds,fieldNum(MainAccount,Name));
        qbrType = SysQuery::findOrCreateRange( qbds,fieldNum(MainAccount,Type));

        str filterText = sender.formRun().design().controlName("FilterName").valueStr();
        if (filterText)
        {
            qbrName.value(SysQuery::valueLike(filterText));
        }
        else
        {
            qbrName.value(SysQuery::valueUnlimited());
        }
        FormComboBoxControl FilterType = sender.formRun().design().controlName("FilterType");
        if (FilterType.selection() == DimensionLedgerAccountType::Blank)
        {
            qbrType.value(SysQuery::valueUnlimited());
        }
        else
        {
            qbrType.value(queryValue(FilterType.selection()));
        }
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    [FormDataSourceEventHandler(formDataSourceStr(MainAccount, MainAccount), FormDataSourceEventType::QueryExecuted)]
    public static void MainAccount_OnQueryExecuted(FormDataSource sender, FormDataSourceEventArgs e)
    {

        FormRun formRun = sender.formRun();
        formRun.CreateTree();
    }

Points to remember

a. The control should be auto declared to Yes

b. On modified should call the execute query.

c. Execute query should define the range, it should check if the range exist if not create and then apply the range.

example qbrName = SysQuery::findOrCreateRange(qbds,fieldNum(MainAccount,Name)); 

d. In case of  text match, use qbrName.value(SysQuery::valueLike(filterText)); else make it value unlimited qbrName.value(SysQuery::valueUnlimited());



Monday, February 21, 2022

ADDING COLOR TO A FORM CONTROL

[FormDataSourceEventHandler(formDataSourceStr(SalesTable, SalesLine), FormDataSourceEventType::DisplayOptionInitialize)]
public static void SalesLine_OnDisplayOptionInitialize(FormDataSource sender, FormDataSourceEventArgs e)
{
FormDataSourceDisplayOptionInitializeEventArgs eventArgs = e as FormDataSourceDisplayOptionInitializeEventArgs;
eventArgs.displayOption().affectedElementsByControl(sender.formRun().design(0).controlName(“ControlName”).id());
eventArgs.displayOption().textColor(WinAPI::RGB2int(255,0,0));
}

Financial Dimension Function

Getting main account from ledger dimension.

 MainAccount mainAccount = MainAccount::findByLedgerDimension(trvCostType.LedgerDimension);


Dimension Value from Dimension name( cost center or )

 public DimensionValue getDimensionValues(DimensionDefault _defaultDimension, str _dimensionName)

    {

        DimensionAttributeValueSetStorage   dimStorage;

        DimensionAttribute                  dimensionAttribute;

        DimensionAttributeValue             dimensionAttributeValue;

        DimensionValue                      dimensionValue;


        dimStorage = DimensionAttributeValueSetStorage::find(_defaultDimension);

        

        dimensionAttribute.clear();

        dimensionAttributeValue.clear();

        dimensionAttribute = DimensionAttribute::findByName(_dimensionName);

        if (dimStorage != null && dimensionAttribute)

        {

            dimensionAttributeValue = DimensionAttributeValue::find(dimStorage.getValueByDimensionAttribute(dimensionAttribute.RecId));


            dimensionValue = dimStorage.getDisplayValueByDimensionAttribute(dimensionAttribute.RecId);

        }


        return dimensionValue;

    }

Saturday, February 19, 2022

Parameter Form - Table of Content(TOC)

 1. Create Parameter table -> Cache Lookup (Entire Table) -> Table Type(Parameter).

2. Add the required fields.

3. Add a field Key and EDT type Parameter Keys, make visibility to false.

4. Create a unique index KeyIdx with Key field.

5. We need to create 4 methods

    a. Find

public static WHSVehicleParameters find(boolean _forupdate = false )

    {

        WHSVehicleParameters parameter;


        parameter.selectForUpdate(_forupdate);


        select firstonly parameter

index KeyIdx

            where parameter.Key == 0;


if(!parameter && !parameter.isTmp())

        {

            Company::createParameter(parameter);

        }

  

        return parameter;

    }

    b Exist

 public static boolean exist()

    {

        

        return ((select firstonly RecId from WHSVehicleParameters).RecId != 0);

    }

    c Update

  public void update()

    {

        super();

        flush WHSVehicleParameters;

    }

    d delete

    public void delete()

    {

        throw Error("Not Allowed");

    }

6. Create a new form and add data source

7. Make allowcreate, allowdelete, insert if empty and insert at end to false.

8. Select form pattern - Table of Content.

9. Follow the pattern control suggestion or as shown in below pic.

10. Override the init method of form and add the find code before super to create one record.

 public void init()

    {

        WHSVehicleParameters::find();

        super();

    }








 Build and Run

    


  

   


 



    

  


Find and Exist Method

 /// <summary>

    ///

    /// </summary>

    public static ConWHSVehicleGroup find(ConWHSVehicleGroupId _groupId,boolean _forupdate = false )

    {

        ConWHSVehicleGroup vehGroup;


        vehGroup.selectForUpdate(false);


select firstonly * from vehGroup

            where vehGroup.WHSVehicleGroupId == _groupId;

        return vehGroup;

    }


    /// <summary>

    ///

    /// </summary>

    public static boolean exist(ConWHSVehicleGroupId _groupId)

    {

        ConWHSVehicleGroup vehGroup; 


if(_groupId)

        {

            select firstonly RecId from vehGroup

where vehGroup.WHSVehicleGroupId == _groupId;  

        }

       

        return (vehGroup.RecId !=0);

    }

Friday, February 18, 2022

OnValidated Event Handler

   [FormControlEventHandler(formControlStr(SalesTable, InventoryDimensionsGrid_inventBatchId), FormControlEventType::Validated)]

    public static void InventoryDimensionsGrid_inventBatchId_OnValidated(FormControl sender, FormControlEventArgs e)

    {

        SalesLine salesLine;

        InventDim inventDim;

        boolean ret;


        FormControlCancelEventArgs args = e as FormControlCancelEventArgs;


        FormRun formRun = sender.formRun();


        FormStringControl batchId = formRun.design(0).controlName("ControlName");

        InventBatchId inventBatchId = batchId.text();


        select firstonly RecId from salesLine

           join inventDim where inventDim.inventDimId == salesLine.InventDimId

            &&  inventDim.inventBatchId == inventBatchId && inventDim.inventBatchId !=''

            && salesLine.ProductionOrderReference !="";


        if(salesLine.RecId)

        {

ret = checkFailed("BatchAllocationError");

args.cancel(true);

        }

    }

How to generate inventory dimension from existing dimension with change in some dimension value

   public InventDimId getInventoryDimension(InventDimId _orignalDimId,EcoResItemConfigurationName _configId)

    {

        InventDim inventDim,inventDimLoc;


        inventDim = InventDim::find(_orignalDimId,false);


        select inventDimLoc where inventDimLoc.InventSiteId == inventDim.InventSiteId && inventDimLoc.InventLocationId == inventDim.InventLocationId

                    && inventDimLoc.InventColorId == inventDim.InventColorId && inventDimLoc.InventStyleId == inventDim.InventStyleId

                    && inventDimLoc.InventSizeId == inventDim.InventSizeId && inventDimLoc.configId == _configId

                    && inventDimLoc.inventBatchId == inventDim.inventBatchId && inventDimLoc.inventSerialId == inventDim.inventSerialId && inventDimLoc.LicensePlateId == inventDim.LicensePlateId

                    && inventDimLoc.wMSLocationId == inventDim.wMSLocationId

                    && inventDimLoc.InventStatusId == inventDim.InventStatusId;

        if(!inventDimLoc.RecId)

        {

            inventDimLoc.clear();

            inventDimLoc.InventSiteId       = inventDim.InventSiteId;

            inventDimLoc.InventLocationId   = inventDim.InventLocationId;

            inventDimLoc.InventColorId      = inventDim.InventColorId;

            inventDimLoc.InventStyleId      = inventDim.InventStyleId;

            inventDimLoc.InventSizeId       = inventDim.InventSizeId ;

            inventDimLoc.configId           = _configId;

            inventDimLoc.inventBatchId      = inventDim.inventBatchId;

            inventDimLoc.inventSerialId     = inventDim.inventSerialId;

            inventDimLoc.LicensePlateId     = inventDim.LicensePlateId;

            inventDimLoc.wMSLocationId      = inventDim.wMSLocationId;

            inventDimLoc.InventStatusId     = inventDim.InventStatusId;

        }


        inventDimLoc = InventDim::findOrCreate(inventDimLoc);


        return inventDimLoc.inventDimId;


    }

Releasing specific variant to legal entity using x++

  EcoResDistinctProductVariant   ecoResDistinctProductVariant;

        EcoResProductReleaseManagerBase   releaseManager;

        RefRecId   ecoResDistinctProductVariantRecId;

        EcoResProduct   ecoResProduct = EcoResProduct::findByProductNumber(_itemId);


        container productDimensions = EcoResProductVariantDimValue::getDimensionValuesContainer(_configId);


        ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions(_itemId,productDimensions);


        if(EcoResProductVariantManager::existDistinctProductVariant(ecoResProduct.RecId,productDimensions))

        {

            ecoResDistinctProductVariantRecId = EcoResProductVariantManager::findDistinctProductVariant(ecoResProduct.RecId,productDimensions).RecId;

        }

        else

        {

            ecoResDistinctProductVariantRecId = EcoResProductVariantManager::createProductVariant(ecoResProduct.RecId,

                                                                                                    ecoResDistinctProductVariant.DisplayProductNumber,productDimensions);

        }


        ecoResDistinctProductVariant = ecoResDistinctProductVariant::find(ecoResDistinctProductVariantRecId);


        releaseManager = EcoResProductReleaseManagerBase::newFromProduct(ecoResDistinctProductVariant);

        releaseManager.release();

Production order Scheduling using x++

 public void productionOrdeOperationScheduling(ProdId _productionId)

    {

        ProdTable prodTable;

        ProdMultiSchedulingOperation ProdMultiSchedulingOperation;

        

        prodTable = ProdTable::find(_productionId);

        ProdMultiSchedulingOperation = ProdMultiScheduling::construct(ProdSchedMethod::OperationScheduling);

        RunBaseMultiParm::initParm(ProdMultiSchedulingOperation);

    

        ProdParmScheduling prodParmScheduling;

        prodParmScheduling = ProdMultiSchedulingOperation.defaultParmBuffer();

        prodParmScheduling.SchedDirection  = ProdSchedDirection::BackwardFromDeliveryDate;

        prodParmScheduling.MatLimited = NoYes::Yes;

        prodParmScheduling.SchedDate = prodTable.DlvDate;

        ProdMultiSchedulingOperation.insert(prodTable, prodParmScheduling);

       

        ProdMultiSchedulingOperation.runOperation();

    }

Production Order Estimate using x++

  public void productionOrderEstimation(ProdId _productionId)

    {

        ProdTable prodTable;

        ProdMultiCostEstimation prodMultiCostEstimation;


        prodTable = ProdTable::find(_productionId,false);


        prodMultiCostEstimation = ProdMultiCostEstimation::construct(new Args());


        RunBaseMultiParm::initParm(prodMultiCostEstimation);

        prodMultiCostEstimation.insert(prodTable, prodMultiCostEstimation.defaultParmBuffer());

        prodMultiCostEstimation.runOperation();

    }

Production Order Reset status functionality using X++

  public void prodStatusChange(ProdId _productionId)

    {

        ProdMultiStatusDecrease prodMultiStatusDecrease;

        ProdParmStatusDecrease prodParmStatusDecrease;

        ProdTable prodTable;        


        ProdId prodId = _productionId;

        Args   args    = new Args();

        ttsbegin;


        prodTable = ProdTable::find(prodId,true);


        if (prodTable.ProdStatus != prodStatus::Created)

        {

            args.record(prodTable);

                

            prodParmStatusDecrease.clear();


            prodParmStatusDecrease.initFromProdTable(prodTable);

            if(prodTable.ProdStatus == ProdStatus::CostEstimated)

            {

                prodParmStatusDecrease.WantedStatus = ProdStatus::Created;

            }

            else if (prodTable.ProdStatus == ProdStatus::Scheduled)

            {

                prodParmStatusDecrease.WantedStatus = ProdStatus::CostEstimated;


            }


            prodParmStatusDecrease.ParmId = NumberSeq::newGetNum(CompanyInfo::numRefParmId()).num();

            prodParmStatusDecrease.insert();


            prodMultiStatusDecrease = prodMultiStatusDecrease::construct();

            prodMultiStatusDecrease.initParmBuffer(prodParmStatusDecrease);

            prodMultiStatusDecrease.parmId(prodParmStatusDecrease.ParmId);

            prodMultiStatusDecrease.runOperation();

        }

        ttsCommit;      

    }

Creating Production Order using X++ in D365FO

 ProdTable       prodtable;

  InventTable     inventTable;

  InventDim       inventDim,inventDimLoc;

    ttsbegin;

            inventTable = inventTable::find("Provide ItemId");  

            prodtable.initValue();

            prodtable.ItemId                               = inventTable.ItemId;

            prodtable.DlvDate                             = _origProdTable.DlvDate;

            prodtable.QtySched                           = _origProdTable.QtySched;

            prodtable.RemainInventPhysical       = _origProdTable.RemainInventPhysical;

            prodtable.DlvDate        = _origProdTable.DlvDate;

            prodtable.DlvTime = _origProdTable.DlvTime;

            prodtable.InventDimId = _inventDimId;

            prodtable.GanttColorId = _origProdTable.GanttColorId;

            prodtable.initFromItemId();

            prodtable.initBOMVersion();

            prodtable.initRouteVersion();

            prodtable.insert();

       ttscommit;

Tuesday, February 15, 2022

Lookup - Unique value and Non repeating value after selection

 

   We need to Group by for distinct values :

   QueryBuildDataSource.orderMode(OrderMode::GroupBy);

QueryBuildDataSource.addGroupByField(fieldNum(TableName, FieldName));
For lookup to not show duplicate value after selection use below:
sysTableLookup.parmUseLookupValue(False);

Sample Dialog Syntax - 1

 class AffiliationAutoAssignment extends RunBaseBatch {     // 1. Class Declaration and Pack variables     #define.CurrentVersion(1)     #de...