Tuesday, August 20, 2019

SQL server error while opening visual studio. - solution

Issue: SQL server error while opening visual studio.

Error: A network-related or instance-specific error occurred when establishing a connection to SQL server. The server was not found or was not accessible. ... (provider: Named pipes provider, error: 40 -  Could not open a connection to SQL server)



Resolution: Make sure the SQL server services are running in the machine. Re-open visual studio after service has been started.

Sunday, August 11, 2019

Adding new print management report node in D365 - code sample

public static class PrintMgmtDelegates_Extension
{
 
    /// <summary>
    ///
    /// </summary>
    /// <param name="_nodeType"></param>
    /// <param name="_result"></param>
    [SubscribesTo(classStr(PrintMgmtDelegates), delegateStr(PrintMgmtDelegates, constructPrintMgmtNodeDelegate))]
    public static void PrintMgmtDelegates_constructPrintMgmtNodeDelegate(PrintMgmtNodeType _nodeType, EventHandlerResult _result)
    {
        switch (_nodeType)
        {
            case printmgmtNOdeTYpe::Custom:

                PrintMgmtNode_Custom    printMgmtNode_Custom = new PrintMgmtNode_Custom();
                _result.result(printMgmtNode_Custom);

                break;
        }
    }

}



--------------------------------------------

[ExtensionOf(classStr(PrintMgmtHierarchy_Sales))]
final class PrintMgmtHierarchy_Sales_Extension
{
    protected List getNodesImplementation()
    {
        //List supportedNodes = new List(Types::Enum);
        var supportedNodes = next getNodesImplementation();
        supportedNodes.addEnd(PrintMgmtNodeType::Custom);
        return supportedNodes;
    }

    protected PrintMgmtNodeInstance getParentImplementation(PrintMgmtNodeInstance _nodeInstance, PrintMgmtDocumentType _docType)
    {
        PrintMgmtNodeInstance result;
        result  = next getParentImplementation(_nodeInstance, _docType);
        return result;
    }

}
----------------------------------------------

class PrintMgmtNode_Custom extends PrintMgmtNode
{
    protected str getDisplayCaptionImplementation(Common _tableBuffer)
    {
        return(strfmt("@SYS108944", _tableBuffer.caption()));
    }

    public List getDocumentTypes()
    {
        List    docTypes;

        docTypes = new List(Types::Enum);

        if (isConfigurationkeyEnabled(configurationkeynum(LogisticsBasic)))
        {
            docTypes.addEnd(PrintMgmtDocumentType::Custom);
        }

        return docTypes;
    }

    public int getIconImageResNum()
    {
        #resAppl

        return #ImagePrintManagementTrans;
    }

    public PrintMgmtNodeType getNodeType()
    {
        return PrintMgmtNodeType::Custom;
    }

    public RefTableId getReferencedTableId()
    {
        return tablenum(CustomTable);
    }

}

----------------------------------------

class PrintMgmtNode_Sales_Custom
{
    /// <summary>
    ///
    /// </summary>
    /// <param name="args"></param>
    [PostHandlerFor(classStr(PrintMgmtNode_Sales), methodStr(PrintMgmtNode_Sales, getDocumentTypes))]
    public static void PrintMgmtNode_Sales_Post_getDocumentTypes(XppPrePostArgs args)
    {
        List docTypes;
        docTypes    = new List(Types::Enum);
        docTypes    = Args.getReturnValue();
        docTypes.addEnd(PrintMgmtDocumentType::Custom);

        Args.setReturnValue(docTypes);
    }

}

----------------------


class PrintMgtDocTypeHandlersExt
{
 

    /// <summary>
    ///
    /// </summary>
    /// <param name="_docType"></param>
    /// <param name="_result"></param>
    [SubscribesTo(classStr(PrintMgmtDocType), delegateStr(PrintMgmtDocType, getDefaultReportFormatDelegate))]
    public static void PrintMgmtDocType_getDefaultReportFormatDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result)
    {
        switch (_docType)
        {
            case PrintMgmtDocumentType::Custom:
                _result.result(ssrsReportStr(SalesConfirmExt, Report));
                break;
        }
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="_docType"></param>
    /// <param name="_result"></param>
    [SubscribesTo(classStr(PrintMgmtDocType), delegateStr(PrintMgmtDocType, getQueryTableIdDelegate))]
    public static void PrintMgmtDocType_getQueryTableIdDelegate(PrintMgmtDocumentType _docType, EventHandlerResult _result)
    {
        TableId     tableId;

        switch(_docType)
        {
            case PrintMgmtDocumentType::Custom:
                tableId = tableNum(CustomTable);
                _result.result(tableId);
                break;
        }
    }

}
---------------

class SalesConfirmControllerExt extends SalesConfirmController
{
    public static SalesConfirmControllerExt construct()
    {
        return new SalesConfirmControllerExt();
    }

    public static void main(Args _args)
    {
        SrsReportRunController      formLetterController = SalesConfirmControllerExt::construct();
        SalesConfirmControllerExt   controller = formLetterController;controller.initArgs(_args, ssrsReportStr(SalesConfirmExt, Report));
     
        if (classIdGet(_args.caller()) == classNum(SalesConfirmJournalPrint))
        {
            formLetterController.renderingCompleted += eventhandler(SalesConfirmJournalPrint::renderingCompleted);
        }
     
        formLetterController.startOperation();
    }

}

----------------------

Thursday, August 1, 2019

More than one form was opened at once for lookup control. - solution


Issue: More than one form was opened at once for lookup control.

Resolution: The form control lookup can be extended to get desired lookup using below code:

[FormControlEventHandler(formControlStr(EcoResProductParameters, EcoResProductParameters_ProductEntityAttributeMasterCompanyId), FormControlEventType::Lookup)]
    public static void EcoResProductParameters_ProductEntityAttributeMasterCompanyId_OnLookup(FormControl sender, FormControlEventArgs e)
    {
        FormControlCancelableSuperEventArgs fccse = e as FormControlCancelableSuperEventArgs;
        SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(CompanyInfo), sender);
        Query query = new Query();
        query.addDataSource(tableNum(CompanyInfo));
        sysTableLookup.addLookupfield(fieldNum(CompanyInfo, DataArea));
        sysTableLookup.addLookupfield(fieldNum(CompanyInfo, TSTGlobalNumber));
        sysTableLookup.parmQuery(query);
        sysTableLookup.performFormLookup();
        fccse.CancelSuperCall();
    }

Fields are not visible in the form after adding field group in D365. - solution

Issue: Fields are not visible in the form after adding field group.

Resolution:  It might be due to "Data group" property. Try to clear the "Data group" property from the grid/group control, so that fields are visible in the form.

Tuesday, July 30, 2019

New number sequence in D365

Issue: How to create a new number sequence in D365?

Solution: 1. Create a new EDT for eg. TSTCustomsJourId.
                2. Extend standard "NumberSeqModule" enum and add a new enum value e.g NumberSeqModule::TSTCustoms.
             
Implement below class and methods.

class TSTNumberSeqModuleCustoms extends NumberSeqApplicationModule
{
    /// <summary>
    /// Sets up the references for the <c>TSTCustoms</c> module number sequences.
    /// </summary>
    protected void loadModule()
    {
        NumberSeqDatatype datatype = NumberSeqDatatype::construct();

        /* Setup document numbers */
        datatype.parmDatatypeId(extendedtypenum(TSTCustomsJourId));
        datatype.parmReferenceHelp(literalstr("TST:CustomsHelpText"));
        datatype.parmWizardIsContinuous(false);
        datatype.parmWizardIsManual(NoYes::No);
        datatype.parmWizardfetchAheadQty(10);
        datatype.parmWizardIsChangeDownAllowed(NoYes::No);
        datatype.parmWizardIsChangeUpAllowed(NoYes::No);
        datatype.parmSortField(1);

        datatype.addParameterType(NumberSeqParameterType::DataArea, true, false);
        this.create(datatype);
    }

    /// <summary>
    /// Gets the number sequence module that the current object is attached to.
    /// </summary>
    /// <returns>
    /// The number sequence module that the current object is attached to.
    /// </returns>
    public NumberSeqModule numberSeqModule()
    {
        return NumberSeqModule::TSTCustoms;
    }

    /// <summary>
    ///    Appends the current class to the map that links modules to number sequence data type generators.
    /// </summary>
    [SubscribesTo(classstr(NumberSeqGlobal),delegatestr(NumberSeqGlobal, buildModulesMapDelegate))]
    static void buildModulesMapSubsciber(Map numberSeqModuleNamesMap)
    {
        NumberSeqGlobal::addModuleToMap(classnum(TSTNumberSeqModuleCustoms), numberSeqModuleNamesMap);
    }

}

Financial dimensions - default dimension - ledger dimension - D365 - code samples



Get dimension value from defaultDimension:

DimensionAttributeValueSet dimAttrValueSet;
DimensionAttributeValueSetItem dimAttrValueSetItem;
DimensionAttributeValue dimAttrValue;
DimensionAttribute dimAttribute;


select dimAttrValueSetItem
where dimAttrValueSetItem.DimensionAttributeValueSet == this.defaultDimension
join dimAttrValue
where dimAttrValue.RecId == dimAttrValueSetItem.DimensionAttributeValue
join dimAttribute
where dimAttribute.RecId == dimAttrValue.DimensionAttribute
   && dimAttribute.BackingEntityType == tableNum(DimAttributeOMBusinessUnit);

Return dimAttrValueSetItem.DisplayValue;


Another way:

public static DimensionValue getDimensionValue(RecId defaultDimension, Name dimName)
{
    DimensionAttributeValueSetStorage dimStorage;
    ;
dimStorage = DimensionAttributeValueSetStorage::find(defaultDimension);
return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);
}


Get dimension value from a ledger dimension:
select dimensionAttributeLevelValueView
     where dimensionAttributeLevelValueView.ValueCombinationRecId == generalJournalAccountEntry.LedgerDimension
     join dimensionAttribute
where dimensionAttribute.RecId == dimensionAttributeLevelValueView.DimensionAttribute
&& dimensionAttribute.BackingEntityType == tableNum(DimAttributeOMBusinessUnit);

custBalanceTmp.BusinessUnit = dimensionAttributeLevelValueView.DisplayValue;

Get main account from ledger dimension:

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


Create ledger dimension using main account and default dimension:

ledgerDimension = LedgerDimensionFacade::serviceCreateLedgerDimension(salesForFreeInvoiceAccount, salesPurchLine.defaultDimension);

How to get all the table names (Standard/Customized) in D365? - solution

Issue: How to get all the table names (Standard/Customized) in D365?

Solution: Below lookup method should be implemented to get the desired lookup.

              /// <summary>
        /// The method will lookup all the table names.
        /// </summary>
        public void lookup()
        {
            Query                   lookupQuery;
            QueryBuildDataSource    qbds;
            SysTableLookup          sysTableLookup = SysTableLookup::newParameters(tablenum(SqlDictionary), this);

            // Display the Name field in the lookup form.
            sysTableLookup.addLookupfield(fieldnum(SqlDictionary, Name));

            lookupQuery = new Query();
            qbds = lookupQuery.addDataSource(tablenum(SqlDictionary));
            qbds.addRange(fieldNum(SqlDictionary, fieldId)).value(queryValue(0));
            qbds.addSortField(fieldNum(SqlDictionary, Name), SortOrder::Ascending);
            qbds.addRange(fieldNum(SqlDictionary, shadow)).value(queryValue(0));
            qbds.addRange(fieldNum(SqlDictionary, flags)).value(queryValue(0));

            sysTableLookup.parmQuery(lookupQuery);

            sysTableLookup.performFormLookup();
        }

How to lookup fields of an existing table (Standard/Customized) in D365? - solution

        Issue: How to lookup fields of an existing table (Standard/Customized) in D365?

        Solution: Below code should be implemented to show lookup of existing table(s).

        public void lookup()
        {
            Query                                lookupQuery;
            QueryBuildDataSource    qbds;
            SysTableLookup               sysTableLookup = SysTableLookup::newParameters(tablenum(SqlDictionary), this);

            // Display the Name field in the lookup form.
            sysTableLookup.addLookupfield(fieldnum(SqlDictionary, Name));

            // Create a custom Query
            lookupQuery = new Query();
            qbds = lookupQuery.addDataSource(tablenum(SqlDictionary));
            qbds.addRange(fieldNum(SqlDictionary, fieldId)).value((SysQuery::valueNot(0)));
            qbds.addSortField(fieldNum(SqlDictionary, Name), SortOrder::Ascending);
            qbds.addRange(fieldNum(SqlDictionary, shadow)).value(queryValue(0));
            qbds.addRange(fieldNum(SqlDictionary, flags)).value(queryValue(0));
            qbds.addRange(fieldNum(SqlDictionary, TabId)).value(queryValue(tableNum("YourTableName")));
         
           // Multiple tables can be added as range, if required
           // qbds.addRange(fieldNum(SqlDictionary, TabId)).value(queryValue(tableNum(InventTable)));

            sysTableLookup.parmQuery(lookupQuery);

            sysTableLookup.performFormLookup();
        }