merging ashoks changes for group closure

This commit is contained in:
Vishwas Babu A J
2013-09-06 17:27:08 +05:30
28 changed files with 467 additions and 36 deletions
@@ -0,0 +1,8 @@
INSERT INTO `m_code` (`code_name`, `is_system_defined`) VALUES ('GroupClosureReason', 1);
ALTER TABLE `m_group` ADD COLUMN `closure_reason_cv_id` INT(11) NULL DEFAULT NULL,
ADD COLUMN `closedon_date` DATE NULL DEFAULT NULL,
ADD CONSTRAINT `FK_m_group_m_code` FOREIGN KEY (`closure_reason_cv_id`) REFERENCES `m_code_value` (`id`);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`) VALUES ('portfolio', 'CLOSE_GROUP', 'GROUP', 'CLOSE');
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`) VALUES ('portfolio', 'CLOSE_CENTER', 'CENTER', 'CLOSE');
@@ -288,11 +288,19 @@ public class CommandWrapper {
public boolean isGroupActivation() {
return this.actionName.equalsIgnoreCase("ACTIVATE") && this.entityName.equalsIgnoreCase("GROUP");
}
public boolean isGroupClose() {
return this.actionName.equalsIgnoreCase("CLOSE") && this.entityName.equalsIgnoreCase("GROUP");
}
public boolean isCenterActivation() {
return this.actionName.equalsIgnoreCase("ACTIVATE") && this.entityName.equalsIgnoreCase("CENTER");
}
public boolean isCenterClose() {
return this.actionName.equalsIgnoreCase("CLOSE") && this.entityName.equalsIgnoreCase("CENTER");
}
public boolean isClientIdentifierResource() {
return this.entityName.equals("CLIENTIDENTIFIER");
}
@@ -1076,7 +1076,16 @@ public class CommandWrapperBuilder {
this.href = "/groups/" + groupId + "?command=assignStaff";
return this;
}
public CommandWrapperBuilder closeGroup(final Long groupId) {
this.actionName = "CLOSE";
this.entityName = "GROUP";
this.entityId = groupId;
this.groupId = groupId;
this.href = "/groups/" + groupId + "?command=close";
return this;
}
public CommandWrapperBuilder createCollateral(final Long loanId) {
this.actionName = "CREATE";
this.entityName = "COLLATERAL";
@@ -1153,6 +1162,15 @@ public class CommandWrapperBuilder {
this.href = "/centers/" + centerId + "?command=saveCollectionSheet";
return this;
}
public CommandWrapperBuilder closeCenter(final Long centerId) {
this.actionName = "CLOSE";
this.entityName = "CENTER";
this.entityId = centerId;
this.groupId = centerId;
this.href = "/centers/" + centerId + "?command=close";
return this;
}
public CommandWrapperBuilder createAccountingRule() {
this.actionName = "CREATE";
@@ -464,6 +464,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = this.applicationContext.getBean("assignGroupStaffCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isTransferClientsBetweenGroups()) {
handler = this.applicationContext.getBean("transferClientsBetweenGroupsCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isGroupClose()) {
handler = this.applicationContext.getBean("closeGroupCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
@@ -478,6 +480,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = this.applicationContext.getBean("activateCenterCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSaveCenterCollectionSheet()) {
handler = this.applicationContext.getBean("saveCenterCollectionSheetCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isCenterClose()) {
handler = this.applicationContext.getBean("closeCenterCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
@@ -28,6 +28,8 @@ import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
@@ -99,6 +101,7 @@ public final class Client extends AbstractPersistable<Long> {
@JoinColumn(name = "staff_id")
private Staff staff;
@LazyCollection(LazyCollectionOption.FALSE)
@ManyToMany
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
private Set<Group> groups;
@@ -270,11 +273,15 @@ public final class Client extends AbstractPersistable<Long> {
return ClientStatus.fromInt(this.status).isActive();
}
public boolean isClosed() {
return ClientStatus.fromInt(this.status).isClosed();
}
public boolean isTransferInProgress() {
return ClientStatus.fromInt(this.status).isTransferInProgress();
}
public boolean isTransferOnHold() {
public boolean isTransferOnHold () {
return ClientStatus.fromInt(this.status).isTransferOnHold();
}
@@ -30,7 +30,7 @@ public class ClientRepositoryWrapper {
if (client == null) { throw new ClientNotFoundException(id); }
return client;
}
public void save(final Client client) {
this.repository.save(client);
}
@@ -96,10 +96,17 @@ public class CentersApiResource {
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId) {
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("command") final String commandParam,
@QueryParam("officeId") final Long officeId) {
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME);
if (is(commandParam, "close")) {
final CenterData centerClosureTemplate = this.centerReadPlatformService.retrieveCenterWithClosureReasons();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.centerApiJsonSerializer.serialize(settings, centerClosureTemplate, GroupingTypesApiConstants.CENTER_RESPONSE_DATA_PARAMETERS);
}
final CenterData template = this.centerReadPlatformService.retrieveTemplate(officeId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -229,6 +236,10 @@ public class CentersApiResource {
final CommandWrapper commandRequest = builder.saveCenterCollectionSheet(centerId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else if (is(commandParam, "close")) {
final CommandWrapper commandRequest = builder.closeCenter(centerId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else {
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet",
"createRole" });
@@ -21,11 +21,14 @@ public class GroupingTypesApiConstants {
public static final String GROUP_ROLE_RESOURCE_NAME = "grouprole";
public static final String GROUP_ROLE_NAME = "GROUPROLE";
public static final String GROUP_CLOSURE_REASON = "GroupClosureReason";
public static final String roleParamName = "role";
public static final String groupIdParamName = "groupId";
public static final String clientIdParamName = "clientId";
public static final String groupRolesParamName = "groupRoles";
// general
public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat";
@@ -53,6 +56,10 @@ public class GroupingTypesApiConstants {
public static final String staffOptionsParamName = "staffOptions";
public static final String clientOptionsParamName = "clientOptions";
public static final String collectionMeetingCalendar = "collectionMeetingCalendar";
//group close parameters
public static final String closureDateParamName = "closureDate";
public static final String closureReasonIdParamName = "closureReasonId";
public static final Set<String> CENTER_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, idParamName, nameParamName, externalIdParamName, officeIdParamName, staffIdParamName, activeParamName,
@@ -86,5 +93,7 @@ public class GroupingTypesApiConstants {
public static final Set<String> COLLECTIONSHEET_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("dueDate", "loanProducts", "groups"));
public static final Set<String> GROUP_CLOSE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, closureDateParamName, closureReasonIdParamName));
}
@@ -117,10 +117,17 @@ public class GroupsApiResource {
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveTemplate(@Context final UriInfo uriInfo, @QueryParam("officeId") final Long officeId,
@QueryParam("center") final boolean isCenterGroup, @QueryParam("centerId") final Long centerId,
@QueryParam("command") final String commandParam,
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly) {
this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
if (is(commandParam, "close")) {
final GroupGeneralData groupClosureTemplate = this.groupReadPlatformService.retrieveGroupWithClosureReasons();
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.groupGeneralApiJsonSerializer.serialize(settings, groupClosureTemplate, GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS);
}
if (centerId != null) {
final GroupGeneralData centerGroupTemplate = this.centerReadPlatformService.retrieveCenterGroupTemplate(centerId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -344,6 +351,10 @@ public class GroupsApiResource {
final CommandWrapper commandRequest = builder.transferClientsBetweenGroups(groupId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else if (is(commandParam, "close")) {
final CommandWrapper commandRequest = builder.closeGroup(groupId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else {
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "generateCollectionSheet",
"saveCollectionSheet", "unassignStaff", "assignRole", "unassignRole", "updateassignRole" });
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.group.data;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.staff.data.StaffData;
@@ -42,18 +43,21 @@ public class CenterData {
private final Collection<StaffData> staffOptions;
private final Collection<GroupGeneralData> groupMembersOptions;
private final CalendarData collectionMeetingCalendar;
private final Collection<CodeValueData> closureReasons;
public static CenterData template(final Long officeId, final LocalDate activationDate, final Collection<OfficeData> officeOptions,
final Collection<StaffData> staffOptions, final Collection<GroupGeneralData> groupMembersOptions) {
final CalendarData collectionMeetingCalendar = null;
final Collection<CodeValueData> closureReasons = null;
return new CenterData(null, null, null, null, activationDate, officeId, null, null, null, null, null, officeOptions, staffOptions,
groupMembersOptions, collectionMeetingCalendar);
groupMembersOptions, collectionMeetingCalendar, closureReasons);
}
public static CenterData withTemplate(final CenterData templateCenter, final CenterData center) {
return new CenterData(center.id, center.name, center.externalId, center.status, center.activationDate, center.officeId,
center.officeName, center.staffId, center.staffName, center.hierarchy, center.groupMembers, templateCenter.officeOptions,
templateCenter.staffOptions, templateCenter.groupMembersOptions, templateCenter.collectionMeetingCalendar);
templateCenter.staffOptions, templateCenter.groupMembersOptions, templateCenter.collectionMeetingCalendar,
templateCenter.closureReasons);
}
public static CenterData instance(final Long id, final String name, final String externalId, final EnumOptionData status,
@@ -65,21 +69,43 @@ public class CenterData {
final Collection<StaffData> staffOptions = null;
final Collection<GroupGeneralData> groupMembersOptions = null;
final CalendarData collectionMeetingCalendar = null;
final Collection<CodeValueData> closureReasons = null;
return new CenterData(id, name, externalId, status, activationDate, officeId, officeName, staffId, staffName, hierarchy,
groupMembers, officeOptions, staffOptions, groupMembersOptions, collectionMeetingCalendar);
groupMembers, officeOptions, staffOptions, groupMembersOptions, collectionMeetingCalendar, closureReasons);
}
public static CenterData withAssociations(final CenterData centerData, final Collection<GroupGeneralData> groupMembers, final CalendarData collectionMeetingCalendar) {
return new CenterData(centerData.id, centerData.name, centerData.externalId, centerData.status, centerData.activationDate,
centerData.officeId, centerData.officeName, centerData.staffId, centerData.staffName, centerData.hierarchy, groupMembers,
centerData.officeOptions, centerData.staffOptions, centerData.groupMembersOptions, collectionMeetingCalendar);
centerData.officeOptions, centerData.staffOptions, centerData.groupMembersOptions, collectionMeetingCalendar, centerData.closureReasons);
}
public static CenterData withClosureReasons(final Collection<CodeValueData> closureReasons) {
final Long id = null;
final String name = null;
final String externalId = null;
final EnumOptionData status = null;
final LocalDate activationDate = null;
final Long officeId = null;
final String officeName = null;
final Long staffId = null;
final String staffName = null;
final String hierarchy = null;
final Collection<GroupGeneralData> groupMembers = null;
final Collection<OfficeData> officeOptions = null;
final Collection<StaffData> staffOptions = null;
final Collection<GroupGeneralData> groupMembersOptions = null;
final CalendarData collectionMeetingCalendar = null;
return new CenterData(id, name, externalId, status, activationDate, officeId, officeName, staffId, staffName, hierarchy,
groupMembers, officeOptions, staffOptions, groupMembersOptions, collectionMeetingCalendar, closureReasons);
}
private CenterData(final Long id, final String name, final String externalId, final EnumOptionData status,
final LocalDate activationDate, final Long officeId, final String officeName, final Long staffId, final String staffName,
final String hierarchy, final Collection<GroupGeneralData> groupMembers, final Collection<OfficeData> officeOptions,
final Collection<StaffData> staffOptions, final Collection<GroupGeneralData> groupMembersOptions, final CalendarData collectionMeetingCalendar) {
final Collection<StaffData> staffOptions, final Collection<GroupGeneralData> groupMembersOptions,
final CalendarData collectionMeetingCalendar, final Collection<CodeValueData> closureReasons) {
this.id = id;
this.name = name;
this.externalId = externalId;
@@ -103,6 +129,7 @@ public class CenterData {
this.staffOptions = staffOptions;
this.groupMembersOptions = groupMembersOptions;
this.collectionMeetingCalendar = collectionMeetingCalendar;
this.closureReasons = closureReasons;
}
public Long officeId() {
@@ -51,13 +51,14 @@ public class GroupGeneralData {
private final Collection<ClientData> clientOptions;
private final Collection<CodeValueData> availableRoles;
private final GroupRoleData selectedRole;
private final Collection<CodeValueData> closureReasons;
public static GroupGeneralData lookup(final Long groupId, final String groupName) {
final Collection<ClientData> clientMembers = null;
final Collection<GroupRoleData> groupRoles = null;
final Collection<CodeValueData> closureReasons = null;
return new GroupGeneralData(groupId, groupName, null, null, null, null, null, null, null, null, null, null, clientMembers, null,
null, null, null, groupRoles, null, null, null, null);
null, null, null, groupRoles, null, null, null, null, closureReasons);
}
public static GroupGeneralData template(final Long officeId, final Long centerId, final String centerName, final Long staffId,
@@ -67,9 +68,10 @@ public class GroupGeneralData {
final Collection<ClientData> clientMembers = null;
final Collection<GroupRoleData> groupRoles = null;
final Collection<CodeValueData> closureReasons = null;
return new GroupGeneralData(null, null, null, null, null, officeId, null, centerId, centerName, staffId, staffName, null,
clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, null, null, null);
clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, null, null, null, closureReasons);
}
public static GroupGeneralData withTemplate(final GroupGeneralData templatedGrouping, final GroupGeneralData grouping) {
@@ -77,7 +79,7 @@ public class GroupGeneralData {
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
grouping.hierarchy, grouping.clientMembers, templatedGrouping.centerOptions, templatedGrouping.officeOptions,
templatedGrouping.staffOptions, templatedGrouping.clientOptions, grouping.groupRoles, templatedGrouping.availableRoles,
grouping.selectedRole, grouping.calendarsData, grouping.collectionMeetingCalendar);
grouping.selectedRole, grouping.calendarsData, grouping.collectionMeetingCalendar, grouping.closureReasons);
}
public static GroupGeneralData withAssocations(final GroupGeneralData grouping, final Collection<ClientData> membersOfGroup,
@@ -85,7 +87,7 @@ public class GroupGeneralData {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
grouping.hierarchy, membersOfGroup, grouping.centerOptions, grouping.officeOptions, grouping.staffOptions,
grouping.clientOptions, groupRoles, grouping.availableRoles, grouping.selectedRole, calendarsData, collectionMeetingCalendar);
grouping.clientOptions, groupRoles, grouping.availableRoles, grouping.selectedRole, calendarsData, collectionMeetingCalendar, grouping.closureReasons);
}
public static GroupGeneralData instance(final Long id, final String name, final String externalId, final EnumOptionData status,
@@ -102,10 +104,11 @@ public class GroupGeneralData {
final GroupRoleData role = null;
final Collection<CalendarData> calendarsData = null;
final CalendarData collectionMeetingCalendar = null;
final Collection<CodeValueData> closureReasons = null;
return new GroupGeneralData(id, name, externalId, status, activationDate, officeId, officeName, centerId, centerName, staffId,
staffName, hierarchy, clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles,
role, calendarsData, collectionMeetingCalendar);
role, calendarsData, collectionMeetingCalendar, closureReasons);
}
private GroupGeneralData(final Long id, final String name, final String externalId, final EnumOptionData status,
@@ -114,7 +117,7 @@ public class GroupGeneralData {
final Collection<CenterData> centerOptions, final Collection<OfficeData> officeOptions,
final Collection<StaffData> staffOptions, final Collection<ClientData> clientOptions,
final Collection<GroupRoleData> groupRoles, final Collection<CodeValueData> availableRoles, final GroupRoleData role,
final Collection<CalendarData> calendarsData, final CalendarData collectionMeetingCalendar) {
final Collection<CalendarData> calendarsData, final CalendarData collectionMeetingCalendar, final Collection<CodeValueData> closureReasons) {
this.id = id;
this.name = name;
this.externalId = externalId;
@@ -151,6 +154,7 @@ public class GroupGeneralData {
this.selectedRole = role;
this.calendarsData = calendarsData;
this.collectionMeetingCalendar = collectionMeetingCalendar;
this.closureReasons = closureReasons;
}
public Long getId() {
@@ -182,7 +186,35 @@ public class GroupGeneralData {
return new GroupGeneralData(grouping.id, grouping.name, grouping.externalId, grouping.status, grouping.activationDate,
grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName,
grouping.hierarchy, grouping.clientMembers, grouping.centerOptions, grouping.officeOptions, grouping.staffOptions,
grouping.clientOptions, grouping.groupRoles, grouping.availableRoles, selectedRole, grouping.calendarsData, grouping.collectionMeetingCalendar);
grouping.clientOptions, grouping.groupRoles, grouping.availableRoles, selectedRole, grouping.calendarsData, grouping.collectionMeetingCalendar, grouping.closureReasons);
}
public static GroupGeneralData withClosureReasons(final Collection<CodeValueData> closureReasons) {
final Long id = null;
final String name = null;
final String externalId = null;
final EnumOptionData status = null;
final LocalDate activationDate = null;
final Long officeId = null;
final String officeName = null;
final Long centerId = null;
final String centerName = null;
final Long staffId = null;
final String staffName = null;
final String hierarchy = null;
final Collection<ClientData> clientMembers = null;
final Collection<CenterData> centerOptions = null;
final Collection<OfficeData> officeOptions = null;
final Collection<StaffData> staffOptions = null;
final Collection<ClientData> clientOptions = null;
final Collection<GroupRoleData> groupRoles = null;
final Collection<CodeValueData> availableRoles = null;
final GroupRoleData role = null;
final Collection<CalendarData> calendarsData = null;
final CalendarData collectionMeetingCalendar = null;
return new GroupGeneralData(id, name, externalId, status, activationDate, officeId, officeName, centerId, centerName, staffId,
staffName, hierarchy, clientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles,
role, calendarsData, collectionMeetingCalendar, closureReasons);
}
}
@@ -31,6 +31,7 @@ import javax.persistence.TemporalType;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
@@ -41,6 +42,7 @@ import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
import org.mifosplatform.portfolio.group.exception.ClientExistInGroupException;
import org.mifosplatform.portfolio.group.exception.ClientNotInGroupException;
import org.mifosplatform.portfolio.group.exception.InvalidGroupStateTransitionException;
import org.springframework.data.jpa.domain.AbstractPersistable;
import com.google.common.collect.Sets;
@@ -95,6 +97,14 @@ public final class Group extends AbstractPersistable<Long> {
@ManyToMany
@JoinTable(name = "m_group_client", joinColumns = @JoinColumn(name = "group_id"), inverseJoinColumns = @JoinColumn(name = "client_id"))
private Set<Client> clientMembers;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "closure_reason_cv_id", nullable = true)
private CodeValue closureReason;
@Column(name = "closedon_date", nullable = true)
@Temporal(TemporalType.DATE)
private Date closureDate;
public Group() {
this.name = null;
@@ -409,5 +419,41 @@ public final class Group extends AbstractPersistable<Long> {
public boolean isChildGroup(){
return (this.parent == null) ? false : true;
}
public boolean isClosed(){
return GroupingTypeStatus.fromInt(this.status).isClosed();
}
public void close(final CodeValue closureReason, final LocalDate closureDate){
if (this.isClosed()) {
final String errorMessage = "Group with identifier " + this.getId() + " is alread closed.";
throw new InvalidGroupStateTransitionException(this.groupLevel.getLevelName(), "close", "already.closed", errorMessage, this.getId());
}
if (this.isNotPending() && this.getActivationLocalDate().isAfter(closureDate)) {
final String errorMessage = "The Group closure Date " + closureDate + " cannot be before the group Activation Date " + this.getActivationLocalDate() + ".";
throw new InvalidGroupStateTransitionException(this.groupLevel.getLevelName(), "close", "date.cannot.before.group.actvation.date", errorMessage, closureDate, this.getActivationLocalDate());
}
this.closureReason = closureReason;
this.closureDate = closureDate.toDate();
this.status = GroupingTypeStatus.CLOSED.getValue();
}
public boolean hasActiveClients(){
for (Client client : this.clientMembers) {
if(!client.isClosed()) return true;
}
return false;
}
public boolean hasActiveGroups(){
for(Group group : this.groupMembers){
if(!group.isClosed()) return true;
}
return false;
}
}
@@ -33,6 +33,14 @@ public class GroupingTypeEnumerations {
optionData = new EnumOptionData(GroupingTypeStatus.CLOSED.getValue().longValue(), GroupingTypeStatus.CLOSED.getCode(),
"Closed");
break;
case TRANSFER_IN_PROGRESS:
optionData = new EnumOptionData(GroupingTypeStatus.TRANSFER_IN_PROGRESS.getValue().longValue(), GroupingTypeStatus.TRANSFER_IN_PROGRESS.getCode(),
"Transfer in progress");
break;
case TRANSFER_ON_HOLD:
optionData = new EnumOptionData(GroupingTypeStatus.TRANSFER_ON_HOLD.getValue().longValue(), GroupingTypeStatus.TRANSFER_ON_HOLD.getCode(),
"Transfer on hold");
break;
}
return optionData;
@@ -0,0 +1,27 @@
package org.mifosplatform.portfolio.group.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.group.service.GroupingTypesWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CloseCenterCommandHandler implements NewCommandSourceHandler {
private final GroupingTypesWritePlatformService groupingTypesWritePlatformService;
@Autowired
public CloseCenterCommandHandler(final GroupingTypesWritePlatformService groupingTypesWritePlatformService) {
this.groupingTypesWritePlatformService = groupingTypesWritePlatformService;
}
@Override
@Transactional
public CommandProcessingResult processCommand(JsonCommand command) {
return this.groupingTypesWritePlatformService.closeCenter(command.entityId(), command);
}
}
@@ -0,0 +1,27 @@
package org.mifosplatform.portfolio.group.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.group.service.GroupingTypesWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CloseGroupCommandHandler implements NewCommandSourceHandler {
private final GroupingTypesWritePlatformService groupingTypesWritePlatformService;
@Autowired
public CloseGroupCommandHandler(final GroupingTypesWritePlatformService groupingTypesWritePlatformService) {
this.groupingTypesWritePlatformService = groupingTypesWritePlatformService;
}
@Override
@Transactional
public CommandProcessingResult processCommand(JsonCommand command) {
return this.groupingTypesWritePlatformService.closeGroup(command.entityId(), command);
}
}
@@ -85,5 +85,5 @@ public class GroupRolesDataValidator {
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
}
@@ -406,4 +406,52 @@ public final class GroupingTypesDataValidator {
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForGroupClose(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, GroupingTypesApiConstants.GROUP_CLOSE_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(GroupingTypesApiConstants.GROUP_RESOURCE_NAME);
final JsonElement element = command.parsedJson();
final LocalDate closureDate = this.fromApiJsonHelper.extractLocalDateNamed(GroupingTypesApiConstants.closureDateParamName, element);
baseDataValidator.reset().parameter(GroupingTypesApiConstants.closureDateParamName).value(closureDate).notNull();
final Long closureReasonId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.closureReasonIdParamName, element);
baseDataValidator.reset().parameter(GroupingTypesApiConstants.closureReasonIdParamName).value(closureReasonId).notNull().longGreaterThanZero();
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForCenterClose(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, GroupingTypesApiConstants.GROUP_CLOSE_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(GroupingTypesApiConstants.CENTER_RESOURCE_NAME);
final JsonElement element = command.parsedJson();
final LocalDate closureDate = this.fromApiJsonHelper.extractLocalDateNamed(GroupingTypesApiConstants.closureDateParamName, element);
baseDataValidator.reset().parameter(GroupingTypesApiConstants.closureDateParamName).value(closureDate).notNull();
final Long closureReasonId = this.fromApiJsonHelper.extractLongNamed(GroupingTypesApiConstants.closureReasonIdParamName, element);
baseDataValidator.reset().parameter(GroupingTypesApiConstants.closureReasonIdParamName).value(closureReasonId).notNull().longGreaterThanZero();
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
}
@@ -24,4 +24,6 @@ public interface CenterReadPlatformService {
GroupGeneralData retrieveCenterGroupTemplate(Long centerId);
Collection<GroupGeneralData> retrieveAssociatedGroups(Long centerId);
CenterData retrieveCenterWithClosureReasons();
}
@@ -7,11 +7,15 @@ package org.mifosplatform.portfolio.group.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
@@ -26,6 +30,7 @@ import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.domain.ClientEnumerations;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
import org.mifosplatform.portfolio.group.data.CenterData;
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
import org.mifosplatform.portfolio.group.domain.GroupTypes;
@@ -47,6 +52,7 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
private final ClientReadPlatformService clientReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
private final StaffReadPlatformService staffReadPlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
// data mappers
private final AllGroupTypesDataMapper allGroupTypesDataMapper = new AllGroupTypesDataMapper();
@@ -60,12 +66,13 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
@Autowired
public CenterReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
final StaffReadPlatformService staffReadPlatformService) {
final StaffReadPlatformService staffReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService) {
this.context = context;
this.clientReadPlatformService = clientReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.officeReadPlatformService = officeReadPlatformService;
this.staffReadPlatformService = staffReadPlatformService;
this.codeValueReadPlatformService = codeValueReadPlatformService;
}
// 'g.' preffix because of ERROR 1052 (23000): Column 'column_name' in where
@@ -331,4 +338,11 @@ public class CenterReadPlatformServiceImpl implements CenterReadPlatformService
String sql = "select " + this.groupDataMapper.schema() + " where g.parent_id = ? ";
return this.jdbcTemplate.query(sql, this.groupDataMapper, new Object[] { centerId });
}
@Override
public CenterData retrieveCenterWithClosureReasons() {
final List<CodeValueData> closureReasons = new ArrayList<CodeValueData>(
codeValueReadPlatformService.retrieveCodeValuesByCode(GroupingTypesApiConstants.GROUP_CLOSURE_REASON));
return CenterData.withClosureReasons(closureReasons);
}
}
@@ -19,4 +19,6 @@ public interface GroupReadPlatformService {
GroupGeneralData retrieveOne(Long groupId);
Collection<GroupGeneralData> retrieveGroupsForLookup(Long officeId);
GroupGeneralData retrieveGroupWithClosureReasons();
}
@@ -7,7 +7,9 @@ package org.mifosplatform.portfolio.group.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
@@ -227,4 +229,11 @@ public class GroupReadPlatformServiceImpl implements GroupReadPlatformService {
}
}
@Override
public GroupGeneralData retrieveGroupWithClosureReasons() {
final List<CodeValueData> closureReasons = new ArrayList<CodeValueData>(
codeValueReadPlatformService.retrieveCodeValuesByCode(GroupingTypesApiConstants.GROUP_CLOSURE_REASON));
return GroupGeneralData.withClosureReasons(closureReasons);
}
}
@@ -11,5 +11,5 @@ public interface GroupRolesWritePlatformService {
CommandProcessingResult updateRole(JsonCommand command);
CommandProcessingResult deleteRole(Long ruleId);
}
@@ -35,7 +35,7 @@ public class GroupRolesWritePlatformServiceJpaRepositoryImpl implements GroupRol
private final CodeValueRepositoryWrapper codeValueRepository;
private final ClientRepositoryWrapper clientRepository;
private final GroupRoleRepositoryWrapper groupRoleRepository;
@Autowired
public GroupRolesWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final GroupRepositoryWrapper groupRepository, final GroupRolesDataValidator fromApiJsonDeserializer,
@@ -143,5 +143,5 @@ public class GroupRolesWritePlatformServiceJpaRepositoryImpl implements GroupRol
this.groupRoleRepository.delete(groupRole);
return new CommandProcessingResultBuilder().withEntityId(groupRole.getId()).build();
}
}
@@ -21,6 +21,10 @@ public interface GroupingTypesWritePlatformService {
CommandProcessingResult updateGroup(Long groupId, JsonCommand command);
CommandProcessingResult deleteGroup(Long groupId);
CommandProcessingResult closeGroup(final Long groupId, final JsonCommand command);
CommandProcessingResult closeCenter(final Long centerId, final JsonCommand command);
CommandProcessingResult unassignGroupOrCenterStaff(Long groupId, JsonCommand command);
@@ -17,6 +17,8 @@ import java.util.Set;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
@@ -30,6 +32,7 @@ import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.client.service.LoanStatusMapper;
import org.mifosplatform.portfolio.group.api.GroupingTypesApiConstants;
import org.mifosplatform.portfolio.group.domain.Group;
import org.mifosplatform.portfolio.group.domain.GroupLevel;
@@ -64,24 +67,26 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
private final PlatformSecurityContext context;
private final GroupRepositoryWrapper groupRepository;
private final ClientRepositoryWrapper clientRepository;
private final ClientRepositoryWrapper clientRepositoryWrapper;
private final OfficeRepository officeRepository;
private final StaffRepositoryWrapper staffRepository;
private final NoteRepository noteRepository;
private final GroupLevelRepository groupLevelRepository;
private final GroupingTypesDataValidator fromApiJsonDeserializer;
private final LoanRepository loanRepository;
private final CodeValueRepositoryWrapper codeValueRepository;
private final SavingsAccountRepository savingsRepository;
@Autowired
public GroupingTypesWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final GroupRepositoryWrapper groupRepository, final ClientRepositoryWrapper clientRepository,
final OfficeRepository officeRepository, final StaffRepositoryWrapper staffRepository, final NoteRepository noteRepository,
final GroupLevelRepository groupLevelRepository, final GroupingTypesDataValidator fromApiJsonDeserializer,
final LoanRepository loanRepository, final SavingsAccountRepository savingsRepository) {
final GroupRepositoryWrapper groupRepository, final ClientRepositoryWrapper clientRepositoryWrapper,
final OfficeRepository officeRepository, final StaffRepositoryWrapper staffRepository,
final NoteRepository noteRepository, final GroupLevelRepository groupLevelRepository,
final GroupingTypesDataValidator fromApiJsonDeserializer, final LoanRepository loanRepository,
final SavingsAccountRepository savingsRepository, final CodeValueRepositoryWrapper codeValueRepository) {
this.context = context;
this.groupRepository = groupRepository;
this.clientRepository = clientRepository;
this.clientRepositoryWrapper = clientRepositoryWrapper;
this.officeRepository = officeRepository;
this.staffRepository = staffRepository;
this.noteRepository = noteRepository;
@@ -89,6 +94,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.loanRepository = loanRepository;
this.savingsRepository = savingsRepository;
this.codeValueRepository = codeValueRepository;
}
private CommandProcessingResult createGroupingType(final JsonCommand command, final GroupTypes groupingType, final Long centerId) {
@@ -403,6 +409,99 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
.build();
}
@Override
public CommandProcessingResult closeGroup(Long groupId, JsonCommand command) {
this.fromApiJsonDeserializer.validateForGroupClose(command);
final Group group = this.groupRepository.findOneWithNotFoundDetection(groupId);
final LocalDate closureDate = command.localDateValueOfParameterNamed(GroupingTypesApiConstants.closureDateParamName);
final Long closureReasonId = command.longValueOfParameterNamed(GroupingTypesApiConstants.closureReasonIdParamName);
CodeValue closureReason = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(
GroupingTypesApiConstants.GROUP_CLOSURE_REASON, closureReasonId);
if(group.hasActiveClients()){
final String errorMessage = group.getGroupLevel().getLevelName() + " cannot be closed because of active clients associated with it.";
throw new InvalidGroupStateTransitionException(group.getGroupLevel().getLevelName(), "close", "active.clients.exist",
errorMessage);
}
validateLoansAndSavingsForGroupOrCenterClose(group, closureDate);
group.close(closureReason, closureDate);
this.groupRepository.saveAndFlush(group);
return new CommandProcessingResultBuilder() //
.withGroupId(groupId) //
.withEntityId(groupId) //
.build();
}
private void validateLoansAndSavingsForGroupOrCenterClose(final Group groupOrCenter, final LocalDate closureDate) {
Collection<Loan> groupLoans = this.loanRepository.findByGroupId(groupOrCenter.getId());
for (Loan loan : groupLoans) {
LoanStatusMapper loanStatus = new LoanStatusMapper(loan.status().getValue());
if (loanStatus.isOpen()) {
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " cannot be closed because of non-closed loans.";
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed",
errorMessage);
} else if (loanStatus.isClosed() && loan.getClosedOnDate().after(closureDate.toDate())) {
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + "closureDate cannot be before the loan closedOnDate.";
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
"date.cannot.before.loan.closed.date", errorMessage, closureDate, loan.getClosedOnDate());
} else if (loanStatus.isPendingApproval()) {
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " cannot be closed because of non-closed loans.";
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed",
errorMessage);
} else if (loanStatus.isAwaitingDisbursal()) {
final String errorMessage = "Group cannot be closed because of non-closed loans.";
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "loan.not.closed",
errorMessage);
}
}
List<SavingsAccount> groupSavingAccounts = this.savingsRepository.findByGroupId(groupOrCenter.getId());
for (SavingsAccount saving : groupSavingAccounts) {
if (saving.isActive() || saving.isSubmittedAndPendingApproval() || saving.isApproved()) {
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " cannot be closed with active savings accounts associated.";
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close", "savings.account.not.closed",
errorMessage);
} else if (saving.isClosed() && saving.getClosedOnDate().isAfter(closureDate)) {
final String errorMessage = groupOrCenter.getGroupLevel().getLevelName() + " closureDate cannot be before the loan closedOnDate.";
throw new InvalidGroupStateTransitionException(groupOrCenter.getGroupLevel().getLevelName(), "close",
"date.cannot.before.loan.closed.date", errorMessage, closureDate, saving.getClosedOnDate());
}
}
}
@Override
public CommandProcessingResult closeCenter(Long centerId, JsonCommand command) {
this.fromApiJsonDeserializer.validateForCenterClose(command);
final Group center = this.groupRepository.findOneWithNotFoundDetection(centerId);
final LocalDate closureDate = command.localDateValueOfParameterNamed(GroupingTypesApiConstants.closureDateParamName);
final Long closureReasonId = command.longValueOfParameterNamed(GroupingTypesApiConstants.closureReasonIdParamName);
CodeValue closureReason = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection(
GroupingTypesApiConstants.GROUP_CLOSURE_REASON, closureReasonId);
if(center.hasActiveGroups()){
final String errorMessage = center.getGroupLevel().getLevelName() + " cannot be closed because of active groups associated with it.";
throw new InvalidGroupStateTransitionException(center.getGroupLevel().getLevelName(), "close", "active.groups.exist",
errorMessage);
}
validateLoansAndSavingsForGroupOrCenterClose(center, closureDate);
center.close(closureReason, closureDate);
this.groupRepository.saveAndFlush(center);
return new CommandProcessingResultBuilder() //
.withEntityId(centerId) //
.build();
}
private Set<Client> assembleSetOfClients(final Long groupOfficeId, final JsonCommand command) {
final Set<Client> clientMembers = new HashSet<Client>();
@@ -411,7 +510,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
if (!ObjectUtils.isEmpty(clientMembersArray)) {
for (final String clientId : clientMembersArray) {
final Long id = Long.valueOf(clientId);
final Client client = this.clientRepository.findOneWithNotFoundDetection(id);
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(id);
if (!client.isOfficeIdentifiedBy(groupOfficeId)) {
final String errorMessage = "Client with identifier " + clientId + " must have the same office as group.";
throw new InvalidOfficeException("client", "attach.to.group", errorMessage, clientId, groupOfficeId);
@@ -91,10 +91,13 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
@Query("from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId")
List<Loan> findByClientIdAndGroupId(@Param("clientId") Long clientId, @Param("groupId") Long groupId);
@Query("from Loan loan where loan.client.id = :clientId")
List<Loan> findLoanByClientId(@Param("clientId") Long clientId);
@Query("from Loan loan where loan.group.id = :groupId and loan.client.id is null")
List<Loan> findByGroupId(@Param("groupId") Long groupId);
@Query("from Loan loan where loan.id IN :ids and loan.loanStatus IN :loanStatuses and loan.loanType IN :loanTypes")
List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids,
@Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes);
@@ -41,6 +41,7 @@ import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
@@ -349,6 +350,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return SavingsAccountStatusType.fromInt(this.status).isApproved();
}
public boolean isClosed(){
return SavingsAccountStatusType.fromInt(this.status).isClosed();
}
public void postInterest(final MathContext mc, final LocalDate interestPostingUpToDate, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds) {
@@ -1762,9 +1767,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return this.withdrawalFeeApplicableForTransfer;
}
public void activateAccountBasedOnBalance() {
if (SavingsAccountStatusType.fromInt(this.status).isClosed() && !this.summary.getAccountBalance(getCurrency()).isZero()) {
this.status = SavingsAccountStatusType.ACTIVE.getValue();
}
public LocalDate getClosedOnDate() {
return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.closedOnDate), null);
}
}
@@ -25,4 +25,7 @@ public interface SavingsAccountRepository extends JpaRepository<SavingsAccount,
@Query("select case when (count (saving) > 0) then true else false end from SavingsAccount saving where saving.client.id = :clientId and saving.status in (100,200,300,303,304)")
boolean doNonClosedSavingAccountsExistForClient(@Param("clientId") Long clientId);
@Query("from SavingsAccount sa where sa.client.id is null and sa.group.id = :groupId")
List<SavingsAccount> findByGroupId(@Param("groupId") Long groupId);
}