FINERACT-1724 Improve cashier data validator
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 dc50061..39c7933 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 @@
 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.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 @@
         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<String, Object> 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 @@
         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<String, Object> 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 89%
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 54b9c3b..5c19e79 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 @@
 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.");
     }