We often go through the requirements where we need to compute the Trail balances to get the vouher transactions amounts. Here , different ways to compute the trail balance in D365 fo X++
1. This is an easy way to compute trail balances without dimension sets. If required we can add the further ranges below in the dynamic query.
protected Amount getProjBalanceForRevenue(ProjId _projId, MainAccountNum _mainaccount) { LedgerAllocationRuleSource ruleSource; RecId keyValue; Map dimensionRange = new Map(Types::Int64, Types::String); Set dimensionRangeIncludeEmpty = new Set(Types::Int64); str emptyQueryStr = SysQuery::valueEmptyString(); GeneralJournalAccountEntry result; Amount DebitAmount,CreditAmount, TotalAllocatedAmount; Query query = new Query(); QueryBuildDataSource qbds = query.addDataSource(tableNum(GeneralJournalAccountEntry)); // Add fields from GeneralJournalAccountEntry to query qbds.addSelectionField(fieldNum(GeneralJournalAccountEntry, TransactionCurrencyAmount), SelectionField::Sum); qbds.addSelectionField(fieldNum(GeneralJournalAccountEntry, AccountingCurrencyAmount), SelectionField::Sum); qbds.addSelectionField(fieldNum(GeneralJournalAccountEntry, ReportingCurrencyAmount), SelectionField::Sum); // Configure the query to do a Group By currency & account/dimension combination qbds.orderMode(OrderMode::GroupBy); qbds.addSortField(fieldNum(GeneralJournalAccountEntry, TransactionCurrencyCode)); qbds.addSortField(fieldNum(GeneralJournalAccountEntry, LedgerDimension)); // qbds.addRange(fieldnum(GeneralJournalAccountEntry,IsCredit )).value(SysQuery::value(Noyes::No)); QueryBuildDataSource qbdsHeader = qbds.addDataSource(tableNum(GeneralJournalEntry)); qbdsHeader.relations(true); qbdsHeader.joinMode(JoinMode::InnerJoin); qbdsHeader.fetchMode(QueryFetchMode::One2One); // qbdsHeader.addLink(fieldNum(GeneralJournalAccountEntry, GeneralJournalEntry), fieldNum(GeneralJournalEntry, RecId)); qbdsHeader.addRange(fieldNum(GeneralJournalEntry, PostingLayer)).value(queryValue(CurrentOperationsTax::Current)); qbdsHeader.addRange(fieldNum(GeneralJournalEntry, Ledger)).value(SysQuery::value(Ledger::current())); QueryBuildDataSource qbdsFiscalPeriod = qbdsHeader.addDataSource(tableNum(FiscalCalendarPeriod)); /// qbdsFiscalPeriod.addLink(fieldNum(GeneralJournalEntry,FiscalCalendarPeriod), fieldNum(fiscalCalendarPeriod, RecId)); qbdsFiscalPeriod.relations(true); qbdsFiscalPeriod.joinMode(JoinMode::ExistsJoin); qbdsFiscalPeriod.addRange( fieldNum(fiscalCalendarPeriod, type)).value(SysQuery::value(FiscalPeriodType::Operating)); QueryBuildRange qbr = qbdsHeader.addRange(fieldNum(GeneralJournalEntry, AccountingDate)); qbr.value(SysQuery::range(fromDate, toDate)); // Build the account and dimension range string from LedgerAllocationRuleSource for this rule this.createRuleSourceCriteria( dimensionRange, _Mainaccount, _projId); QueryBuildDataSource qbdsDavc = qbds.addDataSource(tableNum(DimensionAttributeValueCombination)); qbdsDavc.joinMode(JoinMode::ExistsJoin); qbdsDavc.addLink(fieldNum(GeneralJournalAccountEntry, LedgerDimension), fieldNum(DimensionAttributeValueCombination, RecId)); qbdsDavc.fetchMode(QueryFetchMode::One2One); LedgerAllocationProcessRequest::createDimensionRanges(qbdsDavc, dimensionRange.getEnumerator(), dimensionRangeIncludeEmpty); QueryRun queryRunloc = new QueryRun(query); while (queryRunloc.next()) { result = queryRunloc.get(tableNum(GeneralJournalAccountEntry)) as GeneralJournalAccountEntry; if(result.IsCredit) { CreditAmount += result.AccountingCurrencyAmount; } else { DebitAmount += result.AccountingCurrencyAmount; } } TotalAllocatedAmount = DebitAmount + CreditAmount; return TotalAllocatedAmount; } public void createRuleSourceCriteria(Map _dimensionRange, MainAccountNum _mainaccount, ProjId _ProjId) { DimensionAttributeRecId mainAccountDimAttrId = DimensionAttribute::getWellKnownDimensionAttribute(DimensionAttributeType::MainAccount); _dimensionRange.insert(mainAccountDimAttrId, _mainaccount); _dimensionRange.insert(DimensionAttribute::findByName("Project").RecId, _ProjId); }
2. Computing trial balances and getting required closing balance based on operating type with dimension set.
private void calcClosingBalanceAC() { LedgerTrialBalanceListPageBalanceParms balanceParameters; DimensionHierarchy dimHier; TransDate fromDate,toDate; List selected = new List(Types::Enum); selected.addEnd(CurrentOperationsTax::Current); dimHier = DimensionHierarchy::findByTypeAndName(DimensionHierarchyType::Focus, '@PRO_Synamedia:MaserviceId'); balanceParameters = LedgerTrialBalanceListPageBalanceParms::construct(); balanceParameters.parmDateCode(''); balanceParameters.parmDimensionSetHierarchy(dimHier); balanceParameters.parmStartDate(dateNull()); balanceParameters.parmEndDate(TrandateFilter.dateValue()); balanceParameters.parmPostingLayers(selected); balanceParameters.parmIncludeClosingAdjustments(false); select firstOnly RecId from ledgerTrialBalanceTmp; LedgerTrialBalanceTmp::calculateBalances_V2(ledgerTrialBalanceTmp, dimHier.Name, balanceParameters.getStartDate(), balanceParameters.getEndDate(), balanceParameters.getIncludeOpeningPeriods(), balanceParameters.getIncludeClosingAdjustments(), balanceParameters.getIncludeClosingTransactions(), balanceParameters.getPostingLayers(), true, true, Ledger::current(), balanceParameters.getDisplayMainAccountCategory()); }
private Real getClosingBalanceAc(BusinessUnit _BU) { real CLosingamount; select firstonly * from ledgerTrialBalanceTmp where ledgerTrialBalanceTmp.DimensionValues[1] == unbilledRevnueAccount && ledgerTrialBalanceTmp.DimensionValues[2] == _BU;
if (ledgerTrialBalanceTmp.RecId) { CLosingamount = this.getClosingBalance(); } return CLosingamount; }
private real getClosingBalance() { DimensionAttributeValueCombination dimensionAttributeCombo; GeneralJournalAccountEntry generalJournalAccountEntry; DAXGeneralJourAccountEntryOperatingView GeneralJourAccountEntryOperatingView;
Query query = new Query(); QueryBuildDataSource GJAccountEntryDs, GJEntryDs, FCDS, DAVC_Ds; QueryBuildRange Operatingrange; real closingBalance; GJAccountEntryDs = query.addDataSource(tableNum(DAXGeneralJourAccountEntryOperatingView)); GJAccountEntryDs.addRange(fieldnum(DAXGeneralJourAccountEntryOperatingView, AccountingDate)).value(queryRange(datenull(), TrandateFilter.dateValue()));
DAVC_Ds = GJAccountEntryDs.addDataSource(tableNum(DimensionAttributeValueCombination)); DAVC_Ds.addLink(fieldNum(PROGeneralJourAccountEntryOperatingView , LedgerDimension) , fieldNum(DimensionAttributeValueCombination , RecId)); select firstonly dimensionAttributeCombo where dimensionAttributeCombo.Recid == ledgerTrialBalanceTmp.LedgerDimension; // DimensionHierarchy dimHierLoc = DimensionHierarchy::findByTypeAndName(DimensionHierarchyType::Focus, SubBillParameters::find().PRO_MonthEndAutomationJourDimSet); DimensionHierarchy dimHierLoc = DimensionHierarchy::findByTypeAndName(DimensionHierarchyType::Focus, '@PRO_Synamedia:MaserviceId'); this.updateQueryForLedgerDimension(query, dimensionAttributeCombo, dimHierLoc); QueryRun qr = new QueryRun(query); while (qr.next()) { GeneralJourAccountEntryOperatingView = qr.get(tableNum(DAXGeneralJourAccountEntryOperatingView));
closingBalance += GeneralJourAccountEntryOperatingView.AccountingCurrencyAmount; } return closingBalance; }
3. As performance concerned create a view for GeneralJournalAccountEntry Table for applying theoperating type ranges.
private void updateQueryForLedgerDimension(Query _query, DimensionAttributeValueCombination _davcSearchCriteria, DimensionHierarchy _dimHier) { // If the account transaction details are related to the dimension set containing Main account only, the filter can // be applied directly to GeneralJournalAccountEntry for the account filtering. //boolean mainAccountTransactionDetails = this.updateQueryForMainAccountOnly(_query, _davcSearchCriteria, _dimHier); //if (mainAccountTransactionDetails == false) //{ QueryBuildDataSource davcDS = this.getDimensionAttributeValueCombinationDataSource(_query); DimensionAttributeLevelValueView dalvView; while select DimensionAttribute, DisplayValue from dalvView where dalvView.ValueCombinationRecId == _davcSearchCriteria.RecId { DimensionRefFieldName dimensionValueColumnName = DimensionAttribute::find(dalvView.DimensionAttribute).DimensionValueColumnName; QueryBuildRange qbr = davcDS.addRange(fieldName2Id(tableNum(DimensionAttributeValueCombination), dimensionValueColumnName)); qbr.value(queryValue(dalvView.DisplayValue)); } // For any dimension specified in the hierarchy but not having a value in the ledger account, add an empty string criteria if (_dimHier) { DimensionHierarchyLevel dimHierLevels; while select DimensionAttribute from dimHierLevels where dimHierLevels.DimensionHierarchy == _dimHier.RecId notexists join dalvView where dalvView.DimensionAttribute == dimHierLevels.DimensionAttribute && dalvView.ValueCombinationRecId == _davcSearchCriteria.RecId { DimensionRefFieldName dimensionValueColumnName = DimensionAttribute::find(dimHierLevels.DimensionAttribute).DimensionValueColumnName; QueryBuildRange qbr = davcDS.addRange(fieldName2Id(tableNum(DimensionAttributeValueCombination), dimensionValueColumnName)); qbr.value(SysQuery::valueEmptyString()); } } //} }
private QueryBuildDataSource getDimensionAttributeValueCombinationDataSource(Query _query)
{
QueryBuildDataSource davcDS = _query.dataSourceTable(tableNum(DimensionAttributeValueCombination));
davcDS.joinMode(JoinMode::InnerJoin);
return davcDS;
}