diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java index 664dd5c1ce7..3e9c0c6f291 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java @@ -42,10 +42,9 @@ private AccountNumberFormatEnumerations() { .unmodifiableSet(new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, AccountNumberPrefixType.LOAN_PRODUCT_SHORT_NAME, AccountNumberPrefixType.PREFIX_SHORT_NAME))); - public static final Set accountNumberPrefixesForSavingsAccounts = Collections - .unmodifiableSet(new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, - AccountNumberPrefixType.SAVINGS_PRODUCT_SHORT_NAME, AccountNumberPrefixType.PREFIX_SHORT_NAME, - AccountNumberPrefixType.SAVINGS_CLIENT_ID))); + public static final Set accountNumberPrefixesForSavingsAccounts = Collections.unmodifiableSet( + new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, AccountNumberPrefixType.SAVINGS_PRODUCT_SHORT_NAME, + AccountNumberPrefixType.PREFIX_SHORT_NAME, AccountNumberPrefixType.SAVINGS_CLIENT_ID))); public static final Set accountNumberPrefixesForCenters = Collections .unmodifiableSet(new HashSet<>(Collections.singletonList(AccountNumberPrefixType.OFFICE_NAME))); @@ -60,7 +59,7 @@ public enum AccountNumberPrefixType { "accountNumberPrefixType.loanProductShortName"), SAVINGS_PRODUCT_SHORT_NAME(301, "accountNumberPrefixType.savingsProductShortName"), PREFIX_SHORT_NAME(401, "accountNumberPrefixType.prefixShortName"), SAVINGS_CLIENT_ID(501, - "accountNumberPrefixType.savingsAccountClientId"); + "accountNumberPrefixType.savingsAccountClientId"); private final Integer value; private final String code; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformService.java index c5b75439f22..cf9a624fca6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformService.java @@ -18,7 +18,6 @@ */ package org.apache.fineract.organisation.bankcheque.service; - import java.util.List; import org.apache.fineract.infrastructure.core.data.PaginationParameters; import org.apache.fineract.infrastructure.core.service.Page; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformServiceImpl.java index fac35be36c5..531c195cb72 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeReadPlatformServiceImpl.java @@ -18,7 +18,6 @@ */ package org.apache.fineract.organisation.bankcheque.service; - import com.google.gson.JsonArray; import com.google.gson.JsonElement; import java.math.BigDecimal; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/centerGroup/domain/CenterGroupRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/centerGroup/domain/CenterGroupRepositoryWrapper.java index 2c54161770f..1a16c843154 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/centerGroup/domain/CenterGroupRepositoryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/centerGroup/domain/CenterGroupRepositoryWrapper.java @@ -55,7 +55,7 @@ public List findOverLappingCenterGroups(Long portfolioCenter, Local } public Collection findCenterGroupsByCenterIdAndMeetingTimes(final Long center, final LocalTime startTime, - final LocalTime endTime) { + final LocalTime endTime) { return this.repository.findCenterGroupsByCenterIdAndMeetingTimes(center, startTime, endTime); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/portfolioCenter/service/PortfolioCenterConstants.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/portfolioCenter/service/PortfolioCenterConstants.java index b55ec32235a..79e0811d06a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/portfolioCenter/service/PortfolioCenterConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/portfolioCenter/service/PortfolioCenterConstants.java @@ -42,11 +42,11 @@ public enum PortfolioCenterSupportedParameters { PORTFOLIO_CENTER_ID("id"), NAME("name"), PORTFOLIO_ID("portfolioId"), PORTFOLIO_NAME("portfolioName"), OFFICE_PARENT_ID( "parentId"), RESPONSIBLE_USER_ID("responsibleUserId"), CITY_ID("cityId"), STATE_ID("stateId"), CENTER_TYPE( - "centerTypeId"), LEGACY_CENTER_NUMBER("legacyCenterNumber"), DISTANCE( - "distance"), CREATED_DATE("createdDate"), STATUS_ID("statusId"), MEETING_START("meetingStart"), MEETING_END( - "meetingEnd"), MEETING_DAY("meetingDay"), MEETING_START_TIME("meetingStartTime"), MEETING_END_TIME( - "meetingEndTime"), REFERENCE_POINT("referencePoint"), LOCALE( - "locale"), DATEFORMAT("dateFormat"), CENTER_LOCATION("centerLocation"); + "centerTypeId"), LEGACY_CENTER_NUMBER("legacyCenterNumber"), DISTANCE( + "distance"), CREATED_DATE("createdDate"), STATUS_ID("statusId"), MEETING_START("meetingStart"), MEETING_END( + "meetingEnd"), MEETING_DAY("meetingDay"), MEETING_START_TIME("meetingStartTime"), MEETING_END_TIME( + "meetingEndTime"), REFERENCE_POINT("referencePoint"), LOCALE( + "locale"), DATEFORMAT("dateFormat"), CENTER_LOCATION("centerLocation"); private final String value; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/GroupPrequalificationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/GroupPrequalificationApiResource.java index b4d44879859..5ebfa819af2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/GroupPrequalificationApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/GroupPrequalificationApiResource.java @@ -182,7 +182,7 @@ public String newClientIdentifierDetails(@Context final UriInfo uriInfo) { Long agencyId = null; Long centerId = null; - if (!StringUtils.isBlank(groupId)){ + if (!StringUtils.isBlank(groupId)) { GroupPrequalificationData prequalificationGroup = this.prequalificationReadPlatformService.retrieveOne(Long.valueOf(groupId)); agencyId = prequalificationGroup.getAgencyId(); centerId = prequalificationGroup.getCenterId(); @@ -212,7 +212,7 @@ public String newClientIdentifierDetails(@Context final UriInfo uriInfo) { } final String hierarchy = this.context.authenticatedUser().getOffice().getHierarchy(); - Collection centerData =null; + Collection centerData = null; if (agencyId != null) { centerData = this.centerReadPlatformService.retrieveByOfficeHierarchy(hierarchy, agencyId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/command/PrequalificationDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/command/PrequalificationDataValidator.java index 0ceda74b0f0..d2bf6b6cbea 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/command/PrequalificationDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/command/PrequalificationDataValidator.java @@ -44,7 +44,7 @@ public class PrequalificationDataValidator { @Autowired public PrequalificationDataValidator(final FromJsonHelper fromApiJsonHelper, - final PreQualificationGroupRepository preQualificationGroupRepository) { + final PreQualificationGroupRepository preQualificationGroupRepository) { this.fromApiJsonHelper = fromApiJsonHelper; this.preQualificationGroupRepository = preQualificationGroupRepository; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupMemberData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupMemberData.java index a54e0af9c35..3dcac6d68a5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupMemberData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupMemberData.java @@ -36,7 +36,7 @@ public class GroupMemberData { private BigDecimal requestedAmount; public GroupMemberData(final Long id, final String name, final LocalDate dob, final String dpi, final EnumOptionData status, - final String workWithPuente, final BigDecimal requestedAmount) { + final String workWithPuente, final BigDecimal requestedAmount) { this.id = id; this.name = name; this.dpi = dpi; @@ -48,7 +48,7 @@ public GroupMemberData(final Long id, final String name, final LocalDate dob, fi } public static GroupMemberData instance(final Long id, final String name, final LocalDate dob, final String dpi, - final EnumOptionData status, final String workWithPuente, final BigDecimal requestedAmount) { + final EnumOptionData status, final String workWithPuente, final BigDecimal requestedAmount) { return new GroupMemberData(id, name, dob, dpi, status, workWithPuente, requestedAmount); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsMemberEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsMemberEnumerations.java index 0cb6ef7a9bf..a13ae480d2c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsMemberEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsMemberEnumerations.java @@ -41,11 +41,11 @@ public static EnumOptionData status(final PrequalificationMemberIndication statu case INVALID: optionData = new EnumOptionData(PrequalificationMemberIndication.INVALID.getValue().longValue(), PrequalificationMemberIndication.INVALID.getCode(), "INVALID"); - break; + break; case ACTIVE: optionData = new EnumOptionData(PrequalificationMemberIndication.ACTIVE.getValue().longValue(), PrequalificationMemberIndication.ACTIVE.getCode(), "ACTIVE"); - break; + break; case INACTIVE: optionData = new EnumOptionData(PrequalificationMemberIndication.INACTIVE.getValue().longValue(), PrequalificationMemberIndication.INACTIVE.getCode(), "INACTIVE"); @@ -57,7 +57,7 @@ public static EnumOptionData status(final PrequalificationMemberIndication statu case NONE: optionData = new EnumOptionData(PrequalificationMemberIndication.NONE.getValue().longValue(), PrequalificationMemberIndication.NONE.getCode(), "NONE"); - break; + break; } return optionData; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroupMember.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroupMember.java index 90660b16cfa..a2f91768742 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroupMember.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroupMember.java @@ -165,8 +165,7 @@ public Map update(JsonCommand command) { } if (command.isChangeInBigDecimalParameterNamed(PrequalificatoinApiConstants.approvedAmountParamName, this.approvedAmount)) { - final BigDecimal newValue = command - .bigDecimalValueOfParameterNamed(PrequalificatoinApiConstants.approvedAmountParamName); + final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(PrequalificatoinApiConstants.approvedAmountParamName); actualChanges.put(PrequalificatoinApiConstants.approvedAmountParamName, newValue); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationMemberIndication.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationMemberIndication.java index bf25a93356f..b49fd2bf9ef 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationMemberIndication.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationMemberIndication.java @@ -41,10 +41,10 @@ public static PrequalificationMemberIndication fromInt(final Integer statusValue switch (statusValue) { case 100: enumeration = PrequalificationMemberIndication.ACTIVE; - break; + break; case 200: enumeration = PrequalificationMemberIndication.INACTIVE; - break; + break; case 300: enumeration = PrequalificationMemberIndication.NONE; break; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/MemberHasNoPendingLoanException.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/MemberHasNoPendingLoanException.java index 7a9dc6003fd..724094c3179 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/MemberHasNoPendingLoanException.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/MemberHasNoPendingLoanException.java @@ -26,6 +26,7 @@ public class MemberHasNoPendingLoanException extends AbstractPlatformResourceNotFoundException { public MemberHasNoPendingLoanException(String name, String dpi, String product) { - super("error.msg.client.pending.loan.request", "Client "+name+ " with dpi " + dpi + " doesnt have a pending loan request.", name, dpi, product); + super("error.msg.client.pending.loan.request", "Client " + name + " with dpi " + dpi + " doesnt have a pending loan request.", name, + dpi, product); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationIncorrectStatusException.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationIncorrectStatusException.java new file mode 100644 index 00000000000..587ab954ab0 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationIncorrectStatusException.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.organisation.prequalification.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +/** + * A {@link RuntimeException} thrown when client is already blacklisted. + */ +public class PrequalificationIncorrectStatusException extends AbstractPlatformResourceNotFoundException { + + public PrequalificationIncorrectStatusException(String status) { + super("error.msg.group.prequalification.status.not.correct", "Provided Prequalificaiton has incorrect status " + status, status); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotMappedException.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotMappedException.java index 5e59b6d84e8..e6633cf8544 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotMappedException.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotMappedException.java @@ -24,7 +24,8 @@ public class PrequalificationNotMappedException extends AbstractPlatformDomainRu public PrequalificationNotMappedException(final String prequalificationId) { super("error.msg.prequalification.not.mapped.exception", - "The Prequalification `" + prequalificationId + "` Should be mapped to a group before validating hard policies. ", prequalificationId); + "The Prequalification `" + prequalificationId + "` Should be mapped to a group before validating hard policies. ", + prequalificationId); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotProvidedException.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotProvidedException.java new file mode 100644 index 00000000000..e084f4ce9fc --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationNotProvidedException.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.organisation.prequalification.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +/** + * A {@link RuntimeException} thrown when client is already blacklisted. + */ +public class PrequalificationNotProvidedException extends AbstractPlatformResourceNotFoundException { + + public PrequalificationNotProvidedException() { + super("error.msg.group.prequalification.is.not.provided", "Prequalification is a mandatory"); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistWritePlatformServiceImpl.java index 54e67936e04..441937d6d5e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistWritePlatformServiceImpl.java @@ -168,8 +168,9 @@ private void validateMemberLoanRequest(PrequalificationGroup group) { List members = group.getMembers(); for (PrequalificationGroupMember member : members) { String pendingLoanRequest = "select count(*) from m_loan ml inner join m_client mc on mc.id = ml.client_id where mc.dpi=? AND ml.loan_status_id = 100 and ml.product_id = ?"; - Long loanCount = this.jdbcTemplate.queryForObject(pendingLoanRequest, Long.class, member.getDpi(),group.getLoanProduct().getId()); - if (loanCount<=0) + Long loanCount = this.jdbcTemplate.queryForObject(pendingLoanRequest, Long.class, member.getDpi(), + group.getLoanProduct().getId()); + if (loanCount <= 0) throw new MemberHasNoPendingLoanException(member.getName(), member.getDpi(), group.getLoanProduct().getName()); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformServiceImpl.java index 0e2c7407692..383a894d10c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformServiceImpl.java @@ -84,11 +84,11 @@ public class PrequalificationReadPlatformServiceImpl implements Prequalification @Autowired public PrequalificationReadPlatformServiceImpl(final PlatformSecurityContext context, final PaginationHelper paginationHelper, - final DatabaseSpecificSQLGenerator sqlGenerator, final ColumnValidator columnValidator, - final PrequalificationDataValidator dataValidator, final LoanProductRepository loanProductRepository, - final PreQualificationMemberRepository preQualificationMemberRepository, - final ClientReadPlatformService clientReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService, - final JdbcTemplate jdbcTemplate) { + final DatabaseSpecificSQLGenerator sqlGenerator, final ColumnValidator columnValidator, + final PrequalificationDataValidator dataValidator, final LoanProductRepository loanProductRepository, + final PreQualificationMemberRepository preQualificationMemberRepository, + final ClientReadPlatformService clientReadPlatformService, final CodeValueReadPlatformService codeValueReadPlatformService, + final JdbcTemplate jdbcTemplate) { this.context = context; this.dataValidator = dataValidator; @@ -260,7 +260,7 @@ public Collection retrievePrequalificationGroupsMappi @Override public Collection retrievePrequalificationIndividualMappings(final Long clientId) { - final String sql = "select " + this.prequalificationIndividualMappingsMapper.schema() + " WHERE mc.id = ?"; + final String sql = "select " + this.prequalificationIndividualMappingsMapper.schema() + " WHERE mc.id = ? AND mpg.status = 600"; final Collection prequalificationGroups = this.jdbcTemplate.query(sql, this.prequalificationIndividualMappingsMapper, new Object[] { clientId }); return prequalificationGroups; @@ -582,11 +582,11 @@ public GroupPrequalificationData mapRow(final ResultSet rs, final int rowNum) th } } - private static final class PrequalificationIndividualMappingsMapper implements RowMapper { + public static final class PrequalificationIndividualMappingsMapper implements RowMapper { private final String schema; - PrequalificationIndividualMappingsMapper() { + public PrequalificationIndividualMappingsMapper() { this.schema = """ mpg.id AS id, mpg.prequalification_number AS prequalificationNumber, mpg.group_name AS groupName, mpg.status AS status, mpl.name AS productName, mpg.created_at, ma.firstname, ma.lastname diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformServiceImpl.java index 02a5e88f88c..8a889999b3a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformServiceImpl.java @@ -37,6 +37,7 @@ import java.util.concurrent.atomic.AtomicReference; import javax.transaction.Transactional; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; import org.apache.fineract.infrastructure.core.api.JsonCommand; @@ -106,7 +107,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Service; -import org.springframework.util.ObjectUtils; @Service @Slf4j @@ -545,7 +545,7 @@ public CommandProcessingResult updatePrequalificationGroupMember(Long memberId, } private List assembleMembersForUpdate(JsonCommand command, PrequalificationGroup prequalificationGroup, - AppUser addedBy) { + AppUser addedBy) { final List allMembers = new ArrayList<>(); @@ -855,9 +855,11 @@ public CommandProcessingResult processAnalysisRequest(Long entityId, JsonCommand } } - this.approveOrRejectLoanApplications(prequalificationGroup, prequalificationStatus, memberPrequalificationDataList); - - if (prequalificationGroup.isPrequalificationTypeIndividual() && action.equals("approveanalysis")) { + final Long productId = prequalificationGroup.getLoanProduct().getId(); + final LoanProduct loanProduct = this.loanProductRepository.findById(productId) + .orElseThrow(() -> new LoanProductNotFoundException(productId)); + final Boolean requireCommitteeApproval = ObjectUtils.defaultIfNull(loanProduct.getRequireCommitteeApproval(), Boolean.FALSE); + if (prequalificationGroup.isPrequalificationTypeIndividual() && action.equals("approveanalysis") && requireCommitteeApproval) { PrequalificationStatusRange statusRange = resolveIndividualStatusRange(prequalificationGroup, action); prequalificationStatus = PrequalificationStatus.fromInt(statusRange.getStatus()); @@ -876,7 +878,7 @@ public CommandProcessingResult processAnalysisRequest(Long entityId, JsonCommand PrequalificationStatusLog newStatusLog = PrequalificationStatusLog.fromJson(addedBy, fromStatus, prequalificationGroup.getStatus(), comments, prequalificationGroup); - + this.approveOrRejectLoanApplications(prequalificationGroup, prequalificationStatus, memberPrequalificationDataList); this.preQualificationLogRepository.saveAndFlush(newStatusLog); List currentLogs = this.preQualificationLogRepository.groupStatusLogs(fromStatus, prequalificationGroup); @@ -905,16 +907,19 @@ private void approveOrRejectLoanApplications(final PrequalificationGroup prequal } final PrequalificationGroupMember prequalificationGroupMember = memberOptional.get(); final boolean isApproved = PrequalificationStatus.COMPLETED.equals(prequalificationStatus) - && memberPrequalificationData.getIsSelected(); + && (memberPrequalificationData.getIsSelected() || prequalificationGroup.isPrequalificationTypeIndividual()); + final boolean isRejected = PrequalificationStatus.REJECTED.equals(prequalificationStatus) + || (!memberPrequalificationData.getIsSelected() && PrequalificationStatus.COMPLETED.equals(prequalificationStatus) + && prequalificationGroup.isPrequalificationTypeGroup()); final BigDecimal approvedLoanAmount = prequalificationGroupMember.getApprovedAmount(); final String dpi = prequalificationGroupMember.getDpi(); List submittedLoans; if (prequalificationGroup.isPrequalificationTypeGroup()) { submittedLoans = jdbcTemplate.query(this.groupTypeLoanMapper.schema(), this.groupTypeLoanMapper, - new Object[] { prequalificationId, dpi }); + new Object[] { prequalificationId, dpi, prequalificationId }); } else { submittedLoans = jdbcTemplate.query(this.individualTypeLoanMapper.schema(), this.individualTypeLoanMapper, - new Object[] { prequalificationId, dpi }); + new Object[] { prequalificationId, dpi, prequalificationId }); } if (submittedLoans.isEmpty()) { throw new MemberSubmittedLoanNotFoundException(dpi); @@ -944,7 +949,7 @@ private void approveOrRejectLoanApplications(final PrequalificationGroup prequal groupId, clientId, loanId, null, null, null, null, null, null); command.setJsonCommand(jsonObject.toString()); this.loanApplicationWritePlatformService.approveApplication(loanId, command); - } else { + } else if (isRejected) { final String note = "Rechazada la precalificación " + prequalificationGroup.getPrequalificationNumber(); jsonObject.addProperty("note", note); jsonObject.addProperty("rejectedOnDate", localDateString); @@ -977,7 +982,7 @@ private GroupTypeLoanMapper() { INNER JOIN m_client mc ON (mgc.client_id = mc.id AND mpgm.dpi = mc.dpi) INNER JOIN m_loan ml ON (ml.client_id = mc.id OR ml.group_id = mg.id) WHERE mpg.id = ? AND mpg.prequalification_type_enum = 2 AND (ml.client_id = (SELECT mt.id FROM m_client mt WHERE mt.dpi = ?)) - AND ml.loan_status_id = 100 + AND ml.loan_status_id = 100 AND ml.prequalification_id = ? GROUP BY ml.id """; } @@ -1014,7 +1019,7 @@ private IndividualTypeLoanMapper() { INNER JOIN m_client mc ON mc.dpi = mpgm.dpi INNER JOIN m_loan ml ON ml.client_id = mc.id WHERE mpg.id = ? AND mpg.prequalification_type_enum = 1 AND (ml.client_id = (SELECT mt.id FROM m_client mt WHERE mt.dpi = ?)) - AND ml.loan_status_id = 100 AND ml.group_id IS NULL + AND ml.loan_status_id = 100 AND ml.prequalification_id = ? """; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java index fa52c0b8f79..b9b8b940a14 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/ClientData.java @@ -141,9 +141,9 @@ public final class ClientData implements Comparable, Serializable { private List economicActivityData; public static ClientData importClientEntityInstance(Long legalFormId, Integer rowIndex, String fullname, Long officeId, - Long clientTypeId, Long clientClassificationId, Long staffId, Boolean active, LocalDate activationDate, - LocalDate submittedOnDate, String externalId, LocalDate dateOfBirth, String mobileNo, - ClientNonPersonData clientNonPersonDetails, Collection address, String locale, String dateFormat) { + Long clientTypeId, Long clientClassificationId, Long staffId, Boolean active, LocalDate activationDate, + LocalDate submittedOnDate, String externalId, LocalDate dateOfBirth, String mobileNo, + ClientNonPersonData clientNonPersonDetails, Collection address, String locale, String dateFormat) { return new ClientData(legalFormId, rowIndex, fullname, null, null, null, submittedOnDate, activationDate, active, externalId, officeId, staffId, mobileNo, dateOfBirth, clientTypeId, null, clientClassificationId, null, address, clientNonPersonDetails, locale, dateFormat); @@ -222,9 +222,9 @@ private ClientData(final Long clientId, final Long officeId) { } public static ClientData importClientPersonInstance(Long legalFormId, Integer rowIndex, String firstname, String lastname, - String middlename, LocalDate submittedOn, LocalDate activationDate, Boolean active, String externalId, Long officeId, - Long staffId, String mobileNo, LocalDate dob, Long clientTypeId, Long genderId, Long clientClassificationId, Boolean isStaff, - Collection address, String locale, String dateFormat) { + String middlename, LocalDate submittedOn, LocalDate activationDate, Boolean active, String externalId, Long officeId, + Long staffId, String mobileNo, LocalDate dob, Long clientTypeId, Long genderId, Long clientClassificationId, Boolean isStaff, + Collection address, String locale, String dateFormat) { return new ClientData(legalFormId, rowIndex, null, firstname, lastname, middlename, submittedOn, activationDate, active, externalId, officeId, staffId, mobileNo, dob, clientTypeId, genderId, clientClassificationId, isStaff, address, null, locale, @@ -236,9 +236,9 @@ public static ClientData emptyInstance(Long clientId) { } private ClientData(Long legalFormId, Integer rowIndex, String fullname, String firstname, String lastname, String middlename, - LocalDate submittedOn, LocalDate activationDate, Boolean active, String externalId, Long officeId, Long staffId, - String mobileNo, LocalDate dob, Long clientTypeId, Long genderId, Long clientClassificationId, Boolean isStaff, - Collection address, ClientNonPersonData clientNonPersonDetails, String locale, String dateFormat) { + LocalDate submittedOn, LocalDate activationDate, Boolean active, String externalId, Long officeId, Long staffId, + String mobileNo, LocalDate dob, Long clientTypeId, Long genderId, Long clientClassificationId, Boolean isStaff, + Collection address, ClientNonPersonData clientNonPersonDetails, String locale, String dateFormat) { this.rowIndex = rowIndex; this.dateFormat = dateFormat; this.locale = locale; @@ -395,7 +395,7 @@ public static ClientData templateOnTop(final ClientData clientData, final Client } public static ClientData templateWithSavingAccountOptions(final ClientData clientData, - final Collection savingAccountOptions) { + final Collection savingAccountOptions) { final Set clientCollateralManagements = null; return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName, clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, @@ -416,7 +416,7 @@ public static ClientData templateWithSavingAccountOptions(final ClientData clien } public static ClientData setParentGroups(final ClientData clientData, final Collection parentGroups, - final Set clientCollateralManagements, ClientContactInformationData contactInformation) { + final Set clientCollateralManagements, ClientContactInformationData contactInformation) { return new ClientData(clientData.accountNo, clientData.status, clientData.subStatus, clientData.officeId, clientData.officeName, clientData.transferToOfficeId, clientData.transferToOfficeName, clientData.id, clientData.firstname, clientData.middlename, clientData.lastname, clientData.fullname, clientData.displayName, clientData.externalId, clientData.mobileNo, @@ -435,7 +435,7 @@ public static ClientData setParentGroups(final ClientData clientData, final Coll } public static ClientData clientIdentifier(final Long id, final String accountNo, final String firstname, final String middlename, - final String lastname, final String fullname, final String displayName, final Long officeId, final String officeName) { + final String lastname, final String fullname, final String displayName, final Long officeId, final String officeName) { final Long transferToOfficeId = null; final String transferToOfficeName = null; @@ -777,8 +777,8 @@ public LocalDate getDateOfBirth() { } public void updateClientAddressTemplate(Collection clientAreas, Collection clientLocation, - Collection publicServices, Collection housingTypeOptions, Collection ldepartamento, - Collection lmunicipio) { + Collection publicServices, Collection housingTypeOptions, Collection ldepartamento, + Collection lmunicipio) { this.clientAreaOptions = clientAreas; this.clientLocationOptions = clientLocation; this.publicServiceOptions = publicServices; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java index c3ca8b08892..f357a1867fe 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java @@ -18,6 +18,8 @@ */ package org.apache.fineract.portfolio.client.domain; +import static org.apache.fineract.portfolio.savings.SavingsApiConstants.GURANTEE_PRODUCT_NAME; + import java.math.BigInteger; import java.util.HashMap; import java.util.Map; @@ -38,8 +40,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import static org.apache.fineract.portfolio.savings.SavingsApiConstants.GURANTEE_PRODUCT_NAME; - /** * Example {@link AccountNumberGenerator} for clients that takes an entities auto generated database id and zero fills * it ensuring the identifier is always of a given maxLength. @@ -55,7 +55,7 @@ public class AccountNumberGenerator { private static final String OFFICE_NAME = "officeName"; private static final String LOAN_PRODUCT_SHORT_NAME = "loanProductShortName"; private static final String SAVINGS_PRODUCT_SHORT_NAME = "savingsProductShortName"; - private static final String SAVINGS_CLIENT_ID= "savingsAccountClientId"; + private static final String SAVINGS_CLIENT_ID = "savingsAccountClientId"; private static final String SHARE_PRODUCT_SHORT_NAME = "sharesProductShortName"; private static final String PREFIX_SHORT_NAME = "prefixShortName"; private final AccountNumberFormatRepository accountNumberFormatRepository; @@ -101,7 +101,7 @@ public String generate(SavingsAccount savingsAccount, AccountNumberFormat accoun propertyMap.put(ID, savingsAccount.getId().toString()); propertyMap.put(OFFICE_NAME, savingsAccount.office().getName()); propertyMap.put(SAVINGS_PRODUCT_SHORT_NAME, savingsAccount.savingsProduct().getShortName()); - if(savingsAccount.savingsProduct().getName().equals(GURANTEE_PRODUCT_NAME)){ + if (savingsAccount.savingsProduct().getName().equals(GURANTEE_PRODUCT_NAME)) { propertyMap.put(SAVINGS_CLIENT_ID, String.valueOf(savingsAccount.clientId())); } propertyMap.put(ENTITY_TYPE, "savingsAccount"); @@ -165,7 +165,7 @@ private String generateAccountNumber(Map propertyMap, AccountNum case SAVINGS_CLIENT_ID: prefix = propertyMap.get(SAVINGS_CLIENT_ID); - break; + break; } // FINERACT-590 diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 21686661578..c675a445b47 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -105,8 +105,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import static org.apache.fineract.portfolio.savings.SavingsApiConstants.GURANTEE_PRODUCT_NAME; - @Service @Slf4j public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWritePlatformService { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java index 10ba3446c23..ce4ea0edb2a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/CentersApiResource.java @@ -116,16 +116,16 @@ public class CentersApiResource { @Autowired public CentersApiResource(final PlatformSecurityContext context, final CenterReadPlatformService centerReadPlatformService, - final ToApiJsonSerializer centerApiJsonSerializer, final ToApiJsonSerializer toApiJsonSerializer, - final ToApiJsonSerializer groupSummaryToApiJsonSerializer, - final ApiRequestParameterHelper apiRequestParameterHelper, - final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, - final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper, - final AccountDetailsReadPlatformService accountDetailsReadPlatformService, - final CalendarReadPlatformService calendarReadPlatformService, final MeetingReadPlatformService meetingReadPlatformService, - final EntityDatatableChecksReadService entityDatatableChecksReadService, - final BulkImportWorkbookService bulkImportWorkbookService, - final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService) { + final ToApiJsonSerializer centerApiJsonSerializer, final ToApiJsonSerializer toApiJsonSerializer, + final ToApiJsonSerializer groupSummaryToApiJsonSerializer, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, + final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper, + final AccountDetailsReadPlatformService accountDetailsReadPlatformService, + final CalendarReadPlatformService calendarReadPlatformService, final MeetingReadPlatformService meetingReadPlatformService, + final EntityDatatableChecksReadService entityDatatableChecksReadService, + final BulkImportWorkbookService bulkImportWorkbookService, + final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService) { this.context = context; this.centerReadPlatformService = centerReadPlatformService; this.centerApiJsonSerializer = centerApiJsonSerializer; @@ -152,9 +152,9 @@ public CentersApiResource(final PlatformSecurityContext context, final CenterRea @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.GetCentersTemplateResponse.class))) }) public String retrieveTemplate(@Context final UriInfo uriInfo, - @QueryParam("command") @Parameter(description = "command") final String commandParam, - @QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, - @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly) { + @QueryParam("command") @Parameter(description = "command") final String commandParam, + @QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, + @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly) { this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME); @@ -183,19 +183,19 @@ public String retrieveTemplate(@Context final UriInfo uriInfo, @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.GetCentersResponse.class))) }) public String retrieveAll(@Context final UriInfo uriInfo, - @QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, - @QueryParam("staffId") @Parameter(description = "staffId") final Long staffId, - @QueryParam("externalId") @Parameter(description = "externalId") final String externalId, - @QueryParam("name") @Parameter(description = "name") final String name, - @QueryParam("underHierarchy") @Parameter(description = "underHierarchy") final String hierarchy, - @QueryParam("paged") @Parameter(description = "paged") final Boolean paged, - @QueryParam("offset") @Parameter(description = "offset") final Integer offset, - @QueryParam("limit") @Parameter(description = "limit") final Integer limit, - @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, - @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, - @QueryParam("meetingDate") @Parameter(description = "meetingDate") final DateParam meetingDateParam, - @QueryParam("dateFormat") @Parameter(description = "dateFormat") final String dateFormat, - @QueryParam("locale") @Parameter(description = "locale") final String locale) { + @QueryParam("officeId") @Parameter(description = "officeId") final Long officeId, + @QueryParam("staffId") @Parameter(description = "staffId") final Long staffId, + @QueryParam("externalId") @Parameter(description = "externalId") final String externalId, + @QueryParam("name") @Parameter(description = "name") final String name, + @QueryParam("underHierarchy") @Parameter(description = "underHierarchy") final String hierarchy, + @QueryParam("paged") @Parameter(description = "paged") final Boolean paged, + @QueryParam("offset") @Parameter(description = "offset") final Integer offset, + @QueryParam("limit") @Parameter(description = "limit") final Integer limit, + @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, + @QueryParam("meetingDate") @Parameter(description = "meetingDate") final DateParam meetingDateParam, + @QueryParam("dateFormat") @Parameter(description = "dateFormat") final String dateFormat, + @QueryParam("locale") @Parameter(description = "locale") final String locale) { this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); @@ -228,8 +228,8 @@ public String retrieveAll(@Context final UriInfo uriInfo, @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.GetCentersCenterIdResponse.class))) }) public String retrieveOne(@Context final UriInfo uriInfo, - @PathParam("centerId") @Parameter(description = "centerId") final Long centerId, - @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly) { + @PathParam("centerId") @Parameter(description = "centerId") final Long centerId, + @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly) { this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME); final Set associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); @@ -302,8 +302,8 @@ public String create(@Parameter(hidden = true) final String apiRequestBodyAsJson @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.PostCentersResponse.class))) }) public String modify(@Parameter(hidden = true) final String apiRequestBodyAsJson, - @PathParam("centerId") @Parameter(description = "centerId") final Long centerId, - @PathParam("action") @Parameter(description = "action") final String action) { + @PathParam("centerId") @Parameter(description = "centerId") final Long centerId, + @PathParam("action") @Parameter(description = "action") final String action) { CommandWrapper commandRequest = null; // if (StringUtils.equals(action, "transfer")) { commandRequest = new CommandWrapperBuilder().transferGroup(centerId) // @@ -324,7 +324,7 @@ public String modify(@Parameter(hidden = true) final String apiRequestBodyAsJson @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.PutCentersCenterIdResponse.class))) }) public String update(@PathParam("centerId") @Parameter(description = "centerId") final Long centerId, - @Parameter(hidden = true) final String apiRequestBodyAsJson) { + @Parameter(hidden = true) final String apiRequestBodyAsJson) { final CommandWrapper commandRequest = new CommandWrapperBuilder() // .updateCenter(centerId) // @@ -369,8 +369,8 @@ public String delete(@PathParam("centerId") @Parameter(description = "centerId") @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.PostCentersCenterIdResponse.class))) }) public String activate(@PathParam("centerId") @Parameter(description = "centerId") final Long centerId, - @QueryParam("command") @Parameter(description = "command") final String commandParam, - @Parameter(hidden = true) final String apiRequestBodyAsJson, @Context final UriInfo uriInfo) { + @QueryParam("command") @Parameter(description = "command") final String commandParam, + @Parameter(hidden = true) final String apiRequestBodyAsJson, @Context final UriInfo uriInfo) { final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson); @@ -423,7 +423,7 @@ private boolean is(final String commandParam, final String commandValue) { @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = CentersApiResourceSwagger.GetCentersCenterIdAccountsResponse.class))) }) public String retrieveGroupAccount(@PathParam("centerId") @Parameter(description = "centerId") final Long centerId, - @Context final UriInfo uriInfo) { + @Context final UriInfo uriInfo) { this.context.authenticatedUser().validateHasReadPermission(GroupingTypesApiConstants.CENTER_RESOURCE_NAME); @@ -440,7 +440,7 @@ public String retrieveGroupAccount(@PathParam("centerId") @Parameter(description @Path("downloadtemplate") @Produces("application/vnd.ms-excel") public Response getCentersTemplate(@QueryParam("officeId") final Long officeId, @QueryParam("staffId") final Long staffId, - @QueryParam("dateFormat") final String dateFormat) { + @QueryParam("dateFormat") final String dateFormat) { return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.CENTERS.toString(), officeId, staffId, dateFormat); } @@ -450,8 +450,8 @@ public Response getCentersTemplate(@QueryParam("officeId") final Long officeId, @RequestBody(description = "Upload centers template", content = { @Content(mediaType = MediaType.MULTIPART_FORM_DATA, schema = @Schema(implementation = UploadRequest.class)) }) public String postCentersTemplate(@FormDataParam("file") InputStream uploadedInputStream, - @FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("locale") final String locale, - @FormDataParam("dateFormat") final String dateFormat) { + @FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("locale") final String locale, + @FormDataParam("dateFormat") final String dateFormat) { final Long importDocumentId = this.bulkImportWorkbookService.importWorkbook(GlobalEntityType.CENTERS.toString(), uploadedInputStream, fileDetail, locale, dateFormat); return this.toApiJsonSerializer.serialize(importDocumentId); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java index fe35cc61621..109140cfcd3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/CenterData.java @@ -98,14 +98,14 @@ public final class CenterData implements Serializable { private LocalDate submittedOnDate; public static CenterData importInstance(String name, List groupMembers, LocalDate activationDate, boolean active, - LocalDate submittedOnDate, String externalId, Long officeId, Long staffId, Integer rowIndex, String dateFormat, String locale) { + LocalDate submittedOnDate, String externalId, Long officeId, Long staffId, Integer rowIndex, String dateFormat, String locale) { return new CenterData(name, groupMembers, activationDate, active, submittedOnDate, externalId, officeId, staffId, rowIndex, dateFormat, locale); } private CenterData(String name, List groupMembers, LocalDate activationDate, boolean active, - LocalDate submittedOnDate, String externalId, Long officeId, Long staffId, Integer rowIndex, String dateFormat, String locale) { + LocalDate submittedOnDate, String externalId, Long officeId, Long staffId, Integer rowIndex, String dateFormat, String locale) { this.name = name; this.groupMembers = groupMembers; this.externalId = externalId; @@ -148,11 +148,11 @@ public String getOfficeName() { } public static CenterData template(final Long officeId, final String accountNo, final LocalDate activationDate, - final Collection officeOptions, final Collection staffOptions, - final Collection groupMembersOptions, final BigDecimal totalCollected, final BigDecimal totalOverdue, - final BigDecimal totaldue, final BigDecimal installmentDue, final Collection cityOptions, - final Collection stateOptions, final Collection typeOptions, - final Collection meetingDayOptions) { + final Collection officeOptions, final Collection staffOptions, + final Collection groupMembersOptions, final BigDecimal totalCollected, final BigDecimal totalOverdue, + final BigDecimal totaldue, final BigDecimal installmentDue, final Collection cityOptions, + final Collection stateOptions, final Collection typeOptions, + final Collection meetingDayOptions) { final CalendarData collectionMeetingCalendar = null; final Collection closureReasons = null; @@ -204,9 +204,9 @@ public static CenterData instance(final Long id, final String name) { } public static CenterData instance(final Long id, final String accountNo, 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 GroupTimelineData timeline, final CalendarData collectionMeetingCalendar, - final BigDecimal totalCollected, final BigDecimal totalOverdue, final BigDecimal totaldue, final BigDecimal installmentDue) { + final EnumOptionData status, final LocalDate activationDate, final Long officeId, final String officeName, final Long staffId, + final String staffName, final String hierarchy, final GroupTimelineData timeline, final CalendarData collectionMeetingCalendar, + final BigDecimal totalCollected, final BigDecimal totalOverdue, final BigDecimal totaldue, final BigDecimal installmentDue) { final Collection groupMembers = null; final Collection officeOptions = null; @@ -224,7 +224,7 @@ public static CenterData instance(final Long id, final String accountNo, final S } public static CenterData withAssociations(final CenterData centerData, final Collection groupMembers, - final CalendarData collectionMeetingCalendar) { + final CalendarData collectionMeetingCalendar) { return new CenterData(centerData.id, centerData.accountNo, 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, @@ -285,13 +285,13 @@ public static CenterData withClosureReasons(final Collection clos } private CenterData(final Long id, final String accountNo, 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 groupMembers, final Collection officeOptions, - final Collection staffOptions, final Collection groupMembersOptions, - final CalendarData collectionMeetingCalendar, final Collection closureReasons, final GroupTimelineData timeline, - final BigDecimal totalCollected, final BigDecimal totalOverdue, final BigDecimal totaldue, final BigDecimal installmentDue, - final Collection cityOptions, final Collection stateOptions, - final Collection typeOptions, final Collection meetingDayOptions) { + final LocalDate activationDate, final Long officeId, final String officeName, final Long staffId, final String staffName, + final String hierarchy, final Collection groupMembers, final Collection officeOptions, + final Collection staffOptions, final Collection groupMembersOptions, + final CalendarData collectionMeetingCalendar, final Collection closureReasons, final GroupTimelineData timeline, + final BigDecimal totalCollected, final BigDecimal totalOverdue, final BigDecimal totaldue, final BigDecimal installmentDue, + final Collection cityOptions, final Collection stateOptions, + final Collection typeOptions, final Collection meetingDayOptions) { this.id = id; this.accountNo = accountNo; this.name = name; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java index af10dcaab3c..2d6f887aabc 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/data/GroupGeneralData.java @@ -121,16 +121,16 @@ public class GroupGeneralData implements Serializable { private LocalDate submittedOnDate; public static GroupGeneralData importInstance(String groupName, List clientMembers, LocalDate activationDate, - LocalDate submittedOnDate, Boolean active, String externalId, Long officeId, Long staffId, Long centerId, Integer rowIndex, - String locale, String dateFormat) { + LocalDate submittedOnDate, Boolean active, String externalId, Long officeId, Long staffId, Long centerId, Integer rowIndex, + String locale, String dateFormat) { return new GroupGeneralData(groupName, clientMembers, activationDate, submittedOnDate, active, externalId, officeId, staffId, centerId, rowIndex, locale, dateFormat); } private GroupGeneralData(String name, List clientMembers, LocalDate activationDate, LocalDate submittedOnDate, - Boolean active, String externalId, Long officeId, Long staffId, Long centerId, Integer rowIndex, String locale, - String dateFormat) { + Boolean active, String externalId, Long officeId, Long staffId, Long centerId, Integer rowIndex, String locale, + String dateFormat) { this.dateFormat = dateFormat; this.locale = locale; this.name = name; @@ -268,11 +268,11 @@ public static GroupGeneralData lookup(final Long groupId, final String accountNo } public static GroupGeneralData template(final Long officeId, final Long centerId, final String accountNo, final String centerName, - final Long staffId, final String staffName, final Collection centerOptions, - final Collection officeOptions, final Collection staffOptions, - final Collection clientOptions, final Collection availableRoles, - final Collection parentOfficesOptions, final Collection responsibleUserOptions, - final Collection portfolioCenterOptions, Collection centerGroupLocations) { + final Long staffId, final String staffName, final Collection centerOptions, + final Collection officeOptions, final Collection staffOptions, + final Collection clientOptions, final Collection availableRoles, + final Collection parentOfficesOptions, final Collection responsibleUserOptions, + final Collection portfolioCenterOptions, Collection centerGroupLocations) { final Collection clientMembers = null; final Collection groupRoles = null; @@ -326,8 +326,8 @@ private static GroupGeneralData mapDTO(GroupGeneralData grouping, GroupGeneralDa } public static GroupGeneralData withAssocations(final GroupGeneralData grouping, final Collection membersOfGroup, - final Collection activeClientMembers, final Collection groupRoles, - final Collection calendarsData, final CalendarData collectionMeetingCalendar) { + final Collection activeClientMembers, final Collection groupRoles, + final Collection calendarsData, final CalendarData collectionMeetingCalendar) { GroupGeneralData ret = new GroupGeneralData(grouping.id, grouping.accountNo, grouping.name, grouping.externalId, grouping.status, grouping.activationDate, grouping.officeId, grouping.officeName, grouping.centerId, grouping.centerName, grouping.staffId, grouping.staffName, grouping.hierarchy, grouping.groupLevel, membersOfGroup, activeClientMembers, grouping.centerOptions, @@ -341,9 +341,9 @@ public static GroupGeneralData withAssocations(final GroupGeneralData grouping, } public static GroupGeneralData instance(final Long id, final String accountNo, final String name, final String externalId, - final EnumOptionData status, final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, - final String centerName, final Long staffId, final String staffName, final String hierarchy, final String groupLevel, - final GroupTimelineData timeline, LocalTime meetingStartTime, LocalTime meetingEndTime) { + final EnumOptionData status, final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, + final String centerName, final Long staffId, final String staffName, final String hierarchy, final String groupLevel, + final GroupTimelineData timeline, LocalTime meetingStartTime, LocalTime meetingEndTime) { final Collection clientMembers = null; final Collection activeClientMembers = null; @@ -365,22 +365,23 @@ public static GroupGeneralData instance(final Long id, final String accountNo, f return new GroupGeneralData(id, accountNo, name, externalId, status, activationDate, officeId, officeName, centerId, centerName, staffId, staffName, hierarchy, groupLevel, clientMembers, activeClientMembers, centerOptions, officeOptions, staffOptions, clientOptions, groupRoles, availableRoles, role, calendarsData, collectionMeetingCalendar, closureReasons, timeline, - parentOfficesOptions, responsibleUserOptions, portfolioCenterOptions, centerGroupLocations, - null, null, null, meetingStartTime, meetingEndTime); + parentOfficesOptions, responsibleUserOptions, portfolioCenterOptions, centerGroupLocations, null, null, null, + meetingStartTime, meetingEndTime); } private GroupGeneralData(final Long id, final String accountNo, final String name, final String externalId, final EnumOptionData status, - final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, final String centerName, - final Long staffId, final String staffName, final String hierarchy, final String groupLevel, - final Collection clientMembers, final Collection activeClientMembers, - final Collection centerOptions, final Collection officeOptions, - final Collection staffOptions, final Collection clientOptions, - final Collection groupRoles, final Collection availableRoles, final GroupRoleData role, - final Collection calendarsData, final CalendarData collectionMeetingCalendar, - final Collection closureReasons, final GroupTimelineData timeline, - final Collection parentOfficesOptions, final Collection responsibleUserOptions, - final Collection portfolioCenterOptions, Collection centerGroupLocations, - String prequalificationNumber, Long prequalificationId, EnumOptionData prequalificationStatus, LocalTime meetingStartTime, LocalTime meetingEndTime) { + final LocalDate activationDate, final Long officeId, final String officeName, final Long centerId, final String centerName, + final Long staffId, final String staffName, final String hierarchy, final String groupLevel, + final Collection clientMembers, final Collection activeClientMembers, + final Collection centerOptions, final Collection officeOptions, + final Collection staffOptions, final Collection clientOptions, + final Collection groupRoles, final Collection availableRoles, final GroupRoleData role, + final Collection calendarsData, final CalendarData collectionMeetingCalendar, + final Collection closureReasons, final GroupTimelineData timeline, + final Collection parentOfficesOptions, final Collection responsibleUserOptions, + final Collection portfolioCenterOptions, Collection centerGroupLocations, + String prequalificationNumber, Long prequalificationId, EnumOptionData prequalificationStatus, LocalTime meetingStartTime, + LocalTime meetingEndTime) { this.id = id; this.accountNo = accountNo; this.name = name; @@ -467,8 +468,8 @@ public static GroupGeneralData updateSelectedRole(final GroupGeneralData groupin grouping.staffName, grouping.hierarchy, grouping.groupLevel, grouping.clientMembers, grouping.activeClientMembers, grouping.centerOptions, grouping.officeOptions, grouping.staffOptions, grouping.clientOptions, grouping.groupRoles, grouping.availableRoles, selectedRole, grouping.calendarsData, grouping.collectionMeetingCalendar, grouping.closureReasons, - null, null, null, null, null, grouping.prequalificationNumber, grouping.prequalificationId, - grouping.prequalificationStatus, grouping.meetingStartTime, grouping.meetingEndTime); + null, null, null, null, null, grouping.prequalificationNumber, grouping.prequalificationId, grouping.prequalificationStatus, + grouping.meetingStartTime, grouping.meetingEndTime); } public static GroupGeneralData withClosureReasons(final Collection closureReasons) { @@ -505,8 +506,7 @@ public static GroupGeneralData withClosureReasons(final Collection clientMembers() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java index 7a5e29a5b61..f49ec4612ba 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java @@ -243,9 +243,9 @@ public static Group newGroup(final Office office, final Staff staff, final Group } public static Group assembleNewCenterFrom(final Office office, final GroupLevel groupLevel, final String name, final boolean active, - final LocalDate activationDate, final LocalDate submittedOnDate, final AppUser currentUser, final LocalTime meetingStartTime, - final LocalTime meetingEndTime, final Portfolio portfolio, final Integer meetingStart, final Integer meetingEnd, - final Integer meetingDay) { + final LocalDate activationDate, final LocalDate submittedOnDate, final AppUser currentUser, final LocalTime meetingStartTime, + final LocalTime meetingEndTime, final Portfolio portfolio, final Integer meetingStart, final Integer meetingEnd, + final Integer meetingDay) { // By default new group is created in PENDING status, unless explicitly // status is set to active GroupingTypeStatus status = GroupingTypeStatus.PENDING; @@ -342,7 +342,7 @@ private Group(final Office office, final Staff staff, final Group parent, final } private void setStatus(final LocalDate activationDate, final AppUser loginUser, final GroupingTypeStatus status, - final List dataValidationErrors) { + final List dataValidationErrors) { if (status.isActive()) { activate(loginUser, activationDate, dataValidationErrors); @@ -353,7 +353,7 @@ private void setStatus(final LocalDate activationDate, final AppUser loginUser, } private void activate(final AppUser currentUser, final LocalDate activationLocalDate, - final List dataValidationErrors) { + final List dataValidationErrors) { validateStatusNotEqualToActiveAndLogError(dataValidationErrors); if (dataValidationErrors.isEmpty()) { @@ -376,7 +376,7 @@ public void activate(final AppUser currentUser, final LocalDate activationLocalD } private void setActivationDate(final LocalDate activationDate, final AppUser loginUser, - final List dataValidationErrors) { + final List dataValidationErrors) { if (activationDate != null) { this.activationDate = activationDate; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMeetingTimeCollisionException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMeetingTimeCollisionException.java index 2e51273ce9f..70a67ba7dea 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMeetingTimeCollisionException.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMeetingTimeCollisionException.java @@ -28,16 +28,16 @@ public class GroupMeetingTimeCollisionException extends AbstractPlatformResourceNotFoundException { public GroupMeetingTimeCollisionException(final String groupName, final Long groupId, final LocalTime startTime, - final LocalTime endTime) { + final LocalTime endTime) { super("error.msg.center.group.meeting.times.collision", "Center group " + groupName + " with id " + groupId - + " In the destination center has meetings in given time: " + startTime + "-" + endTime, groupName, groupId, startTime, + + " In the destination center has meetings in given time: " + startTime + "-" + endTime, groupName, groupId, startTime, endTime); } public GroupMeetingTimeCollisionException(final String groupName, final Long groupId, final LocalTime startTime, - final LocalTime endTime, EmptyResultDataAccessException e) { + final LocalTime endTime, EmptyResultDataAccessException e) { super("error.msg.center.group.meeting.times.collision", "Center group " + groupName + " with id " + groupId - + " In the destination center has meetings in given time: " + startTime + "-" + endTime, groupName, groupId, startTime, + + " In the destination center has meetings in given time: " + startTime + "-" + endTime, groupName, groupId, startTime, endTime); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java index 28d9aa02893..17c3af52f7a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformServiceImpl.java @@ -422,7 +422,7 @@ public GroupGeneralData mapRow(final ResultSet rs, @SuppressWarnings("unused") f closedByUsername, closedByFirstname, closedByLastname); return GroupGeneralData.instance(id, accountNo, name, externalId, status, activationDate, officeId, officeName, null, null, - staffId, staffName, hierarchy, groupLevel, timeline, meetingStartTime,meetingEndTime); + staffId, staffName, hierarchy, groupLevel, timeline, meetingStartTime, meetingEndTime); } } @@ -667,7 +667,7 @@ public CenterData retrieveCenterWithClosureReasons() { @Override public Collection retriveAllCentersByMeetingDate(final Long officeId, final LocalDate meetingDate, - final Long staffId) { + final Long staffId) { validateForGenerateCollectionSheet(staffId); final CenterCalendarDataMapper centerCalendarMapper = new CenterCalendarDataMapper(); String sql = centerCalendarMapper.schema(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java index 72faec6ef09..e98b29107eb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java @@ -248,7 +248,7 @@ private CommandProcessingResult createGroupingType(final JsonCommand command, fi LocalTime newMeetingEndTime = newMeetingStarTime.plusMinutes(meetingDefaultDuration).plusMinutes(timeBetweenMeetings); meetingEndTime = newMeetingEndTime; - if (centerId !=null){ + if (centerId != null) { String schemaSql = "select cgroup.id from m_group cgroup where cgroup.parent_id = ? and " + "( ( ? >= cgroup.meeting_start_time and ? < cgroup.meeting_end_time) OR " + "( ? > cgroup.meeting_start_time and ? < cgroup.meeting_end_time) ) order by id desc"; @@ -259,7 +259,8 @@ private CommandProcessingResult createGroupingType(final JsonCommand command, fi Long groupId = groupIds.get(0); GroupGeneralData existingGroup = this.groupReadPlatformService.retrieveOne(groupId); - throw new GroupMeetingTimeCollisionException(existingGroup.getName(), existingGroup.getId(), meetingStartTime, meetingEndTime); + throw new GroupMeetingTimeCollisionException(existingGroup.getName(), existingGroup.getId(), meetingStartTime, + meetingEndTime); } } @@ -550,20 +551,21 @@ private CommandProcessingResult updateGroupingType(final Long groupId, final Jso Group parent = groupForUpdate.getParent(); if (actualChanges.containsKey(GroupingTypesApiConstants.meetingStartTime)) { - if (parent !=null){ + if (parent != null) { String schemaSql = "select cgroup.id from m_group cgroup where cgroup.parent_id = ? and " + "( ( ? >= cgroup.meeting_start_time and ? < cgroup.meeting_end_time) OR " + "( ? > cgroup.meeting_start_time and ? < cgroup.meeting_end_time) ) order by id desc"; LocalTime meetingEndTime = groupForUpdate.getMeetingEndTime(); LocalTime meetingStartTime = groupForUpdate.getMeetingStartTime(); - List groupIds = jdbcTemplate.queryForList(schemaSql, Long.class, parent.getId(), meetingStartTime, meetingStartTime, - meetingEndTime, meetingEndTime); + List groupIds = jdbcTemplate.queryForList(schemaSql, Long.class, parent.getId(), meetingStartTime, + meetingStartTime, meetingEndTime, meetingEndTime); if (groupIds.size() > 0) { Long existingGroupId = groupIds.get(0); GroupGeneralData existingGroup = this.groupReadPlatformService.retrieveOne(existingGroupId); - throw new GroupMeetingTimeCollisionException(existingGroup.getName(), existingGroup.getId(), meetingStartTime, meetingEndTime); + throw new GroupMeetingTimeCollisionException(existingGroup.getName(), existingGroup.getId(), meetingStartTime, + meetingEndTime); } } } @@ -938,18 +940,18 @@ private Set assembleSetOfChildGroups(final Long officeId, final JsonComma * Guaranteed to throw an exception no matter what the data integrity issue is. */ private void handleGroupDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dve, - final GroupTypes groupLevel) { + final GroupTypes groupLevel) { String levelName = "Invalid"; switch (groupLevel) { case CENTER: levelName = "Center"; - break; + break; case GROUP: levelName = "Group"; - break; + break; case INVALID: - break; + break; } String errorMessageForUser = null; @@ -1198,7 +1200,7 @@ void validateForJLGSavings(final Long groupId, final Set clientMembers) } public void validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(final Office groupOffice, final GroupLevel groupLevel, - final LocalDate activationDate) { + final LocalDate activationDate) { if (activationDate != null && groupOffice.getOpeningLocalDate().isAfter(activationDate)) { final String levelName = groupLevel.getLevelName(); final String errorMessage = levelName + " activation date should be greater than or equal to the parent Office's creation date " diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java index 143c04a2ce9..2bd2fd31362 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java @@ -157,6 +157,7 @@ public interface LoanApiConstants { String DEPOSIT_GUARANTEE_NUMBER = "depositGuaranteeNo"; String CHEQUE_DESCRIPTION = "description"; String CHEQUE_ID = "chequeId"; + String PREQUALIFICATION_ID = "prequalificationId"; String LOAN_RESOURCE_NAME = "LOAN"; String LOAN_ACTION_UPDATE_FUND = "UPDATEFUND"; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java index 12e6d144938..eb7e6f5877a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java @@ -89,6 +89,7 @@ import org.apache.fineract.organisation.agency.service.AgencyReadPlatformServiceImpl; import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.office.domain.OfficeHierarchyLevel; +import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.portfolio.account.PortfolioAccountType; import org.apache.fineract.portfolio.account.data.PortfolioAccountDTO; @@ -594,6 +595,8 @@ public String retrieveLoan(@PathParam("loanId") @Parameter(description = "loanId this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId); + final Long prequalificationId = loanBasicDetails.getPrequalificationId(); + final GroupPrequalificationData prequalificationData = loanBasicDetails.getPrequalificationData(); if (loanBasicDetails.isInterestRecalculationEnabled()) { Collection interestRecalculationCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity( loanBasicDetails.getInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue(), @@ -861,7 +864,8 @@ public String retrieveLoan(@PathParam("loanId") @Parameter(description = "loanId collectionData); loanAccount.setLinkedCupo(linkedCupo); loanAccount.setCupoLinkingOptions(cupoLinkingOptions); - + loanAccount.setPrequalificationId(prequalificationId); + loanAccount.setPrequalificationData(prequalificationData); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(), mandatoryResponseParameters); return this.toApiJsonSerializer.serialize(settings, loanAccount, this.loanDataParameters); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java index 1edb570e8ba..5741f12a97a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java @@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.DatatableData; import org.apache.fineract.organisation.agency.data.AgencyData; import org.apache.fineract.organisation.monetary.data.CurrencyData; +import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.portfolio.account.data.PortfolioAccountData; import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData; @@ -254,6 +255,8 @@ public final class LoanAccountData { private final Collection groupOptions; private final Collection facilitatorOptions; private final Collection disbursementMethodOptions; + private Long prequalificationId; + private GroupPrequalificationData prequalificationData; public static LoanAccountData disburseLoanByCheques(final Collection agencyOptions, final Collection centerOptions, final Collection groupOption, @@ -980,7 +983,8 @@ public static LoanAccountData populateClientDefaults(final LoanAccountData acc, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } /** @@ -1168,7 +1172,8 @@ public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, f acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product, @@ -1549,32 +1554,35 @@ public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, loanProductConfigurableAttributes = acc.product.getloanProductConfigurableAttributes(); } - return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientAccountNo, acc.clientName, - acc.clientOfficeId, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, - acc.isLoanProductLinkedToFloatingRate, acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, - acc.loanOfficerName, acc.currency, acc.proposedPrincipal, acc.principal, acc.approvedPrincipal, acc.netDisbursalAmount, - acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, - acc.repaymentEvery, acc.repaymentFrequencyType, acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, - acc.transactionProcessingStrategyId, acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, - acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.isFloatingInterestRate, - acc.interestRateDifferential, acc.interestCalculationPeriodType, acc.allowPartialPeriodInterestCalcualtion, - acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.recurringMoratoriumOnPrincipalPeriods, - acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, - acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, - productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, - repaymentFrequencyDayOfWeekTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, - amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, - chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions, - acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, accountLinkingOptions, linkedAccount, - disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstallmentAmount, acc.fixedEmiAmount, - acc.maxOutstandingLoanBalance, emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, + final LoanAccountData loanAccountData = new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, + acc.clientAccountNo, acc.clientName, acc.clientOfficeId, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, + acc.loanProductDescription, acc.isLoanProductLinkedToFloatingRate, acc.fundId, acc.fundName, acc.loanPurposeId, + acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.proposedPrincipal, acc.principal, + acc.approvedPrincipal, acc.netDisbursalAmount, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, + acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, + acc.repaymentFrequencyNthDayType, acc.repaymentFrequencyDayOfWeekType, acc.transactionProcessingStrategyId, + acc.transactionProcessingStrategyName, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, + acc.annualInterestRate, acc.interestType, acc.isFloatingInterestRate, acc.interestRateDifferential, + acc.interestCalculationPeriodType, acc.allowPartialPeriodInterestCalcualtion, acc.expectedFirstRepaymentOnDate, + acc.graceOnPrincipalPayment, acc.recurringMoratoriumOnPrincipalPeriods, acc.graceOnInterestPayment, + acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, + repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, productOptions, termFrequencyTypeOptions, + repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions, + transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, + interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, + loanCollateralOptions, calendarOptions, acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, + accountLinkingOptions, linkedAccount, disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstallmentAmount, + acc.fixedEmiAmount, acc.maxOutstandingLoanBalance, emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule, acc.createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, acc.isVariableInstallmentsAllowed, acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, rates, isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); + loanAccountData.setPrequalificationId(acc.prequalificationId); + return loanAccountData; } public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection productOptions, @@ -1618,7 +1626,8 @@ public static LoanAccountData associateGroup(final LoanAccountData acc, final Gr acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map memberLoanCycle) { @@ -1685,7 +1694,8 @@ public static LoanAccountData associateMemberVariations(final LoanAccountData ac acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData, @@ -1720,7 +1730,8 @@ public static LoanAccountData withInterestRecalculationCalendarData(final LoanAc acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } public static LoanAccountData withLoanCalendarData(final LoanAccountData acc, final CalendarData calendarData) { @@ -1750,7 +1761,8 @@ public static LoanAccountData withLoanCalendarData(final LoanAccountData acc, fi acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, final LoanScheduleData originalSchedule) { @@ -1781,7 +1793,8 @@ public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, fi acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup, acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled, acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.contractNo, acc.agencyOptions, acc.centerOptions, - acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, acc.actualGuaranteeAmount); + acc.groupOptions, acc.facilitatorOptions, acc.disbursementMethodOptions, acc.requiredGuaranteeAmount, + acc.actualGuaranteeAmount); } private LoanAccountData(final Long id, // @@ -1838,7 +1851,7 @@ private LoanAccountData(final Long id, // final String contractNo, final Collection agencyOptions, final Collection centerOptions, final Collection groupOptions, final Collection facilitatorOptions, final Collection disbursementMethodOptions, BigDecimal requiredGuaranteeAmount, - final BigDecimal actualGuaranteeAmount) { + final BigDecimal actualGuaranteeAmount) { this.id = id; this.accountNo = accountNo; @@ -2200,4 +2213,20 @@ public void setCupoLinkingOptions(Collection cupoLinkingOptions) { public void setLinkedCupo(CupoData linkedCupo) { this.linkedCupo = linkedCupo; } + + public Long getPrequalificationId() { + return this.prequalificationId; + } + + public void setPrequalificationId(Long prequalificationId) { + this.prequalificationId = prequalificationId; + } + + public GroupPrequalificationData getPrequalificationData() { + return prequalificationData; + } + + public void setPrequalificationData(GroupPrequalificationData prequalificationData) { + this.prequalificationData = prequalificationData; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index c021f28a4b3..2a55da0eccf 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -81,6 +81,7 @@ import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.organisation.monetary.domain.MoneyHelper; import org.apache.fineract.organisation.office.domain.Office; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; import org.apache.fineract.organisation.staff.domain.Staff; import org.apache.fineract.organisation.workingdays.domain.WorkingDays; import org.apache.fineract.organisation.workingdays.service.WorkingDaysUtil; @@ -412,6 +413,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { @JoinColumn(name = "cheque_id") private Cheque cheque; + @ManyToOne + @JoinColumn(name = "prequalification_id") + private PrequalificationGroup prequalificationGroup; + @ManyToOne() @JoinColumn(name = "disbursed_by_cheque_userid") private AppUser disbursedByChequeAppUser; @@ -7044,4 +7049,12 @@ public LocalDate getDisbursedByChequeDate() { public void setDisbursedByChequeDate(LocalDate disbursedByChequeDate) { this.disbursedByChequeDate = disbursedByChequeDate; } + + public PrequalificationGroup getPrequalificationGroup() { + return prequalificationGroup; + } + + public void setPrequalificationGroup(PrequalificationGroup prequalificationGroup) { + this.prequalificationGroup = prequalificationGroup; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java index f3ed82f7c62..a68ac669ec6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonHelper.java @@ -70,7 +70,7 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper { LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName, LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, LoanApiConstants.datatables, LoanApiConstants.isEqualAmortizationParam, LoanProductConstants.RATES_PARAM_NAME, LoanApiConstants.daysInYearTypeParameterName, LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, - LoanApiConstants.cupoIdParameterName)); + LoanApiConstants.cupoIdParameterName, LoanApiConstants.PREQUALIFICATION_ID)); private final FromJsonHelper fromApiJsonHelper; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/DisburseByChequesCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/DisburseByChequesCommandFromApiJsonDeserializer.java index deec66696bf..c05d06372b0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/DisburseByChequesCommandFromApiJsonDeserializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/DisburseByChequesCommandFromApiJsonDeserializer.java @@ -61,7 +61,7 @@ public List commandFromApiJson(String json) { final String depositGuaranteeNo = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.DEPOSIT_GUARANTEE_NUMBER, element); final BigDecimal depositGuaranteeAmount = this.fromApiJsonHelper .extractBigDecimalWithLocaleNamed(LoanApiConstants.DEPOSIT_GUARANTEE_AMOUNT, element); - if(requiredGuaranteeAmount.compareTo(actualGuaranteeAmount) > 0 || depositGuaranteeAmount.compareTo(BigDecimal.ZERO) > 0){ + if (requiredGuaranteeAmount.compareTo(actualGuaranteeAmount) > 0 || depositGuaranteeAmount.compareTo(BigDecimal.ZERO) > 0) { baseDataValidator.reset().parameter(LoanApiConstants.DEPOSIT_GUARANTEE_NUMBER).value(depositGuaranteeNo).notBlank() .notExceedingLengthOf(1000); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java index 80b1ef18379..4f6b67f8085 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java @@ -97,7 +97,7 @@ public final class LoanApplicationCommandFromApiJsonHelper { LoanApiConstants.applicationId, // glim specific LoanApiConstants.lastApplication, // glim specific LoanApiConstants.daysInYearTypeParameterName, LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, - LoanApiConstants.cupoIdParameterName)); + LoanApiConstants.cupoIdParameterName, LoanApiConstants.PREQUALIFICATION_ID)); private final FromJsonHelper fromApiJsonHelper; private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper; @@ -572,6 +572,13 @@ public void validateForModify(final String json, final LoanProduct loanProduct, baseDataValidator.reset().parameter(productIdParameterName).value(productId).notNull().integerGreaterThanZero(); } + final String prequalificationIdParameterName = "prequalificationId"; + if (this.fromApiJsonHelper.parameterExists(prequalificationIdParameterName, element)) { + atLeastOneParameterPassedForUpdate = true; + final Long prequalificationId = this.fromApiJsonHelper.extractLongNamed(prequalificationIdParameterName, element); + baseDataValidator.reset().parameter(productIdParameterName).value(prequalificationId).notNull().integerGreaterThanZero(); + } + final String accountNoParameterName = "accountNo"; if (this.fromApiJsonHelper.parameterExists(accountNoParameterName, element)) { atLeastOneParameterPassedForUpdate = true; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java index 2e2337f9d25..e1d81c4c4f6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java @@ -243,9 +243,9 @@ public void validateNewRepaymentTransaction(final String json) { throw new InvalidJsonException(); } - final Set transactionParameters = new HashSet<>( - Arrays.asList("transactionDate", "transactionAmount", "externalId", "note", "locale", "dateFormat", "paymentTypeId", - "accountNumber", "checkNumber", "routingCode", "receiptNumber", "bankNumber", "loanId", "isBatchPayment")); + final Set transactionParameters = new HashSet<>(Arrays.asList("transactionDate", "transactionAmount", "externalId", "note", + "locale", "dateFormat", "paymentTypeId", "accountNumber", "checkNumber", "routingCode", "receiptNumber", "bankNumber", + "loanId", "isBatchPayment", "adjustGuarantee")); final Type typeOfMap = new TypeToken>() {}.getType(); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, transactionParameters); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index 8ded55770d8..080db551b8e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -33,7 +33,6 @@ import java.util.Map; import java.util.Set; import javax.persistence.PersistenceException; - import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.fineract.accounting.journalentry.data.LumaBitacoraTransactionTypeEnum; @@ -73,6 +72,9 @@ import org.apache.fineract.organisation.bankcheque.domain.BankChequeStatus; import org.apache.fineract.organisation.bankcheque.domain.Cheque; import org.apache.fineract.organisation.bankcheque.domain.ChequeBatchRepositoryWrapper; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroupRepositoryWrapper; +import org.apache.fineract.organisation.prequalification.exception.PrequalificationNotProvidedException; import org.apache.fineract.organisation.staff.domain.Staff; import org.apache.fineract.portfolio.account.domain.AccountAssociationType; import org.apache.fineract.portfolio.account.domain.AccountAssociations; @@ -228,6 +230,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final CodeValueRepositoryWrapper codeValueRepository; private final DisburseByChequesCommandFromApiJsonDeserializer disburseByChequesCommandFromApiJsonDeserializer; private final ChequeBatchRepositoryWrapper chequeBatchRepositoryWrapper; + private final PrequalificationGroupRepositoryWrapper prequalificationGroupRepositoryWrapper; @Autowired private BitaCoraMasterRepository bitaCoraMasterRepository; @@ -265,8 +268,10 @@ public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecuri final ClientCollateralManagementRepository clientCollateralManagementRepository, final CupoRepositoryWrapper cupoRepositoryWrapper, final LumaAccountingProcessorForLoan lumaAccountingProcessorForLoan, DisburseByChequesCommandFromApiJsonDeserializer disburseByChequesCommandFromApiJsonDeserializer, - ChequeBatchRepositoryWrapper chequeBatchRepositoryWrapper, final SavingsAccountWritePlatformService savingsAccountWritePlatformService, - final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper) { + ChequeBatchRepositoryWrapper chequeBatchRepositoryWrapper, + PrequalificationGroupRepositoryWrapper prequalificationGroupRepositoryWrapper, + final SavingsAccountWritePlatformService savingsAccountWritePlatformService, + final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper) { this.context = context; this.fromJsonHelper = fromJsonHelper; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; @@ -315,6 +320,7 @@ public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecuri this.codeValueRepository = codeValueRepository; this.disburseByChequesCommandFromApiJsonDeserializer = disburseByChequesCommandFromApiJsonDeserializer; this.chequeBatchRepositoryWrapper = chequeBatchRepositoryWrapper; + this.prequalificationGroupRepositoryWrapper = prequalificationGroupRepositoryWrapper; this.savingsAccountWritePlatformService = savingsAccountWritePlatformService; this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper; } @@ -871,6 +877,20 @@ public CommandProcessingResult modifyApplication(final Long loanId, final JsonCo .orElseThrow(() -> new LoanProductNotFoundException(productId)); } + final String prequalificationIdParameterName = "prequalificationId"; + PrequalificationGroup prequalificationGroup = existingLoanApplication.getPrequalificationGroup(); + final Long existingPrequalificationId = existingLoanApplication.getPrequalificationGroup() != null + ? existingLoanApplication.getPrequalificationGroup().getId() + : null; + if (command.isChangeInLongParameterNamed(prequalificationIdParameterName, existingPrequalificationId)) { + final Long prequalificationId = command.longValueOfParameterNamed(prequalificationIdParameterName); + prequalificationGroup = this.prequalificationGroupRepositoryWrapper.findOneWithNotFoundDetection(prequalificationId); + } + if (prequalificationGroup == null) { + throw new PrequalificationNotProvidedException(); + } + existingLoanApplication.setPrequalificationGroup(prequalificationGroup); + LoanProduct loanProductForValidations = newLoanProduct == null ? existingLoanApplication.loanProduct() : newLoanProduct; this.fromApiJsonDeserializer.validateForModify(command.json(), loanProductForValidations, existingLoanApplication); @@ -1945,9 +1965,10 @@ public CommandProcessingResult disburseLoanByCheques(JsonCommand command) { // TODO: FBR-47 Handle deposit to guarantee savings account here BigDecimal depositAmount = cheque.getGuaranteeAmount().subtract(cheque.getRequiredGuaranteeAmount()); - if(depositAmount != null && depositAmount.compareTo(BigDecimal.ZERO) < 0){ - CommandProcessingResult depositCommandResult = this.savingsAccountWritePlatformService.depositAndHoldToClientGuaranteeAccount(depositAmount.abs(), - cheque.getRequiredGuaranteeAmount(), loanAccount.getClientId(), loanAccount.getId(), localDate); + if (depositAmount != null && depositAmount.compareTo(BigDecimal.ZERO) < 0) { + CommandProcessingResult depositCommandResult = this.savingsAccountWritePlatformService + .depositAndHoldToClientGuaranteeAccount(depositAmount.abs(), cheque.getRequiredGuaranteeAmount(), + loanAccount.getClientId(), loanAccount.getId(), localDate); } } return new CommandProcessingResultBuilder().withCommandId(command.commandId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java index ddbd77f3d91..42f56185c81 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java @@ -37,6 +37,10 @@ import org.apache.fineract.organisation.holiday.domain.Holiday; import org.apache.fineract.organisation.holiday.domain.HolidayRepository; import org.apache.fineract.organisation.holiday.domain.HolidayStatusType; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroupRepositoryWrapper; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatus; +import org.apache.fineract.organisation.prequalification.exception.PrequalificationIncorrectStatusException; import org.apache.fineract.organisation.staff.domain.Staff; import org.apache.fineract.organisation.staff.domain.StaffRepository; import org.apache.fineract.organisation.staff.exception.StaffNotFoundException; @@ -112,6 +116,7 @@ public class LoanAssembler { private final WorkingDaysRepositoryWrapper workingDaysRepository; private final LoanUtilService loanUtilService; private final RateAssembler rateAssembler; + private final PrequalificationGroupRepositoryWrapper prequalificationGroupRepositoryWrapper; @Autowired public LoanAssembler(final FromJsonHelper fromApiJsonHelper, final LoanRepositoryWrapper loanRepository, @@ -123,7 +128,8 @@ public LoanAssembler(final FromJsonHelper fromApiJsonHelper, final LoanRepositor final LoanCollateralAssembler collateralAssembler, final LoanSummaryWrapper loanSummaryWrapper, final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService, - final WorkingDaysRepositoryWrapper workingDaysRepository, final LoanUtilService loanUtilService, RateAssembler rateAssembler) { + final WorkingDaysRepositoryWrapper workingDaysRepository, final LoanUtilService loanUtilService, RateAssembler rateAssembler, + PrequalificationGroupRepositoryWrapper prequalificationGroupRepositoryWrapper) { this.fromApiJsonHelper = fromApiJsonHelper; this.loanRepository = loanRepository; this.loanProductRepository = loanProductRepository; @@ -143,6 +149,7 @@ public LoanAssembler(final FromJsonHelper fromApiJsonHelper, final LoanRepositor this.workingDaysRepository = workingDaysRepository; this.loanUtilService = loanUtilService; this.rateAssembler = rateAssembler; + this.prequalificationGroupRepositoryWrapper = prequalificationGroupRepositoryWrapper; } public Loan assembleFrom(final Long accountId) { @@ -341,6 +348,12 @@ private Loan assembleApplication(final JsonElement element, final Long clientId, } } + final Long prequalificationId = this.fromApiJsonHelper.extractLongNamed("prequalificationId", element); + final PrequalificationGroup prequalificationGroup = this.prequalificationGroupRepositoryWrapper + .findOneWithNotFoundDetection(prequalificationId); + if (!PrequalificationStatus.BURO_CHECKED.getValue().equals(prequalificationGroup.getStatus())) { + throw new PrequalificationIncorrectStatusException(PrequalificationStatus.fromInt(prequalificationGroup.getStatus()).getCode()); + } loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element); loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate(); final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); @@ -353,7 +366,7 @@ private Loan assembleApplication(final JsonElement element, final Long clientId, isHolidayEnabled, holidays, workingDays, element, disbursementDetails); loanApplication.loanApplicationSubmittal(loanScheduleModel, loanApplicationTerms, defaultLoanLifecycleStateMachine(), submittedOnDate, externalId, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); - + loanApplication.setPrequalificationGroup(prequalificationGroup); return loanApplication; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 0b4a0b47789..7147bd68692 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -56,6 +56,8 @@ import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; +import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; +import org.apache.fineract.organisation.prequalification.service.PrequalificationReadPlatformServiceImpl; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.organisation.staff.service.StaffReadPlatformService; import org.apache.fineract.portfolio.account.data.AccountTransferData; @@ -165,21 +167,22 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { private final AccountDetailsReadPlatformService accountDetailsReadPlatformService; private final ColumnValidator columnValidator; private final DatabaseSpecificSQLGenerator sqlGenerator; + private final PrequalificationReadPlatformServiceImpl.PrequalificationIndividualMappingsMapper prequalificationIndividualMappingsMapper = new PrequalificationReadPlatformServiceImpl.PrequalificationIndividualMappingsMapper(); @Autowired public LoanReadPlatformServiceImpl(final PlatformSecurityContext context, - final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository, - final LoanProductReadPlatformService loanProductReadPlatformService, final ClientReadPlatformService clientReadPlatformService, - final GroupReadPlatformService groupReadPlatformService, final LoanDropdownReadPlatformService loanDropdownReadPlatformService, - final FundReadPlatformService fundReadPlatformService, final ChargeReadPlatformService chargeReadPlatformService, - final CodeValueReadPlatformService codeValueReadPlatformService, final JdbcTemplate jdbcTemplate, - final NamedParameterJdbcTemplate namedParameterJdbcTemplate, final CalendarReadPlatformService calendarReadPlatformService, - final StaffReadPlatformService staffReadPlatformService, final PaymentTypeReadPlatformService paymentTypeReadPlatformService, - final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, - final FloatingRatesReadPlatformService floatingRatesReadPlatformService, final LoanUtilService loanUtilService, - final ConfigurationDomainService configurationDomainService, final CodeValueRepositoryWrapper codeValueRepositoryWrapper, - final AccountDetailsReadPlatformService accountDetailsReadPlatformService, final LoanRepositoryWrapper loanRepositoryWrapper, - final ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) { + final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository, + final LoanProductReadPlatformService loanProductReadPlatformService, final ClientReadPlatformService clientReadPlatformService, + final GroupReadPlatformService groupReadPlatformService, final LoanDropdownReadPlatformService loanDropdownReadPlatformService, + final FundReadPlatformService fundReadPlatformService, final ChargeReadPlatformService chargeReadPlatformService, + final CodeValueReadPlatformService codeValueReadPlatformService, final JdbcTemplate jdbcTemplate, + final NamedParameterJdbcTemplate namedParameterJdbcTemplate, final CalendarReadPlatformService calendarReadPlatformService, + final StaffReadPlatformService staffReadPlatformService, final PaymentTypeReadPlatformService paymentTypeReadPlatformService, + final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, + final FloatingRatesReadPlatformService floatingRatesReadPlatformService, final LoanUtilService loanUtilService, + final ConfigurationDomainService configurationDomainService, final CodeValueRepositoryWrapper codeValueRepositoryWrapper, + final AccountDetailsReadPlatformService accountDetailsReadPlatformService, final LoanRepositoryWrapper loanRepositoryWrapper, + final ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) { this.context = context; this.loanRepositoryWrapper = loanRepositoryWrapper; this.applicationCurrencyRepository = applicationCurrencyRepository; @@ -225,7 +228,24 @@ public LoanAccountData retrieveOne(final Long loanId) { sqlBuilder.append(" where l.id=? and ( o.hierarchy like ? or transferToOffice.hierarchy like ?)"); sqlBuilder.append(" GROUP BY l.id"); - return this.jdbcTemplate.queryForObject(sqlBuilder.toString(), rm, loanId, hierarchySearchString, hierarchySearchString); + LoanAccountData loanAccountData = this.jdbcTemplate.queryForObject(sqlBuilder.toString(), rm, loanId, hierarchySearchString, + hierarchySearchString); + if (loanAccountData != null) { + final Long prequalificationId = loanAccountData.getPrequalificationId(); + final Long clientId = loanAccountData.getClientId(); + if (prequalificationId != null && clientId != null) { + final String sql = "select " + this.prequalificationIndividualMappingsMapper.schema() + + " WHERE mc.id = ? AND mpg.id = ?"; + final Collection prequalificationGroups = this.jdbcTemplate.query(sql, + this.prequalificationIndividualMappingsMapper, new Object[] { clientId, prequalificationId }); + if (!CollectionUtils.isEmpty(prequalificationGroups)) { + final GroupPrequalificationData groupPrequalificationData = new ArrayList<>(prequalificationGroups).get(0); + loanAccountData.setPrequalificationData(groupPrequalificationData); + } + + } + } + return loanAccountData; } catch (final EmptyResultDataAccessException e) { throw new LoanNotFoundException(loanId, e); } @@ -259,8 +279,8 @@ public List retrieveGLIMChildLoansByGLIMParentAccount(String pa @Override public LoanScheduleData retrieveRepaymentSchedule(final Long loanId, - final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection disbursementData, - boolean isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges) { + final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection disbursementData, + boolean isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges) { try { this.context.authenticatedUser(); @@ -530,7 +550,7 @@ public LoanTransactionData retrieveLoanTransactionTemplate(final Long loanId) { @Override public LoanTransactionData retrieveLoanPrePaymentTemplate(final LoanTransactionType repaymentTransactionType, final Long loanId, - LocalDate onDate) { + LocalDate onDate) { this.context.authenticatedUser(); this.loanUtilService.validateRepaymentTransactionType(repaymentTransactionType); @@ -678,7 +698,7 @@ private static final class LoanMapper implements RowMapper { public String loanSchema() { - return "l.id as id, mlrs.first_duedate As firstInstallmentDate, l.account_no as accountNo, l.contract as contractNo, l.external_id as externalId, l.fund_id as fundId, f.name as fundName," + return "l.id as id, mlrs.first_duedate As firstInstallmentDate, l.account_no as accountNo, l.contract as contractNo, l.external_id as externalId, l.fund_id as fundId, f.name as fundName, l.prequalification_id AS prequalificationId, " + " l.loan_type_enum as loanType, l.loanpurpose_cv_id as loanPurposeId, cv.code_value as loanPurposeName," + " lp.id as loanProductId, lp.name as loanProductName, lp.description as loanProductDescription," + " (coalesce(lp.required_guarantee_percent,0)*l.principal_amount) as requiredGuaranteeAmount ," @@ -805,6 +825,7 @@ public LoanAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") fi currencyDisplaySymbol, currencyNameCode, intCode); final Long id = rs.getLong("id"); + final Long prequalificationId = rs.getLong("prequalificationId"); final String accountNo = rs.getString("accountNo"); final String externalId = rs.getString("externalId"); @@ -1103,22 +1124,25 @@ public LoanAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") fi ? requiredGuaranteeAmount.divide(new BigDecimal(100)) : BigDecimal.ZERO; final BigDecimal actualGuaranteeAmount = rs.getBigDecimal("actualGuaranteeAmount"); + final LoanAccountData loanAccountData = LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, + clientAccountNo, clientName, clientOfficeId, groupData, loanType, loanProductId, loanProductName, + loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName, loanPurposeId, loanPurposeName, + loanOfficerId, loanOfficerName, currencyData, proposedPrincipal, principal, approvedPrincipal, netDisbursalAmount, + totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, + repaymentFrequencyType, null, null, transactionStrategyId, transactionStrategyName, amortizationType, + interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, isFloatingInterestRate, + interestRateDifferential, interestCalculationPeriodType, allowPartialPeriodInterestCalcualtion, + expectedFirstRepaymentOnDate, graceOnPrincipalPayment, recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, + graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged, + syncDisbursementWithMeeting, loanCounter, loanProductCounter, multiDisburseLoan, canDefineInstallmentAmount, + fixedEmiAmount, outstandingLoanBalance, inArrears, graceOnArrearsAgeing, isNPA, daysInMonthType, daysInYearType, + isInterestRecalculationEnabled, interestRecalculationData, createStandingInstructionAtDisbursement, + isvariableInstallmentsAllowed, minimumGap, maximumGap, loanSubStatus, canUseForTopup, isTopup, closureLoanId, + closureLoanAccountNo, topupAmount, isEqualAmortization, fixedPrincipalPercentagePerInstallment, contractNo, + requiredGuaranteeAmountPercent, actualGuaranteeAmount); + loanAccountData.setPrequalificationId(prequalificationId); + return loanAccountData; - return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, - clientOfficeId, groupData, loanType, loanProductId, loanProductName, loanProductDescription, - isLoanProductLinkedToFloatingRate, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, - currencyData, proposedPrincipal, principal, approvedPrincipal, netDisbursalAmount, totalOverpaid, inArrearsTolerance, - termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, null, null, - transactionStrategyId, transactionStrategyName, amortizationType, interestRatePerPeriod, interestRateFrequencyType, - annualInterestRate, interestType, isFloatingInterestRate, interestRateDifferential, interestCalculationPeriodType, - allowPartialPeriodInterestCalcualtion, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, - recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, - timeline, loanSummary, feeChargesDueAtDisbursementCharged, syncDisbursementWithMeeting, loanCounter, loanProductCounter, - multiDisburseLoan, canDefineInstallmentAmount, fixedEmiAmount, outstandingLoanBalance, inArrears, graceOnArrearsAgeing, - isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, - createStandingInstructionAtDisbursement, isvariableInstallmentsAllowed, minimumGap, maximumGap, loanSubStatus, - canUseForTopup, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, - fixedPrincipalPercentagePerInstallment, contractNo, requiredGuaranteeAmountPercent, actualGuaranteeAmount); } } @@ -1180,7 +1204,7 @@ private static final class LoanScheduleResultSetExtractor implements ResultSetEx private final BigDecimal totalPaidFeeCharges; LoanScheduleResultSetExtractor(final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, - Collection disbursementData, boolean isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges) { + Collection disbursementData, boolean isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges) { this.currency = repaymentScheduleRelatedLoanData.getCurrency(); this.disbursement = repaymentScheduleRelatedLoanData.disbursementData(); this.totalFeeChargesDueAtDisbursement = repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement(); @@ -1505,7 +1529,7 @@ public LoanTransactionData mapRow(final ResultSet rs, @SuppressWarnings("unused" @Override public LoanAccountData retrieveLoanProductDetailsTemplate(final Long productId, final Long clientId, final Long groupId, - String templateType) { + String templateType) { this.context.authenticatedUser(); @@ -1656,7 +1680,7 @@ public Collection retrieveAllowedLoanOfficers(final Long selectedOffi @Override public Collection retrieveAllLoansWithOverdueInstallments(final Long penaltyWaitPeriod, - final Boolean backdatePenalties) { + final Boolean backdatePenalties) { final MusoniOverdueLoanScheduleMapper rm = new MusoniOverdueLoanScheduleMapper(); final StringBuilder sqlBuilder = new StringBuilder(400); @@ -1784,7 +1808,7 @@ public Collection retriveScheduleAccrualData() { LocalDate organisationStartDate = this.configurationDomainService.retrieveOrganisationStartDate(); final StringBuilder sqlBuilder = new StringBuilder(400); sqlBuilder.append("select ").append(mapper.schema()).append( - " where (recaldet.is_compounding_to_be_posted_as_transaction is null or recaldet.is_compounding_to_be_posted_as_transaction = false) ") + " where (recaldet.is_compounding_to_be_posted_as_transaction is null or recaldet.is_compounding_to_be_posted_as_transaction = false) ") .append(" and (((ls.fee_charges_amount <> COALESCE(ls.accrual_fee_charges_derived, 0))") .append(" or ( ls.penalty_charges_amount <> COALESCE(ls.accrual_penalty_charges_derived, 0))") .append(" or ( ls.interest_amount <> COALESCE(ls.accrual_interest_derived, 0)))") @@ -1809,7 +1833,7 @@ public Collection retrivePeriodicAccrualData(final Loca LocalDate organisationStartDate = this.configurationDomainService.retrieveOrganisationStartDate(); final StringBuilder sqlBuilder = new StringBuilder(400); sqlBuilder.append("select ").append(mapper.schema()).append( - " where (recaldet.is_compounding_to_be_posted_as_transaction is null or recaldet.is_compounding_to_be_posted_as_transaction = false) ") + " where (recaldet.is_compounding_to_be_posted_as_transaction is null or recaldet.is_compounding_to_be_posted_as_transaction = false) ") .append(" and (((ls.fee_charges_amount <> COALESCE(ls.accrual_fee_charges_derived, 0))") .append(" or (ls.penalty_charges_amount <> COALESCE(ls.accrual_penalty_charges_derived, 0))") .append(" or (ls.interest_amount <> COALESCE(ls.accrual_interest_derived, 0)))") @@ -2256,7 +2280,7 @@ public LoanTransactionData retrieveCreditBalanceRefundTemplate(Long loanId) { } private LoanTransactionData retrieveRefundTemplate(Long loanId, LoanTransactionType loanTransactionType, - Collection paymentOptions, MonetaryCurrency currency, BigDecimal transactionAmount, BigDecimal netDisbursal) { + Collection paymentOptions, MonetaryCurrency currency, BigDecimal transactionAmount, BigDecimal netDisbursal) { final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); @@ -2316,7 +2340,7 @@ private void updateInterestRatePeriodData(InterestRatePeriodData rate, LoanAccou public Collection retrieveLoanIdsWithPendingIncomePostingTransactions() { LocalDate currentdate = DateUtils.getBusinessLocalDate(); StringBuilder sqlBuilder = new StringBuilder().append(" select distinct loan.id ").append(" from m_loan as loan ").append( - " inner join m_loan_recalculation_details as recdet on (recdet.loan_id = loan.id and recdet.is_compounding_to_be_posted_as_transaction is not null and recdet.is_compounding_to_be_posted_as_transaction = true) ") + " inner join m_loan_recalculation_details as recdet on (recdet.loan_id = loan.id and recdet.is_compounding_to_be_posted_as_transaction is not null and recdet.is_compounding_to_be_posted_as_transaction = true) ") .append(" inner join m_loan_repayment_schedule as repsch on repsch.loan_id = loan.id ") .append(" inner join m_loan_interest_recalculation_additional_details as adddet on adddet.loan_repayment_schedule_id = repsch.id ") .append(" left join m_loan_transaction as trans on (trans.is_reversed <> true and trans.transaction_type_enum = 19 and trans.loan_id = loan.id and trans.transaction_date = adddet.effective_date) ") diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 5732b49bc51..d0d7614f644 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -971,7 +971,6 @@ public CommandProcessingResult makeLoanRepayment(final LoanTransactionType repay } this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements); } - return commandProcessingResultBuilder.withCommandId(command.commandId()) // .withLoanId(loanId) // .with(changes) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java index 96e6a7c1a92..09a0339ed2d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java @@ -206,6 +206,7 @@ public class LoanProductData implements Serializable { private final Integer daysLimitAddOn; private final BigDecimal guaranteePercentage; private final BigDecimal paymentToleranceLimit; + private final Boolean requireCommitteeApproval; /** * Used when returning lookup information about loan product for dropdowns. @@ -314,7 +315,7 @@ public static LoanProductData lookup(final Long id, final String name, final Boo maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, ageLimitWarning, ageLimitBlock, ownerTypeOption, addNewCyclesEnabled, - daysLimitAddOn, null, paymentToleranceLimit); + daysLimitAddOn, null, paymentToleranceLimit, null); } @@ -406,6 +407,7 @@ public static LoanProductData lookupWithCurrency(final Long id, final String nam final boolean addNewCyclesEnabled = true; final Integer daysLimitAddOn = null; final BigDecimal paymentToleranceLimit = null; + final Boolean requireCommitteeApproval = false; return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, @@ -423,7 +425,7 @@ public static LoanProductData lookupWithCurrency(final Long id, final String nam maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, ageLimitWarning, ageLimitBlock, ownerTypeOption, addNewCyclesEnabled, - daysLimitAddOn, null, paymentToleranceLimit); + daysLimitAddOn, null, paymentToleranceLimit, requireCommitteeApproval); } @@ -520,6 +522,7 @@ public static LoanProductData sensibleDefaultsForNewLoanProductCreation() { final Integer ageLimitBlock = null; final EnumOptionData ownerTypeOption = null; final boolean addNewCyclesEnabled = true; + final boolean requireCommitteeApproval = false; final Integer daysLimitAddOn = LoanProductConstants.DEFAULT_LIMIT_OF_DAYS_FOR_ADDON; final BigDecimal paymentToleranceLimit = null; return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance, @@ -539,7 +542,7 @@ public static LoanProductData sensibleDefaultsForNewLoanProductCreation() { maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, ageLimitWarning, ageLimitBlock, ownerTypeOption, addNewCyclesEnabled, - daysLimitAddOn, null, paymentToleranceLimit); + daysLimitAddOn, null, paymentToleranceLimit, requireCommitteeApproval); } @@ -649,7 +652,7 @@ public static LoanProductData loanProductWithFloatingRates(final Long id, final maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, ageLimitWarning, ageLimitBlock, ownerTypeOption, addNewCyclesEnabled, - daysLimitAddOn, null, paymentToleranceLimit); + daysLimitAddOn, null, paymentToleranceLimit, null); } @@ -696,7 +699,7 @@ public LoanProductData(final Long id, final String name, final String shortName, Collection rateOptions, Collection rates, final boolean isRatesEnabled, final BigDecimal fixedPrincipalPercentagePerInstallmen, final Integer ageLimitWarning, final Integer ageLimitBlock, final EnumOptionData ownerTypeOption, final boolean addNewCyclesEnabled, final Integer daysLimitAddOn, - BigDecimal guaranteePercentage, final BigDecimal paymentToleranceLimit) { + BigDecimal guaranteePercentage, final BigDecimal paymentToleranceLimit, Boolean requireCommitteeApproval) { this.id = id; this.name = name; this.shortName = shortName; @@ -818,6 +821,7 @@ public LoanProductData(final Long id, final String name, final String shortName, this.daysLimitAddOn = daysLimitAddOn; this.guaranteePercentage = guaranteePercentage; this.paymentToleranceLimit = paymentToleranceLimit; + this.requireCommitteeApproval = requireCommitteeApproval; } @@ -974,6 +978,7 @@ public LoanProductData(final LoanProductData productData, final Collection nullIfEmpty(final Collection charges) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java index 2ee19069788..3aab23f43e5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java @@ -216,6 +216,9 @@ public class LoanProduct extends AbstractPersistableCustom { @Column(name = "payment_tolerance_limit", nullable = false) private BigDecimal paymentToleranceLimit; + @Column(name = "required_committee_approval") + private Boolean requireCommitteeApproval; + public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy, final List productCharges, final JsonCommand command, final AprCalculator aprCalculator, FloatingRate floatingRate, final List productRates) { @@ -235,6 +238,7 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio final Integer ageLimitBlock = command.integerValueOfParameterNamed("ageLimitBlock"); final Integer daysLimitAddOn = command.integerValueOfParameterNamed("daysLimitAddOn"); final BigDecimal requiredGuaranteePercent = command.bigDecimalValueOfParameterNamed("guaranteePercentage"); + final Boolean requireCommitteeApproval = command.booleanObjectValueOfParameterNamed("requireCommitteeApproval"); final InterestMethod interestMethod = InterestMethod.fromInt(command.integerValueOfParameterNamed("interestType")); final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod @@ -419,7 +423,8 @@ public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactio minimumGapBetweenInstallments, maximumGapBetweenInstallments, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, productRates, fixedPrincipalPercentagePerInstallment, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber, ageLimitWarning, ageLimitBlock, - addNewCyclesEnabled, loanProductOwnerType, daysLimitAddOn, requiredGuaranteePercent, paymentToleranceLimit); + addNewCyclesEnabled, loanProductOwnerType, daysLimitAddOn, requiredGuaranteePercent, paymentToleranceLimit, + requireCommitteeApproval); } @@ -658,7 +663,7 @@ public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy tran final boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType, final Integer overAppliedNumber, final Integer ageLimitWarning, final Integer ageLimitBlock, final boolean addNewCyclesEnabled, final LoanProductOwnerType loanProductOwnerType, final Integer daysLimitAddOn, BigDecimal requiredGuaranteePercent, - final BigDecimal paymentToleranceLimit) { + final BigDecimal paymentToleranceLimit, Boolean requireCommitteeApproval) { this.fund = fund; this.transactionProcessingStrategy = transactionProcessingStrategy; this.name = name.trim(); @@ -742,6 +747,7 @@ public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy tran this.daysLimitAddOn = daysLimitAddOn; this.requiredGuaranteePercent = requiredGuaranteePercent; this.paymentToleranceLimit = paymentToleranceLimit; + this.requireCommitteeApproval = requireCommitteeApproval; if (loanProductOwnerType != null) { this.ownerType = loanProductOwnerType.getValue(); @@ -980,6 +986,13 @@ public Map update(final JsonCommand command, final AprCalculator this.includeInBorrowerCycle = newValue; } + final String requireCommitteeApproval = "requireCommitteeApproval"; + if (command.isChangeInBooleanParameterNamed(requireCommitteeApproval, this.requireCommitteeApproval)) { + final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(requireCommitteeApproval); + actualChanges.put(requireCommitteeApproval, newValue); + this.requireCommitteeApproval = newValue; + } + if (command.isChangeInBooleanParameterNamed(LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME, this.useBorrowerCycle)) { final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME); actualChanges.put(LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME, newValue); @@ -1685,4 +1698,12 @@ public BigDecimal getPaymentToleranceLimit() { public void setPaymentToleranceLimit(BigDecimal paymentToleranceLimit) { this.paymentToleranceLimit = paymentToleranceLimit; } + + public Boolean getRequireCommitteeApproval() { + return requireCommitteeApproval; + } + + public void setRequireCommitteeApproval(Boolean requireCommitteeApproval) { + this.requireCommitteeApproval = requireCommitteeApproval; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java index b33486bf2dc..7b7619529b1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java @@ -72,13 +72,14 @@ public final class LoanProductDataValidator { "closeDate", "externalId", "isLinkedToFloatingInterestRates", "floatingRatesId", "interestRateDifferential", "minDifferentialLendingRate", "defaultDifferentialLendingRate", "maxDifferentialLendingRate", "isFloatingInterestRateCalculationAllowed", "syncExpectedWithDisbursementDate", "ageLimitWarning", "ageLimitBlock", "ownerType", - "guaranteePercentage", LoanProductConstants.ADD_NEW_CYCLES_ENABLED, LoanProductConstants.LOAN_PRODUCT_OWNER_TYPE, - LoanProductAccountingParams.FEES_RECEIVABLE.getValue(), LoanProductAccountingParams.FUND_SOURCE.getValue(), - LoanProductAccountingParams.INCOME_FROM_FEES.getValue(), LoanProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), - LoanProductAccountingParams.INTEREST_ON_LOANS.getValue(), LoanProductAccountingParams.INTEREST_RECEIVABLE.getValue(), - LoanProductAccountingParams.LOAN_PORTFOLIO.getValue(), LoanProductAccountingParams.OVERPAYMENT.getValue(), - LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), LoanProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), - LoanProductAccountingParams.GOODWILL_CREDIT.getValue(), LoanProductAccountingParams.PENALTIES_RECEIVABLE.getValue(), + "guaranteePercentage", "requireCommitteeApproval", LoanProductConstants.ADD_NEW_CYCLES_ENABLED, + LoanProductConstants.LOAN_PRODUCT_OWNER_TYPE, LoanProductAccountingParams.FEES_RECEIVABLE.getValue(), + LoanProductAccountingParams.FUND_SOURCE.getValue(), LoanProductAccountingParams.INCOME_FROM_FEES.getValue(), + LoanProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), LoanProductAccountingParams.INTEREST_ON_LOANS.getValue(), + LoanProductAccountingParams.INTEREST_RECEIVABLE.getValue(), LoanProductAccountingParams.LOAN_PORTFOLIO.getValue(), + LoanProductAccountingParams.OVERPAYMENT.getValue(), LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), + LoanProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), LoanProductAccountingParams.GOODWILL_CREDIT.getValue(), + LoanProductAccountingParams.PENALTIES_RECEIVABLE.getValue(), LoanProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), LoanProductAccountingParams.FEE_INCOME_ACCOUNT_MAPPING.getValue(), LoanProductAccountingParams.INCOME_FROM_RECOVERY.getValue(), LoanProductAccountingParams.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(), LoanProductConstants.USE_BORROWER_CYCLE_PARAMETER_NAME, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java index 96277a38125..2a058d6d593 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -200,7 +200,7 @@ public String loanProductSchema() { + "lp.repay_every as repaidEvery, lp.repayment_period_frequency_enum as repaymentPeriodFrequency, lp.number_of_repayments as numberOfRepayments, lp.min_number_of_repayments as minNumberOfRepayments, lp.max_number_of_repayments as maxNumberOfRepayments, " + "lp.grace_on_principal_periods as graceOnPrincipalPayment, lp.recurring_moratorium_principal_periods as recurringMoratoriumOnPrincipalPeriods, lp.grace_on_interest_periods as graceOnInterestPayment, lp.grace_interest_free_periods as graceOnInterestCharged,lp.grace_on_arrears_ageing as graceOnArrearsAgeing,lp.overdue_days_for_npa as overdueDaysForNPA, " + "lp.min_days_between_disbursal_and_first_repayment As minimumDaysBetweenDisbursalAndFirstRepayment, " - + "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, " + + "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, lp.required_committee_approval as requireCommitteeApproval, " + "lp.accounting_type as accountingType, lp.include_in_borrower_cycle as includeInBorrowerCycle,lp.use_borrower_cycle as useBorrowerCycle, lp.start_date as startDate, lp.close_date as closeDate, " + "lp.allow_multiple_disbursals as multiDisburseLoan, lp.max_disbursals as maxTrancheCount, lp.max_outstanding_loan_balance as outstandingLoanBalance, " + "lp.disallow_expected_disbursements as disallowExpectedDisbursements, lp.allow_approved_disbursed_amounts_over_applied as allowApprovedDisbursedAmountsOverApplied, lp.over_applied_calculation_type as overAppliedCalculationType, over_applied_number as overAppliedNumber, " @@ -477,6 +477,7 @@ public LoanProductData mapRow(final ResultSet rs, @SuppressWarnings("unused") fi final Integer daysLimitAddOn = JdbcSupport.getInteger(rs, "daysLimitAddOn"); final BigDecimal guaranteePercentage = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "guaranteePercentage"); final BigDecimal paymentToleranceLimit = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "paymentToleranceLimit"); + final Boolean requireCommitteeApproval = rs.getBoolean("requireCommitteeApproval"); return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, @@ -496,7 +497,7 @@ public LoanProductData mapRow(final ResultSet rs, @SuppressWarnings("unused") fi maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableIntallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, this.rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, ageLimitWarning, ageLimitBlock, ownerTypeOption, - addNewCyclesEnabled, daysLimitAddOn, guaranteePercentage, paymentToleranceLimit); + addNewCyclesEnabled, daysLimitAddOn, guaranteePercentage, paymentToleranceLimit, requireCommitteeApproval); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java index 0809ee9a198..9de36118165 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java @@ -45,12 +45,10 @@ public class SavingsAccountConstant extends SavingsApiConstants { * These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to * get response parameters to match those of request parameters. */ - protected static final Set SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>( Arrays.asList(localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName, transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName, retailEntriesParamName, childAccountIdParamName, noteParamName)); - protected static final Set SAVINGS_ACCOUNT_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>( Arrays.asList(idParamName, accountNoParamName)); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/exception/HoldTransactionNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/exception/HoldTransactionNotFoundException.java new file mode 100644 index 00000000000..9aacec0d331 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/exception/HoldTransactionNotFoundException.java @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformServiceUnavailableException; + +/** + * A {@link RuntimeException} thrown when update not allowed. + */ +public class HoldTransactionNotFoundException extends AbstractPlatformServiceUnavailableException { + + public HoldTransactionNotFoundException(final Long savingsId, final Long transactionId) { + super("error.msg.saving.account.hold.transaction.not.found", + "Savings Account hold transaction not found with identifier " + savingsId + " and transaction identifier " + transactionId, + savingsId, transactionId); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java index e5dcff70157..4e1cc9ddc63 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java @@ -120,6 +120,7 @@ SavingsAccountData postInterest(SavingsAccountData account, boolean postInterest CommandProcessingResult bulkGSIMClose(Long gsimId, JsonCommand command); - CommandProcessingResult depositAndHoldToClientGuaranteeAccount(BigDecimal depositAmount, BigDecimal requiredGuaranteeAmount, Long clientId, Long loanId, LocalDate transactionDate); + CommandProcessingResult depositAndHoldToClientGuaranteeAccount(BigDecimal depositAmount, BigDecimal requiredGuaranteeAmount, + Long clientId, Long loanId, LocalDate transactionDate); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index 5b908c15b1c..7f406439488 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -48,7 +48,6 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; - import org.apache.commons.lang3.StringUtils; import org.apache.fineract.accounting.journalentry.domain.BitaCoraMasterRepository; import org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService; @@ -2078,16 +2077,18 @@ private void validateReasonForHold(String reasonForBlock) { } @Override - public CommandProcessingResult depositAndHoldToClientGuaranteeAccount(BigDecimal depositAmount, BigDecimal requiredGuaranteeAmount, Long clientId, Long loanId, LocalDate transactionDate) { + public CommandProcessingResult depositAndHoldToClientGuaranteeAccount(BigDecimal depositAmount, BigDecimal requiredGuaranteeAmount, + Long clientId, Long loanId, LocalDate transactionDate) { CommandProcessingResult result = null; - List savingsAccounts = this.savingAccountRepositoryWrapper.findSavingAccountByClientId(clientId); - Optional guaranteeAccount = savingsAccounts.stream().filter(account -> account.savingsProduct().getName().equals(GURANTEE_PRODUCT_NAME)).findFirst(); + List savingsAccounts = this.savingAccountRepositoryWrapper.findSavingAccountByClientId(clientId); + Optional guaranteeAccount = savingsAccounts.stream() + .filter(account -> account.savingsProduct().getName().equals(GURANTEE_PRODUCT_NAME)).findFirst(); boolean isGsim = false; final boolean backdatedTxnsAllowedTill = this.savingAccountAssembler.getPivotConfigStatus(); - if(!guaranteeAccount.isEmpty()){ + if (!guaranteeAccount.isEmpty()) { SavingsAccount savingsAccount = guaranteeAccount.get(); final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccount.getId(), backdatedTxnsAllowedTill); @@ -2101,11 +2102,13 @@ public CommandProcessingResult depositAndHoldToClientGuaranteeAccount(BigDecimal this.savingsAccountTransactionDataValidator.validateTransactionWithPivotDate(transactionDate, account); final Map changes = new LinkedHashMap<>(); - final PaymentDetail paymentDetail = null;//this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes); + final PaymentDetail paymentDetail = null;// this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, + // changes); boolean isAccountTransfer = false; boolean isRegularTransaction = true; - final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, DateUtils.DEFAULT_DATE_FORMATER, transactionDate, - depositAmount, paymentDetail, isAccountTransfer, isRegularTransaction, backdatedTxnsAllowedTill); + final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, + DateUtils.DEFAULT_DATE_FORMATER, transactionDate, depositAmount, paymentDetail, isAccountTransfer, isRegularTransaction, + backdatedTxnsAllowedTill); if (isGsim && (deposit.getId() != null)) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java index f7bb8127f20..008676cb133 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java @@ -177,12 +177,12 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { final SavingsAccount account = this.savingAccountAssembler.assembleFrom(command, submittedBy); - //FBR-47 if client already has a savings account don't create another + // FBR-47 if client already has a savings account don't create another List savingsAccounts = this.savingAccountRepository.findSavingAccountByClientId(account.clientId()); - if(savingsAccounts.isEmpty()) { + if (savingsAccounts.isEmpty()) { this.savingAccountRepository.save(account); - }else { + } else { throw new ClientHasSavingsAccountException(account.clientId()); } String accountNumber = ""; @@ -297,9 +297,9 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { private void generateAccountNumber(final SavingsAccount account) { if (account.isAccountNumberRequiresAutoGeneration()) { AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.SAVINGS); - if(account != null && account.savingsProduct().getName().equals(GURANTEE_PRODUCT_NAME)){ - accountNumberFormat = new AccountNumberFormat(EntityAccountType.SAVINGS, AccountNumberFormatEnumerations.AccountNumberPrefixType.SAVINGS_CLIENT_ID, - String.valueOf(account.clientId())); + if (account != null && account.savingsProduct().getName().equals(GURANTEE_PRODUCT_NAME)) { + accountNumberFormat = new AccountNumberFormat(EntityAccountType.SAVINGS, + AccountNumberFormatEnumerations.AccountNumberPrefixType.SAVINGS_CLIENT_ID, String.valueOf(account.clientId())); } account.updateAccountNo(this.accountNumberGenerator.generate(account, accountNumberFormat)); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 90a0e79acee..7b6858cf7b3 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -125,4 +125,6 @@ + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/FBR-401_insert_savings_product_for_guarantees.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/FBR-401_insert_savings_product_for_guarantees.sql index 00a7d28f041..904f6f9ab82 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/commands/FBR-401_insert_savings_product_for_guarantees.sql +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/FBR-401_insert_savings_product_for_guarantees.sql @@ -40,4 +40,4 @@ INSERT INTO m_savings_product ( name, short_name, description, currency_code, cu nominal_annual_interest_rate, interest_compounding_period_enum, interest_posting_period_enum, interest_calculation_type_enum, interest_calculation_days_in_year_type_enum, min_required_balance, accounting_type) -VALUES ("Garantías", "GUA", "Saving product for Guarantees", "GTQ", 2, 1, 0, 1, 4, 1, 365, 0, 1); \ No newline at end of file +VALUES ("Garantías", "GUA", "Saving product for Guarantees", "GTQ", 2, 1, 0, 1, 4, 1, 365, 0, 1); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/insert_loan_guarantee_report.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/insert_loan_guarantee_report.sql new file mode 100644 index 00000000000..8628e209d0e --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/insert_loan_guarantee_report.sql @@ -0,0 +1,70 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + +-- liquibase formatted sql +-- changeset fineract:1 +-- MySQL dump 10.13 Distrib 5.1.60, for Win32 (ia32) +-- +-- Host: localhost Database: fineract_default +-- ------------------------------------------------------ +-- Server version 5.1.60-community + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES UTF8MB4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Reporte de Garantias vinculado a Prestamos", "Table", "Loan", "select sat.transaction_date as 'Fecha depósito', sa.client_id as 'Clienta', concat(c.firstname,' ', c.lastname) as 'Clienta Nombre', +ifnull(g.id, 'N/A') as 'Código de grupo', ifnull(g.display_name, 'N/A') as 'Grupo',a.name as 'Agencia', +case + when releaseTbl.id is not null then 'Released' + WHEN releaseTbl.id is null then 'In Reserve' +end as Status, releaseTbl.transaction_date as 'Fecha de Liberación', sa.account_balance_derived as 'Saldo:', +ifnull(creditTbl.loanCount, 0) as 'Crédito vigente' +from m_savings_account_transaction sat +join m_savings_account sa on sa.id = sat.savings_account_id +left join m_client c on c.id = sa.client_id +left join m_group g on g.id = sa.group_id +left join m_group center ON center.id = g.parent_id +left join m_portfolio mp ON mp.id = center.portfolio_id +left join m_supervision ms ON ms.id = mp.supervision_id +left join m_agency a ON a.id = ms.agency_id +left join (select sat.id, sat.loan_id, sat.transaction_date from m_savings_account_transaction sat where sat.transaction_type_enum = 20 and sat.loan_id is not null + and sat.release_id_of_hold_amount is not null) as releaseTbl on releaseTbl.loan_id = sat.loan_id +left join (select count(l.id) as loanCount, c.id as clientId, g.id as groupId from m_loan l +left join m_client c on c.id = l.client_id +left join m_group g on g.id = l.group_id +where l.loan_status_id = 300 group by c.id, g.id) as creditTbl on creditTbl.clientId = c.id or creditTbl.groupId = g.id +where sat.loan_id is not null and sat.transaction_type_enum = 1 +and sat.transaction_date <= '${depositDate}'", "Reporte de Garantías vinculado a Préstamos", 1, 1, 0); + + +INSERT INTO stretchy_parameter (parameter_name, parameter_variable, parameter_label, parameter_displayType, parameter_FormatType, parameter_default) VALUES("depositDateSelect", "depositDate", "Deposit or Release Date", "date", "date", "n/a"); + + + +INSERT INTO stretchy_report_parameter (report_id, parameter_id, report_parameter_name) VALUES((SELECT sr.id + FROM stretchy_report sr WHERE sr.report_name = "Reporte de Garantias vinculado a Prestamos"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "depositDateSelect"), "depositDateSelect"); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0097_Add_Required_Guarantee_Percentage_on_Loan.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0097_Add_Required_Guarantee_Percentage_on_Loan.xml index 77487334b4d..15c1b7fb848 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0097_Add_Required_Guarantee_Percentage_on_Loan.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0097_Add_Required_Guarantee_Percentage_on_Loan.xml @@ -67,4 +67,4 @@ short_name = 'BCOT' - \ No newline at end of file + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0109_FBR_437_add_loan_id_to_savings_transaction_table.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0109_FBR_437_add_loan_id_to_savings_transaction_table.xml new file mode 100644 index 00000000000..7154051cd2b --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0109_FBR_437_add_loan_id_to_savings_transaction_table.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0111_FBR_489_add_require_committee_approval.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0111_FBR_489_add_require_committee_approval.xml new file mode 100644 index 00000000000..cde2bc5e432 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0111_FBR_489_add_require_committee_approval.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + +