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;
}