Cash Management initial commit

This commit is contained in:
Binny G Sreevas
2014-11-20 14:35:42 +05:30
parent 9dadb669a4
commit 5afed47767
45 changed files with 4747 additions and 0 deletions
@@ -375,6 +375,30 @@ public class CommandWrapper {
public boolean isLoanResource() {
return this.entityName.equalsIgnoreCase("LOAN");
}
public boolean isTellerResource() {
return this.entityName.equalsIgnoreCase("TELLER");
}
public boolean isAllocateCashier() {
return this.actionName.equalsIgnoreCase("ALLOCATECASHIER");
}
public boolean isUpdateCashierAllocation() {
return this.actionName.equalsIgnoreCase("UPDATECASHIERALLOCATION");
}
public boolean isDeleteCashierAllocation() {
return this.actionName.equalsIgnoreCase("DELETECASHIERALLOCATION");
}
public boolean isAllocateCashToCashier() {
return this.actionName.equalsIgnoreCase("ALLOCATECASHTOCASHIER");
}
public boolean isSettleCashFromCashier() {
return this.actionName.equalsIgnoreCase("SETTLECASHFROMCASHIER");
}
public boolean isLoanChargeResource() {
return this.entityName.equalsIgnoreCase("LOANCHARGE");
@@ -23,6 +23,7 @@ public class CommandWrapperBuilder {
private String transactionId;
private Long productId;
private Long templateId;
private Long tellerId;
public CommandWrapper build() {
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName,
@@ -58,6 +59,11 @@ public class CommandWrapperBuilder {
this.subentityId = withSubEntityId;
return this;
}
public CommandWrapperBuilder withTellerId(final Long withTellerId) {
this.tellerId = withTellerId;
return this;
}
public CommandWrapperBuilder withJson(final String withJson) {
this.json = withJson;
@@ -2112,4 +2118,73 @@ public class CommandWrapperBuilder {
this.href = "/rescheduleloans/" + requestId + "?command=reject";
return this;
}
public CommandWrapperBuilder createTeller() {
this.actionName = "CREATE";
this.entityName = "TELLER";
this.entityId = null;
this.href = "/tellers/templates";
return this;
}
public CommandWrapperBuilder updateTeller(final Long tellerId) {
this.actionName = "UPDATE";
this.entityName = "TELLER";
this.entityId = tellerId;
this.href = "/tellers/" + tellerId;
return this;
}
public CommandWrapperBuilder deleteTeller(final Long tellerId) {
this.actionName = "DELETE";
this.entityName = "TELLER";
this.entityId = tellerId;
this.href = "/tellers/" + tellerId;
return this;
}
public CommandWrapperBuilder allocateTeller(final long tellerId) {
this.actionName = "ALLOCATECASHIER";
this.entityName = "TELLER";
this.entityId = tellerId;
this.href = "/tellers/" + tellerId + "/cashiers/templates";
return this;
}
public CommandWrapperBuilder updateAllocationTeller(final Long tellerId, final Long cashierId) {
this.actionName = "UPDATECASHIERALLOCATION";
this.entityName = "TELLER";
this.entityId = tellerId;
this.subentityId = cashierId;
this.href = "/tellers/" + tellerId + "/cashiers/" + cashierId;
return this;
}
public CommandWrapperBuilder deleteAllocationTeller(final Long tellerId, final Long cashierId) {
this.actionName = "DELETECASHIERALLOCATION";
this.entityName = "TELLER";
this.entityId = tellerId;
this.subentityId = cashierId;
this.href = "/tellers/" + tellerId + "/cashiers/" + cashierId;
return this;
}
public CommandWrapperBuilder allocateCashToCashier(final Long tellerId, final Long cashierId) {
this.actionName = "ALLOCATECASHTOCASHIER";
this.entityName = "TELLER";
this.entityId = tellerId;
this.subentityId = cashierId;
this.href = "/tellers/" + tellerId + "/cashiers/" + cashierId + "/allocate";
return this;
}
public CommandWrapperBuilder settleCashFromCashier(final Long tellerId, final Long cashierId) {
this.actionName = "SETTLECASHFROMCASHIER";
this.entityName = "TELLER";
this.entityId = tellerId;
this.subentityId = cashierId;
this.href = "/tellers/" + tellerId + "/cashiers/" + cashierId + "/settle";
return this;
}
}
@@ -261,6 +261,26 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isTellerResource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createTellerCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateTellerCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDelete()) {
handler = this.applicationContext.getBean("deleteTellerCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isAllocateCashier()) {
handler = this.applicationContext.getBean("allocateCashierToTellerCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdateCashierAllocation()) {
handler = this.applicationContext.getBean("updateCashierAllocationCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDeleteCashierAllocation()) {
handler = this.applicationContext.getBean("deleteCashierAllocationCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isAllocateCashToCashier()) {
handler = this.applicationContext.getBean("allocateCashToCashierCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSettleCashFromCashier()) {
handler = this.applicationContext.getBean("settleCashFromCashierCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isCollateralResource()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createCollateralCommandHandler", NewCommandSourceHandler.class);
@@ -0,0 +1,52 @@
package org.mifosplatform.organisation.teller.api;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.teller.data.CashierData;
import org.mifosplatform.organisation.teller.service.TellerManagementReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Collection;
import java.util.Date;
@Path("cashiers")
@Component
@Scope("singleton")
public class CashierApiResource {
private final PlatformSecurityContext securityContext;
private final DefaultToApiJsonSerializer<CashierData> jsonSerializer;
private final TellerManagementReadPlatformService readPlatformService;
private final PortfolioCommandSourceWritePlatformService commandWritePlatformService;
@Autowired
public CashierApiResource(PlatformSecurityContext securityContext, DefaultToApiJsonSerializer<CashierData> jsonSerializer,
TellerManagementReadPlatformService readPlatformService,
PortfolioCommandSourceWritePlatformService commandWritePlatformService) {
this.securityContext = securityContext;
this.jsonSerializer = jsonSerializer;
this.readPlatformService = readPlatformService;
this.commandWritePlatformService = commandWritePlatformService;
}
@GET
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getCashierData(@QueryParam("officeId") final Long officeId, @QueryParam("tellerId") final Long tellerId,
@QueryParam("staffId") final Long staffId, @QueryParam("date") final String date) {
final DateTimeFormatter dateFormatter = ISODateTimeFormat.basicDate();
final Date dateRestriction = (date != null ? dateFormatter.parseDateTime(date).toDate() : new Date());
final Collection<CashierData> allCashiers = this.readPlatformService.getCashierData(officeId, tellerId, staffId, dateRestriction);
return this.jsonSerializer.serialize(allCashiers);
}
}
@@ -0,0 +1,317 @@
package org.mifosplatform.organisation.teller.api;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.teller.data.CashierData;
import org.mifosplatform.organisation.teller.data.CashierTransactionData;
import org.mifosplatform.organisation.teller.data.CashierTransactionsWithSummaryData;
import org.mifosplatform.organisation.teller.data.TellerData;
import org.mifosplatform.organisation.teller.data.TellerJournalData;
import org.mifosplatform.organisation.teller.data.TellerTransactionData;
import org.mifosplatform.organisation.teller.domain.Teller;
import org.mifosplatform.organisation.teller.service.TellerManagementReadPlatformService;
import org.mifosplatform.organisation.teller.util.DateRange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Collection;
import java.util.Date;
@Path("tellers")
@Component
@Scope("singleton")
public class TellerApiResource {
private final PlatformSecurityContext securityContext;
private final DefaultToApiJsonSerializer<TellerData> jsonSerializer;
private final TellerManagementReadPlatformService readPlatformService;
private final PortfolioCommandSourceWritePlatformService commandWritePlatformService;
@Autowired
public TellerApiResource(PlatformSecurityContext securityContext, DefaultToApiJsonSerializer<TellerData> jsonSerializer,
TellerManagementReadPlatformService readPlatformService, PortfolioCommandSourceWritePlatformService commandWritePlatformService) {
super();
this.securityContext = securityContext;
this.jsonSerializer = jsonSerializer;
this.readPlatformService = readPlatformService;
this.commandWritePlatformService = commandWritePlatformService;
}
@GET
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getTellerData(@QueryParam("officeId") final Long officeId) {
final Collection<TellerData> foundTellers = this.readPlatformService.getTellers(officeId);
return this.jsonSerializer.serialize(foundTellers);
}
@Path("{tellerId}")
@GET
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String findTeller(@PathParam("tellerId") final Long tellerId) {
final TellerData teller = this.readPlatformService.findTeller(tellerId);
return this.jsonSerializer.serialize(teller);
}
@POST
@Consumes({MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String createTeller(final String tellerData) {
final CommandWrapper request = new CommandWrapperBuilder().createTeller().withJson(tellerData).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@Path("{tellerId}")
@PUT
@Consumes({MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String updateTeller(@PathParam("tellerId") final Long tellerId, final String tellerData) {
final CommandWrapper request = new CommandWrapperBuilder().updateTeller(tellerId).withJson(tellerData).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@Path("{tellerId}")
@DELETE
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String deleteTeller(@PathParam("tellerId") final Long tellerId) {
final CommandWrapper request = new CommandWrapperBuilder().deleteTeller(tellerId).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@GET
@Path("{tellerId}/cashiers")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getCashierData(@PathParam("tellerId") final Long tellerId, @QueryParam("fromdate") final String fromDateStr,
@QueryParam("todate") final String toDateStr) {
final DateTimeFormatter dateFormatter = ISODateTimeFormat.basicDate();
final Date fromDate = (fromDateStr != null ? dateFormatter.parseDateTime(fromDateStr).toDate() : new Date());
final Date toDate = (toDateStr != null ? dateFormatter.parseDateTime(toDateStr).toDate() : new Date());
final TellerData teller = this.readPlatformService.findTeller(tellerId);
final Collection<CashierData> cashiers = this.readPlatformService.getCashiersForTeller(tellerId, fromDate, toDate);
CashiersForTeller cashiersForTeller = new CashiersForTeller();
cashiersForTeller.cashiers = cashiers;
cashiersForTeller.tellerId = tellerId;
cashiersForTeller.tellerName = teller.getName();
cashiersForTeller.officeId = teller.getOfficeId();
cashiersForTeller.officeName = teller.getOfficeName();
return this.jsonSerializer.serialize(cashiersForTeller);
}
@GET
@Path("{tellerId}/cashiers/{cashierId}")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String findCashierData(@PathParam("tellerId") final Long tellerId, @PathParam("cashierId") final Long cashierId) {
final CashierData cashier = this.readPlatformService.findCashier(cashierId);
return this.jsonSerializer.serialize(cashier);
}
@GET
@Path("{tellerId}/cashiers/template")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getCashierTemplate(@PathParam("tellerId") final Long tellerId) {
final TellerData teller = this.readPlatformService.findTeller(tellerId);
Long officeId = teller.getOfficeId();
final CashierData cashier =
this.readPlatformService.retrieveCashierTemplate(officeId, tellerId, true);
return this.jsonSerializer.serialize(cashier);
}
@POST
@Path("{tellerId}/cashiers")
@Consumes({MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String createCashier(@PathParam("tellerId") final Long tellerId, final String cashierData) {
final CommandWrapper request = new CommandWrapperBuilder().allocateTeller(tellerId).withJson(cashierData).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@PUT
@Path("{tellerId}/cashiers/{cashierId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String updateCashier(@PathParam("tellerId") final Long tellerId, @PathParam("cashierId") final Long cashierId, final String cashierDate) {
final CommandWrapper request = new CommandWrapperBuilder().updateAllocationTeller(tellerId, cashierId).withJson(cashierDate).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@DELETE
@Path("{tellerId}/cashiers/{cashierId}")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String deleteCashier(@PathParam("tellerId") final Long tellerId, @PathParam("cashierId") final Long cashierId) {
final CommandWrapper request = new CommandWrapperBuilder().deleteAllocationTeller(tellerId, cashierId).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@POST
@Path("{tellerId}/cashiers/{cashierId}/allocate")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String allocateCashToCashier (@PathParam("tellerId") final Long tellerId, @PathParam("cashierId") final Long cashierId, final String cashierTxnData) {
final CommandWrapper request = new CommandWrapperBuilder().allocateCashToCashier(tellerId, cashierId).withJson(cashierTxnData).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@POST
@Path("{tellerId}/cashiers/{cashierId}/settle")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String settleCashFromCashier (@PathParam("tellerId") final Long tellerId, @PathParam("cashierId") final Long cashierId, final String cashierTxnData) {
final CommandWrapper request = new CommandWrapperBuilder().settleCashFromCashier(tellerId, cashierId).withJson(cashierTxnData).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
}
@GET
@Path("{tellerId}/cashiers/{cashierId}/transactions")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getTransactionsForCashier (@PathParam("tellerId") final Long tellerId,
@PathParam("cashierId") final Long cashierId,
final String fromDateStr, final String toDateStr) {
final TellerData teller = this.readPlatformService.findTeller(tellerId);
final CashierData cashier = this.readPlatformService.findCashier(cashierId);
final Date fromDate = null;
final Date toDate = null;
final Collection<CashierTransactionData> cashierTxns =
this.readPlatformService.retrieveCashierTransactions(cashierId,
true, fromDate, toDate);
return this.jsonSerializer.serialize(cashierTxns);
}
@GET
@Path("{tellerId}/cashiers/{cashierId}/summaryandtransactions")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getTransactionsWtihSummaryForCashier (@PathParam("tellerId") final Long tellerId,
@PathParam("cashierId") final Long cashierId,
final String fromDateStr, final String toDateStr) {
final TellerData teller = this.readPlatformService.findTeller(tellerId);
final CashierData cashier = this.readPlatformService.findCashier(cashierId);
final Date fromDate = null;
final Date toDate = null;
final CashierTransactionsWithSummaryData cashierTxnWithSummary =
this.readPlatformService.retrieveCashierTransactionsWithSummary
(cashierId,
true, fromDate, toDate);
return this.jsonSerializer.serialize(cashierTxnWithSummary);
}
@GET
@Path("{tellerId}/cashiers/{cashierId}/transactions/template")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getCashierTxnTemplate(@PathParam("tellerId") final Long tellerId, @PathParam("cashierId") final Long cashierId) {
final CashierTransactionData cashierTxnTemplate =
this.readPlatformService.retrieveCashierTxnTemplate(cashierId);
return this.jsonSerializer.serialize(cashierTxnTemplate);
}
@GET
@Path("{tellerId}/transactions")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getTransactionData(@PathParam("tellerId") final Long tellerId,
@QueryParam("dateRange") final String dateRange) {
final DateRange dateRangeHolder = DateRange.fromString(dateRange);
final Collection<TellerTransactionData> transactions =
this.readPlatformService.fetchTellerTransactionsByTellerId(tellerId, dateRangeHolder.getStartDate(), dateRangeHolder.getEndDate());
return this.jsonSerializer.serialize(transactions);
}
@GET
@Path("{tellerId}/transactions/{transactionId}")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String findTransactionData(@PathParam("tellerId") final Long tellerid,
@PathParam("transactionId") final Long transactionId) {
final TellerTransactionData transaction = this.readPlatformService.findTellerTransaction(transactionId);
return this.jsonSerializer.serialize(transaction);
}
@GET
@Path("{tellerId}/journals")
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getJournalData(@PathParam("tellerId") final Long tellerId,
@QueryParam("cashierId") final Long cashierDate,
@QueryParam("dateRange") final String dateRange) {
final DateRange dateRangeHolder = DateRange.fromString(dateRange);
final Collection<TellerJournalData> journals =
this.readPlatformService.fetchTellerJournals(tellerId, cashierDate, dateRangeHolder.getStartDate(), dateRangeHolder.getEndDate());
return this.jsonSerializer.serialize(journals);
}
private class CashiersForTeller {
public Long tellerId;
public String tellerName;
public Long officeId;
public String officeName;
public Collection<CashierData> cashiers;
}
}
@@ -0,0 +1,46 @@
package org.mifosplatform.organisation.teller.api;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.teller.data.TellerData;
import org.mifosplatform.organisation.teller.data.TellerJournalData;
import org.mifosplatform.organisation.teller.service.TellerManagementReadPlatformService;
import org.mifosplatform.organisation.teller.util.DateRange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Collection;
@Path("cashiersjournal")
@Component
@Scope("singleton")
public class TellerJournalApiResource {
private final PlatformSecurityContext securityContext;
private final DefaultToApiJsonSerializer<TellerData> jsonSerializer;
private final TellerManagementReadPlatformService readPlatformService;
@Autowired
public TellerJournalApiResource(final PlatformSecurityContext securityContext, final DefaultToApiJsonSerializer jsonSerializer,
final TellerManagementReadPlatformService readPlatformService) {
super();
this.securityContext = securityContext;
this.jsonSerializer = jsonSerializer;
this.readPlatformService = readPlatformService;
}
@GET
@Consumes({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public String getJournalData(@QueryParam("officeId") final Long officeId, @QueryParam("tellerId") final Long tellerId,
@QueryParam("cashierId") final Long cashierId, @QueryParam("dateRange") final String dateRange) {
final DateRange dateRangeHolder = DateRange.fromString(dateRange);
final Collection<TellerJournalData> journals = this.readPlatformService.getJournals(officeId, tellerId, cashierId, dateRangeHolder.getStartDate(), dateRangeHolder.getEndDate());
return this.jsonSerializer.serialize(journals);
}
}
@@ -0,0 +1,225 @@
/**
* 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.organisation.teller.data;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
/**
* Represents a cashier, providing access to the cashier's office, staff
* information, teller, and more.
*
* @author Markus Geiss
<<<<<<< HEAD
* @since 2.0.0
* @see org.mifosplatform.organisation.teller.domain.Cashier
* @since 2.0.0
*/
public final class CashierData implements Serializable {
private final Long id;
private final Long tellerId;
private final Long officeId;
private final Long staffId;
private final String description;
private final Date startDate;
private final Date endDate;
private final Boolean isFullDay;
private final String startTime;
private final String endTime;
// Template fields
private final String officeName;
private final String tellerName;
private final String staffName;
private final Collection<StaffData> staffOptions;
/*
* Creates a new cashier.
*/
private CashierData(final Long id, final Long officeId, String officeName,
final Long staffId, final String staffName, final Long tellerId, final String tellerName,
final String description,
final Date startDate, final Date endDate, final Boolean isFullDay,
final String startTime, final String endTime, Collection<StaffData> staffOptions) {
this.id = id;
this.officeId = officeId;
this.staffId = staffId;
this.tellerId = tellerId;
this.description = description;
this.startDate = startDate;
this.endDate = endDate;
this.isFullDay = isFullDay;
this.startTime = startTime;
this.endTime = endTime;
this.officeName = officeName;
this.tellerName = tellerName;
this.staffName = staffName;
this.staffOptions = staffOptions;
}
/**
* Creates a new cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @param id the primary key of this cashier
* @param officeId the primary key of the related office
* @param staffId the primary key of the related staff
* @param tellerId the primary key of the related teller
* @param description the description of this cashier
* @param validFrom the valid from date of this cashier
* @param validTo the valid to date of this cashier
* @param partTime the part time flag of this cashier
* @param startTime the start time of this cashier
* @param endTime the end time of this cashier
* @return the cashier
*/
public static CashierData instance(final Long id, final Long officeId, String officeName,
final Long staffId, final String staffName, final Long tellerId, final String tellerName,
final String description, final Date startDate, final Date endDate,
final Boolean isFullDay, final String startTime, final String endTime) {
return new CashierData(id, officeId, officeName, staffId, staffName, tellerId, tellerName,
description, startDate, endDate, isFullDay, startTime, endTime, null);
}
/*
* Creates a new cashier.
*/
public static CashierData template (final Long officeId, final String officeName,
final Long tellerId, final String tellerName, final Collection<StaffData> staffOptions) {
return new CashierData(null, officeId, officeName, null, null, tellerId, tellerName,
null, null, null, null, null, null, staffOptions);
}
/**
* Returns the primary key of this cashier.
*
* @return the primary key of this cashier
*/
public Long getId() {
return id;
}
/**
* Returns the primary key of this cashiers related office.
*
* @return the primary key of this cashiers related office
*/
public Long getOfficeId() {
return officeId;
}
/**
* Returns the primary key of this cashiers related staff.
*
* @return the primary key of this cashiers related staff
*/
public Long getStaffId() {
return staffId;
}
/**
* Returns the primary key of this cashiers related teller.
*
* @return the primary key of this cashiers related teller
*/
public Long getTellerId() {
return tellerId;
}
/**
* Returns the description of this cashier.
*
* @return the description of this cashier
*/
public String getDescription() {
return description;
}
/**
* Returns the valid from date of this cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
*
* @return the valid from date of this cashier
*/
public Date getStartDate() {
return startDate;
}
/**
* Returns the valid to date of this cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
*
* @return the valid to date of this cashier
*/
public Date getEndDate() {
return endDate;
}
/**
* Returns whether this cashier works part time or not.
*
* @return {@code true} if this cashier works part time; {@code false} otherwise
*/
public Boolean isFullDay() {
return isFullDay;
}
/**
* Returns the start time of this cashier.
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @return the start time of this cashier
*/
public String getStartTime() {
return startTime;
}
/**
* Returns the end time of this cashier.
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @return the start time of this cashier
*/
public String getEndTime() {
return endTime;
}
public String getOfficeName() {
return officeName;
}
public String getTellerName() {
return tellerName;
}
public String getStaffName() {
return staffName;
}
}
@@ -0,0 +1,161 @@
/**
* 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.organisation.teller.data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.organisation.teller.domain.CashierTxnType;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
public final class CashierTransactionData implements Serializable {
private final Long id;
private final Long cashierId;
private final CashierTxnType txnType;
private final BigDecimal txnAmount;
private final Date txnDate;
private final Long entityId;
private final String entityType;
private final String txnNote;
private final Date createdDate;
// Template fields
private final Long officeId;
private final String officeName;
private final Long tellerId;
private final String tellerName;
private final String cashierName;
private final CashierData cashierData;
private final Date startDate;
private final Date endDate;
/*
* Creates a new cashier.
*/
private CashierTransactionData(final Long id, final Long cashierId, CashierTxnType txnType,
final BigDecimal txnAmount, final Date txnDate, String txnNote,
String entityType, Long entityId, Date createdDate,
Long officeId, String officeName, Long tellerId, String tellerName, String cashierName,
CashierData cashierData, Date startDate, Date endDate ) {
this.id = id;
this.cashierId = cashierId;
this.txnType = txnType;
this.txnAmount = txnAmount;
this.txnDate = txnDate;
this.txnNote = txnNote;
this.entityType = entityType;
this.entityId = entityId;
this.createdDate = createdDate;
this.officeId = officeId;
this.officeName = officeName;
this.tellerId = tellerId;
this.tellerName = tellerName;
this.cashierName = cashierName;
this.cashierData = cashierData;
this.startDate = startDate;
this.endDate = endDate;
}
public static CashierTransactionData instance(final Long id, final Long cashierId, CashierTxnType txnType,
final BigDecimal txnAmount, final Date txnDate, final String txnNote,
final String entityType, final Long entityId, final Date createdDate,
final Long officeId, final String officeName, final Long tellerId,
final String tellerName, final String cashierName, final CashierData cashierData,
Date startDate, Date endDate) {
return new CashierTransactionData(id, cashierId, txnType, txnAmount, txnDate, txnNote, entityType,
entityId, createdDate, officeId, officeName, tellerId,
tellerName, cashierName, cashierData, startDate, endDate);
}
public static CashierTransactionData template (final Long cashierId,
final Long tellerId, final String tellerName,
final Long officeId, final String officeName, final String cashierName,
final CashierData cashierData, Date startDate, Date endDate) {
return new CashierTransactionData(null, cashierId, null, null, null, null, null,
null, null, officeId, officeName, tellerId, tellerName, cashierName, cashierData,
startDate, endDate);
}
public Long getId() {
return id;
}
public Long getCashierId() {
return cashierId;
}
public CashierTxnType getTxnType() {
return txnType;
}
public BigDecimal getTxnAmount() {
return txnAmount;
}
public Date getTxnDate() {
return txnDate;
}
public String getTxnNote() {
return txnNote;
}
public String getEntityType() {
return entityType;
}
public Long getEntityId() {
return entityId;
}
public Date getCreatedDate() {
return createdDate;
}
public Long getOfficeId() {
return officeId;
}
public String getOfficeName() {
return officeName;
}
public Long getTellerId() {
return tellerId;
}
public String getTellerName() {
return tellerName;
}
public String getCashierName() {
return cashierName;
}
public Date getStartDate() {
return startDate;
}
public Date getEndDate() {
return endDate;
}
public CashierData getCashierData() {
return cashierData;
}
}
@@ -0,0 +1,39 @@
/**
* 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.organisation.teller.data;
import java.io.Serializable;
import java.math.BigDecimal;
public final class CashierTransactionTypeTotalsData implements Serializable {
private final Integer cashierTxnType;
private final BigDecimal cashTotal;
private CashierTransactionTypeTotalsData (
final Integer cashierTxnType,
final BigDecimal cashTotal
) {
this.cashierTxnType = cashierTxnType;
this.cashTotal = cashTotal;
}
public static CashierTransactionTypeTotalsData instance(
final Integer cashierTxnType,
final BigDecimal cashTotal
) {
return new CashierTransactionTypeTotalsData(
cashierTxnType, cashTotal);
}
public Integer getCashierTxnType() {
return cashierTxnType;
}
public BigDecimal getCashTotal() {
return cashTotal;
}
}
@@ -0,0 +1,122 @@
/**
* 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.organisation.teller.data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
public final class CashierTransactionsWithSummaryData implements Serializable {
private final BigDecimal sumCashAllocation;
private final BigDecimal sumInwardCash;
private final BigDecimal sumOutwardCash;
private final BigDecimal sumCashSettlement;
private final BigDecimal netCash;
private final String officeName;
private final long tellerId;
private final String tellerName;
private final long cashierId;
private final String cashierName;
private final Collection<CashierTransactionData> cashierTransactions;
private CashierTransactionsWithSummaryData(
final Collection<CashierTransactionData> cashierTransactions,
final BigDecimal sumCashAllocation,
final BigDecimal sumInwardCash,
final BigDecimal sumOutwardCash,
final BigDecimal sumCashSettlement,
final BigDecimal netCash,
final String officeName,
final Long tellerId,
final String tellerName,
final Long cashierId,
final String cashierName
) {
this.cashierTransactions = cashierTransactions;
this.sumCashAllocation = sumCashAllocation;
this.sumInwardCash = sumInwardCash;
this.sumOutwardCash = sumOutwardCash;
this.sumCashSettlement = sumCashSettlement;
this.netCash = netCash;
this.officeName = officeName;
this.tellerId = tellerId;
this.tellerName = tellerName;
this.cashierId = cashierId;
this.cashierName = cashierName;
}
public static CashierTransactionsWithSummaryData instance(
final Collection<CashierTransactionData> cashierTransactions,
final BigDecimal sumCashAllocation,
final BigDecimal sumInwardCash,
final BigDecimal sumOutwardCash,
final BigDecimal sumCashSettlement,
final String officeName,
final Long tellerId,
final String tellerName,
final Long cashierId,
final String cashierName
) {
final BigDecimal netCash =
sumCashAllocation.add(sumInwardCash).
subtract(sumOutwardCash).
subtract(sumCashSettlement);
return new CashierTransactionsWithSummaryData(
cashierTransactions,
sumCashAllocation,
sumInwardCash,
sumOutwardCash,
sumCashSettlement, netCash,
officeName, tellerId, tellerName, cashierId, cashierName);
}
public BigDecimal getSumCashAllocation() {
return sumCashAllocation;
}
public BigDecimal getSumInwardCash() {
return sumInwardCash;
}
public BigDecimal getSumOutwardCash() {
return sumOutwardCash;
}
public BigDecimal getSumCashSettlement() {
return sumCashSettlement;
}
public BigDecimal getNetCash() {
return netCash;
}
public String getOfficeName() {
return officeName;
}
public Long getTellerId() {
return tellerId;
}
public String getTellerName() {
return tellerName;
}
public Long getCashierId() {
return cashierId;
}
public String getCashierName() {
return cashierName;
}
public Collection<CashierTransactionData> getCashierTransactions() {
return cashierTransactions;
}
}
@@ -0,0 +1,147 @@
/**
* 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.organisation.teller.data;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.organisation.teller.domain.TellerStatus;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
/**
* {@code TellerData} represents an immutable data object for teller data.
*
* @version 1.0
<<<<<<< HEAD
* @since 2.0.0
* @see java.io.Serializable
* @since 2.0.0
*/
public final class TellerData implements Serializable {
private final Long id;
private final Long officeId;
private final Long debitAccountId;
private final Long creditAccountId;
private final String name;
private final String description;
private final LocalDate startDate;
private final LocalDate endDate;
private final TellerStatus status;
private final Boolean hasTransactions;
private final Boolean hasMappedCashiers;
private String officeName;
private final Collection<OfficeData> officeOptions;
private final Collection<StaffData> staffOptions;
/*
* Sole private CTOR to create a new instance.
*/
private TellerData(final Long id, final Long officeId, final Long debitAccountId, final Long creditAccountId,
final String name, final String description, final LocalDate startDate, final LocalDate endDate,
final TellerStatus status, final Boolean hasTransactions, final Boolean hasMappedCashiers) {
super();
this.id = id;
this.officeId = officeId;
this.debitAccountId = debitAccountId;
this.creditAccountId = creditAccountId;
this.name = name;
this.description = description;
this.startDate = startDate;
this.endDate = endDate;
this.status = status;
this.hasTransactions = hasTransactions;
this.hasMappedCashiers = hasMappedCashiers;
this.officeOptions = null;
this.staffOptions = null;
}
/**
* Creates a new teller data object.
*
* @param id - id of the teller
* @param officeId - id of the related office
* @param debitAccountId - id of the debit account to use
* @param creditAccountId - id of the credit account to use
* @param name - name of the teller
* @param description - description of the teller
* @param startDate - date when the teller becomes available
* @param endDate - date when the teller becomes unavailable
* @param status - current state of the teller, eg. active, inactive, pending
* @param hasTransactions - indicates that this teller already is used to perform postings
* @param hasMappedCashiers - indicates that the teller already has @code Cashier}s assigned to it
* @return the new created {@code TellerData}
*/
public static TellerData instance(final Long id, final Long officeId, final Long debitAccountId,
final Long creditAccountId, final String name, final String description,
final LocalDate startDate, final LocalDate endDate, final TellerStatus status,
final String officeName,
final Boolean hasTransactions, final Boolean hasMappedCashiers) {
TellerData tellerData = new TellerData(id, officeId, debitAccountId, creditAccountId, name, description, startDate, endDate,
status, hasTransactions, hasMappedCashiers);
tellerData.officeName = officeName;
return tellerData;
}
public static TellerData lookup(final Long id, final String name) {
return new TellerData(id, null, null, null, name, null, null, null, null, null, null);
}
public Long getId() {
return this.id;
}
public Long getOfficeId() {
return this.officeId;
}
public Long getDebitAccountId() {
return this.debitAccountId;
}
public Long getCreditAccountId() {
return this.creditAccountId;
}
public String getName() {
return this.name;
}
public String getOfficeName() {
return this.officeName;
}
public String getDescription() {
return this.description;
}
public LocalDate getStartDate() {
return this.startDate;
}
public LocalDate getEndDate() {
return this.endDate;
}
public TellerStatus getStatus() {
return this.status;
}
public Boolean hasTransactions() {
return this.hasTransactions;
}
public Boolean hasMappedCashiers() {
return this.hasMappedCashiers;
}
}
@@ -0,0 +1,99 @@
/**
* 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.organisation.teller.data;
import java.io.Serializable;
import java.util.Date;
/**
* {@code TellerJournalData} represents an immutable journal data object.
*
* @version 1.0.0
<<<<<<< HEAD
* @since 2.0.0
* @see java.io.Serializable
* @since 2.0.0
*/
public final class TellerJournalData implements Serializable {
private final Long officeId;
private final Long tellerId;
private final Date day;
private final Double openingBalance;
private final Double settledBalance;
private final Double closingBalance;
private final Double sumReceipts;
private final Double sumPayments;
/*
* Sole private CTOR to create a new instance.
*/
private TellerJournalData(final Long officeId, final Long tellerId, final Date day, final Double openingBalance,
final Double settledBalance, final Double closingBalance, final Double sumReceipts,
final Double sumPayments) {
this.officeId = officeId;
this.tellerId = tellerId;
this.day = day;
this.openingBalance = openingBalance;
this.settledBalance = settledBalance;
this.closingBalance = closingBalance;
this.sumReceipts = sumReceipts;
this.sumPayments = sumPayments;
}
/**
* Create a new teller journal data object.
*
* @param officeId - id of related office
* @param tellerId - id of related teller
* @param day - day of this journals data
* @param openingBalance - balance at the time of opening the teller
* @param settledBalance - balance at the time od settling the teller
* @param closingBalance - balance at the time of closing the teller
* @param sumReceipts - sum of all posted receipts
* @param sumPayments - sum of all posted payments
* @return the new created {@code TellerJournalData}
*/
public static TellerJournalData instance(final Long officeId, final Long tellerId, final Date day,
final Double openingBalance, final Double settledBalance,
final Double closingBalance, final Double sumReceipts,
final Double sumPayments) {
return new TellerJournalData(officeId, tellerId, day, openingBalance, settledBalance, closingBalance, sumReceipts,
sumPayments);
}
public Long getOfficeId() {
return officeId;
}
public Long getTellerId() {
return tellerId;
}
public Date getDay() {
return day;
}
public Double getOpeningBalance() {
return openingBalance;
}
public Double getSettledBalance() {
return settledBalance;
}
public Double getClosingBalance() {
return closingBalance;
}
public Double getSumReceipts() {
return sumReceipts;
}
public Double getSumPayments() {
return sumPayments;
}
}
@@ -0,0 +1,99 @@
/**
* 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.organisation.teller.data;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import java.io.Serializable;
import java.util.Date;
/**
* {@code TellerTransactionData} represents an immutable data object for a transction.
*
* @version 1.0.0
<<<<<<< HEAD
* @since 2.0.0
* @see java.io.Serializable
* @since 2.0.0
*/
public final class TellerTransactionData implements Serializable {
private final Long id;
private final Long officeId;
private final Long tellerId;
private final Long cashierId;
private final Long clientId;
private final EnumOptionData type;
private final Double amount;
private final Date postingDate;
/*
* Sole private CTOR to create a new instance
*/
private TellerTransactionData(final Long id, final Long officeId, final Long tellerId, final Long cashierId,
final Long clientId, final EnumOptionData type, final Double amount,
final Date postingDate) {
this.id = id;
this.officeId = officeId;
this.tellerId = tellerId;
this.cashierId = cashierId;
this.clientId = clientId;
this.type = type;
this.amount = amount;
this.postingDate = postingDate;
}
/**
* Creates a new teller transaction data object.
*
* @param id - id of the transaction
* @param officeId - id of the related office
* @param tellerId - id of the related teller
* @param cashierId - id of the cashier
* @param clientId - id of the client
* @param type - type of transaction (eg receipt, payment, open, close, settle)
* @param amount - amount of the transaction
* @param postingDate - posting date of the transaction
* @return the new created {@code TellerTransactionData}
*/
public static TellerTransactionData instance(final Long id, final Long officeId, final Long tellerId, final Long cashierId,
final Long clientId, final EnumOptionData type, final Double amount,
final Date postingDate) {
return new TellerTransactionData(id, officeId, tellerId, cashierId, clientId, type, amount, postingDate);
}
public Long getId() {
return id;
}
public Long getOfficeId() {
return officeId;
}
public Long getTellerId() {
return tellerId;
}
public Long getCashierId() {
return cashierId;
}
public Long getClientId() {
return clientId;
}
public EnumOptionData getType() {
return type;
}
public Double getAmount() {
return amount;
}
public Date getPostingDate() {
return postingDate;
}
}
@@ -0,0 +1,376 @@
/**
* 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.organisation.teller.domain;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.*;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Provides the base model for a cashier. Represents a row in the &quot;m_cashiers&quot; database table, with
* each column mapped to a property of this class.
*
* @author Markus Geiss
* @since 2.0.0
*/
@Entity
@Table(name = "m_cashiers", uniqueConstraints = {
@UniqueConstraint(name = "ux_cashiers_staff_teller", columnNames = {"staff_id", "teller_id"})
})
public class Cashier extends AbstractPersistable<Long> {
// ManyToOne(fetch = FetchType.LAZY)
// JoinColumn(name = "office_id", nullable = false)
@Transient
private Office office;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "staff_id", nullable = false)
private Staff staff;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "teller_id", nullable = false)
private Teller teller;
@Column(name = "description", nullable = true, length = 500)
private String description;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "start_date", nullable = false)
private Date startDate;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "end_date", nullable = false)
private Date endDate;
@Column(name = "full_day", nullable = true)
private Boolean isFullDay;
@Column(name = "start_time", nullable = true, length = 10)
private String startTime;
@Column(name = "end_time", nullable = true, length = 10)
private String endTime;
/**
* Creates a new cashier.
*/
public Cashier() {
super();
}
public static Cashier fromJson(final Office cashierOffice,
final Teller teller,
final Staff staff,
final JsonCommand command) {
// final Long tellerId = teller.getId();
// final Long staffId = command.longValueOfParameterNamed("staffId");
final String description = command.stringValueOfParameterNamed("description");
final LocalDate startDate = command.localDateValueOfParameterNamed("startDate");
final LocalDate endDate = command.localDateValueOfParameterNamed("endDate");
final Boolean isFullDay = command.booleanObjectValueOfParameterNamed("isFullDay");
final String startTime = command.stringValueOfParameterNamed("startTime");
final String endTime = command.stringValueOfParameterNamed("endTime");
return new Cashier (cashierOffice, teller, staff, description, startDate, endDate,
isFullDay, startTime, endTime);
}
public Cashier (Office office, Teller teller, Staff staff,
String description, LocalDate startDate, LocalDate endDate,
Boolean isFullDay, String startTime, String endTime) {
this.office = office;
this.teller = teller;
this.staff = staff;
this.description = description;
this.startDate = startDate.toDate();
this.endDate = endDate.toDate();
this.isFullDay = isFullDay;
this.startTime = startTime;
this.endTime = endTime;
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String dateFormatAsInput = command.dateFormat();
final String localeAsInput = command.locale();
final String descriptionParamName = "description";
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
actualChanges.put(descriptionParamName, newValue);
this.description = newValue;
}
final String startDateParamName = "startDate";
if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
actualChanges.put(startDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName);
this.startDate = newValue.toDate();
}
final String endDateParamName = "endDate";
if (command.isChangeInLocalDateParameterNamed(endDateParamName, getEndLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(endDateParamName);
actualChanges.put(endDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final LocalDate newValue = command.localDateValueOfParameterNamed(endDateParamName);
this.endDate = newValue.toDate();
}
final Boolean isFullDay = command.booleanObjectValueOfParameterNamed("isFullDay");
final String isFullDayParamName = "isFullDay";
if (command.isChangeInBooleanParameterNamed(isFullDayParamName, this.isFullDay)) {
final Boolean newValue = command.booleanObjectValueOfParameterNamed(isFullDayParamName);
actualChanges.put(isFullDayParamName, newValue);
this.isFullDay = newValue;
}
final String startTimeParamName = "startTime";
if (command.isChangeInStringParameterNamed(startTimeParamName, this.startTime)) {
final String newValue = command.stringValueOfParameterNamed(startTimeParamName);
actualChanges.put(startTimeParamName, newValue);
this.startTime = newValue;
}
final String endTimeParamName = "endTime";
if (command.isChangeInStringParameterNamed(endTimeParamName, this.endTime)) {
final String newValue = command.stringValueOfParameterNamed(endTimeParamName);
actualChanges.put(endTimeParamName, newValue);
this.endTime = newValue;
}
return actualChanges;
}
/**
* Returns the office of this cashier.
*
* @return the office of this cashier
* @see org.mifosplatform.organisation.office.domain.Office
*/
public Office getOffice() {
return office;
}
/**
* Sets the office of this cashier.
*
* @param office the office of this cashier
* @see org.mifosplatform.organisation.office.domain.Office
*/
public void setOffice(Office office) {
this.office = office;
}
/**
* Returns the staff of this cashier.
*
* @return the staff of this cashier
* @see org.mifosplatform.organisation.staff.domain.Staff
*/
public Staff getStaff() {
return staff;
}
/**
* Sets the staff of this cashier.
*
* @param staff the staff of this cashier
* @see org.mifosplatform.organisation.staff.domain.Staff
*/
public void setStaff(Staff staff) {
this.staff = staff;
}
/**
* Returns the teller of this cashier.
*
* @return the teller of this cashier
* @see org.mifosplatform.organisation.teller.domain.Teller
*/
public Teller getTeller() {
return teller;
}
/**
* Sets the teller of this cashier.
*
* @param teller the teller of this cashier
* @see org.mifosplatform.organisation.teller.domain.Teller
*/
public void setTeller(Teller teller) {
this.teller = teller;
}
/**
* Returns the description of this cashier.
* .
*
* @return the description of this cashier or {@code null} if not present.
*/
public String getDescription() {
return description;
}
/**
* Sets the description of this cashier.
*
* @param description the description of this cashier
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Returns the valid from date of this cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
*
* @return the valid from date of this cashier
*/
public Date getStartDate() {
return startDate;
}
public LocalDate getStartLocalDate() {
LocalDate startLocalDate = null;
if (this.startDate != null) {
startLocalDate = LocalDate.fromDateFields(this.startDate);
}
return startLocalDate;
}
/**
* Sets the valid from date of this cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
*
* @param validFrom the valid from date of this cashier
*/
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
/**
* Returns the valid to date of this cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
*
* @return the valid to date of this cashier
*/
public Date getEndDate() {
return endDate;
}
public LocalDate getEndLocalDate() {
LocalDate endLocalDate = null;
if (this.endDate != null) {
endLocalDate = LocalDate.fromDateFields(this.endDate);
}
return endLocalDate;
}
/**
* Sets the valid to date of this cashier.
* <p/>
* <p>The valid from/to dates may be used to define a time period in which
* the cashier is assignable to a teller.</p>
*
* @param validTo the valid to date of this cashier
*/
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
/**
* Returns whether this cashier works part time or not.
*
* @return {@code true} if this cashier works part time; {@code false} otherwise
*/
public Boolean isFullDay() {
return isFullDay;
}
/**
* Sets the part time flag of this cashier.
*
* @param partTime the part time flag of this cashier
*/
public void setFullDay (Boolean isFullDay) {
this.isFullDay = isFullDay;
}
/**
* Returns the start time of this cashier.
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @return the start time of this cashier
*/
public String getStartTime() {
return startTime;
}
/**
* Set the start time of this cashier.
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @param startTime the start time of this cashier
*/
public void setStartTime(String startTime) {
this.startTime = startTime;
}
/**
* Returns the end time of this cashier.
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @return the end time of this cashier
*/
public String getEndTime() {
return endTime;
}
/**
* Sets the end time of this cashier.
* <p/>
* <p>The start/end times may be used to define a time period in which
* the cashier works part time.</p>
*
* @param endTime the end time of this cashier
*/
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
@@ -0,0 +1,20 @@
/**
* 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.organisation.teller.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* Provides the domain repository for accessing, adding, modifying or deleting cashiers.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.domain.Cashier
* @since 2.0.0
*/
public interface CashierRepository extends JpaRepository<Cashier, Long>, JpaSpecificationExecutor<Cashier> {
// no added behavior
}
@@ -0,0 +1,247 @@
/**
* 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.organisation.teller.domain;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.office.domain.Office;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
@Entity
@Table(name = "m_cashier_transactions")
public class CashierTransaction extends AbstractPersistable<Long> {
@Transient
private Office office;
@Transient
private Teller teller;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cashier_id", nullable = false)
private Cashier cashier;
@Column(name = "txn_type", nullable = false)
private Integer txnType;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "txn_date", nullable = false)
private Date txnDate;
@Column(name = "txn_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal txnAmount;
@Column(name = "txn_note", nullable = true)
private String txnNote;
@Column(name = "entity_type", nullable = false)
private String entityType;
@Column(name = "entity_id", nullable = false)
private Long entityId;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_date", nullable = false)
private Date createdDate;
/**
* Creates a new cashier.
*/
public CashierTransaction() {
super();
}
public static CashierTransaction fromJson(
final Cashier cashier,
final JsonCommand command) {
final Integer txnType = command.integerValueOfParameterNamed("txnType");
final BigDecimal txnAmount = command.bigDecimalValueOfParameterNamed("txnAmount");
final LocalDate txnDate = command.localDateValueOfParameterNamed("txnDate");
final String entityType = command.stringValueOfParameterNamed("entityType");
final String txnNote = command.stringValueOfParameterNamed("txnNote");
final Long entityId = command.longValueOfParameterNamed("entityId");
// TODO: get client/loan/savings details
return new CashierTransaction (cashier, txnType, txnAmount, txnDate,
entityType, entityId, txnNote);
}
public CashierTransaction (Cashier cashier, Integer txnType, BigDecimal txnAmount,
LocalDate txnDate, String entityType, Long entityId, String txnNote) {
this.cashier = cashier;
this.txnType = txnType;
if (txnDate != null) {
this.txnDate = txnDate.toDate();
}
this.txnAmount = txnAmount;
this.entityType = entityType;
this.entityId = entityId;
this.txnNote = txnNote;
this.createdDate = new Date();
}
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String dateFormatAsInput = command.dateFormat();
final String localeAsInput = command.locale();
final String txnTypeParamName = "txnType";
if (command.isChangeInIntegerParameterNamed(txnTypeParamName, this.txnType)) {
final Integer newValue = command.integerValueOfParameterNamed(txnTypeParamName);
actualChanges.put(txnTypeParamName, newValue);
this.txnType = newValue;
}
final String txnDateParamName = "txnDate";
if (command.isChangeInLocalDateParameterNamed(txnDateParamName, getTxnLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(txnDateParamName);
actualChanges.put(txnDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final LocalDate newValue = command.localDateValueOfParameterNamed(txnDateParamName);
this.txnDate = newValue.toDate();
}
final String txnAmountParamName = "txnAmount";
if (command.isChangeInBigDecimalParameterNamed(txnAmountParamName, this.txnAmount)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(txnAmountParamName);
actualChanges.put(txnAmountParamName, newValue);
this.txnAmount = newValue;
}
final String txnNoteParamName = "txnNote";
if (command.isChangeInStringParameterNamed(txnNoteParamName, this.txnNote)) {
final String newValue = command.stringValueOfParameterNamed(txnNoteParamName);
actualChanges.put(txnNoteParamName, newValue);
this.txnNote = newValue;
}
return actualChanges;
}
/**
* Returns the office of this cashier transaction.
*
* @return the office of this cashier transaction
* @see org.mifosplatform.organisation.office.domain.Office
*/
public Office getOffice() {
return office;
}
/**
* Sets the office of this cashier transaction.
*
* @param office the office of this cashier transaction
* @see org.mifosplatform.organisation.office.domain.Office
*/
public void setOffice(Office office) {
this.office = office;
}
/**
* Returns the teller of this cashier transaction.
*
* @return the teller of this cashier transaction
* @see org.mifosplatform.organisation.teller.domain.Teller
*/
public Teller getTeller() {
return teller;
}
/**
* Sets the teller of this cashier transaction.
*
* @param teller the teller of this cashier transaction
* @see org.mifosplatform.organisation.teller.domain.Teller
*/
public void setTeller(Teller teller) {
this.teller = teller;
}
/**
* Returns the transaction type of this cashier transaction.
* .
*
* @return the transaction type of this cashier transaction or {@code null} if not present.
*/
public Integer getTxnType() {
return txnType;
}
/**
* Sets the transaction type of this cashier transaction.
*
* @param description the transaction type of this cashier transaction
*/
public void setTxnType(Integer txnType) {
this.txnType = txnType;
}
/**
* Returns the transaction date of this cashier transaction.
*
* @return the transaction date of this cashier transaction
*/
public Date getTxnDate() {
return txnDate;
}
public LocalDate getTxnLocalDate() {
LocalDate txnLocalDate = null;
if (this.txnDate != null) {
txnLocalDate = LocalDate.fromDateFields(this.txnDate);
}
return txnLocalDate;
}
/**
* Sets the transaction date of this cashier transaction.
*
* @param transaction date of this cashier transaction
*/
public void setTxnDate(Date txnDate) {
this.txnDate = txnDate;
}
public String getEntityType() {
return entityType;
}
public void setEntityType(String entityType) {
this.entityType = entityType;
}
public Long getEntityId() {
return entityId;
}
public void setEntityId(Long entityId) {
this.entityId = entityId;
}
public String getTxnNote() {
return txnNote;
}
public void setTxnNote (String txnNote) {
this.txnNote = txnNote;
}
}
@@ -0,0 +1,13 @@
/**
* 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.organisation.teller.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface CashierTransactionRepository extends JpaRepository<CashierTransaction, Long>, JpaSpecificationExecutor<CashierTransaction> {
// no added behavior
}
@@ -0,0 +1,48 @@
package org.mifosplatform.organisation.teller.domain;
import java.util.HashMap;
public class CashierTxnType {
private Integer id;
private String value;
public static CashierTxnType ALLOCATE = new CashierTxnType (101, "Allocate Cash");
public static CashierTxnType SETTLE = new CashierTxnType (102, "Settle Cash");
public static CashierTxnType INWARD_CASH_TXN = new CashierTxnType (103, "Cash In");
public static CashierTxnType OUTWARD_CASH_TXN = new CashierTxnType (104, "Cash Out");
private CashierTxnType () {
}
private CashierTxnType (Integer id, String value) {
this.id = id;
this.value = value;
}
public Integer getId () {
return id;
}
public String getValue () {
return value;
}
public static CashierTxnType getCashierTxnType (Integer id) {
CashierTxnType retVal = null;
switch(id) {
case 101:
retVal = ALLOCATE; break;
case 102:
retVal = SETTLE; break;
case 103:
retVal = INWARD_CASH_TXN; break;
case 104:
retVal = OUTWARD_CASH_TXN; break;
default:
break;
}
return retVal;
}
}
@@ -0,0 +1,276 @@
/**
* 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.organisation.teller.domain;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.accounting.glaccount.domain.GLAccount;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.exception.RootOfficeParentCannotBeUpdated;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.*;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@Entity
@Table(name = "m_tellers", uniqueConstraints = {
@UniqueConstraint(name = "ux_tellers_name", columnNames = {"name"})
})
public class Teller extends AbstractPersistable<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "office_id", nullable = false)
private Office office;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "debit_account_id", nullable = false)
private GLAccount debitAccount;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "credit_account_id", nullable = false)
private GLAccount creditAccount;
@Column(name = "name", nullable = false, length = 100)
private String name;
@Column(name = "description", nullable = true, length = 500)
private String description;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "valid_from", nullable = false)
private Date startDate;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "valid_to", nullable = false)
private Date endDate;
@Column(name = "state", nullable = false)
private Integer status;
@OneToMany(mappedBy = "teller", fetch = FetchType.LAZY)
private Set<Cashier> cashiers;
@OneToMany(mappedBy = "teller", fetch = FetchType.LAZY)
private Set<TellerTransaction> tellerTransactions;
public Teller() {
super();
}
private Teller (final Office staffOffice, final String name, final String description, final LocalDate startDate,
final LocalDate endDate, final TellerStatus status) {
this.name = StringUtils.defaultIfEmpty(name, null);
this.description = StringUtils.defaultIfEmpty(description, null);
if (startDate != null) {
this.startDate = startDate.toDateTimeAtStartOfDay().toDate();
}
if (endDate != null) {
this.endDate = endDate.toDateTimeAtStartOfDay().toDate();
}
if (status != null) {
this.status = status.getValue();
}
this.office = staffOffice;
/*
if (StringUtils.isNotBlank(name)) {
this.name = name.trim();
} else {
this.name = null;
}
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
} else {
this.description = null;
} */
}
public static Teller fromJson(final Office tellerOffice, final JsonCommand command) {
final String name = command.stringValueOfParameterNamed("name");
final String description = command.stringValueOfParameterNamed("description");
final LocalDate startDate = command.localDateValueOfParameterNamed("startDate");
final LocalDate endDate = command.localDateValueOfParameterNamed("endDate");
final Integer tellerStatusInt = command.integerValueOfParameterNamed("status");
final TellerStatus status = TellerStatus.fromInt(tellerStatusInt);
return new Teller (tellerOffice, name, description, startDate, endDate, status);
}
public Map<String, Object> update(Office tellerOffice, final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
final String dateFormatAsInput = command.dateFormat();
final String localeAsInput = command.locale();
final String officeIdParamName = "officeId";
if (command.isChangeInLongParameterNamed(officeIdParamName, this.officeId())) {
final long newValue = command.longValueOfParameterNamed(officeIdParamName);
actualChanges.put(officeIdParamName, newValue);
this.office = tellerOffice;
}
final String nameParamName = "name";
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
final String newValue = command.stringValueOfParameterNamed(nameParamName);
actualChanges.put(nameParamName, newValue);
this.name = newValue;
}
final String descriptionParamName = "description";
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
actualChanges.put(descriptionParamName, newValue);
this.description = newValue;
}
final String startDateParamName = "startDate";
if (command.isChangeInLocalDateParameterNamed(startDateParamName, getStartLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(startDateParamName);
actualChanges.put(startDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final LocalDate newValue = command.localDateValueOfParameterNamed(startDateParamName);
this.startDate = newValue.toDate();
}
final String endDateParamName = "endDate";
if (command.isChangeInLocalDateParameterNamed(endDateParamName, getEndLocalDate())) {
final String valueAsInput = command.stringValueOfParameterNamed(endDateParamName);
actualChanges.put(endDateParamName, valueAsInput);
actualChanges.put("dateFormat", dateFormatAsInput);
actualChanges.put("locale", localeAsInput);
final LocalDate newValue = command.localDateValueOfParameterNamed(endDateParamName);
this.endDate = newValue.toDate();
}
final String statusParamName = "status";
if (command.isChangeInIntegerParameterNamed(statusParamName, getStatus())) {
final Integer valueAsInput = command.integerValueOfParameterNamed(statusParamName);
actualChanges.put(statusParamName, valueAsInput);
final Integer newValue = command.integerValueOfParameterNamed(statusParamName);
final TellerStatus status = TellerStatus.fromInt(newValue);
if (status != TellerStatus.INVALID) {
this.status = status.getValue();
}
}
return actualChanges;
}
public Office getOffice() {
return office;
}
public void setOffice(Office office) {
this.office = office;
}
public GLAccount getDebitAccount() {
return debitAccount;
}
public void setDebitAccount(GLAccount debitAccount) {
this.debitAccount = debitAccount;
}
public GLAccount getCreditAccount() {
return creditAccount;
}
public void setCreditAccount(GLAccount creditAccount) {
this.creditAccount = creditAccount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getStartDate() {
return startDate;
}
public LocalDate getStartLocalDate() {
LocalDate startLocalDate = null;
if (this.startDate != null) {
startLocalDate = LocalDate.fromDateFields(this.startDate);
}
return startLocalDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public LocalDate getEndLocalDate() {
LocalDate endLocalDate = null;
if (this.endDate != null) {
endLocalDate = LocalDate.fromDateFields(this.endDate);
}
return endLocalDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Long officeId() {
return this.office.getId();
}
public Set<Cashier> getCashiers() {
return cashiers;
}
public void setCashiers(Set<Cashier> cashiers) {
this.cashiers = cashiers;
}
public Set<TellerTransaction> getTransactions() {
return tellerTransactions;
}
public void setTransactions(Set<TellerTransaction> tellerTransactions) {
this.tellerTransactions = tellerTransactions;
}
}
@@ -0,0 +1,9 @@
/**
* 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.organisation.teller.domain;
public class TellerJournal {
}
@@ -0,0 +1,21 @@
/**
* 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.organisation.teller.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.Collection;
/**
* Provides the domain repository for accessing, adding, modifying or deleting tellers.
*
* @see org.mifosplatform.organisation.teller.domain.Teller
* @since 2.0.0
*/
public interface TellerRepository extends JpaRepository<Teller, Long>, JpaSpecificationExecutor<Teller> {
Collection<Teller> findTellerByOfficeId(Long officeId);
}
@@ -0,0 +1,77 @@
/**
* 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.organisation.teller.domain;
/**
* Enum representation of teller status states.
*/
public enum TellerStatus {
INVALID(0, "tellerStatusType.invalid"),
PENDING(100, "tellerStatusType.pending"),
ACTIVE(300, "tellerStatusType.active"),
INACTIVE(400, "tellerStatusType.inactive"),
CLOSED(600, "tellerStatusType.closed");
private final Integer value;
private final String code;
public static TellerStatus fromInt(final Integer statusValue) {
TellerStatus status = TellerStatus.INVALID;
switch (statusValue) {
case 100:
status = TellerStatus.PENDING;
break;
case 300:
status = TellerStatus.ACTIVE;
break;
case 400:
status = TellerStatus.INACTIVE;
break;
case 600:
status = TellerStatus.CLOSED;
break;
}
return status;
}
private TellerStatus(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final TellerStatus state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isPending() {
return this.value.equals(TellerStatus.PENDING.getValue());
}
public boolean isActive() {
return this.value.equals(TellerStatus.ACTIVE.getValue());
}
public boolean isClosed() {
return this.value.equals(TellerStatus.CLOSED.getValue());
}
public boolean isInactive() {
return this.value.equals(TellerStatus.INACTIVE.getValue());
}
}
@@ -0,0 +1,104 @@
/**
* 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.organisation.teller.domain;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.portfolio.client.domain.Client;
import org.springframework.data.jpa.domain.AbstractPersistable;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "m_teller_transactions")
public class TellerTransaction extends AbstractPersistable<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "office_id", nullable = false)
private Office office;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "teller_id", nullable = false)
private Teller teller;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "cashier_id", nullable = false)
private Cashier cashier;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@Column(name = "type", nullable = false)
private Integer type;
@Column(name = "amount", nullable = false)
private Double amount;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "posting_date", nullable = false)
private Date postingDate;
public TellerTransaction() {
super();
}
public Office getOffice() {
return office;
}
public void setOffice(Office office) {
this.office = office;
}
public Teller getTeller() {
return teller;
}
public void setTeller(Teller teller) {
this.teller = teller;
}
public Cashier getCashier() {
return cashier;
}
public void setCashier(Cashier cashier) {
this.cashier = cashier;
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public Date getPostingDate() {
return postingDate;
}
public void setPostingDate(Date postingDate) {
this.postingDate = postingDate;
}
}
@@ -0,0 +1,20 @@
/**
* 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.organisation.teller.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* Provides the domain repository for accessing, adding, modifying or deleting teller transactions.
*
* @see org.mifosplatform.organisation.teller.domain.TellerTransaction
* @since 2.0.0
*/
public interface TellerTransactionRepository extends JpaRepository<TellerTransaction, Long>,
JpaSpecificationExecutor<TellerTransaction> {
// no added behavior
}
@@ -0,0 +1,29 @@
/**
* 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.organisation.teller.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* Indicates that a cashier could not be found.
*
* @author Markus Geiss
* @since 2.0.0
*/
public class CashierNotFoundException extends AbstractPlatformResourceNotFoundException {
private static final String ERROR_MESSAGE_CODE = "error.msg.cashier.not.found";
private static final String DEFAULT_ERROR_MESSAGE = "Cashier with identifier {0,number,long} not found!";
/**
* Creates a new instance.
*
* @param cashierId the primary key of the cashier
*/
public CashierNotFoundException(Long cashierId) {
super(ERROR_MESSAGE_CODE, DEFAULT_ERROR_MESSAGE, cashierId);
}
}
@@ -0,0 +1,29 @@
/**
* 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.organisation.teller.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* Indicates that a teller could not be found.
*
* @author Markus Geiss
* @since 2.0.0
*/
public class TellerNotFoundException extends AbstractPlatformResourceNotFoundException {
private static final String ERROR_MESSAGE_CODE = "error.msg.teller.not.found";
private static final String DEFAULT_ERROR_MESSAGE = "Teller with identifier {0,number,long} not found!";
/**
* Creates a new instance.
*
* @param tellerId the primary key of the teller
*/
public TellerNotFoundException(Long tellerId) {
super(ERROR_MESSAGE_CODE, DEFAULT_ERROR_MESSAGE, tellerId);
}
}
@@ -0,0 +1,36 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AllocateCashToCashierCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance.
*
* @param writePlatformService the {@code CashierWritePlatformService} used to access the backend
*/
@Autowired
public AllocateCashToCashierCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.allocateCashToCashier(command.subentityId(), command);
}
}
@@ -0,0 +1,37 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AllocateCashierToTellerCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance.
*
* @param writePlatformService the {@code CashierWritePlatformService} used to access the backend
*/
@Autowired
public AllocateCashierToTellerCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.allocateCashierToTeller(
command.entityId(), command);
}
}
@@ -0,0 +1,43 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Handles a create teller command.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.service.TellerWritePlatformService
* @since 2.0.0
*/
@Service
public class CreateTellerCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance
*
* @param writePlatformService the {@code TellerWritePlatformService} used to access the backend
*/
@Autowired
public CreateTellerCommandHandler(final TellerWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.createTeller(command);
}
}
@@ -0,0 +1,28 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerTransactionWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
public class CreateTellerTransactionCommandHandler implements NewCommandSourceHandler {
private final TellerTransactionWritePlatformService writePlatformService;
@Autowired
public CreateTellerTransactionCommandHandler(final TellerTransactionWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.createTellerTransaction(command);
}
}
@@ -0,0 +1,43 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Handles a delete cashier command.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.service.CashierWritePlatformService
* @since 2.0.0
*/
@Service
public class DeleteCashierAllocationCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance.
*
* @param writePlatformService the {@code CashierWritePlatformService} used to access the backend
*/
@Autowired
public DeleteCashierAllocationCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.deleteCashierAllocation(command.entityId(),
command.subentityId(), command);
}
}
@@ -0,0 +1,40 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Handles a delete teller command.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.service.TellerWritePlatformService
* @since 2.0.0
*/
public class DeleteTellerCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance
*
* @param writePlatformService the {@code TellerWritePlatformService} used to access the backend
*/
@Autowired
public DeleteTellerCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.deleteTeller(command.entityId());
}
}
@@ -0,0 +1,41 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.CashierWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Handles a modify cashier command.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.service.CashierWritePlatformService
* @since 2.0.0
*/
public class ModifyCashierCommandHandler implements NewCommandSourceHandler {
private final CashierWritePlatformService writePlatformService;
/**
* Creates a new instance.
*
* @param writePlatformService the {@code CashierWritePlatformService} used to access the backend
*/
@Autowired
public ModifyCashierCommandHandler(final CashierWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.modifyCashier(command.entityId(), command);
}
}
@@ -0,0 +1,36 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SettleCashFromCashierCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance.
*
* @param writePlatformService the {@code CashierWritePlatformService} used to access the backend
*/
@Autowired
public SettleCashFromCashierCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.settleCashFromCashier(command.subentityId(), command);
}
}
@@ -0,0 +1,43 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Handles a delete teller command.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.service.TellerWritePlatformService
* @since 2.0.0
*/
@Service
public class UpdateCashierAllocationCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance
*
* @param writePlatformService the {@code TellerWritePlatformService} used to access the backend
*/
@Autowired
public UpdateCashierAllocationCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.updateCashierAllocation(command.entityId(),
command.subentityId(), command);
}
}
@@ -0,0 +1,42 @@
/**
* 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.organisation.teller.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.organisation.teller.service.TellerWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Handles a delete teller command.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.service.TellerWritePlatformService
* @since 2.0.0
*/
@Service
public class UpdateTellerCommandHandler implements NewCommandSourceHandler {
private final TellerWritePlatformService writePlatformService;
/**
* Creates a new instance
*
* @param writePlatformService the {@code TellerWritePlatformService} used to access the backend
*/
@Autowired
public UpdateTellerCommandHandler(final TellerWritePlatformService writePlatformService) {
super();
this.writePlatformService = writePlatformService;
}
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.modifyTeller(command.entityId(), command);
}
}
@@ -0,0 +1,168 @@
package org.mifosplatform.organisation.teller.serialization;
/**
* 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/.
*/
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Deserializer of JSON for Teller API.
*/
@Component
public final class TellerCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList(
"officeId", "name", "description", "startDate",
"endDate", "status", "dateFormat", "locale",
"isFullDay", "staffId", "startTime", "endTime",
"txnAmount","txnDate", "txnNote", "entityType", "entityId"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public TellerCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForCreate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("teller");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final Long officeId = this.fromApiJsonHelper.extractLongNamed("officeId", element);
baseDataValidator.reset().parameter("officeId").value(officeId).notNull().integerGreaterThanZero();
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(50);
final String description = this.fromApiJsonHelper.extractStringNamed("description", element);
baseDataValidator.reset().parameter("description").value(description).notExceedingLengthOf(100);
final LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed("startDate", element);
baseDataValidator.reset().parameter("startDate").value(startDate).notNull();
final LocalDate endDate = this.fromApiJsonHelper.extractLocalDateNamed("endDate", element);
final String status = this.fromApiJsonHelper.extractStringNamed("status", element);
baseDataValidator.reset().parameter("status").value(status).notBlank().notExceedingLengthOf(50);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("teller");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final String name = this.fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(50);
final String description = this.fromApiJsonHelper.extractStringNamed("description", element);
baseDataValidator.reset().parameter("description").value(description).notBlank().notExceedingLengthOf(100);
final LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed("startDate", element);
baseDataValidator.reset().parameter("startDate").value(startDate).notNull();
final String status = this.fromApiJsonHelper.extractStringNamed("status", element);
baseDataValidator.reset().parameter("status").value(status).notBlank().notExceedingLengthOf(50);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForAllocateCashier (final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("teller");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final Long staffId = this.fromApiJsonHelper.extractLongNamed("staffId", element);
baseDataValidator.reset().parameter("staffId").value(staffId).notNull().integerGreaterThanZero();
final String description = this.fromApiJsonHelper.extractStringNamed("description", element);
baseDataValidator.reset().parameter("description").value(description).notExceedingLengthOf(100);
final LocalDate startDate = this.fromApiJsonHelper.extractLocalDateNamed("startDate", element);
baseDataValidator.reset().parameter("startDate").value(startDate).notNull();
final LocalDate endDate = this.fromApiJsonHelper.extractLocalDateNamed("endDate", element);
baseDataValidator.reset().parameter("endDate").value(endDate).notNull();
final Boolean isFullDay = this.fromApiJsonHelper.extractBooleanNamed("isFullDay", element);
baseDataValidator.reset().parameter("isFullDay").value(isFullDay).notNull();
final String startTime = this.fromApiJsonHelper.extractStringNamed("startTime", element);
final String endTime = this.fromApiJsonHelper.extractStringNamed("endTime", element);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForCashTxnForCashier (final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("teller");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final BigDecimal txnAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("txnAmount", element);
baseDataValidator.reset().parameter("txnAmount").value(txnAmount).notNull();
final LocalDate txnDate = this.fromApiJsonHelper.extractLocalDateNamed("txnDate", element);
baseDataValidator.reset().parameter("txnDate").value(txnDate).notNull();
final String txnNote = this.fromApiJsonHelper.extractStringNamed("txnNote", element);
baseDataValidator.reset().parameter("txnNote").value(txnNote).notExceedingLengthOf(200);
}
}
@@ -0,0 +1,24 @@
package org.mifosplatform.organisation.teller.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public class CashierWritePlatformService {
public CommandProcessingResult allocateCashierToTeller(JsonCommand command) {
// TODO Auto-generated method stub
return null;
}
public CommandProcessingResult deleteCashier(Long entityId) {
// TODO Auto-generated method stub
return null;
}
public CommandProcessingResult modifyCashier(Long entityId,
JsonCommand command) {
// TODO Auto-generated method stub
return null;
}
}
@@ -0,0 +1,58 @@
/**
* 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.organisation.teller.service;
import org.mifosplatform.organisation.teller.data.CashierData;
import org.mifosplatform.organisation.teller.data.CashierTransactionData;
import org.mifosplatform.organisation.teller.data.CashierTransactionsWithSummaryData;
import org.mifosplatform.organisation.teller.data.TellerData;
import org.mifosplatform.organisation.teller.data.TellerJournalData;
import org.mifosplatform.organisation.teller.data.TellerTransactionData;
import java.util.Collection;
import java.util.Date;
public interface TellerManagementReadPlatformService {
public Collection<TellerData> getTellers(Long officeId);
public TellerData findTeller(Long tellerId);
public CashierData findCashier(Long cashierId);
public Collection<CashierData> getCashierData(Long officeId, Long tellerId, Long staffId, Date date);
public Collection<CashierData> getTellerCashiers(Long tellerId, Date date);
public CashierData retrieveCashierTemplate (Long officeId, Long tellerId, boolean staffInSelectedOfficeOnly);
public CashierTransactionData retrieveCashierTxnTemplate(Long cashierId);
public TellerTransactionData findTellerTransaction(Long transactionId);
public Collection<TellerTransactionData> fetchTellerTransactionsByTellerId(Long tellerId, Date fromDate, Date toDate);
public Collection<TellerJournalData> getJournals(Long officeId, Long tellerId, Long cashierId, Date dateFrom, Date dateTo);
public Collection<TellerJournalData> fetchTellerJournals(Long tellerId, Long cashierId, Date fromDate, Date toDate);
public Collection<TellerData> retrieveAllTellersForDropdown(Long officeId);
public Collection<TellerData> retrieveAllTellers(String sqlSearch, Long officeId, String status);
public Collection<CashierData> getCashiersForTeller(Long tellerId, Date fromDate, Date toDate);
public Collection<CashierData> retrieveCashiersForTellers(String sqlSearch,
Long tellerId);
public Collection<CashierTransactionData> retrieveCashierTransactions(
Long cashierId, boolean includeAllTellers, Date fromDate,
Date toDate);
public CashierTransactionsWithSummaryData retrieveCashierTransactionsWithSummary (
Long cashierId, boolean includeAllTellers, Date fromDate, Date toDate);
}
@@ -0,0 +1,779 @@
/**
* 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.organisation.teller.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.organisation.staff.exception.StaffNotFoundException;
import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
import org.mifosplatform.organisation.teller.data.CashierData;
import org.mifosplatform.organisation.teller.data.CashierTransactionData;
import org.mifosplatform.organisation.teller.data.CashierTransactionTypeTotalsData;
import org.mifosplatform.organisation.teller.data.CashierTransactionsWithSummaryData;
import org.mifosplatform.organisation.teller.data.TellerData;
import org.mifosplatform.organisation.teller.data.TellerJournalData;
import org.mifosplatform.organisation.teller.data.TellerTransactionData;
import org.mifosplatform.organisation.teller.domain.CashierTxnType;
import org.mifosplatform.organisation.teller.domain.TellerStatus;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
public class TellerManagementReadPlatformServiceImpl implements TellerManagementReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
private final TellerLookupMapper lookupMapper = new TellerLookupMapper();
private final TellerInOfficeHierarchyMapper tellerInOfficeHierarchyMapper = new TellerInOfficeHierarchyMapper();
private final OfficeReadPlatformService officeReadPlatformService;
private final StaffReadPlatformService staffReadPlatformService;
@Autowired
public TellerManagementReadPlatformServiceImpl(final PlatformSecurityContext context,
final RoutingDataSource dataSource,
final OfficeReadPlatformService officeReadPlatformService,
StaffReadPlatformService staffReadPlatformService
) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.officeReadPlatformService = officeReadPlatformService;
this.staffReadPlatformService = staffReadPlatformService;
}
private static final class TellerMapper implements RowMapper<TellerData> {
public String schema() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("t.id as id,t.office_id as office_id, t.name as teller_name, t.description as description, ");
sqlBuilder.append("t.valid_from as start_date, t.valid_to as end_date, t.state as status, o.name as office_name, ");
sqlBuilder.append("t.debit_account_id as debit_account_id, t.credit_account_id as credit_account_id ");
sqlBuilder.append("from m_tellers t ");
sqlBuilder.append("join m_office o on o.id = t.office_id ");
return sqlBuilder.toString();
}
@Override
public TellerData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long officeId = rs.getLong("office_id");
final String tellerName = rs.getString("teller_name");
final String description = rs.getString("description");
final String officeName = rs.getString("office_name");
TellerStatus tellerStatus = null;
final Integer status = rs.getInt("status");
if (status != null) {
tellerStatus = TellerStatus.fromInt(status);
}
final Long debitAccountId = rs.getLong("debit_account_id");
final Long creditAccountId = rs.getLong("credit_account_id");
final LocalDate startDate = JdbcSupport.getLocalDate(rs, "start_date");
final LocalDate endDate = JdbcSupport.getLocalDate(rs, "end_date");
return TellerData.instance(id, officeId, debitAccountId, creditAccountId,
tellerName, description, startDate, endDate, tellerStatus, officeName, null, null);
}
}
private static final class TellerInOfficeHierarchyMapper implements RowMapper<TellerData> {
public String schema() {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("t.id as id,t.office_id as office_id, t.name as teller_name, t.description as description, ");
sqlBuilder.append("t.valid_from as start_date, t.valid_to as end_date, t.state as status, o.name as office_name ");
sqlBuilder.append("t.debit_account_id as debit_account_id, t.credit_account_id as credit_account_id ");
sqlBuilder.append("from m_office o ");
sqlBuilder.append("join m_office ohierarchy on o.hierarchy like concat(ohierarchy.hierarchy, '%') ");
sqlBuilder.append("join m_tellers t on t.office_id = ohierarchy.id and s.is_active=1 ");
sqlBuilder.append("where o.id = ? ");
return sqlBuilder.toString();
}
@Override
public TellerData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String tellerName = rs.getString("teller_name");
final String description = rs.getString("description");
final String officeName = rs.getString("office_name");
final Long officeId = rs.getLong("office_id");
TellerStatus tellerStatus = null;
final Integer status = rs.getInt("status");
if (status != null) {
tellerStatus = TellerStatus.fromInt(status);
}
final Long debitAccountId = rs.getLong("debit_account_id");
final Long creditAccountId = rs.getLong("credit_account_id");
final LocalDate startDate = JdbcSupport.getLocalDate(rs, "start_date");
final LocalDate endDate = JdbcSupport.getLocalDate(rs, "end_date");
return TellerData.instance(id, officeId, debitAccountId, creditAccountId,
tellerName, description, startDate, endDate, tellerStatus, officeName, null, null);
}
}
private static final class TellerLookupMapper implements RowMapper<TellerData> {
private final String schemaSql;
public TellerLookupMapper() {
final StringBuilder sqlBuilder = new StringBuilder(100);
sqlBuilder.append("t.id as id, t.name as teller_name ");
sqlBuilder.append("from m_tellers t ");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public TellerData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final String tellerName = rs.getString("teller_name");
return TellerData.lookup(id, tellerName);
}
}
@Override
public Collection<TellerData> retrieveAllTellersForDropdown(final Long officeId) {
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
final String sql = "select " + this.lookupMapper.schema() + " where s.office_id = ? and s.is_active=1 ";
return this.jdbcTemplate.query(sql, this.lookupMapper, new Object[] { defaultOfficeId });
}
private Long defaultToUsersOfficeIfNull(final Long officeId) {
Long defaultOfficeId = officeId;
if (defaultOfficeId == null) {
defaultOfficeId = this.context.authenticatedUser().getOffice().getId();
}
return defaultOfficeId;
}
@Override
public TellerData findTeller(final Long tellerId) {
try {
final TellerMapper tm = new TellerMapper();
final String sql = "select " + tm.schema() + " where t.id = ?";
return this.jdbcTemplate.queryForObject(sql, tm, new Object[] { tellerId });
} catch (final EmptyResultDataAccessException e) {
throw new StaffNotFoundException(tellerId);
}
}
@Override
public Collection<TellerData> retrieveAllTellers(final String sqlSearch, final Long officeId, final String status) {
final String extraCriteria = getTellerCriteria(sqlSearch, officeId, status);
return retrieveAllTeller(extraCriteria);
}
private Collection<TellerData> retrieveAllTeller(final String extraCriteria) {
final TellerMapper tm = new TellerMapper();
String sql = "select " + tm.schema();
if (StringUtils.isNotBlank(extraCriteria)) {
sql += " where " + extraCriteria;
}
sql = sql + " order by t.teller_name";
return this.jdbcTemplate.query(sql, tm, new Object[] {});
}
private String getTellerCriteria(final String sqlSearch, final Long officeId, final String status) {
final StringBuffer extraCriteria = new StringBuffer(200);
if (sqlSearch != null) {
extraCriteria.append(" and (").append(sqlSearch).append(")");
}
if (officeId != null) {
extraCriteria.append(" and office_id = ").append(officeId).append(" ");
}
// Passing status parameter to get ACTIVE (By Default), INACTIVE or ALL
// (Both active and Inactive) employees
if (status.equalsIgnoreCase("active")) {
extraCriteria.append(" and status = 300 ");
} else if (status.equalsIgnoreCase("inActive")) {
extraCriteria.append(" and status = 0 ");
} else if (status.equalsIgnoreCase("all")) {} else {
throw new UnrecognizedQueryParamException("status", status, new Object[] { "all", "active", "inactive" });
}
if (StringUtils.isNotBlank(extraCriteria.toString())) {
extraCriteria.delete(0, 4);
}
// remove begin four letter including a space from the string.
return extraCriteria.toString();
}
@Override
public Collection<TellerData> getTellers(Long officeId) {
return retrieveAllTellers (false);
}
@Override
public Collection<CashierData> getCashiersForTeller(Long tellerId,
Date fromDate, Date toDate) {
return retrieveCashiersForTellers (null, tellerId);
}
@Override
public Collection<CashierData> retrieveCashiersForTellers(final String sqlSearch, final Long tellerId) {
final String extraCriteria = getTellerCriteria(sqlSearch, tellerId);
return fetchCashiers (extraCriteria);
}
private String getTellerCriteria(final String sqlSearch, final Long tellerId) {
final StringBuffer extraCriteria = new StringBuffer(200);
if (sqlSearch != null) {
extraCriteria.append(" and (").append(sqlSearch).append(")");
}
if (tellerId != null) {
extraCriteria.append(" and teller_id = ").append(tellerId).append(" ");
}
// remove begin four letter including a space from the string.
if (StringUtils.isNotBlank(extraCriteria.toString())) {
extraCriteria.delete(0, 4);
}
return extraCriteria.toString();
}
private Collection<CashierData> fetchCashiers (final String extraCriteria) {
final CashierMapper cm = new CashierMapper();
String sql = "select " + cm.schema();
if (StringUtils.isNotBlank(extraCriteria)) {
sql += " where " + extraCriteria;
}
sql = sql + " order by teller_name";
return this.jdbcTemplate.query(sql, cm, new Object[] {});
}
@Override
public CashierData findCashier(Long cashierId) {
try {
final CashierMapper cm = new CashierMapper();
final String sql = "select " + cm.schema() + " where c.id = ?";
return this.jdbcTemplate.queryForObject(sql, cm, new Object[] { cashierId });
} catch (final EmptyResultDataAccessException e) {
throw new StaffNotFoundException(cashierId);
}
}
@Override
public Collection<CashierData> getCashierData(Long officeId, Long tellerId,
Long staffId, Date date) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<CashierData> getTellerCashiers(Long tellerId, Date date) {
// TODO Auto-generated method stub
return null;
}
@Override
public TellerTransactionData findTellerTransaction(Long transactionId) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<TellerTransactionData> fetchTellerTransactionsByTellerId(
Long tellerId, Date fromDate, Date toDate) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<TellerJournalData> getJournals(Long officeId,
Long tellerId, Long cashierId, Date dateFrom, Date dateTo) {
// TODO Auto-generated method stub
return null;
}
@Override
public Collection<TellerJournalData> fetchTellerJournals(Long tellerId,
Long cashierId, Date fromDate, Date toDate) {
// TODO Auto-generated method stub
return null;
}
@Cacheable(value = "tellers", key = "T(org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil).getTenant().getTenantIdentifier().concat(#root.target.context.authenticatedUser().getOffice().getHierarchy()+'of')")
public Collection<TellerData> retrieveAllTellers(final boolean includeAllTellers) {
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = null;
if (includeAllTellers) {
hierarchySearchString = "." + "%";
} else {
hierarchySearchString = hierarchy + "%";
}
final TellerMapper tm = new TellerMapper();
final String sql = "select " + tm.schema() + "where o.hierarchy like ? order by o.hierarchy";
return this.jdbcTemplate.query(sql, tm, new Object[] { hierarchySearchString });
}
@Override
public CashierData retrieveCashierTemplate(Long officeId, Long tellerId,
boolean staffInSelectedOfficeOnly) {
final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
final OfficeData officeData = this.officeReadPlatformService.retrieveOffice(defaultOfficeId);
String officeName = "";
if (officeData != null) {
officeName = officeData.name();
}
TellerData tellerData = findTeller(tellerId);
String tellerName = "";
if (tellerData != null) {
tellerName = tellerData.getName();
}
final Collection<OfficeData> offices = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
Collection<StaffData> staffOptions = null;
final boolean loanOfficersOnly = false;
if (staffInSelectedOfficeOnly) {
staffOptions = this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
} else {
staffOptions = this.staffReadPlatformService.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(defaultOfficeId,
loanOfficersOnly);
}
if (CollectionUtils.isEmpty(staffOptions)) {
staffOptions = null;
}
return CashierData.template(officeId, officeName,
tellerId, tellerName, staffOptions);
}
@Override
public CashierTransactionData retrieveCashierTxnTemplate(Long cashierId) {
String officeName = "";
String tellerName = "";
String cashierName = "";
Long officeId = null;
Long tellerId = null;
Date startDate = null;
Date endDate = null ;
CashierData cashierData = findCashier(cashierId);
if (cashierData != null) {
cashierName = cashierData.getStaffName();
tellerId = cashierData.getTellerId();
if (tellerId != null) {
TellerData tellerData = findTeller(tellerId);
if (tellerData != null) {
tellerName = tellerData.getName();
officeName = tellerData.getOfficeName();
}
}
startDate = cashierData.getStartDate();
endDate = cashierData.getEndDate();
}
return CashierTransactionData.template(cashierId, tellerId, tellerName, officeId,
officeName, cashierName, cashierData, startDate, endDate);
}
@Override
public CashierTransactionsWithSummaryData retrieveCashierTransactionsWithSummary (
final Long cashierId, final boolean includeAllTellers,
final Date fromDate, final Date toDate) {
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = null;
if (includeAllTellers) {
hierarchySearchString = "." + "%";
} else {
hierarchySearchString = hierarchy + "%";
}
final CashierTransactionSummaryMapper ctsm =
new CashierTransactionSummaryMapper();
final String sql = "select " + ctsm.cashierTxnSummarySchema() + " limit 1000";
Collection<CashierTransactionTypeTotalsData> cashierTxnTypeTotals =
this.jdbcTemplate.query(sql, ctsm, new Object[] {
cashierId, hierarchySearchString,
cashierId, hierarchySearchString,
cashierId, hierarchySearchString });
Iterator<CashierTransactionTypeTotalsData> itr = cashierTxnTypeTotals.iterator();
BigDecimal allocAmount = new BigDecimal (0);
BigDecimal cashInAmount = new BigDecimal (0);
BigDecimal cashOutAmount = new BigDecimal (0);
BigDecimal settleAmount = new BigDecimal (0);
while(itr.hasNext()) {
CashierTransactionTypeTotalsData total = itr.next();
if (total != null) {
if ( total.getCashierTxnType() == CashierTxnType.ALLOCATE.getId() ) {
allocAmount = total.getCashTotal();
} else if ( total.getCashierTxnType() == CashierTxnType.SETTLE.getId() ) {
settleAmount = total.getCashTotal();
} else if ( total.getCashierTxnType() == CashierTxnType.INWARD_CASH_TXN.getId() ) {
cashInAmount = total.getCashTotal();
} else if ( total.getCashierTxnType() == CashierTxnType.OUTWARD_CASH_TXN.getId() ) {
cashOutAmount = total.getCashTotal();
}
}
}
final Collection<CashierTransactionData> cashierTransactions =
retrieveCashierTransactions (cashierId, includeAllTellers,
fromDate, toDate);
CashierTransactionData cashierTxnTemplate = retrieveCashierTxnTemplate (cashierId);
CashierTransactionsWithSummaryData txnsWithSummary =
CashierTransactionsWithSummaryData.instance(
cashierTransactions,
allocAmount,
cashInAmount,
cashOutAmount,
settleAmount,
cashierTxnTemplate.getOfficeName(),
cashierTxnTemplate.getTellerId(), cashierTxnTemplate.getTellerName(),
cashierTxnTemplate.getCashierId(), cashierTxnTemplate.getCashierName()
);
return txnsWithSummary;
}
@Override
public Collection<CashierTransactionData> retrieveCashierTransactions (
final Long cashierId, final boolean includeAllTellers,
final Date fromDate, final Date toDate) {
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = null;
if (includeAllTellers) {
hierarchySearchString = "." + "%";
} else {
hierarchySearchString = hierarchy + "%";
}
final CashierTransactionMapper ctm = new CashierTransactionMapper();
final String sql = "select * from (select " +
ctm.cashierTxnSchema() +
" where txn.cashier_id = ? and o.hierarchy like ? ) cashier_txns " +
" union (select " +
ctm.savingsTxnSchema() +
" where sav_txn.is_reversed = 0 and c.id = ? and o.hierarchy like ? and " +
" created_date between c.start_date and date_add(c.end_date, interval 1 day) " +
" and renum.enum_value in ('deposit','withdrawal fee', 'Pay Charge', 'withdrawal') ) " +
" union (select " +
ctm.loansTxnSchema() +
" where loan_txn.is_reversed = 0 and c.id = ? and o.hierarchy like ? and " +
" created_date between c.start_date and date_add(c.end_date, interval 1 day) " +
" and renum.enum_value in ('Repayment At Disbursement','Repayment', 'Recovery Payment','Disbursement') ) " +
" order by created_date ";
return this.jdbcTemplate.query(sql, ctm,
new Object[] { cashierId, hierarchySearchString,
cashierId, hierarchySearchString,
cashierId, hierarchySearchString});
}
private static final class CashierMapper implements RowMapper<CashierData> {
public String schema() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("c.id as id,c.teller_id as teller_id, t.name as teller_name, c.description as description, ");
sqlBuilder.append("c.staff_id as staff_id, s.display_name as staff_name, ");
sqlBuilder.append("c.start_date as start_date, c.end_date as end_date, ");
sqlBuilder.append("c.full_day as full_day, c.start_time as start_time, c.end_time as end_time ");
sqlBuilder.append("from m_cashiers c ");
sqlBuilder.append("join m_tellers t on t.id = c.teller_id ");
sqlBuilder.append("join m_staff s on s.id = c.staff_id ");
return sqlBuilder.toString();
}
@Override
public CashierData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long tellerId = rs.getLong("teller_id");
final String tellerName = rs.getString("teller_name");
final Long staffId = rs.getLong("staff_id");
final String staffName = rs.getString("staff_name");
final String description = rs.getString("description");
final LocalDate startDate = JdbcSupport.getLocalDate(rs, "start_date");
final LocalDate endDate = JdbcSupport.getLocalDate(rs, "end_date");
final Integer fullDayFromDB = rs.getInt ("full_day");
Boolean fullDay = false;
if (fullDayFromDB == 1) {
fullDay = true;
}
final String startTime = rs.getString("start_time");
final String endTime = rs.getString("end_time");
return CashierData.instance(id, null, null,
staffId, staffName, tellerId, tellerName,
description, startDate.toDate(), endDate.toDate(), fullDay, startTime, endTime);
}
}
private static final class CashierTransactionMapper implements RowMapper<CashierTransactionData> {
public String cashierTxnSchema() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append(" txn.id as txn_id, txn.cashier_id as cashier_id, ");
sqlBuilder.append(" txn.txn_type as txn_type, ");
sqlBuilder.append(" txn.txn_amount as txn_amount, txn.txn_date as txn_date, txn.txn_note as txn_note, ");
sqlBuilder.append(" txn.entity_type as entity_type, txn.entity_id as entity_id, txn.created_date as created_date, ");
sqlBuilder.append(" o.id as office_id, o.name as office_name, t.id as teller_id, t.name as teller_name, s.display_name as cashier_name ");
sqlBuilder.append(" from m_cashier_transactions txn ");
sqlBuilder.append(" left join m_cashiers c on c.id = txn.cashier_id ");
sqlBuilder.append(" left join m_tellers t on t.id = c.teller_id ");
sqlBuilder.append(" left join m_office o on o.id = t.office_id ");
sqlBuilder.append(" left join m_staff s on s.id = c.staff_id ");
return sqlBuilder.toString();
}
public String savingsTxnSchema() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append(" sav_txn.id as txn_id, null as cashier_id, ");
sqlBuilder.append(" case ");
sqlBuilder.append(" when renum.enum_value in ('deposit','withdrawal fee', 'Pay Charge') ");
sqlBuilder.append(" then 103 ");
sqlBuilder.append(" when renum.enum_value in ('withdrawal', '') ");
sqlBuilder.append(" then 104 ");
sqlBuilder.append(" else ");
sqlBuilder.append(" 105 ");
sqlBuilder.append(" end as txn_type, ");
sqlBuilder.append(" sav_txn.amount as txn_amount, sav_txn.transaction_date as txn_date, ");
sqlBuilder.append(" concat (renum.enum_value, ', Sav:', sav.id, '-', sav.account_no, ',Client:', cl.id, '-',cl.display_name) as txn_note, ");
sqlBuilder.append(" 'savings' as entity_type, sav.id as entity_id, sav_txn.created_date as created_date, ");
sqlBuilder.append(" o.id as office_id, o.name as office_name, null as teller_id, null as teller_name, staff.display_name as cashier_name ");
sqlBuilder.append(" from m_savings_account_transaction sav_txn ");
sqlBuilder.append(" left join r_enum_value renum on sav_txn.transaction_type_enum = renum.enum_id and renum.enum_name = 'savings_transaction_type_enum' ");
sqlBuilder.append(" left join m_savings_account sav on sav_txn.savings_account_id = sav.id ");
sqlBuilder.append(" left join m_client cl on sav.client_id = cl.id ");
sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
sqlBuilder.append(" left join m_appuser user on sav_txn.appuser_id = user.id ");
sqlBuilder.append(" left join m_staff staff on user.staff_id = staff.id ");
sqlBuilder.append(" left join m_cashiers c on c.staff_id = staff.id ");
return sqlBuilder.toString();
}
public String loansTxnSchema() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append(" loan_txn.id as txn_id, c.id as cashier_id, ");
sqlBuilder.append(" case ");
sqlBuilder.append(" when renum.enum_value in ('Repayment At Disbursement','Repayment', 'Recovery Payment') ");
sqlBuilder.append(" then 103 ");
sqlBuilder.append(" when renum.enum_value in ('Disbursement') ");
sqlBuilder.append(" then 104 ");
sqlBuilder.append(" else ");
sqlBuilder.append(" 105 ");
sqlBuilder.append(" end as cash_txn_type, ");
sqlBuilder.append(" loan_txn.amount as txn_amount, loan_txn.transaction_date as txn_date, ");
sqlBuilder.append(" concat (renum.enum_value, ', Loan:', loan.id, '-', loan.account_no, ',Client:', cl.id, '-',cl.display_name) as txn_note, ");
sqlBuilder.append(" 'loans' as entity_type, loan.id as entity_id, loan_txn.created_date as created_date, ");
sqlBuilder.append(" o.id as office_id, o.name as office_name, null as teller_id, null as teller_name, staff.display_name as cashier_name ");
sqlBuilder.append(" from m_loan_transaction loan_txn ");
sqlBuilder.append(" left join r_enum_value renum on loan_txn.transaction_type_enum = renum.enum_id and renum.enum_name = 'transaction_type_enum' ");
sqlBuilder.append(" left join m_loan loan on loan_txn.loan_id = loan.id ");
sqlBuilder.append(" left join m_client cl on loan.client_id = cl.id ");
sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
sqlBuilder.append(" left join m_appuser user on loan_txn.appuser_id = user.id ");
sqlBuilder.append(" left join m_staff staff on user.staff_id = staff.id ");
sqlBuilder.append(" left join m_cashiers c on c.staff_id = staff.id ");
return sqlBuilder.toString();
}
@Override
public CashierTransactionData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("txn_id");
final Long cashierId = rs.getLong("cashier_id");
final Integer tType = rs.getInt("txn_type");
final CashierTxnType txnType = CashierTxnType.getCashierTxnType(tType);
final BigDecimal txnAmount = rs.getBigDecimal("txn_amount");
final LocalDate txnLocalDate = JdbcSupport.getLocalDate(rs, "txn_date");
final String txnNote = rs.getString("txn_note");
final String entityType = rs.getString("entity_type");
final Long entityId = rs.getLong("entity_id");
final LocalDate createdLocalDate = JdbcSupport.getLocalDate(rs, "created_date");
Date txnDate = null;
if (txnLocalDate != null) {
txnDate = txnLocalDate.toDate();
}
Date createdDate = null;
if (createdLocalDate != null) {
createdDate = createdLocalDate.toDate();
}
final Long officeId = rs.getLong("office_id");
final String officeName = rs.getString("office_name");
final Long tellerId = rs.getLong("teller_id");
final String tellerName = rs.getString("teller_name");
final String cashierName = rs.getString("cashier_name");
return CashierTransactionData.instance(
id, cashierId, txnType, txnAmount, txnDate, txnNote,
entityType, entityId, createdDate, officeId, officeName,
tellerId, tellerName, cashierName, null, null, null);
}
}
private static final class CashierTransactionSummaryMapper implements RowMapper<CashierTransactionTypeTotalsData> {
public String cashierTxnSummarySchema() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append(" cash_txn_type, sum(txn_amount) as txn_total from ");
sqlBuilder.append(" (select * from ");
sqlBuilder.append(" (select txn.id as txn_id, txn.cashier_id as cashier_id, ");
sqlBuilder.append(" txn.txn_type as cash_txn_type, ");
sqlBuilder.append(" txn.txn_amount as txn_amount, txn.txn_date as txn_date, txn.txn_note as txn_note, ");
sqlBuilder.append(" txn.entity_type as entity_type, txn.entity_id as entity_id, txn.created_date as created_date, ");
sqlBuilder.append(" o.id as office_id, o.name as office_name, t.id as teller_id, t.name as teller_name, s.display_name as cashier_name ");
sqlBuilder.append(" from m_cashier_transactions txn ");
sqlBuilder.append(" left join m_cashiers c on c.id = txn.cashier_id ");
sqlBuilder.append(" left join m_tellers t on t.id = c.teller_id ");
sqlBuilder.append(" left join m_office o on o.id = t.office_id ");
sqlBuilder.append(" left join m_staff s on s.id = c.staff_id ");
sqlBuilder.append(" where txn.cashier_id = ? ");
sqlBuilder.append(" and o.hierarchy like ? ) cashier_txns ");
sqlBuilder.append(" UNION ");
sqlBuilder.append(" (select sav_txn.id as txn_id, c.id as cashier_id, ");
sqlBuilder.append(" case ");
sqlBuilder.append(" when renum.enum_value in ('deposit','withdrawal fee', 'Pay Charge') ");
sqlBuilder.append(" then 103 ");
sqlBuilder.append(" when renum.enum_value in ('withdrawal') ");
sqlBuilder.append(" then 104 ");
sqlBuilder.append(" else ");
sqlBuilder.append(" 105 ");
sqlBuilder.append(" end as cash_txn_type, ");
sqlBuilder.append(" sav_txn.amount as txn_amount, sav_txn.transaction_date as txn_date, ");
sqlBuilder.append(" concat (renum.enum_value, ', Sav:', sav.id, '-', sav.account_no, ',Client:', cl.id, '-',cl.display_name) as txn_note, ");
sqlBuilder.append(" 'savings' as entity_type, sav.id as entity_id, sav_txn.created_date as created_date, ");
sqlBuilder.append(" o.id as office_id, o.name as office_name, null as teller_id, null as teller_name, staff.display_name as cashier_name ");
sqlBuilder.append(" from m_savings_account_transaction sav_txn ");
sqlBuilder.append(" left join r_enum_value renum on sav_txn.transaction_type_enum = renum.enum_id and renum.enum_name = 'savings_transaction_type_enum' ");
sqlBuilder.append(" left join m_savings_account sav on sav_txn.savings_account_id = sav.id ");
sqlBuilder.append(" left join m_client cl on sav.client_id = cl.id ");
sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
sqlBuilder.append(" left join m_appuser user on sav_txn.appuser_id = user.id ");
sqlBuilder.append(" left join m_staff staff on user.staff_id = staff.id ");
sqlBuilder.append(" left join m_cashiers c on c.staff_id = staff.id ");
sqlBuilder.append(" where sav_txn.is_reversed = 0 and c.id = ? ");
sqlBuilder.append(" and o.hierarchy like ? and ");
sqlBuilder.append(" created_date between c.start_date and date_add(c.end_date, interval 1 day) ");
sqlBuilder.append(" ) ");
sqlBuilder.append(" UNION ");
sqlBuilder.append(" ( ");
sqlBuilder.append(" select loan_txn.id as txn_id, c.id as cashier_id, ");
sqlBuilder.append(" case ");
sqlBuilder.append(" when renum.enum_value in ('Repayment At Disbursement','Repayment', 'Recovery Payment') ");
sqlBuilder.append(" then 103 ");
sqlBuilder.append(" when renum.enum_value in ('Disbursement') ");
sqlBuilder.append(" then 104 ");
sqlBuilder.append(" else ");
sqlBuilder.append(" 105 ");
sqlBuilder.append(" end as cash_txn_type, ");
sqlBuilder.append(" loan_txn.amount as txn_amount, loan_txn.transaction_date as txn_date, ");
sqlBuilder.append(" concat (renum.enum_value, ', Loan:', loan.id, '-', loan.account_no, ',Client:', cl.id, '-',cl.display_name) as txn_note, ");
sqlBuilder.append(" 'loans' as entity_type, loan.id as entity_id, loan_txn.created_date as created_date, ");
sqlBuilder.append(" o.id as office_id, o.name as office_name, null as teller_id, null as teller_name, staff.display_name as cashier_name ");
sqlBuilder.append(" from m_loan_transaction loan_txn ");
sqlBuilder.append(" left join r_enum_value renum on loan_txn.transaction_type_enum = renum.enum_id and renum.enum_name = 'transaction_type_enum' ");
sqlBuilder.append(" left join m_loan loan on loan_txn.loan_id = loan.id ");
sqlBuilder.append(" left join m_client cl on loan.client_id = cl.id ");
sqlBuilder.append(" left join m_office o on cl.office_id = o.id ");
sqlBuilder.append(" left join m_appuser user on loan_txn.appuser_id = user.id ");
sqlBuilder.append(" left join m_staff staff on user.staff_id = staff.id ");
sqlBuilder.append(" left join m_cashiers c on c.staff_id = staff.id ");
sqlBuilder.append(" where loan_txn.is_reversed = 0 and c.id = ? ");
sqlBuilder.append(" and o.hierarchy like ? ");
sqlBuilder.append(" and created_date between c.start_date and date_add(c.end_date, interval 1 day) ");
sqlBuilder.append(" ) ");
sqlBuilder.append(" ) txns ");
sqlBuilder.append(" group by cash_txn_type ");
return sqlBuilder.toString();
}
@Override
public CashierTransactionTypeTotalsData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Integer cashierTxnType = rs.getInt("cash_txn_type");
final BigDecimal txnTotal = rs.getBigDecimal("txn_total");
return CashierTransactionTypeTotalsData.instance(
cashierTxnType, txnTotal);
}
}
}
@@ -0,0 +1,26 @@
/**
* 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.organisation.teller.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
/**
* Provides the local service for adding teller transactions.
*
* @see org.mifosplatform.organisation.teller.domain.TellerTransactionRepository
* @since 2.0.0
*/
public interface TellerTransactionWritePlatformService {
/**
* Stores teller transactions into the data base.
*
* @param command the command containing the teller transaction details
* @return the result i
*/
public CommandProcessingResult createTellerTransaction(JsonCommand command);
}
@@ -0,0 +1,76 @@
/**
* 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.organisation.teller.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.useradministration.domain.AppUser;
/**
* Provides the local service for adding, modifying and deleting tellers.
*
* @author Markus Geiss
* @see org.mifosplatform.organisation.teller.domain.TellerRepository
* @since 2.0.0
*/
public interface TellerWritePlatformService {
/**
* Creates a new teller.
*
* @param command the command to create a new teller
* @return {@code CommandProcessingResult} if successful
* @throws org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException
* @throws org.mifosplatform.infrastructure.core.exception.InvalidJsonException
*/
public CommandProcessingResult createTeller(JsonCommand command);
/**
* Modifies a new teller.
*
* @param tellerId the primary key of the teller
* @param command the command to modifya new teller
* @return {@code CommandProcessingResult} if successful
* @throws org.mifosplatform.organisation.teller.exception.TellerNotFoundException
* @throws org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException
* @throws org.mifosplatform.infrastructure.core.exception.InvalidJsonException
*/
public CommandProcessingResult modifyTeller(Long tellerId, JsonCommand command);
/**
* deletes a new teller.
*
* @param tellerId the primary key of the teller
* @return {@code CommandProcessingResult} if successful
* @throws org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException
* @throws org.mifosplatform.infrastructure.core.exception.InvalidJsonException
*/
public CommandProcessingResult deleteTeller(Long tellerId);
/**
* Allocates a cashier to an existing teller. The allocation can be for a duration
* from a date to a date
* from a certain start time to an end time.
*
* @param command the command to allocate a cashier for a specific teller
* @return {@code CommandProcessingResult} if successful
* @throws org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException
* @throws org.mifosplatform.infrastructure.core.exception.InvalidJsonException
*/
public CommandProcessingResult allocateCashierToTeller(Long tellerId, JsonCommand command);
CommandProcessingResult updateCashierAllocation(Long tellerId, Long cashierId,
JsonCommand command);
CommandProcessingResult deleteCashierAllocation(final Long tellerId, Long cashierId,
JsonCommand command);
CommandProcessingResult allocateCashToCashier(Long cashierId,
JsonCommand command);
CommandProcessingResult settleCashFromCashier(Long cashierId,
JsonCommand command);
}
@@ -0,0 +1,345 @@
package org.mifosplatform.organisation.teller.service;
import java.util.Map;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepository;
import org.mifosplatform.organisation.staff.exception.StaffNotFoundException;
import org.mifosplatform.organisation.teller.domain.Cashier;
import org.mifosplatform.organisation.teller.domain.CashierRepository;
import org.mifosplatform.organisation.teller.domain.CashierTransaction;
import org.mifosplatform.organisation.teller.domain.CashierTransactionRepository;
import org.mifosplatform.organisation.teller.domain.CashierTxnType;
import org.mifosplatform.organisation.teller.domain.Teller;
import org.mifosplatform.organisation.teller.domain.TellerRepository;
import org.mifosplatform.organisation.teller.exception.CashierNotFoundException;
import org.mifosplatform.organisation.teller.exception.TellerNotFoundException;
import org.mifosplatform.organisation.teller.serialization.TellerCommandFromApiJsonDeserializer;
import org.mifosplatform.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TellerWritePlatformServiceJpaImpl implements TellerWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(TellerWritePlatformServiceJpaImpl.class);
private final PlatformSecurityContext context;
private final TellerCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final TellerRepository tellerRepository;
private final OfficeRepository officeRepository;
private final StaffRepository staffRepository;
private final CashierRepository cashierRepository;
private final CashierTransactionRepository cashierTxnRepository;
@Autowired
public TellerWritePlatformServiceJpaImpl (final PlatformSecurityContext context,
final TellerCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final TellerRepository tellerRepository, final OfficeRepository officeRepository,
final StaffRepository staffRepository, CashierRepository cashierRepository,
CashierTransactionRepository cashierTxnRepository) {
this.context = context;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.tellerRepository = tellerRepository;
this.officeRepository = officeRepository;
this.staffRepository = staffRepository;
this.cashierRepository = cashierRepository;
this.cashierTxnRepository = cashierTxnRepository;
}
@Override
@Transactional
public CommandProcessingResult createTeller(JsonCommand command) {
try {
final AppUser currentUser = this.context.authenticatedUser();
final Long officeId = command.longValueOfParameterNamed("officeId");
this.fromApiJsonDeserializer.validateForCreate(command.json());
// final Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, officeId);
final Office tellerOffice = this.officeRepository.findOne(officeId);
if (tellerOffice == null) { throw new OfficeNotFoundException(officeId); }
final Teller teller = Teller.fromJson(tellerOffice, command);
// pre save to generate id for use in office hierarchy
this.tellerRepository.save(teller);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(teller.getId()) //
.withOfficeId(teller.getOffice().getId()) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleTellerDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
@Override
@Transactional
public CommandProcessingResult modifyTeller(Long tellerId,
JsonCommand command) {
try {
final Long officeId = command.longValueOfParameterNamed("officeId");
final Office tellerOffice = this.officeRepository.findOne(officeId);
if (tellerOffice == null) { throw new OfficeNotFoundException(officeId); }
final AppUser currentUser = this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForUpdate(command.json());
final Teller teller = validateUserPriviledgeOnTellerAndRetrieve(currentUser, tellerId);
final Map<String, Object> changes = teller.update(tellerOffice, command);
if (!changes.isEmpty()) {
this.tellerRepository.saveAndFlush(teller);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(teller.getId()) //
.withOfficeId(teller.officeId()) //
.with(changes) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleTellerDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
/*
* used to restrict modifying operations to office that are either the users
* office or lower (child) in the office hierarchy
*/
private Teller validateUserPriviledgeOnTellerAndRetrieve(final AppUser currentUser, final Long tellerId) {
final Long userOfficeId = currentUser.getOffice().getId();
final Office userOffice = this.officeRepository.findOne(userOfficeId);
if (userOffice == null) { throw new OfficeNotFoundException(userOfficeId); }
final Teller tellerToReturn = this.tellerRepository.findOne(tellerId);
if (tellerToReturn != null) {
final Long tellerOfficeId = tellerToReturn.officeId();
if (userOffice.doesNotHaveAnOfficeInHierarchyWithId(tellerOfficeId)) { throw new NoAuthorizationException(
"User does not have sufficient priviledges to act on the provided office."); }
} else {
throw new TellerNotFoundException(tellerId);
}
return tellerToReturn;
}
@Override
@Transactional
public CommandProcessingResult deleteTeller(Long tellerId) {
// TODO Auto-generated method stub
return null;
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue
* is.
*/
private void handleTellerDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("m_tellers_name_unq")) {
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.teller.duplicate.name", "Teller with name `" + name + "` already exists",
"name", name);
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.teller.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
@Override
public CommandProcessingResult allocateCashierToTeller(final Long tellerId, JsonCommand command) {
try {
final AppUser currentUser = this.context.authenticatedUser();
// final Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, officeId);
final Teller teller = this.tellerRepository.findOne(tellerId);
if (teller == null) { throw new TellerNotFoundException(tellerId); }
final Office tellerOffice = teller.getOffice();
final Long staffId = command.longValueOfParameterNamed("staffId");
this.fromApiJsonDeserializer.validateForAllocateCashier(command.json());
final Staff staff = this.staffRepository.findOne(staffId);
if (staff == null) { throw new StaffNotFoundException(staffId); }
final Cashier cashier = Cashier.fromJson(tellerOffice, teller, staff,
command);
// pre save to generate id for use in office hierarchy
this.cashierRepository.save(cashier);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(teller.getId()) //
.withSubEntityId(cashier.getId()) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleTellerDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
@Override
@Transactional
public CommandProcessingResult updateCashierAllocation (Long tellerId, Long cashierId,
JsonCommand command) {
try {
final AppUser currentUser = this.context.authenticatedUser();
this.fromApiJsonDeserializer.validateForAllocateCashier(command.json());
final Long staffId = command.longValueOfParameterNamed("staffId");
final Staff staff = this.staffRepository.findOne(staffId);
if (staff == null) { throw new StaffNotFoundException(staffId); }
final Cashier cashier = validateUserPriviledgeOnCashierAndRetrieve(currentUser, tellerId, cashierId);
cashier.setStaff(staff);
//TODO - check if staff office and teller office match
final Map<String, Object> changes = cashier.update(command);
if (!changes.isEmpty()) {
this.cashierRepository.saveAndFlush(cashier);
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(cashier.getTeller().getId()) //
.withSubEntityId(cashier.getId()) //
.with(changes) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleTellerDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
private Cashier validateUserPriviledgeOnCashierAndRetrieve(final AppUser currentUser,
final Long tellerId, final Long cashierId) {
validateUserPriviledgeOnTellerAndRetrieve(currentUser, tellerId);
final Cashier cashierToReturn = this.cashierRepository.findOne(cashierId);
return cashierToReturn;
}
@Override
@Transactional
public CommandProcessingResult deleteCashierAllocation (Long tellerId, Long cashierId,
JsonCommand command) {
try {
final AppUser currentUser = this.context.authenticatedUser();
final Cashier cashier = validateUserPriviledgeOnCashierAndRetrieve(currentUser, tellerId, cashierId);
this.cashierRepository.delete(cashier);
} catch (final DataIntegrityViolationException dve) {
handleTellerDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
return new CommandProcessingResultBuilder() //
.withEntityId(cashierId) //
.build();
}
/*
@Override
public CommandProcessingResult inwardCashToCashier (final Long cashierId,
final CashierTransaction cashierTxn) {
CashierTxnType txnType = CashierTxnType.INWARD_CASH_TXN;
// pre save to generate id for use in office hierarchy
this.cashierTxnRepository.save(cashierTxn);
} */
@Override
public CommandProcessingResult allocateCashToCashier(final Long cashierId, JsonCommand command) {
return doTransactionForCashier(cashierId, CashierTxnType.ALLOCATE, command); // For fund allocation to cashier
}
@Override
public CommandProcessingResult settleCashFromCashier(final Long cashierId, JsonCommand command) {
return doTransactionForCashier(cashierId, CashierTxnType.SETTLE, command); // For fund settlement from cashier
}
private CommandProcessingResult doTransactionForCashier(final Long cashierId,
final CashierTxnType txnType, JsonCommand command) {
try {
final AppUser currentUser = this.context.authenticatedUser();
final Cashier cashier = this.cashierRepository.findOne(cashierId);
if (cashier == null) { throw new CashierNotFoundException(cashierId); }
this.fromApiJsonDeserializer.validateForCashTxnForCashier(command.json());
final String entityType = command.stringValueOfParameterNamed("entityType");
final Long entityId = command.longValueOfParameterNamed("entityId");
if (entityType != null) {
if (entityType.equals("loan account")) {
// TODO : Check if loan account exists
// LoanAccount loan = null;
// if (loan == null) { throw new LoanAccountFoundException(entityId); }
} else if (entityType.equals("savings account")) {
// TODO : Check if loan account exists
// SavingsAccount savingsaccount = null;
// if (savingsaccount == null) { throw new SavingsAccountNotFoundException(entityId); }
} if (entityType.equals("client")) {
// TODO: Check if client exists
// Client client = null;
// if (client == null) { throw new ClientNotFoundException(entityId); }
} else {
// TODO : Invalid type handling
}
}
final CashierTransaction cashierTxn = CashierTransaction.fromJson(cashier, command);
cashierTxn.setTxnType(txnType.getId());
// pre save to generate id for use in office hierarchy
this.cashierTxnRepository.save(cashierTxn);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(cashier.getId()) //
.withSubEntityId(cashierTxn.getId()) //
.build();
} catch (final DataIntegrityViolationException dve) {
handleTellerDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
}
}
@@ -0,0 +1,80 @@
package org.mifosplatform.organisation.teller.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.StringTokenizer;
public class DateRange {
private static final String ISO_8601_DATE_PATTERN = "yyy-MM-dd";
private static final String RANGE_DELIMITER = "..";
private Date startDate;
private Date endDate;
public DateRange() {
super();
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public static DateRange fromString(final String dateToParse) {
final DateRange dateRange = new DateRange();
final SimpleDateFormat sdf = new SimpleDateFormat(DateRange.ISO_8601_DATE_PATTERN);
final Calendar cal = Calendar.getInstance();
final String testee;
if (dateToParse == null) {
testee = sdf.format(cal.getTime());
} else {
testee = dateToParse;
}
final StringTokenizer tokenizer = new StringTokenizer(testee, DateRange.RANGE_DELIMITER);
try {
cal.setTime(sdf.parse(tokenizer.nextToken()));
} catch (ParseException ex) {
}
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
dateRange.setStartDate(cal.getTime());
if (tokenizer.hasMoreTokens()) {
try {
cal.setTime(sdf.parse(tokenizer.nextToken()));
} catch (ParseException ex) {
}
}
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
dateRange.setEndDate(cal.getTime());
return dateRange;
}
}
@@ -0,0 +1,107 @@
CREATE TABLE `m_tellers` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`office_id` BIGINT(20) NOT NULL,
`debit_account_id` BIGINT(20),
`credit_account_id` BIGINT(20),
`name` VARCHAR(50) NOT NULL,
`description` VARCHAR(100),
`valid_from` DATE,
`valid_to` DATE,
`state` SMALLINT(5),
PRIMARY KEY (`id`),
UNIQUE INDEX `m_tellers_name_unq` (`name`),
INDEX `IK_m_tellers_m_office` (`office_id`),
CONSTRAINT `FK_m_tellers_m_office` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`),
CONSTRAINT `FK_m_tellers_gl_account_debit_account_id` FOREIGN KEY (`debit_account_id`) REFERENCES `acc_gl_account` (`id`),
CONSTRAINT `FK_m_tellers_gl_account_credit_account_id` FOREIGN KEY (`credit_account_id`) REFERENCES `acc_gl_account` (`id`)
);
CREATE TABLE `m_cashiers` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`staff_id` BIGINT(20),
`teller_id` BIGINT(20),
`description` VARCHAR(100),
`start_date` DATE,
`end_date` DATE,
`start_time` varchar(10),
`end_time` varchar(10),
`full_day` TINYINT,
PRIMARY KEY (`id`),
INDEX `IK_m_cashiers_m_staff` (`staff_id`),
INDEX `IK_m_cashiers_m_teller` (`teller_id`),
CONSTRAINT `FK_m_cashiers_m_staff` FOREIGN KEY (`staff_id`) REFERENCES `m_staff` (`id`),
CONSTRAINT `FK_m_cashiers_m_teller` FOREIGN KEY (`teller_id`) REFERENCES `m_tellers` (`id`)
);
CREATE TABLE `m_cashier_transactions` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`cashier_id` BIGINT(20) NOT NULL,
`txn_type` SMALLINT(5) NOT NULL,
`txn_amount` DECIMAL (19,6) NOT NULL,
`txn_date` DATE NOT NULL,
`created_date` DATETIME NOT NULL,
`entity_type` VARCHAR(50),
`entity_id` BIGINT(20),
`txn_note` VARCHAR(200),
PRIMARY KEY (`id`),
INDEX `IK_m_teller_transactions_m_cashier` (`cashier_id`),
CONSTRAINT `FK_m_teller_transactions_m_cashiers` FOREIGN KEY (`cashier_id`) REFERENCES `m_cashiers` (`id`)
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'CREATE_TELLER', 'TELLER', 'CREATE', 1
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'UPDATE_TELLER', 'TELLER', 'CREATE', 1
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'ALLOCATECASHIER_TELLER', 'TELLER', 'ALLOCATE', 1
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'UPDATECASHIERALLOCATION_TELLER', 'TELLER', 'UPDATECASHIERALLOCATION', 1
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'DELETECASHIERALLOCATION_TELLER', 'TELLER', 'DELETECASHIERALLOCATION', 1
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'ALLOCATECASHTOCASHIER_TELLER', 'TELLER', 'ALLOCATECASHTOCASHIER', 1
);
INSERT INTO m_permission (
grouping, code, entity_name, action_name, can_maker_checker
) values (
'cash_mgmt', 'SETTLECASHFROMCASHIER_TELLER', 'TELLER', 'SETTLECASHFROMCASHIER', 1
);
INSERT INTO r_enum_value (
enum_name, enum_id, enum_message_property, enum_value, enum_type
) values (
'teller_status', 300, 'Active', 'Active',0
);
INSERT INTO r_enum_value (
enum_name, enum_id, enum_message_property, enum_value, enum_type
) values (
'teller_status', 400, 'Inactive', 'Inactive',0
);
INSERT INTO r_enum_value (
enum_name, enum_id, enum_message_property, enum_value, enum_type
) values (
'teller_status', 600, 'Closed', 'Closed',0
);