cleaning up group validations
This commit is contained in:
+7
-3
@@ -34,9 +34,13 @@ public interface ConfigurationDomainService {
|
||||
Long retrievePasswordLiveTime();
|
||||
|
||||
Long retrieveGraceOnPenaltyPostingPeriod();
|
||||
|
||||
|
||||
boolean isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
|
||||
|
||||
Integer retrieveFinancialYearBeginningMonth();
|
||||
|
||||
|
||||
public Integer retrieveMinAllowedClientsInGroup();
|
||||
|
||||
public Integer retrieveMaxAllowedClientsInGroup();
|
||||
|
||||
}
|
||||
+21
-7
@@ -113,7 +113,7 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
return property.getValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Long retrieveGraceOnPenaltyPostingPeriod() {
|
||||
final String propertyName = "grace-on-penalty-posting";
|
||||
@@ -121,7 +121,6 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
return property.getValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPasswordForcedResetEnable() {
|
||||
final String propertyName = "force-password-reset-days";
|
||||
@@ -135,21 +134,36 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
return property.getValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSavingsInterestPostingAtCurrentPeriodEnd() {
|
||||
final String propertyName = "savings-interest-posting-current-period-end";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
return property.isEnabled();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Integer retrieveFinancialYearBeginningMonth() {
|
||||
final String propertyName = "financial-year-beginning-month";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
if(property.isEnabled())
|
||||
return property.getValue().intValue();
|
||||
return 1;
|
||||
if (property.isEnabled()) return property.getValue().intValue();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer retrieveMinAllowedClientsInGroup() {
|
||||
final String propertyName = "min-clients-in-group";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
if (property.isEnabled()) { return property.getValue().intValue(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer retrieveMaxAllowedClientsInGroup() {
|
||||
final String propertyName = "max-clients-in-group";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
if (property.isEnabled()) { return property.getValue().intValue(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-20
@@ -298,12 +298,11 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
validateNameParts(dataValidationErrors);
|
||||
validateActivationDate(dataValidationErrors);
|
||||
validateClientsGroupRules(dataValidationErrors);
|
||||
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean isAccountNumberRequiresAutoGeneration() {
|
||||
return this.accountNumberRequiresAutoGeneration;
|
||||
}
|
||||
@@ -449,7 +448,6 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
actualChanges.put(ClientApiConstants.savingsProductIdParamName, newValue);
|
||||
}
|
||||
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ClientApiConstants.genderIdParamName, genderId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.genderIdParamName);
|
||||
actualChanges.put(ClientApiConstants.genderIdParamName, newValue);
|
||||
@@ -465,7 +463,6 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
actualChanges.put(ClientApiConstants.clientClassificationIdParamName, newValue);
|
||||
}
|
||||
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
@@ -490,7 +487,7 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
this.dateOfBirth = newValue.toDate();
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(ClientApiConstants.submittedOnDateParamName,getSubmittedOnDate())) {
|
||||
if (command.isChangeInLocalDateParameterNamed(ClientApiConstants.submittedOnDateParamName, getSubmittedOnDate())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(ClientApiConstants.submittedOnDateParamName);
|
||||
actualChanges.put(ClientApiConstants.submittedOnDateParamName, valueAsInput);
|
||||
actualChanges.put(ClientApiConstants.dateFormatParamName, dateFormatAsInput);
|
||||
@@ -507,7 +504,6 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
|
||||
private void validateNameParts(final List<ApiParameterError> dataValidationErrors) {
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client");
|
||||
|
||||
@@ -571,18 +567,6 @@ public final class Client extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To become a part of a group, group may have set of criteria to be met
|
||||
* before client can become member of it. This method is placeholder for
|
||||
* such validation.
|
||||
*/
|
||||
|
||||
private void validateClientsGroupRules(final List<ApiParameterError> dataValidationErrors) {
|
||||
for (Group group : this.groups) {
|
||||
group.validateGroupHasMoreThanRequiredNumberOfClientsAngLogError(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
private void deriveDisplayName() {
|
||||
|
||||
|
||||
+26
-2
@@ -18,6 +18,7 @@ import org.mifosplatform.commands.service.CommandProcessingService;
|
||||
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
@@ -42,6 +43,7 @@ import org.mifosplatform.portfolio.client.exception.InvalidClientSavingProductEx
|
||||
import org.mifosplatform.portfolio.client.exception.InvalidClientStateTransitionException;
|
||||
import org.mifosplatform.portfolio.group.domain.Group;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupMemberCountNotInPermissibleRangeException;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository;
|
||||
@@ -82,6 +84,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
private final SavingsProductRepository savingsProductRepository;
|
||||
private final SavingsApplicationProcessWritePlatformService savingsApplicationProcessWritePlatformService;
|
||||
private final CommandProcessingService commandProcessingService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -91,7 +94,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
final CodeValueRepositoryWrapper codeValueRepository, final LoanRepository loanRepository,
|
||||
final SavingsAccountRepository savingsRepository, final SavingsProductRepository savingsProductRepository,
|
||||
final SavingsApplicationProcessWritePlatformService savingsApplicationProcessWritePlatformService,
|
||||
final CommandProcessingService commandProcessingService) {
|
||||
final CommandProcessingService commandProcessingService, final ConfigurationDomainService configurationDomainService) {
|
||||
this.context = context;
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepository = officeRepository;
|
||||
@@ -106,6 +109,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
this.savingsProductRepository = savingsProductRepository;
|
||||
this.savingsApplicationProcessWritePlatformService = savingsApplicationProcessWritePlatformService;
|
||||
this.commandProcessingService = commandProcessingService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -215,6 +219,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
clientType, clientClassification, command);
|
||||
boolean rollbackTransaction = false;
|
||||
if (newClient.isActive()) {
|
||||
validateParentGroupRulesBeforeClientActivation(newClient);
|
||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateClient(null).build();
|
||||
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
|
||||
}
|
||||
@@ -275,7 +280,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
}
|
||||
clientForUpdate.updateStaff(newStaff);
|
||||
}
|
||||
|
||||
|
||||
if (changes.containsKey(ClientApiConstants.genderIdParamName)) {
|
||||
|
||||
final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.genderIdParamName);
|
||||
@@ -351,6 +356,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
this.fromApiJsonDeserializer.validateActivation(command);
|
||||
|
||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
validateParentGroupRulesBeforeClientActivation(client);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
@@ -568,4 +574,22 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
||||
.build();
|
||||
}
|
||||
|
||||
/*
|
||||
* To become a part of a group, group may have set of criteria to be met
|
||||
* before client can become member of it.
|
||||
*/
|
||||
private void validateParentGroupRulesBeforeClientActivation(Client client) {
|
||||
Integer minNumberOfClients = configurationDomainService.retrieveMinAllowedClientsInGroup();
|
||||
Integer maxNumberOfClients = configurationDomainService.retrieveMaxAllowedClientsInGroup();
|
||||
for (Group group : client.getGroups()) {
|
||||
/**
|
||||
* Since this Client has not yet been associated with the group,
|
||||
* reduce maxNumberOfClients by 1
|
||||
**/
|
||||
final boolean validationsuccess = group.isGroupsClientCountWithinMaxRange(maxNumberOfClients - 1);
|
||||
if (!validationsuccess) { throw new GroupMemberCountNotInPermissibleRangeException(group.getId(), minNumberOfClients,
|
||||
maxNumberOfClients); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+58
-94
@@ -117,19 +117,20 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
@ManyToOne(optional = true)
|
||||
@JoinColumn(name = "submittedon_userid", nullable = true)
|
||||
private AppUser submittedBy;
|
||||
|
||||
// JPA default constructor for entity
|
||||
|
||||
// JPA default constructor for entity
|
||||
protected Group() {
|
||||
this.name = null;
|
||||
this.externalId = null;
|
||||
this.clientMembers = new HashSet<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Group newGroup(final Office office, final Staff staff, final Group parent, final GroupLevel groupLevel,
|
||||
final String name, final String externalId, final boolean active, final LocalDate activationDate,
|
||||
final Set<Client> clientMembers, final Set<Group> groupMembers, final LocalDate submittedOnDate, final AppUser currentUser) {
|
||||
|
||||
// By default new group is created in PENDING status, unless explicitly status is set to active
|
||||
|
||||
// By default new group is created in PENDING status, unless explicitly
|
||||
// status is set to active
|
||||
GroupingTypeStatus status = GroupingTypeStatus.PENDING;
|
||||
LocalDate groupActivationDate = null;
|
||||
if (active) {
|
||||
@@ -144,7 +145,7 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
private Group(final Office office, final Staff staff, final Group parent, final GroupLevel groupLevel, final String name,
|
||||
final String externalId, final GroupingTypeStatus status, final LocalDate activationDate, final Set<Client> clientMembers,
|
||||
final Set<Group> groupMembers, final LocalDate submittedOnDate, final AppUser currentUser) {
|
||||
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
|
||||
this.office = office;
|
||||
@@ -175,24 +176,23 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
this.submittedBy = currentUser;
|
||||
|
||||
associateClients(clientMembers);
|
||||
|
||||
|
||||
/*
|
||||
* Always keep status change at the bottom, as status change rule depends on the attribute's value
|
||||
* Always keep status change at the bottom, as status change rule
|
||||
* depends on the attribute's value
|
||||
*/
|
||||
|
||||
|
||||
setStatus(activationDate, currentUser, status, dataValidationErrors);
|
||||
|
||||
|
||||
throwExceptionIfErrors(dataValidationErrors);
|
||||
}
|
||||
|
||||
|
||||
private void setStatus(final LocalDate activationDate, final AppUser loginUser, final GroupingTypeStatus status,
|
||||
final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (status.isActive()) {
|
||||
activate(loginUser, activationDate, dataValidationErrors);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
this.status = status.getValue();
|
||||
}
|
||||
|
||||
@@ -201,13 +201,11 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
private void activate(final AppUser currentUser, final LocalDate activationLocalDate, final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
validateStatusNotEqualToActiveAndLogError(dataValidationErrors);
|
||||
validateRequiredNumberOfClientPerGroupAngLogError(dataValidationErrors);
|
||||
|
||||
if (dataValidationErrors.isEmpty()) {
|
||||
this.status = GroupingTypeStatus.ACTIVE.getValue();
|
||||
setActivationDate(activationLocalDate.toDate(), currentUser, dataValidationErrors);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void activate(final AppUser currentUser, final LocalDate activationLocalDate) {
|
||||
@@ -215,10 +213,10 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
activate(currentUser, activationLocalDate, dataValidationErrors);
|
||||
throwExceptionIfErrors(dataValidationErrors);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void setActivationDate(final Date activationDate, final AppUser loginUser, final List<ApiParameterError> dataValidationErrors){
|
||||
private void setActivationDate(final Date activationDate, final AppUser loginUser, final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (activationDate != null) {
|
||||
this.activationDate = activationDate;
|
||||
@@ -226,7 +224,7 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
validateActivationDate(dataValidationErrors);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public boolean isActivatedAfter(final LocalDate submittedOn) {
|
||||
@@ -238,7 +236,7 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.status != null ? GroupingTypeStatus.fromInt(this.status).isActive(): false;
|
||||
return this.status != null ? GroupingTypeStatus.fromInt(this.status).isActive() : false;
|
||||
}
|
||||
|
||||
private boolean isDateInTheFuture(final LocalDate localDate) {
|
||||
@@ -313,15 +311,6 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public List<String> associateClients(final Set<Client> clientMembersSet) {
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final List<String> newlyAssociatedClients = associateClients(clientMembersSet, dataValidationErrors);
|
||||
throwExceptionIfErrors(dataValidationErrors);
|
||||
return newlyAssociatedClients;
|
||||
|
||||
}
|
||||
|
||||
public List<String> associateClients(final Set<Client> clientMembersSet, final List<ApiParameterError> dataValidationErrors) {
|
||||
final List<String> differences = new ArrayList<>();
|
||||
for (final Client client : clientMembersSet) {
|
||||
if (hasClientAsMember(client)) { throw new ClientExistInGroupException(client.getId(), getId()); }
|
||||
@@ -329,13 +318,6 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
differences.add(client.getId().toString());
|
||||
}
|
||||
|
||||
/*
|
||||
* Minimum and maximum number of client rule is applicable only for active group
|
||||
*/
|
||||
if (isActive()) {
|
||||
validateGroupHasMoreThanRequiredNumberOfClientsAngLogError(dataValidationErrors);
|
||||
}
|
||||
|
||||
return differences;
|
||||
}
|
||||
|
||||
@@ -352,7 +334,7 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
|
||||
return differences;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasClientAsMember(final Client client) {
|
||||
return this.clientMembers.contains(client);
|
||||
}
|
||||
@@ -425,6 +407,10 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
return this.groupLevel.isCenter();
|
||||
}
|
||||
|
||||
public boolean isGroup() {
|
||||
return this.groupLevel.isGroup();
|
||||
}
|
||||
|
||||
public boolean isTransferInProgress() {
|
||||
return GroupingTypeStatus.fromInt(this.status).isTransferInProgress();
|
||||
}
|
||||
@@ -512,7 +498,6 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
.getParent().getId(), group.getId());
|
||||
}
|
||||
|
||||
|
||||
this.groupMembers.add(group);
|
||||
differences.add(group.getId().toString());
|
||||
}
|
||||
@@ -535,76 +520,55 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
return differences;
|
||||
}
|
||||
|
||||
public void validateRequiredNumberOfClientPerGroupAngLogError(final List<ApiParameterError> dataValidationErrors) {
|
||||
public Boolean isGroupsClientCountWithinMinMaxRange(Integer minClients, Integer maxClients) {
|
||||
|
||||
if (!hasGroupRequiredNumberOfClients()) {
|
||||
if (maxClients == null && minClients == null) { return true; }
|
||||
|
||||
// This validation not strictly related to a parameter, that is the
|
||||
// reason parameterName is set null
|
||||
|
||||
final String parameterName = null;
|
||||
final String globalisationMessageCode = "error.msg.group.activation.without.required.number.of.members";
|
||||
final String defaultUserMessage = "Group should have number of members between " + this.groupLevel.getMinClients() + " and "
|
||||
+ this.groupLevel.getMaxClients();
|
||||
final ApiParameterError error = ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage, parameterName);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
// set minClients or maxClients to 0 if null
|
||||
|
||||
if (minClients == null) {
|
||||
minClients = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean hasGroupRequiredNumberOfClients() {
|
||||
|
||||
/*
|
||||
* If maximum clients required per group is set to zero or less then zero
|
||||
* then irrespective of minimum required number, below condition returns true
|
||||
* that means this is rule is not validated
|
||||
*/
|
||||
|
||||
if (this.clientMembers.size() >= this.groupLevel.getMinClients()
|
||||
&& (this.clientMembers.size() < this.groupLevel.getMaxClients() || this.groupLevel.getMaxClients() <= 0)) { return true; }
|
||||
if (maxClients == null) {
|
||||
maxClients = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
Set<Client> activeClientMembers = getActiveClientMembers();
|
||||
|
||||
if (activeClientMembers.size() >= minClients && activeClientMembers.size() <= maxClients) { return true; }
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public void validateGroupHasMoreThanRequiredNumberOfClientsAngLogError(final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (hasGroupMoreThanRequiredNumberOfClients()) {
|
||||
|
||||
// This validation not strictly related to a parameter, that is the
|
||||
// reason parameterName is set null
|
||||
|
||||
final String parameterName = null;
|
||||
final String globalisationMessageCode = "error.msg.group.can.not.have.more.than.required.number.of.members";
|
||||
final String defaultUserMessage = "Group should have number of members between " + this.groupLevel.getMinClients() + " and "
|
||||
+ this.groupLevel.getMaxClients();
|
||||
final ApiParameterError error = ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage, parameterName);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
public Boolean isGroupsClientCountWithinMaxRange(Integer maxClients) {
|
||||
Set<Client> activeClientMembers = getActiveClientMembers();
|
||||
if (maxClients == null) {
|
||||
return true;
|
||||
} else if (activeClientMembers.size() <= maxClients) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean hasGroupMoreThanRequiredNumberOfClients(){
|
||||
/*
|
||||
* If maximum clients required per group is set to zero or less then zero
|
||||
* then below condition returns always false
|
||||
* that means this is rule is not validated and group can have unlimited number of clients.
|
||||
*/
|
||||
|
||||
if (this.clientMembers.size() > this.groupLevel.getMaxClients() && this.groupLevel.getMaxClients() > 0) { return true; }
|
||||
return false;
|
||||
|
||||
public Set<Client> getActiveClientMembers() {
|
||||
Set<Client> activeClientMembers = new HashSet<>();
|
||||
for (Client client : this.clientMembers) {
|
||||
if (client.isActive()) {
|
||||
activeClientMembers.add(client);
|
||||
}
|
||||
}
|
||||
return activeClientMembers;
|
||||
}
|
||||
|
||||
|
||||
private void validateActivationDate(final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (getSubmittedOnDate() != null && isDateInTheFuture(getSubmittedOnDate())) {
|
||||
|
||||
final String defaultUserMessage = "Submitted on date cannot be in the future.";
|
||||
final String globalisationMessageCode = "error.msg.group.submittedOnDate.in.the.future";
|
||||
final ApiParameterError error = ApiParameterError.parameterError(globalisationMessageCode ,
|
||||
defaultUserMessage, GroupingTypesApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
||||
final ApiParameterError error = ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage,
|
||||
GroupingTypesApiConstants.submittedOnDateParamName, this.submittedOnDate);
|
||||
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
@@ -638,11 +602,11 @@ public final class Group extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateStatusNotEqualToActiveAndLogError(final List<ApiParameterError> dataValidationErrors){
|
||||
|
||||
private void validateStatusNotEqualToActiveAndLogError(final List<ApiParameterError> dataValidationErrors) {
|
||||
|
||||
if (isActive()) {
|
||||
final String defaultUserMessage = "Cannot activate group. Group is already active.";
|
||||
final String globalisationMessageCode = "error.msg.group.already.active";
|
||||
final String globalisationMessageCode = "error.msg.group.already.active";
|
||||
final ApiParameterError error = ApiParameterError.parameterError(globalisationMessageCode, defaultUserMessage,
|
||||
GroupingTypesApiConstants.activeParamName, true);
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
+5
-19
@@ -30,12 +30,6 @@ public class GroupLevel extends AbstractPersistable<Long> {
|
||||
@Column(name = "can_have_clients", nullable = false)
|
||||
private boolean canHaveClients = false;
|
||||
|
||||
@Column(name = "min_clients", nullable = false)
|
||||
private final Long minClients;
|
||||
|
||||
@Column(name = "max_clients", nullable = false)
|
||||
private final Long maxClients;
|
||||
|
||||
public GroupLevel() {
|
||||
|
||||
this.parentId = null;
|
||||
@@ -43,22 +37,17 @@ public class GroupLevel extends AbstractPersistable<Long> {
|
||||
this.levelName = null;
|
||||
this.recursable = false;
|
||||
this.canHaveClients = false;
|
||||
this.minClients = null;
|
||||
this.maxClients = null;
|
||||
|
||||
}
|
||||
|
||||
public GroupLevel(final Long parentId, final boolean isSuperParent, final String levelName, final boolean recursable,
|
||||
final boolean canHaveClients, final Long minClients, final Long maxClients) {
|
||||
final boolean canHaveClients) {
|
||||
|
||||
this.superParent = isSuperParent;
|
||||
this.parentId = parentId;
|
||||
this.levelName = levelName;
|
||||
this.recursable = recursable;
|
||||
this.canHaveClients = canHaveClients;
|
||||
this.minClients = minClients;
|
||||
this.maxClients = maxClients;
|
||||
|
||||
}
|
||||
|
||||
public Long getParentId() {
|
||||
@@ -88,12 +77,9 @@ public class GroupLevel extends AbstractPersistable<Long> {
|
||||
public boolean isCenter() {
|
||||
return this.levelName.equalsIgnoreCase("Center");
|
||||
}
|
||||
|
||||
public Long getMinClients(){
|
||||
return this.minClients;
|
||||
}
|
||||
|
||||
public Long getMaxClients(){
|
||||
return this.maxClients;
|
||||
|
||||
public boolean isGroup() {
|
||||
return this.levelName.equalsIgnoreCase("Group");
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 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.portfolio.group.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class GroupMemberCountNotInPermissibleRangeException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public GroupMemberCountNotInPermissibleRangeException(final Long groupId, final Integer minClients, final Integer maxClients) {
|
||||
super("error.msg.group.members.count.must.be.in.permissible.range", "Number of members in the group with Id " + groupId
|
||||
+ " should be between " + minClients + " and " + maxClients, groupId, minClients, maxClients);
|
||||
}
|
||||
|
||||
}
|
||||
+32
-1
@@ -19,6 +19,7 @@ import org.mifosplatform.commands.service.CommandProcessingService;
|
||||
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepositoryWrapper;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
@@ -47,6 +48,7 @@ import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.group.domain.GroupTypes;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupAccountExistsException;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupHasNoStaffException;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupMemberCountNotInPermissibleRangeException;
|
||||
import org.mifosplatform.portfolio.group.exception.GroupMustBePendingToBeDeletedException;
|
||||
import org.mifosplatform.portfolio.group.exception.InvalidGroupLevelException;
|
||||
import org.mifosplatform.portfolio.group.exception.InvalidGroupStateTransitionException;
|
||||
@@ -85,6 +87,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
private final SavingsAccountRepository savingsRepository;
|
||||
private final CommandProcessingService commandProcessingService;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public GroupingTypesWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -93,7 +96,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
final GroupLevelRepository groupLevelRepository, final GroupingTypesDataValidator fromApiJsonDeserializer,
|
||||
final LoanRepository loanRepository, final SavingsAccountRepository savingsRepository,
|
||||
final CodeValueRepositoryWrapper codeValueRepository, final CommandProcessingService commandProcessingService,
|
||||
final CalendarInstanceRepository calendarInstanceRepository) {
|
||||
final CalendarInstanceRepository calendarInstanceRepository, final ConfigurationDomainService configurationDomainService) {
|
||||
this.context = context;
|
||||
this.groupRepository = groupRepository;
|
||||
this.clientRepositoryWrapper = clientRepositoryWrapper;
|
||||
@@ -107,6 +110,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
this.codeValueRepository = codeValueRepository;
|
||||
this.commandProcessingService = commandProcessingService;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
private CommandProcessingResult createGroupingType(final JsonCommand command, final GroupTypes groupingType, final Long centerId) {
|
||||
@@ -157,6 +161,11 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
|
||||
boolean rollbackTransaction = false;
|
||||
if (newGroup.isActive()) {
|
||||
// validate Group creation rules for Group
|
||||
if (newGroup.isGroup()) {
|
||||
validateGroupRulesBeforeActivation(newGroup);
|
||||
}
|
||||
|
||||
if (newGroup.isCenter()) {
|
||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateCenter(null).build();
|
||||
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
|
||||
@@ -226,6 +235,10 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
|
||||
final Group group = this.groupRepository.findOneWithNotFoundDetection(groupId);
|
||||
|
||||
if (group.isGroup()) {
|
||||
validateGroupRulesBeforeActivation(group);
|
||||
}
|
||||
|
||||
final LocalDate activationDate = command.localDateValueOfParameterNamed("activationDate");
|
||||
|
||||
validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(group.getOffice(), group.getGroupLevel(), activationDate);
|
||||
@@ -245,6 +258,20 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
}
|
||||
}
|
||||
|
||||
private void validateGroupRulesBeforeActivation(final Group group) {
|
||||
Integer minClients = configurationDomainService.retrieveMinAllowedClientsInGroup();
|
||||
Integer maxClients = configurationDomainService.retrieveMaxAllowedClientsInGroup();
|
||||
boolean isGroupClientCountValid = group.isGroupsClientCountWithinMinMaxRange(minClients, maxClients);
|
||||
if (!isGroupClientCountValid) { throw new GroupMemberCountNotInPermissibleRangeException(group.getId(), minClients, maxClients); }
|
||||
}
|
||||
|
||||
public void validateGroupRulesBeforeClientAssociation(final Group group) {
|
||||
Integer minClients = configurationDomainService.retrieveMinAllowedClientsInGroup();
|
||||
Integer maxClients = configurationDomainService.retrieveMaxAllowedClientsInGroup();
|
||||
boolean isGroupClientCountValid = group.isGroupsClientCountWithinMaxRange(maxClients);
|
||||
if (!isGroupClientCountValid) { throw new GroupMemberCountNotInPermissibleRangeException(group.getId(), minClients, maxClients); }
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult updateCenter(final Long centerId, final JsonCommand command) {
|
||||
@@ -645,6 +672,10 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
||||
final Map<String, Object> actualChanges = new HashMap<>();
|
||||
|
||||
final List<String> changes = groupForUpdate.associateClients(clientMembers);
|
||||
|
||||
if (groupForUpdate.isGroup()) {
|
||||
validateGroupRulesBeforeClientAssociation(groupForUpdate);
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
actualChanges.put(GroupingTypesApiConstants.clientMembersParamName, changes);
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
INSERT INTO `c_configuration` (`id`, `name`,`value`, `enabled`, `description`)
|
||||
VALUES (NULL, 'min-clients-in-group', '5', '0',"Minimum number of Clients that a Group should have");
|
||||
|
||||
INSERT INTO `c_configuration` (`id`, `name`, `value`, `enabled`, `description`)
|
||||
VALUES (NULL, 'max-clients-in-group', '5', '0', "Maximum number of Clients that a Group can have");
|
||||
|
||||
ALTER TABLE `m_group_level`
|
||||
DROP COLUMN `min_clients`,
|
||||
DROP COLUMN `max_clients`;
|
||||
Reference in New Issue
Block a user