diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java index dc500616d..39c793322 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/data/CashierTransactionDataValidator.java @@ -21,13 +21,15 @@ package org.apache.fineract.organisation.teller.data; import java.math.BigDecimal; import java.time.LocalDate; import java.time.OffsetDateTime; +import java.util.HashMap; +import java.util.Map; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.MathUtil; import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.organisation.teller.domain.Cashier; import org.apache.fineract.organisation.teller.domain.Teller; -import org.apache.fineract.organisation.teller.exception.CashierAlreadyAlloacated; +import org.apache.fineract.organisation.teller.exception.CashierAlreadyAllocated; import org.apache.fineract.organisation.teller.exception.CashierDateRangeOutOfTellerDateRangeException; import org.apache.fineract.organisation.teller.exception.CashierInsufficientAmountException; import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformService; @@ -36,19 +38,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Component; @Component public class CashierTransactionDataValidator { private final TellerManagementReadPlatformService tellerManagementReadPlatformService; - private final JdbcTemplate jdbcTemplate; + private final NamedParameterJdbcTemplate jdbcTemplate; private static final Logger LOG = LoggerFactory.getLogger(CashierTransactionDataValidator.class); @Autowired public CashierTransactionDataValidator(final TellerManagementReadPlatformService tellerManagementReadPlatformService, - final JdbcTemplate jdbcTemplate) { + final NamedParameterJdbcTemplate jdbcTemplate) { this.tellerManagementReadPlatformService = tellerManagementReadPlatformService; this.jdbcTemplate = jdbcTemplate; } @@ -80,25 +82,35 @@ public class CashierTransactionDataValidator { final LocalDate endDate = cashier.getEndDate(); final LocalDate tellerFromDate = teller.getStartDate(); final LocalDate tellerEndDate = teller.getEndDate(); - // to validate cashier date range in range of teller date range + // Validate cashier date range in range of teller date range if (DateUtils.isBefore(fromDate, tellerFromDate) || DateUtils.isBefore(endDate, tellerFromDate) || (tellerEndDate != null && (DateUtils.isAfter(fromDate, tellerEndDate) || DateUtils.isAfter(endDate, tellerEndDate)))) { throw new CashierDateRangeOutOfTellerDateRangeException(); } - // to validate cashier has not been assigned for same duration - String sql = "select count(*) from m_cashiers c where c.staff_id = " + staffId + " AND " + "(('" + fromDate - + "' BETWEEN c.start_date AND c.end_date OR '" + endDate + "' BETWEEN c.start_date AND c.end_date )" - + " OR ( c.start_date BETWEEN '" + fromDate + "' AND '" + endDate + "' OR c.end_date BETWEEN '" + fromDate + "' AND '" - + endDate + "'))"; + + // Validate cashier has not been assigned for the same duration + String sql = "SELECT COUNT(*) FROM m_cashiers c WHERE c.staff_id = :staffId AND " + + "((:fromDate BETWEEN c.start_date AND c.end_date OR :endDate BETWEEN c.start_date AND c.end_date) " + + "OR (c.start_date BETWEEN :fromDate AND :endDate OR c.end_date BETWEEN :fromDate AND :endDate))"; + if (!cashier.getIsFullDay()) { - String startTime = cashier.getStartTime(); - String endTime = cashier.getEndTime(); - sql = sql + " AND ( Time(c.start_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime - + "') or Time(c.end_time) BETWEEN TIME('" + startTime + "') and TIME('" + endTime + "')) "; + sql += " AND (TIME(c.start_time) BETWEEN TIME(:startTime) AND TIME(:endTime) " + + "OR TIME(c.end_time) BETWEEN TIME(:startTime) AND TIME(:endTime))"; } - int count = this.jdbcTemplate.queryForObject(sql, Integer.class); // NOSONAR - if (count > 0) { - throw new CashierAlreadyAlloacated(); + + Map paramMap = new HashMap<>(); + paramMap.put("staffId", staffId); + paramMap.put("fromDate", fromDate); + paramMap.put("endDate", endDate); + + if (!cashier.getIsFullDay()) { + paramMap.put("startTime", cashier.getStartTime()); + paramMap.put("endTime", cashier.getEndTime()); + } + + Integer count = jdbcTemplate.queryForObject(sql, paramMap, Integer.class); + if (count != null && count > 0) { + throw new CashierAlreadyAllocated(); } } @@ -106,12 +118,18 @@ public class CashierTransactionDataValidator { LocalDate tenantDate = DateUtils.getLocalDateOfTenant(); OffsetDateTime tenantDateTime = DateUtils.getOffsetDateTimeOfTenant(); if (user.getStaff() != null) { - String sql = "select c.id from m_cashiers c where c.staff_id = " + user.getStaff().getId() + " AND (case when c.full_day then '" - + tenantDate + "' BETWEEN c.start_date AND c.end_date else ('" + tenantDate - + "' BETWEEN c.start_date AND c.end_date and TIME('" + tenantDateTime - + "') BETWEEN TIME(c.start_time) AND TIME(c.end_time)) end)"; + String sql = "SELECT c.id FROM m_cashiers c WHERE c.staff_id = :staffId " + + "AND (CASE WHEN c.full_day THEN :tenantDate BETWEEN c.start_date AND c.end_date " + + "ELSE (:tenantDate BETWEEN c.start_date AND c.end_date AND " + + "TIME(:tenantDateTime) BETWEEN TIME(c.start_time) AND TIME(c.end_time)) END)"; + + Map paramMap = new HashMap<>(); + paramMap.put("staffId", user.getStaff().getId()); + paramMap.put("tenantDate", tenantDate); + paramMap.put("tenantDateTime", tenantDateTime); + try { - Long cashierId = this.jdbcTemplate.queryForObject(sql, Long.class); // NOSONAR + Long cashierId = jdbcTemplate.queryForObject(sql, paramMap, Long.class); validateSettleCashAndCashOutTransactions(cashierId, currencyCode, transactionAmount); } catch (EmptyResultDataAccessException e) { LOG.error("Problem occurred in validateOnLoanDisbursal function", e); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/exception/CashierAlreadyAlloacated.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/exception/CashierAlreadyAllocated.java similarity index 90% rename from fineract-provider/src/main/java/org/apache/fineract/organisation/teller/exception/CashierAlreadyAlloacated.java rename to fineract-provider/src/main/java/org/apache/fineract/organisation/teller/exception/CashierAlreadyAllocated.java index 54b9c3bc9..5c19e79db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/exception/CashierAlreadyAlloacated.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/exception/CashierAlreadyAllocated.java @@ -21,9 +21,9 @@ package org.apache.fineract.organisation.teller.exception; import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; @SuppressWarnings("serial") -public class CashierAlreadyAlloacated extends AbstractPlatformDomainRuleException { +public class CashierAlreadyAllocated extends AbstractPlatformDomainRuleException { - public CashierAlreadyAlloacated() { + public CashierAlreadyAllocated() { super("cashier.already.allocated.for.given.data.and.time.exception", "Cashier already allocated for given date and time range."); }