Customer aging report for multiple legal entities
In one of our client, there were more than 5 legal entities which share the same customers as the customer were merged from Global address book.
System doesn't provide the aging for multiple legal entities, so it was very difficult for the user to export the aging report from each company and then merge them because there were thousands of customers.
Hence it was decided to create a separate aging report.
First I created a query in AOT.
Thats it! Just deploy the report, create a new menu item and assign controller class to it and add it to menu.
System doesn't provide the aging for multiple legal entities, so it was very difficult for the user to export the aging report from each company and then merge them because there were thousands of customers.
Hence it was decided to create a separate aging report.
First I created a query in AOT.
Here is the contract class to get As on date.
[DataContractAttribute]
class DSS_CustomerAgingComparisonContract
{
Amount Amount;
FromDate asOnDate;
[DataMemberAttribute("As On Date") ,SysOperationLabelAttribute(literalStr('As of date'))]
public FromDate parmFromDate(FromDate _asOnDate = asOnDate)
{
asOnDate = _asOnDate;
return asOnDate;
}
}
I created a data provider class with the name 'DSS_CustomerAgingComparisonDP ' and added query and contract attribute and declared some global variables/buffers.
[
SRSReportQueryAttribute(queryStr(DSS_CustomerAgingComparisonQuery)),
SRSReportParameterAttribute(classStr(DSS_CustomerAgingComparisonContract))
]
class DSS_CustomerAgingComparisonDP extends SRSReportDataProviderBase
{
DSS_CustomerAgingComparisonTmp tmpCreditAging,
tmpCreditAgingLocal,
tmpCreditAgingFinilizedData;
DueDate asOnDate;
CustTrans custTrans;
CustTable custTable;
CustTransOpen custTransOpen;
public Name currentCompany;
}
to get the table for the report to show the data.
[SRSReportDataSetAttribute(tableStr(DSS_CustomerAgingComparisonTmp))]
Public DSS_CustomerAgingComparisonTmp getTmpCreditAging()
{
select * from tmpCreditAging;
return tmpCreditAging;
}
In process report I used insert_recordset and update_recordset approach to generate the data fast.
For data the I used fixed aging periods.
[SysEntryPointAttribute(false)]
public void ProcessReport()
{
Map fieldMapping;
QueryBuildFieldList fldList_custTable;
Amount totalBalance;
real amount = 0;
QueryBuildDataSource qbds_custTable;
DSS_CustomerAgingComparisonContract creditAgingContract;
Query query;
QueryRun queryRun;
CompanyInfo companyInfo;
currentCompany = curExt();
creditAgingContract = this.parmDataContract();
asOnDate = creditAgingContract.parmFromDate();
query = this.parmQuery();
query.clearAllFields();
qbds_custTable = query.dataSourceTable(tableNum(CustTable));
fldList_custTable = qbds_custTable.fields();
fldList_custTable.addField(fieldNum(CustTable, AccountNum));
fldList_custTable.addField(fieldNum(CustTable, DataAreaId));
fldList_custTable.addField(fieldNum(CustTable, Party));
fldList_custTable.addField(fieldNum(CustTable, CustGroup));
fldList_custTable.addField(fieldNum(CustTable, Currency));
fldList_custTable.dynamic(QueryFieldListDynamic::No);
fieldMapping = new Map(Types::String, Types::Container);
fieldMapping.insert(fieldStr(DSS_CustomerAgingComparisonTmp, AccountId), [qbds_custTable.uniqueId(), fieldStr(CustTable, AccountNum)]);
fieldMapping.insert(fieldStr(DSS_CustomerAgingComparisonTmp, DataArea), [qbds_custTable.uniqueId(), fieldStr(CustTable, DataAreaId)]);
fieldMapping.insert(fieldStr(DSS_CustomerAgingComparisonTmp, Party), [qbds_custTable.uniqueId(), fieldStr(CustTable, Party)]);
fieldMapping.insert(fieldStr(DSS_CustomerAgingComparisonTmp, CustGroup), [qbds_custTable.uniqueId(), fieldStr(CustTable, CustGroup)]);
fieldMapping.insert(fieldStr(DSS_CustomerAgingComparisonTmp, Currency), [qbds_custTable.uniqueId(), fieldStr(CustTable, Currency)]);
query::insert_recordset(tmpCreditAging, fieldMapping, query);
while select DataArea from companyInfo
{
changecompany (companyInfo.DataArea)
{
this.prepareData();
this.updateData();
}
}
}
Here I'm preparing the data for the report.
public void prepareData()
{
this.clearBuffers();
insert_recordset tmpCreditAgingLocal (Party, Day30)
select custTrans
join Party from custTable
group by custTable.Party
where custTable.AccountNum == custTrans.AccountNum
&& custTrans.TransDate <= asOnDate && custTrans.TransDate >= asOnDate - 30
join sum(AmountCur) from custTransOpen
where custTransOpen.AccountNum == custTrans.AccountNum
&& custTransOpen.RefRecId == custTrans.RecId;
//this.clearBuffers();
insert_recordset tmpCreditAgingLocal (Party, Day60)
select custTrans
join Party from custTable
group by custTable.Party
where custTable.AccountNum == custTrans.AccountNum
&& custTrans.TransDate <= asOnDate - 31 && custTrans.TransDate >= asOnDate - 60
join sum(AmountCur) from custTransOpen
where custTransOpen.AccountNum == custTrans.AccountNum
&& custTransOpen.RefRecId == custTrans.RecId;
//this.clearBuffers();
insert_recordset tmpCreditAgingLocal (Party, Day90)
select custTrans
join Party from custTable
group by custTable.Party
where custTable.AccountNum == custTrans.AccountNum
&& custTrans.TransDate <= asOnDate - 61 && custTrans.TransDate >= asOnDate - 90
join sum(AmountCur) from custTransOpen
where custTransOpen.AccountNum == custTrans.AccountNum
&& custTransOpen.RefRecId == custTrans.RecId;
//this.clearBuffers();
insert_recordset tmpCreditAgingLocal (Party, Day120)
select custTrans
join Party from custTable
group by custTable.Party
where custTable.AccountNum == custTrans.AccountNum
&& custTrans.TransDate <= asOnDate - 91 && custTrans.TransDate >= asOnDate - 120
join sum(AmountCur) from custTransOpen
where custTransOpen.AccountNum == custTrans.AccountNum
&& custTransOpen.RefRecId == custTrans.RecId;
//this.clearBuffers();
insert_recordset tmpCreditAgingLocal (Party, Day150)
select custTrans
join Party from custTable
group by custTable.Party
where custTable.AccountNum == custTrans.AccountNum
&& custTrans.TransDate <= asOnDate - 121 && custTrans.TransDate >= asOnDate - 150
join sum(AmountCur) from custTransOpen
where custTransOpen.AccountNum == custTrans.AccountNum
&& custTransOpen.RefRecId == custTrans.RecId;
//this.clearBuffers();
insert_recordset tmpCreditAgingLocal (Party, Above150)
select custTrans
join Party from custTable
group by custTable.Party
where custTable.AccountNum == custTrans.AccountNum
&& custTrans.TransDate <= asOnDate - 151 && custTrans.TransDate >= dateNull()
join sum(AmountCur) from custTransOpen
where custTransOpen.AccountNum == custTrans.AccountNum
&& custTransOpen.RefRecId == custTrans.RecId;
}
Updating some data after inserting it in report's temporary table.
public void updateData()
{
Ledger ledger = null;
DirPartyTable dirPartyTable = null;
CurrencyExchangeRate exchRate;
select ledger where ledger.Name == curExt();
exchRate = this.getExchangeRate(asOnDate, ledger.AccountingCurrency);
tmpCreditAgingFinilizedData = null;
insert_recordset tmpCreditAgingFinilizedData (Day30, Day60, Day90, Day120, Day150, Above150, Party)
select sum(Day30), sum(Day60), sum(Day90), sum(Day120), sum(Day150), sum(Above150), Party from tmpCreditAgingLocal
group by Party;
update_recordset tmpCreditAging
setting Day30 = tmpCreditAgingFinilizedData.Day30,
Day60 = tmpCreditAgingFinilizedData.Day60,
Day90 = tmpCreditAgingFinilizedData.Day90,
Day120 = tmpCreditAgingFinilizedData.Day120,
Day150 = tmpCreditAgingFinilizedData.Day150,
Above150 = tmpCreditAgingFinilizedData.Above150,
PartyName = dirPartyTable.Name,
Period1Start = asOnDate,
Period1End = asOnDate - 30,
Period2Start = asOnDate - 31,
Period2End = asOnDate - 60,
Period3Start = asOnDate - 61,
Period3End = asOnDate - 90,
Period4Start = asOnDate - 91,
Period4End = asOnDate - 120,
Period5Start = asOnDate - 121,
Period5End = asOnDate - 150,
Period6Start = asOnDate - 151,
Period6End = dateNull(),
ExchangeRate = exchRate,
Balance = tmpCreditAgingFinilizedData.Day30 +
tmpCreditAgingFinilizedData.Day60 +
tmpCreditAgingFinilizedData.Day90 +
tmpCreditAgingFinilizedData.Day120 +
tmpCreditAgingFinilizedData.Day150 +
tmpCreditAgingFinilizedData.Above150
join tmpCreditAgingFinilizedData
where tmpCreditAgingFinilizedData.Party == tmpCreditAging.Party
join dirPartyTable
where dirPartyTable.RecId == tmpCreditAgingFinilizedData.Party;
// deleting records with zero balances
//delete_from tmpCreditAging
// where tmpCreditAging.Balance == 0;
}
to get the exchange rate, as It was required to show the amount in USD as per the date provided.
public CurrencyExchangeRate getExchangeRate(TransDate _date, CurrencyCode _fromCurrency)
{
Ledger ledger = null;
ExchangeRate exchangeRate = null;
ExchangeRateType exchangeRateType = null;
CurrencyExchangeRate currencyExchangeRate = 0;
ExchangeRateCurrencyPair exchangeRateCurrencyPair = null;
select ExchangeRate from exchangeRate
join exchangeRateCurrencyPair
where exchangeRateCurrencyPair.RecId == exchangeRate.ExchangeRateCurrencyPair
&& exchangeRateCurrencyPair.FromCurrencyCode == 'USD'
&& exchangeRateCurrencyPair.ToCurrencyCode == _fromCurrency
&& exchangeRate.ValidFrom <= _date && exchangeRate.ValidTo >= _date
join exchangeRateType
where exchangeRateType.RECID == exchangeRateCurrencyPair.EXCHANGERATETYPE
join ledger
where ledger.DEFAULTEXCHANGERATETYPE == exchangeRateType.RECID
&& ledger.Name == currentCompany;
if(exchangeRate.ExchangeRate)
{
currencyExchangeRate = exchangeRate.ExchangeRate/100;
}
else
{
currencyExchangeRate = 1;
}
return currencyExchangeRate;
}
Table buffers should set to null before using in cross company query otherwise data won't be inserted or wrong data will be inserted in the temp table.
public void clearBuffers()
{
custTrans = null;
custTable = null;
custTransOpen = null;
//tmpCreditAgingLocal = null;
}
Thats it! Just deploy the report, create a new menu item and assign controller class to it and add it to menu.
To know more on how ERP can help business book a free consultation session at Dynamics Stream Dubai at www.dynamicsstream.com
Follow us on LinkedIn for latest updates on Microsoft ecosystem - https://www.linkedin.com/company/dynamicsstream.com
Comments
Post a Comment