Sunday, July 24, 2022

Calculate MarkupTrans Amount in D365FO using X++

 static void calculateMarkupTrans(Args _args)
{
    SalesTable              salesTable = SalesTable::find('000854');
    SalesLine               salesLine;
    AmountCur               markupAmount;
    MarkupTrans             markupTrans;
    CurrencyExchangeHelper  curCurrencyExchangeHelper;
     
    while select salesLine
        where salesLine.SalesId == salesTable.SalesId
    {
        while select markupTrans
            where markupTrans.TransTableId  == salesLine.TableId
                && markupTrans.TransRecId    == salesLine.RecId
        {
            markupAmount = Markup::calcTrans(markupTrans, salesLine.SalesQty, salesLine.LineAmount);
            if (markupTrans.CurrencyCode != salesTable.CurrencyCode)
            {
                // To automatically conver amount Markup::calcMarkupAmount can be used
                curCurrencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate(Ledger::primaryLedger(CompanyInfo::findDataArea(markupTrans.company()).RecId), systemDateGet());
                markupAmount = curCurrencyExchangeHelper.calculateAccountingToTransaction(salesTable.CurrencyCode, markupAmount, true);
            }
        }
    }
}

Report name in report contract cannot be null or empty.

 I ran into this issue while running the invoice journal report.



After spending sometime, I'm able to find the solution. To fix this issue just run  the following code in the runnable class:

class RunnableClass
{
    /// <summary>
    /// Run the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {
        PrintMgmtReportFormat                     printMgmtReportFormat;
        
        ttsbegin;
        select forupdate printMgmtReportFormat
            where printMgmtReportFormat.Name == 'ReportName.Report';
        printMgmtReportFormat.System = NoYes::Yes;
        printMgmtReportFormat.doUpdate();
        ttscommit;
    }
}

Create Offset Ledger Dimension using String Value in D365FO

Create offset ledger dimension using string value in D365FO X++:

Str offsetAccountValue = XXXX-XXXXXX-XXXX.XXXX-XXXX-XXXX-XXXXXX-XXXXXX


public RefRecId createOffsetLedgerDimension(str _offsetAccountVal)
    {
        LedgerAccountContract                      ledgerAccountContract, ledgerAccountContractLoc;
        List                                                      valueContracts, valueContractsLoc;
        DimensionHierarchy                           dimHierarchy;
        int                                                        dimCounterLoc;
        DimensionAttribute                            dimAttributeLoc;
        str                                                        dimAttValueLoc;
        DimensionAttributeValue                   dimAttributeVal, dimAttributeValLoc;
        DimensionAttributeValueContract     dimAttributeValueContract, dimAttributeValueContractLoc;
        MainAccountNum                              mainAccountId, mainAccountIdLoc;
        DimensionStorage                              dimStorage, dimStorageLoc;
        
        valueContracts                      = new List(Types::Class);
        valueContractsLoc                = new List(Types::Class);
        ledgerAccountContract         = new LedgerAccountContract();
        ledgerAccountContractLoc   = new LedgerAccountContract();

        select firstonly * from dimHierarchy
                                    where dimHierarchy.StructureType == DimensionHierarchyType::DataEntityLedgerDimensionFormat
                                    && dimHierarchy.IsDraft          == NoYes::No;
        
        if(offsetAccountVal)
        {
            for(int counterLoc = 0; counterLoc <= strLen(offsetAccountVal); counterLoc++)
            {
                dimCounterLoc++;
                dimAttributeLoc = DimensionAttribute::find(DimensionHierarchyLevel::findByDimensionHierarchyAndLevel(dimHierarchy.RecId, dimCounterLoc).DimensionAttribute);
                                    
                if(strFind(offsetAccountVal, "-", counterLoc, strLen(offsetAccountVal)) > 0)
                {
                    dimAttValueLoc = subStr(offsetAccountVal, counterLoc, (strFind(offsetAccountVal, "-", counterLoc, strLen(offsetAccountVal)) - counterLoc));
                                        
                    if(strFind(dimAttValueLoc, "-",0, strLen(dimAttValueLoc)) > 0)
                    {
                        dimAttValueLoc = subStr(dimAttValueLoc, 0, (strFind(dimAttValueLoc, "-",0, strLen(dimAttValueLoc)) - 1));
                    }
                    counterLoc = strFind(offsetAccountVal, "-", counterLoc, strLen(offsetAccountVal));
                }
                else
                {
                    dimAttValueLoc = subStr(offsetAccountVal, counterLoc, strLen(offsetAccountVal));
                    counterLoc     = strLen(offsetAccountVal);
                }
                dimAttributeValLoc = DimensionAttributeValue::findByDimensionAttributeAndValue(dimAttributeLoc, dimAttValueLoc);
                if(dimAttributeLoc.Name == "MainAccount")
                {
                    if(!MainAccount::findByMainAccountId(dimAttValueLoc).RecId)
                    {
                        throw Error(strFmt("Invalid value of %1",dimAttributeLoc.Name));
                    }
                    mainAccountIdLoc = dimAttValueLoc;
                    continue;
                }
                if(dimAttributeValLoc.RecId)
                {
                    dimAttributeValueContractLoc = new DimensionAttributeValueContract();
                    dimAttributeValueContractLoc.parmName(dimAttributeLoc.Name);
                    dimAttributeValueContractLoc.parmValue(dimAttributeValLoc.CachedDisplayValue);
                    valueContractsLoc.addEnd(dimAttributeValueContractLoc);
                }
                else
                {
                    throw Error(strFmt("Invalid value of %1",dimAttributeLoc.Name));
                }
            }
            ledgerAccountContractLoc.parmMainAccount(mainAccountIdLoc);
            ledgerAccountContractLoc.parmValues(valueContractsLoc);
            dimStorageLoc = DimensionServiceProvider::buildDimensionStorageForLedgerAccount(ledgerAccountContractLoc);
            return DimensionAttributeValueCombination::find(dimStorageLoc.save()).RecId;
        }
        return 0;
        
    }

You can get format combination from the below line. Currently it's for ledger dimension, you can also get the same for other dimension by changing the type of enum (DimensionHierarchyType).

select firstonly * from dimHierarchy
                                    where dimHierarchy.StructureType == DimensionHierarchyType::DataEntityLedgerDimensionFormat
                                    && dimHierarchy.IsDraft          == NoYes::No;