fix(cashier): fix GL account search SQL bug, running balance, and add CASHIER role permissions
- Fix searchParam SQL syntax: parameterized LIKE with %value% instead of literal %?% - Fix organizationRunningBalance: correlated subquery for latest journal entry (ORDER BY id DESC LIMIT 1) - Migration 0317: grant READ_GLACCOUNT, READ_LOAN, READ_SHAREACCOUNT to CASHIER role Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
6d0c1fe7f6
commit
53b6a94bf8
+275
-272
@@ -1,272 +1,275 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.glaccount.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingEnumerations;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountDataForLookup;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
|
||||
import org.apache.fineract.accounting.glaccount.exception.GLAccountInvalidClassificationException;
|
||||
import org.apache.fineract.accounting.glaccount.exception.GLAccountNotFoundException;
|
||||
import org.apache.fineract.accounting.journalentry.data.JournalEntryAssociationParametersData;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformService {
|
||||
|
||||
private static final String NAME_DECORATED_BASE_ON_HIERARCHY = "concat(substring('........................................', 1, ((LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '.', '')) - 1) * 4)), name)";
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private static final String SQL_AND = " and ";
|
||||
|
||||
private static final class GLAccountMapper implements RowMapper<GLAccountData> {
|
||||
|
||||
private final JournalEntryAssociationParametersData associationParametersData;
|
||||
|
||||
GLAccountMapper(final JournalEntryAssociationParametersData associationParametersData) {
|
||||
if (associationParametersData == null) {
|
||||
this.associationParametersData = new JournalEntryAssociationParametersData();
|
||||
} else {
|
||||
this.associationParametersData = associationParametersData;
|
||||
}
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(
|
||||
" gl.id as id, name as name, parent_id as parentId, gl_code as glCode, disabled as disabled, manual_journal_entries_allowed as manualEntriesAllowed, ")
|
||||
.append("classification_enum as classification, account_usage as accountUsage, gl.description as description, ")
|
||||
.append(NAME_DECORATED_BASE_ON_HIERARCHY).append(" as nameDecorated, ")
|
||||
.append("cv.id as codeId, cv.code_value as codeValue ");
|
||||
if (this.associationParametersData.isRunningBalanceRequired()) {
|
||||
sb.append(",gl_j.organization_running_balance as organizationRunningBalance ");
|
||||
}
|
||||
sb.append("from acc_gl_account gl left join m_code_value cv on tag_id=cv.id ");
|
||||
if (this.associationParametersData.isRunningBalanceRequired()) {
|
||||
sb.append("left outer Join acc_gl_journal_entry gl_j on gl_j.account_id = gl.id");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String name = rs.getString("name");
|
||||
final Long parentId = JdbcSupport.getLong(rs, "parentId");
|
||||
final String glCode = rs.getString("glCode");
|
||||
final boolean disabled = rs.getBoolean("disabled");
|
||||
final boolean manualEntriesAllowed = rs.getBoolean("manualEntriesAllowed");
|
||||
final int accountTypeId = JdbcSupport.getInteger(rs, "classification");
|
||||
final EnumOptionData accountType = AccountingEnumerations.gLAccountType(accountTypeId);
|
||||
final int usageId = JdbcSupport.getInteger(rs, "accountUsage");
|
||||
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(usageId);
|
||||
final String description = rs.getString("description");
|
||||
final String nameDecorated = rs.getString("nameDecorated");
|
||||
final Long codeId = rs.wasNull() ? null : rs.getLong("codeId");
|
||||
final String codeValue = rs.getString("codeValue");
|
||||
final CodeValueData tagId = CodeValueData.instance(codeId, codeValue);
|
||||
Long organizationRunningBalance = null;
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
organizationRunningBalance = rs.getLong("organizationRunningBalance");
|
||||
}
|
||||
return new GLAccountData().setId(id).setName(name).setParentId(parentId).setGlCode(glCode).setDisabled(disabled)
|
||||
.setManualEntriesAllowed(manualEntriesAllowed).setType(accountType).setUsage(usage).setDescription(description)
|
||||
.setNameDecorated(nameDecorated).setTagId(tagId).setOrganizationRunningBalance(organizationRunningBalance);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllGLAccounts(final Integer accountClassification, final String searchParam, final Integer usage,
|
||||
final Boolean manualTransactionsAllowed, final Boolean disabled,
|
||||
JournalEntryAssociationParametersData associationParametersData) {
|
||||
if (accountClassification != null && !checkValidGLAccountType(accountClassification)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
|
||||
if (usage != null && !checkValidGLAccountUsage(usage)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
|
||||
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
|
||||
String sql = "select " + rm.schema();
|
||||
// append SQL statement for fetching account totals
|
||||
if (associationParametersData != null && associationParametersData.isRunningBalanceRequired()) {
|
||||
sql = sql + " and gl_j.id in (select t1.id from (select t2.account_id, max(t2.id) as id from "
|
||||
+ "(select id, max(entry_date) as entry_date, account_id from acc_gl_journal_entry where is_running_balance_calculated = true "
|
||||
+ "group by account_id desc, id) t3 inner join acc_gl_journal_entry t2 on t2.account_id = t3.account_id and t2.entry_date = t3.entry_date "
|
||||
+ "group by t2.account_id desc) t1)";
|
||||
}
|
||||
final Object[] parameterArray = new Object[3];
|
||||
int arrayPos = 0;
|
||||
boolean filtersPresent = false;
|
||||
if ((accountClassification != null) || StringUtils.isNotBlank(searchParam) || (usage != null) || (manualTransactionsAllowed != null)
|
||||
|| (disabled != null)) {
|
||||
filtersPresent = true;
|
||||
sql += " where";
|
||||
}
|
||||
|
||||
if (filtersPresent) {
|
||||
boolean firstWhereConditionAdded = false;
|
||||
if (accountClassification != null) {
|
||||
sql += " classification_enum = ?";
|
||||
parameterArray[arrayPos] = accountClassification.shortValue();
|
||||
arrayPos = arrayPos + 1;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (StringUtils.isNotBlank(searchParam)) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
sql += " ( name like %?% or gl_code like %?% )";
|
||||
parameterArray[arrayPos] = searchParam;
|
||||
arrayPos = arrayPos + 1;
|
||||
parameterArray[arrayPos] = searchParam;
|
||||
arrayPos = arrayPos + 1;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (usage != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
if (GLAccountUsage.HEADER.getValue().equals(usage)) {
|
||||
sql += " account_usage = 2 ";
|
||||
} else if (GLAccountUsage.DETAIL.getValue().equals(usage)) {
|
||||
sql += " account_usage = 1 ";
|
||||
}
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (manualTransactionsAllowed != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
|
||||
sql += " manual_journal_entries_allowed = " + manualTransactionsAllowed;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (disabled != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
|
||||
sql += " disabled = " + disabled;
|
||||
}
|
||||
}
|
||||
|
||||
sql += " ORDER BY gl_code ASC";
|
||||
|
||||
final Object[] finalObjectArray = Arrays.copyOf(parameterArray, arrayPos);
|
||||
return this.jdbcTemplate.query(sql, rm, (Object[]) finalObjectArray);// NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData retrieveGLAccountById(final long glAccountId, JournalEntryAssociationParametersData associationParametersData) {
|
||||
try {
|
||||
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
|
||||
final StringBuilder sql = new StringBuilder();
|
||||
sql.append("select ").append(rm.schema());
|
||||
sql.append(" where gl.id = ?");
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
sql.append(" and gl_j.is_running_balance_calculated = true ")
|
||||
.append(" ORDER BY gl_j.entry_date DESC,gl_j.id DESC LIMIT 1");
|
||||
}
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql.toString(), rm, new Object[] { glAccountId });
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new GLAccountNotFoundException(glAccountId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllEnabledDetailGLAccounts(final GLAccountType accountType) {
|
||||
return retrieveAllGLAccounts(accountType.getValue(), null, GLAccountUsage.DETAIL.getValue(), null, false,
|
||||
new JournalEntryAssociationParametersData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllEnabledDetailGLAccounts() {
|
||||
return retrieveAllGLAccounts(null, null, GLAccountUsage.DETAIL.getValue(), null, false,
|
||||
new JournalEntryAssociationParametersData());
|
||||
}
|
||||
|
||||
private static boolean checkValidGLAccountType(final int type) {
|
||||
for (final GLAccountType accountType : GLAccountType.values()) {
|
||||
if (accountType.getValue().equals(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean checkValidGLAccountUsage(final int type) {
|
||||
for (final GLAccountUsage accountUsage : GLAccountUsage.values()) {
|
||||
if (accountUsage.getValue().equals(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData retrieveNewGLAccountDetails(final Integer type) {
|
||||
return GLAccountData.sensibleDefaultsForNewGLAccountCreation(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllEnabledHeaderGLAccounts(final GLAccountType accountType) {
|
||||
return retrieveAllGLAccounts(accountType.getValue(), null, GLAccountUsage.HEADER.getValue(), null, false,
|
||||
new JournalEntryAssociationParametersData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountDataForLookup> retrieveAccountsByTagId(final Long ruleId, final Integer transactionType) {
|
||||
final GLAccountDataLookUpMapper mapper = new GLAccountDataLookUpMapper();
|
||||
final String sql = "Select " + GLAccountDataLookUpMapper.LOOKUP_SCHEMA + " where rule.id=? and tags.acc_type_enum=?";
|
||||
return this.jdbcTemplate.query(sql, mapper, (Object[]) new Object[] { ruleId, transactionType });// NOSONAR
|
||||
}
|
||||
|
||||
private static final class GLAccountDataLookUpMapper implements RowMapper<GLAccountDataForLookup> {
|
||||
|
||||
private static final String LOOKUP_SCHEMA = " gl.id as id, gl.name as name, gl.gl_code as glCode from acc_accounting_rule rule join acc_rule_tags tags on tags.acc_rule_id = rule.id join acc_gl_account gl on gl.tag_id=tags.tag_id";
|
||||
|
||||
@Override
|
||||
public GLAccountDataForLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final String name = rs.getString("name");
|
||||
final String glCode = rs.getString("glCode");
|
||||
|
||||
return new GLAccountDataForLookup().setId(id).setName(name).setGlCode(glCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.accounting.glaccount.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingEnumerations;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountDataForLookup;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountUsage;
|
||||
import org.apache.fineract.accounting.glaccount.exception.GLAccountInvalidClassificationException;
|
||||
import org.apache.fineract.accounting.glaccount.exception.GLAccountNotFoundException;
|
||||
import org.apache.fineract.accounting.journalentry.data.JournalEntryAssociationParametersData;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GLAccountReadPlatformServiceImpl implements GLAccountReadPlatformService {
|
||||
|
||||
private static final String NAME_DECORATED_BASE_ON_HIERARCHY = "concat(substring('........................................', 1, ((LENGTH(hierarchy) - LENGTH(REPLACE(hierarchy, '.', '')) - 1) * 4)), name)";
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private static final String SQL_AND = " and ";
|
||||
|
||||
private static final class GLAccountMapper implements RowMapper<GLAccountData> {
|
||||
|
||||
private final JournalEntryAssociationParametersData associationParametersData;
|
||||
|
||||
GLAccountMapper(final JournalEntryAssociationParametersData associationParametersData) {
|
||||
if (associationParametersData == null) {
|
||||
this.associationParametersData = new JournalEntryAssociationParametersData();
|
||||
} else {
|
||||
this.associationParametersData = associationParametersData;
|
||||
}
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(
|
||||
" gl.id as id, name as name, parent_id as parentId, gl_code as glCode, disabled as disabled, manual_journal_entries_allowed as manualEntriesAllowed, ")
|
||||
.append("classification_enum as classification, account_usage as accountUsage, gl.description as description, ")
|
||||
.append(NAME_DECORATED_BASE_ON_HIERARCHY).append(" as nameDecorated, ")
|
||||
.append("cv.id as codeId, cv.code_value as codeValue ");
|
||||
if (this.associationParametersData.isRunningBalanceRequired()) {
|
||||
sb.append(",gl_j.organization_running_balance as organizationRunningBalance ");
|
||||
}
|
||||
sb.append("from acc_gl_account gl left join m_code_value cv on tag_id=cv.id ");
|
||||
if (this.associationParametersData.isRunningBalanceRequired()) {
|
||||
sb.append("left outer join acc_gl_journal_entry gl_j on gl_j.id = (")
|
||||
.append("select id from acc_gl_journal_entry ")
|
||||
.append("where account_id = gl.id ")
|
||||
.append("order by id desc limit 1) ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String name = rs.getString("name");
|
||||
final Long parentId = JdbcSupport.getLong(rs, "parentId");
|
||||
final String glCode = rs.getString("glCode");
|
||||
final boolean disabled = rs.getBoolean("disabled");
|
||||
final boolean manualEntriesAllowed = rs.getBoolean("manualEntriesAllowed");
|
||||
final int accountTypeId = JdbcSupport.getInteger(rs, "classification");
|
||||
final EnumOptionData accountType = AccountingEnumerations.gLAccountType(accountTypeId);
|
||||
final int usageId = JdbcSupport.getInteger(rs, "accountUsage");
|
||||
final EnumOptionData usage = AccountingEnumerations.gLAccountUsage(usageId);
|
||||
final String description = rs.getString("description");
|
||||
final String nameDecorated = rs.getString("nameDecorated");
|
||||
final Long codeId = rs.wasNull() ? null : rs.getLong("codeId");
|
||||
final String codeValue = rs.getString("codeValue");
|
||||
final CodeValueData tagId = CodeValueData.instance(codeId, codeValue);
|
||||
Long organizationRunningBalance = null;
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
organizationRunningBalance = rs.getLong("organizationRunningBalance");
|
||||
}
|
||||
return new GLAccountData().setId(id).setName(name).setParentId(parentId).setGlCode(glCode).setDisabled(disabled)
|
||||
.setManualEntriesAllowed(manualEntriesAllowed).setType(accountType).setUsage(usage).setDescription(description)
|
||||
.setNameDecorated(nameDecorated).setTagId(tagId).setOrganizationRunningBalance(organizationRunningBalance);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllGLAccounts(final Integer accountClassification, final String searchParam, final Integer usage,
|
||||
final Boolean manualTransactionsAllowed, final Boolean disabled,
|
||||
JournalEntryAssociationParametersData associationParametersData) {
|
||||
if (accountClassification != null && !checkValidGLAccountType(accountClassification)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
|
||||
if (usage != null && !checkValidGLAccountUsage(usage)) {
|
||||
throw new GLAccountInvalidClassificationException(accountClassification);
|
||||
}
|
||||
|
||||
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
|
||||
String sql = "select " + rm.schema();
|
||||
// append SQL statement for fetching account totals
|
||||
if (associationParametersData != null && associationParametersData.isRunningBalanceRequired()) {
|
||||
sql = sql + " and gl_j.id in (select t1.id from (select t2.account_id, max(t2.id) as id from "
|
||||
+ "(select id, max(entry_date) as entry_date, account_id from acc_gl_journal_entry where is_running_balance_calculated = true "
|
||||
+ "group by account_id desc, id) t3 inner join acc_gl_journal_entry t2 on t2.account_id = t3.account_id and t2.entry_date = t3.entry_date "
|
||||
+ "group by t2.account_id desc) t1)";
|
||||
}
|
||||
final Object[] parameterArray = new Object[3];
|
||||
int arrayPos = 0;
|
||||
boolean filtersPresent = false;
|
||||
if ((accountClassification != null) || StringUtils.isNotBlank(searchParam) || (usage != null) || (manualTransactionsAllowed != null)
|
||||
|| (disabled != null)) {
|
||||
filtersPresent = true;
|
||||
sql += " where";
|
||||
}
|
||||
|
||||
if (filtersPresent) {
|
||||
boolean firstWhereConditionAdded = false;
|
||||
if (accountClassification != null) {
|
||||
sql += " classification_enum = ?";
|
||||
parameterArray[arrayPos] = accountClassification.shortValue();
|
||||
arrayPos = arrayPos + 1;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (StringUtils.isNotBlank(searchParam)) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
sql += " ( name like ? or gl_code like ? )";
|
||||
parameterArray[arrayPos] = "%" + searchParam + "%";
|
||||
arrayPos = arrayPos + 1;
|
||||
parameterArray[arrayPos] = "%" + searchParam + "%";
|
||||
arrayPos = arrayPos + 1;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (usage != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
if (GLAccountUsage.HEADER.getValue().equals(usage)) {
|
||||
sql += " account_usage = 2 ";
|
||||
} else if (GLAccountUsage.DETAIL.getValue().equals(usage)) {
|
||||
sql += " account_usage = 1 ";
|
||||
}
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (manualTransactionsAllowed != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
|
||||
sql += " manual_journal_entries_allowed = " + manualTransactionsAllowed;
|
||||
firstWhereConditionAdded = true;
|
||||
}
|
||||
if (disabled != null) {
|
||||
if (firstWhereConditionAdded) {
|
||||
sql += SQL_AND;
|
||||
}
|
||||
|
||||
sql += " disabled = " + disabled;
|
||||
}
|
||||
}
|
||||
|
||||
sql += " ORDER BY gl_code ASC";
|
||||
|
||||
final Object[] finalObjectArray = Arrays.copyOf(parameterArray, arrayPos);
|
||||
return this.jdbcTemplate.query(sql, rm, (Object[]) finalObjectArray);// NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData retrieveGLAccountById(final long glAccountId, JournalEntryAssociationParametersData associationParametersData) {
|
||||
try {
|
||||
final GLAccountMapper rm = new GLAccountMapper(associationParametersData);
|
||||
final StringBuilder sql = new StringBuilder();
|
||||
sql.append("select ").append(rm.schema());
|
||||
sql.append(" where gl.id = ?");
|
||||
if (associationParametersData.isRunningBalanceRequired()) {
|
||||
sql.append(" and gl_j.is_running_balance_calculated = true ")
|
||||
.append(" ORDER BY gl_j.entry_date DESC,gl_j.id DESC LIMIT 1");
|
||||
}
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql.toString(), rm, new Object[] { glAccountId });
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new GLAccountNotFoundException(glAccountId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllEnabledDetailGLAccounts(final GLAccountType accountType) {
|
||||
return retrieveAllGLAccounts(accountType.getValue(), null, GLAccountUsage.DETAIL.getValue(), null, false,
|
||||
new JournalEntryAssociationParametersData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllEnabledDetailGLAccounts() {
|
||||
return retrieveAllGLAccounts(null, null, GLAccountUsage.DETAIL.getValue(), null, false,
|
||||
new JournalEntryAssociationParametersData());
|
||||
}
|
||||
|
||||
private static boolean checkValidGLAccountType(final int type) {
|
||||
for (final GLAccountType accountType : GLAccountType.values()) {
|
||||
if (accountType.getValue().equals(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean checkValidGLAccountUsage(final int type) {
|
||||
for (final GLAccountUsage accountUsage : GLAccountUsage.values()) {
|
||||
if (accountUsage.getValue().equals(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLAccountData retrieveNewGLAccountDetails(final Integer type) {
|
||||
return GLAccountData.sensibleDefaultsForNewGLAccountCreation(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountData> retrieveAllEnabledHeaderGLAccounts(final GLAccountType accountType) {
|
||||
return retrieveAllGLAccounts(accountType.getValue(), null, GLAccountUsage.HEADER.getValue(), null, false,
|
||||
new JournalEntryAssociationParametersData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GLAccountDataForLookup> retrieveAccountsByTagId(final Long ruleId, final Integer transactionType) {
|
||||
final GLAccountDataLookUpMapper mapper = new GLAccountDataLookUpMapper();
|
||||
final String sql = "Select " + GLAccountDataLookUpMapper.LOOKUP_SCHEMA + " where rule.id=? and tags.acc_type_enum=?";
|
||||
return this.jdbcTemplate.query(sql, mapper, (Object[]) new Object[] { ruleId, transactionType });// NOSONAR
|
||||
}
|
||||
|
||||
private static final class GLAccountDataLookUpMapper implements RowMapper<GLAccountDataForLookup> {
|
||||
|
||||
private static final String LOOKUP_SCHEMA = " gl.id as id, gl.name as name, gl.gl_code as glCode from acc_accounting_rule rule join acc_rule_tags tags on tags.acc_rule_id = rule.id join acc_gl_account gl on gl.tag_id=tags.tag_id";
|
||||
|
||||
@Override
|
||||
public GLAccountDataForLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final String name = rs.getString("name");
|
||||
final String glCode = rs.getString("glCode");
|
||||
|
||||
return new GLAccountDataForLookup().setId(id).setName(name).setGlCode(glCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,4 +344,5 @@
|
||||
<include file="parts/0314_cashier_staff_unique_constraint.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0315_grant_cashier_transaction_entry_permissions.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0316_create_clerk_role_and_permissions.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0317_grant_cashier_gl_loan_share_read_permissions.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
for licensing details.
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!--
|
||||
Grant READ permissions to CASHIER role for new account types added
|
||||
in the Cashier Transaction Entry screen:
|
||||
- READ_GLACCOUNT : GL account lookup and balance (AC. TP. = GL)
|
||||
- READ_LOAN : Loan account lookup (AC. TP. = LA)
|
||||
- READ_SHAREACCOUNT : Share account lookup (AC. TP. = SHR)
|
||||
-->
|
||||
<changeSet id="0317_grant_cashier_gl_loan_share_read_permissions" author="fineract">
|
||||
<sql>
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
JOIN m_permission p ON p.code IN (
|
||||
'READ_GLACCOUNT',
|
||||
'READ_LOAN',
|
||||
'READ_SHAREACCOUNT'
|
||||
)
|
||||
WHERE r.name = 'CASHIER'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
</sql>
|
||||
<rollback>
|
||||
DELETE FROM m_role_permission
|
||||
WHERE role_id = (SELECT id FROM m_role WHERE name = 'CASHIER')
|
||||
AND permission_id IN (
|
||||
SELECT id FROM m_permission
|
||||
WHERE code IN (
|
||||
'READ_GLACCOUNT',
|
||||
'READ_LOAN',
|
||||
'READ_SHAREACCOUNT'
|
||||
)
|
||||
);
|
||||
</rollback>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user