added running balance for journal entries
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE `acc_gl_journal_entry`
|
||||
ADD COLUMN `is_running_balance_caculated` TINYINT NOT NULL DEFAULT '0' AFTER `lastmodified_date`,
|
||||
ADD COLUMN `office_running_balance` DECIMAL(19,6) NOT NULL DEFAULT '0.000000' AFTER `is_running_balance_caculated`;
|
||||
|
||||
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`, `task_priority`, `group_name`, `previous_run_start_time`, `next_run_time`, `job_key`, `initializing_errorlog`, `is_active`, `currently_running`, `updates_allowed`, `scheduler_group`, `is_misfired`) VALUES ('Update Accounting Running Balances', 'Update Accounting Running Balances', '0 1 0 1/1 * ? *', now(), 5, NULL, NULL, NULL, NULL, NULL, 1, 0, 1, 0, 0);
|
||||
+25
@@ -87,4 +87,29 @@ public class JournalEntryData {
|
||||
this.referenceNumber = referenceNumber;
|
||||
}
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
||||
public Long getGlAccountId() {
|
||||
return this.glAccountId;
|
||||
}
|
||||
|
||||
|
||||
public EnumOptionData getGlAccountType() {
|
||||
return this.glAccountType;
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
|
||||
public EnumOptionData getEntryType() {
|
||||
return this.entryType;
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package org.mifosplatform.accounting.journalentry.service;
|
||||
|
||||
|
||||
public interface JournalEntryRunningBalanceUpdateService {
|
||||
|
||||
void updateRunningBalance();
|
||||
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.accounting.journalentry.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.accounting.common.AccountingEnumerations;
|
||||
import org.mifosplatform.accounting.glaccount.domain.GLAccountType;
|
||||
import org.mifosplatform.accounting.journalentry.data.JournalEntryData;
|
||||
import org.mifosplatform.accounting.journalentry.domain.JournalEntryType;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
|
||||
import org.mifosplatform.infrastructure.jobs.service.JobName;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class JournalEntryRunningBalanceUpdateServiceImpl implements JournalEntryRunningBalanceUpdateService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private final GLJournalEntryMapper entryMapper = new GLJournalEntryMapper();
|
||||
private final String runningBalanceSql = "select je.office_running_balance as runningBalance,je.account_id as accountId from acc_gl_journal_entry je "
|
||||
+ "inner join (select max(id) as id from acc_gl_journal_entry where office_id=? and entry_date < ? group by account_id,entry_date) je2 "
|
||||
+ "inner join (select max(entry_date) as date from acc_gl_journal_entry where office_id=? and entry_date < ? group by account_id) je3 "
|
||||
+ "where je2.id = je.id and je.entry_date = je3.date group by je.id order by je.entry_date DESC";
|
||||
|
||||
@Autowired
|
||||
public JournalEntryRunningBalanceUpdateServiceImpl(final RoutingDataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CronTarget(jobName = JobName.ACCOUNTING_RUNNING_BALANCE_UPDATE)
|
||||
public void updateRunningBalance() {
|
||||
|
||||
String dateFinder = "select je.office_id as officeId,MIN(je.entry_date) as entityDate " + "from acc_gl_journal_entry je "
|
||||
+ "where je.is_running_balance_caculated=0 " + "group by je.office_id";
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(dateFinder);
|
||||
for (Map<String, Object> entries : list) {
|
||||
Long officeId = (Long) entries.get("officeId");
|
||||
Date entityDate = (Date) entries.get("entityDate");
|
||||
updateRunningBalance(officeId, entityDate);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private void updateRunningBalance(Long officeId, Date entityDate) {
|
||||
Map<Long, BigDecimal> runningBalanceMap = new HashMap<Long, BigDecimal>(5);
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(runningBalanceSql, officeId, entityDate, officeId, entityDate);
|
||||
for (Map<String, Object> entries : list) {
|
||||
Long accountId = (Long) entries.get("accountId");
|
||||
if (!runningBalanceMap.containsKey(accountId)) {
|
||||
runningBalanceMap.put(accountId, (BigDecimal) entries.get("runningBalance"));
|
||||
}
|
||||
}
|
||||
List<JournalEntryData> entryDatas = jdbcTemplate.query(entryMapper.schema(), entryMapper, new Object[] { officeId, entityDate });
|
||||
String[] updateSql = new String[entryDatas.size()];
|
||||
int i = 0;
|
||||
for (JournalEntryData entryData : entryDatas) {
|
||||
BigDecimal runningBalance = calculateRunningBalance(entryData, runningBalanceMap);
|
||||
String sql = "UPDATE acc_gl_journal_entry je SET je.is_running_balance_caculated=1, je.office_running_balance="
|
||||
+ runningBalance + " WHERE je.id=" + entryData.getId();
|
||||
updateSql[i++] = sql;
|
||||
}
|
||||
this.jdbcTemplate.batchUpdate(updateSql);
|
||||
}
|
||||
|
||||
private BigDecimal calculateRunningBalance(JournalEntryData entry, Map<Long, BigDecimal> runningBalanceMap) {
|
||||
BigDecimal runningBalance = BigDecimal.ZERO;
|
||||
if (runningBalanceMap.containsKey(entry.getGlAccountId())) {
|
||||
runningBalance = runningBalanceMap.get(entry.getGlAccountId());
|
||||
}
|
||||
GLAccountType accounttype = GLAccountType.fromInt(entry.getGlAccountType().getId().intValue());
|
||||
JournalEntryType entryType = JournalEntryType.fromInt(entry.getEntryType().getId().intValue());
|
||||
boolean isIncrease = false;
|
||||
switch (accounttype) {
|
||||
case ASSET:
|
||||
if (entryType.isDebitType()) {
|
||||
isIncrease = true;
|
||||
}
|
||||
break;
|
||||
case EQUITY:
|
||||
if (entryType.isCreditType()) {
|
||||
isIncrease = true;
|
||||
}
|
||||
break;
|
||||
case EXPENSE:
|
||||
if (entryType.isDebitType()) {
|
||||
isIncrease = true;
|
||||
}
|
||||
break;
|
||||
case INCOME:
|
||||
if (entryType.isCreditType()) {
|
||||
isIncrease = true;
|
||||
}
|
||||
break;
|
||||
case LIABILITY:
|
||||
if (entryType.isCreditType()) {
|
||||
isIncrease = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (isIncrease) {
|
||||
runningBalance = runningBalance.add(entry.getAmount());
|
||||
} else {
|
||||
runningBalance = runningBalance.subtract(entry.getAmount());
|
||||
}
|
||||
runningBalanceMap.put(entry.getGlAccountId(), runningBalance);
|
||||
return runningBalance;
|
||||
}
|
||||
|
||||
private static final class GLJournalEntryMapper implements RowMapper<JournalEntryData> {
|
||||
|
||||
public String schema() {
|
||||
return "select je.id as id,je.account_id as glAccountId," + "je.type_enum as entryType,je.amount as amount, "
|
||||
+ "glAccount.classification_enum as classification " + "from acc_gl_journal_entry je , acc_gl_account glAccount "
|
||||
+ "where je.account_id = glAccount.id " + "and je.office_id=? and je.entry_date >= ? order by je.entry_date,je.id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JournalEntryData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final Long glAccountId = rs.getLong("glAccountId");
|
||||
final int accountTypeId = JdbcSupport.getInteger(rs, "classification");
|
||||
final EnumOptionData accountType = AccountingEnumerations.gLAccountType(accountTypeId);
|
||||
final BigDecimal amount = rs.getBigDecimal("amount");
|
||||
final int entryTypeId = JdbcSupport.getInteger(rs, "entryType");
|
||||
final EnumOptionData entryType = AccountingEnumerations.journalEntryType(entryTypeId);
|
||||
|
||||
return new JournalEntryData(id, null, null, null, glAccountId, null, accountType, null, entryType, amount, null, null, null,
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ public enum JobName {
|
||||
UPDATE_LOAN_SUMMARY("Update loan Summary"), UPDATE_LOAN_ARREARS_AGEING("Update Loan Arrears Ageing"), UPDATE_LOAN_PAID_IN_ADVANCE(
|
||||
"Update Loan Paid In Advance"), APPLY_ANNUAL_FEE_FOR_SAVINGS("Apply Annual Fee For Savings"), APPLY_HOLIDAYS_TO_LOANS(
|
||||
"Apply Holidays To Loans"), POST_INTEREST_FOR_SAVINGS("Post Interest For Savings"), TRANSFER_FEE_CHARGE_FOR_LOANS(
|
||||
"Transfer Fee For Loans From Savings");
|
||||
"Transfer Fee For Loans From Savings"), ACCOUNTING_RUNNING_BALANCE_UPDATE("Update Accounting Running Balances");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user