diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index b84e6ff5b39..c6103a2ae84 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -3982,4 +3982,12 @@ public CommandWrapperBuilder deleteCommittee(Long committeeId) { this.href = "/committees" + committeeId; return this; } + + public CommandWrapperBuilder assigntoPrequalificationSelf(Long prequalificationId) { + this.actionName = "ASSIGN"; + this.entityName = "PREQUALIFICATIONS"; + this.entityId = prequalificationId; + this.href = "/prequalification/assign/" + prequalificationId; + return this; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java index 8284a50bae0..7cf2e5c5811 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/constants/OfficeConstants.java @@ -30,6 +30,7 @@ private OfficeConstants() { public static final int PARENT_OFFICE_ID_COL = 2; public static final int OPENED_ON_COL = 3; public static final int EXTERNAL_ID_COL = 4; + public static final int OFFICE_CODE_COL = 5; public static final int LOOKUP_OFFICE_COL = 7; public static final int LOOKUP_OFFICE_ID_COL = 8; public static final int STATUS_COL = 10; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java index a7fc9f983a6..2d69216ce8a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/importhandler/office/OfficeImportHandler.java @@ -82,7 +82,8 @@ private OfficeData readOffice(Row row, final String locale, final String dateFor Long parentId = ImportHandlerUtils.readAsLong(OfficeConstants.PARENT_OFFICE_ID_COL, row); LocalDate openedDate = ImportHandlerUtils.readAsDate(OfficeConstants.OPENED_ON_COL, row); String externalId = ImportHandlerUtils.readAsString(OfficeConstants.EXTERNAL_ID_COL, row); - OfficeData office = OfficeData.importInstance(officeName, parentId, openedDate, externalId); + String officeCode = ImportHandlerUtils.readAsString(OfficeConstants.OFFICE_CODE_COL, row); + OfficeData office = OfficeData.importInstance(officeName, parentId, openedDate, externalId, officeCode); office.setImportFields(row.getRowNum(), locale, dateFormat); return office; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/office/OfficeWorkbookPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/office/OfficeWorkbookPopulator.java index 643f4e00c8a..e491dfdc074 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/office/OfficeWorkbookPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/office/OfficeWorkbookPopulator.java @@ -69,6 +69,7 @@ private void setLayout(final Sheet worksheet) { worksheet.setColumnWidth(OfficeConstants.PARENT_OFFICE_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE); worksheet.setColumnWidth(OfficeConstants.OPENED_ON_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE); worksheet.setColumnWidth(OfficeConstants.EXTERNAL_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE); + worksheet.setColumnWidth(OfficeConstants.OFFICE_CODE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE); worksheet.setColumnWidth(OfficeConstants.LOOKUP_OFFICE_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE); worksheet.setColumnWidth(OfficeConstants.LOOKUP_OFFICE_ID_COL, TemplatePopulateImportConstants.SMALL_COL_SIZE); @@ -77,6 +78,7 @@ private void setLayout(final Sheet worksheet) { writeString(OfficeConstants.PARENT_OFFICE_ID_COL, rowHeader, "Parent OfficeId*"); writeString(OfficeConstants.OPENED_ON_COL, rowHeader, "Opened On Date*"); writeString(OfficeConstants.EXTERNAL_ID_COL, rowHeader, "External Id*"); + writeString(OfficeConstants.OFFICE_CODE_COL, rowHeader, "Office Code*"); writeString(OfficeConstants.LOOKUP_OFFICE_COL, rowHeader, "Lookup Offices"); writeString(OfficeConstants.LOOKUP_OFFICE_ID_COL, rowHeader, "Lookup OfficeId*"); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java index fbf0539b77a..9ca14f77ab1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/SearchParameters.java @@ -56,6 +56,7 @@ public final class SearchParameters { private final String type; private final String groupName; private final String centerName; + private final String groupingType; private final String accountNumber; private final String bankName; @@ -127,7 +128,8 @@ public static SearchParameters forBlacklist(final String displayName, final Stri } public static SearchParameters forPrequalification(final String displayName, final String status, final Integer offset, - final Integer limit, final String orderBy, final String sortOrder, final String type, String searchText) { + final Integer limit, final String orderBy, final String sortOrder, final String type, String searchText, + final String groupingType) { final Integer maxLimitAllowed = getCheckedLimit(limit); final Long staffId = null; @@ -136,7 +138,7 @@ public static SearchParameters forPrequalification(final String displayName, fin final Long savingsId = null; return new SearchParameters(searchText, null, null, displayName, null, null, null, status, offset, maxLimitAllowed, orderBy, - sortOrder, staffId, accountNo, loanId, savingsId, null, false, null, type, null, null, null); + sortOrder, staffId, accountNo, loanId, savingsId, null, false, null, type, null, null, null, groupingType); } public static SearchParameters forBankCheques(final Long agencyId, final String chequeNo, final String bankAccNo, final Long batchId, @@ -512,6 +514,7 @@ private SearchParameters(final String sqlSearch, final Long officeId, final Stri this.centerId = centerId; this.facilitatorId = facilitatorId; this.isIndividualBusinessLoan = isIndividualBusinessLoan; + this.groupingType = null; } private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, @@ -560,6 +563,7 @@ private SearchParameters(final String sqlSearch, final Long officeId, final Stri this.centerId = null; this.facilitatorId = null; this.isIndividualBusinessLoan = null; + this.groupingType = null; } private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, @@ -609,13 +613,14 @@ private SearchParameters(final String sqlSearch, final Long officeId, final Stri this.centerId = null; this.facilitatorId = null; this.isIndividualBusinessLoan = null; + this.groupingType = null; } private SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, final String hierarchy, final String firstname, final String lastname, final String status, final Integer offset, final Integer limit, final String orderBy, final String sortOrder, final Long staffId, final String accountNo, final Long loanId, final Long savingsId, final Boolean orphansOnly, boolean isSelfUser, final String dpiNumber, - final String type, final String groupName, final String groupNumber, final String centerName) { + final String type, final String groupName, final String groupNumber, final String centerName, final String groupingType) { this.sqlSearch = sqlSearch; this.officeId = officeId; this.externalId = externalId; @@ -658,6 +663,7 @@ private SearchParameters(final String sqlSearch, final Long officeId, final Stri this.centerId = null; this.facilitatorId = null; this.isIndividualBusinessLoan = null; + this.groupingType = groupingType; } private SearchParameters(final Long officeId, final String externalId, final String name, final String hierarchy, @@ -707,6 +713,7 @@ private SearchParameters(final Long officeId, final String externalId, final Str this.centerId = null; this.facilitatorId = null; this.isIndividualBusinessLoan = null; + this.groupingType = null; } private SearchParameters(final Long provisioningEntryId, final Long officeId, final Long productId, final Long categoryId, @@ -753,6 +760,7 @@ private SearchParameters(final Long provisioningEntryId, final Long officeId, fi this.centerId = null; this.facilitatorId = null; this.isIndividualBusinessLoan = null; + this.groupingType = null; } public SearchParameters(final String sqlSearch, final Long officeId, final String externalId, final String name, final String hierarchy, @@ -801,6 +809,7 @@ public SearchParameters(final String sqlSearch, final Long officeId, final Strin this.centerId = null; this.facilitatorId = null; this.isIndividualBusinessLoan = null; + this.groupingType = null; } public boolean isOrderByRequested() { @@ -1112,4 +1121,9 @@ public Long getFacilitatorId() { public Boolean getIndividualBusinessLoan() { return isIndividualBusinessLoan; } + + public String getGroupingType() { + return groupingType; + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformService.java index 97297c1507e..437a4befaef 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformService.java @@ -28,4 +28,6 @@ public interface AgencyReadPlatformService { AgencyData retrieveNewAgencyTemplate(); Collection retrieveAllByUser(); + + Collection retrieveByOfficeHierarchy(final String hierarchy); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformServiceImpl.java index e83b29a208a..3dd6c61826a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/agency/service/AgencyReadPlatformServiceImpl.java @@ -267,7 +267,24 @@ public AgencyData mapRow(final ResultSet rs, @SuppressWarnings("unused") final i public String schema() { return this.schema; } - } + @Override + public Collection retrieveByOfficeHierarchy(final String hierarchy) { + final String sql = """ + SELECT + ma.id AS id, + ma.name AS name + FROM + m_office mo + INNER JOIN m_office office_under ON + office_under.hierarchy LIKE CONCAT(mo.hierarchy, '%')AND office_under.hierarchy LIKE CONCAT(?, '%') + INNER JOIN m_appuser agency_responsible_user ON agency_responsible_user.office_id = office_under.id + INNER JOIN m_office agency_responsible_user_office ON agency_responsible_user_office.id = agency_responsible_user.office_id + INNER JOIN m_agency ma ON ma.responsible_user_id = agency_responsible_user.id + GROUP BY ma.id + """; + return this.jdbcTemplate.query(sql, (rs, rowNum) -> AgencyData.instance(rs.getLong("id"), rs.getString("name")), + new Object[] { hierarchy }); + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/bank/serialization/BankCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/bank/serialization/BankCommandFromApiJsonDeserializer.java index a1e6b5e8630..4ba049bfee2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/bank/serialization/BankCommandFromApiJsonDeserializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/bank/serialization/BankCommandFromApiJsonDeserializer.java @@ -69,7 +69,7 @@ public void validateForCreate(final String json) { final String code = this.fromApiJsonHelper.extractStringNamed(BankConstants.BankSupportedParameters.CODE.getValue(), element); baseDataValidator.reset().parameter(BankConstants.BankSupportedParameters.CODE.getValue()).value(code).notBlank() - .notExceedingLengthOf(2); + .notExceedingLengthOf(5); final String name = this.fromApiJsonHelper.extractStringNamed(BankConstants.BankSupportedParameters.NAME.getValue(), element); baseDataValidator.reset().parameter(BankConstants.BankSupportedParameters.NAME.getValue()).value(name).notBlank() @@ -94,7 +94,7 @@ public void validateForUpdate(final String json) { final String code = this.fromApiJsonHelper.extractStringNamed(BankConstants.BankSupportedParameters.CODE.getValue(), element); baseDataValidator.reset().parameter(BankConstants.BankSupportedParameters.CODE.getValue()).value(code).notBlank() - .notExceedingLengthOf(2); + .notExceedingLengthOf(5); final String name = this.fromApiJsonHelper.extractStringNamed(BankConstants.BankSupportedParameters.NAME.getValue(), element); baseDataValidator.reset().parameter(BankConstants.BankSupportedParameters.NAME.getValue()).value(name).notBlank() 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 5c9ed0d268e..cc1f319d22f 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 @@ -411,11 +411,12 @@ public List retrieveGuarantees(String caseId, final String locale for (int i = 0; i < jsonArray.size(); i++) { final JsonElement element = jsonArray.get(i); final Long id = this.fromApiJsonHelper.extractLongNamed("id", element); + final String status = ObjectUtils.defaultIfNull(this.fromApiJsonHelper.extractStringNamed("estado", element), + "Nueva Solicitud"); final JsonElement data = this.fromApiJsonHelper.extractJsonObjectNamed("datos", element); final String clientNo = this.fromApiJsonHelper.extractStringNamed("numero_cliente", data); final String clientName = this.fromApiJsonHelper.extractStringNamed("name", data); final String withdrawalReason = this.fromApiJsonHelper.extractStringNamed("razon_retiro", data); - final String status = this.fromApiJsonHelper.extractStringNamed("razon_retiro", data); final BigDecimal requestedAmount = this.fromApiJsonHelper.extractBigDecimalNamed("monto", data, reqLocale); final GuaranteeData guarantee = GuaranteeData.builder().id(id).caseId(caseId).clientNo(clientNo).clientName(clientName) .withdrawalReason(withdrawalReason).requestedAmount(requestedAmount).status(status).build(); @@ -429,7 +430,8 @@ public List retrieveGuarantees(String caseId, final String locale int index = 0; for (final GuaranteeData data : List.copyOf(guaranteeDataList)) { for (final ChequeData chequeData : chequeDataList) { - if (chequeData.getGuaranteeId().equals(data.getId())) { + if (!(chequeData.getStatus().getId().equals(BankChequeStatus.VOIDED.getValue().longValue()) + && chequeData.getGuaranteeId().equals(data.getId()))) { guaranteeDataList.remove(index); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeWritePlatformServiceImpl.java index e24be616259..8e5ed24a204 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/bankcheque/service/ChequeWritePlatformServiceImpl.java @@ -31,7 +31,9 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; +import org.apache.fineract.infrastructure.core.data.PaginationParameters; import org.apache.fineract.infrastructure.core.service.DateUtils; +import org.apache.fineract.infrastructure.core.service.Page; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.organisation.agency.domain.Agency; import org.apache.fineract.organisation.bankAccount.domain.BankAccount; @@ -45,6 +47,7 @@ import org.apache.fineract.organisation.bankcheque.command.UpdateChequeCommand; import org.apache.fineract.organisation.bankcheque.command.VoidChequeCommand; import org.apache.fineract.organisation.bankcheque.data.ChequeData; +import org.apache.fineract.organisation.bankcheque.data.ChequeSearchParams; import org.apache.fineract.organisation.bankcheque.domain.BankChequeStatus; import org.apache.fineract.organisation.bankcheque.domain.Batch; import org.apache.fineract.organisation.bankcheque.domain.Cheque; @@ -60,11 +63,14 @@ import org.apache.fineract.organisation.bankcheque.serialization.UpdateChequeCommandFromApiJsonDeserializer; import org.apache.fineract.organisation.bankcheque.serialization.VoidChequeCommandFromApiJsonDeserializer; import org.apache.fineract.organisation.monetary.domain.NumberToWordsConverter; +import org.apache.fineract.portfolio.loanaccount.domain.Loan; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService; import org.apache.fineract.useradministration.domain.AppUser; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; @Service @Slf4j @@ -86,6 +92,8 @@ public class ChequeWritePlatformServiceImpl implements ChequeWritePlatformServic private final PrintChequeCommandFromApiJsonDeserializer printChequeCommandFromApiJsonDeserializer; private final ChequeReadPlatformServiceImpl.ChequeMapper chequeMapper = new ChequeReadPlatformServiceImpl.ChequeMapper(); private final LoanWritePlatformService loanWritePlatformService; + private final LoanRepositoryWrapper loanRepositoryWrapper; + private final ChequeReadPlatformService chequeReadPlatformService; @Override public CommandProcessingResult createBatch(JsonCommand command) { @@ -179,6 +187,22 @@ public CommandProcessingResult reassignCheque(final Long chequeId, JsonCommand c ReassignChequeCommand reassignChequeCommand = reassignChequeCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); Cheque newCheque = chequeBatchRepositoryWrapper.findOneChequeWithNotFoundDetection(reassignChequeCommand.getChequeId()); Cheque oldCheque = chequeBatchRepositoryWrapper.findOneChequeWithNotFoundDetection(reassignChequeCommand.getOldChequeId()); + if (!BankChequeStatus.AVAILABLE.getValue().equals(newCheque.getStatus())) { + throw new BankChequeException("status", "invalid.loan.status.for.cheque.reassignment"); + } + + final PaginationParameters parameters = PaginationParameters.instance(null, null, null, null, null); + final ChequeSearchParams chequeSearchParams = ChequeSearchParams.builder().chequeId(reassignChequeCommand.getOldChequeId()).build(); + final Page cheques = this.chequeReadPlatformService.retrieveAll(chequeSearchParams, parameters); + if (!CollectionUtils.isEmpty(cheques.getPageItems())) { + final ChequeData chequeData = cheques.getPageItems().get(0); + if (chequeData.getId().equals(reassignChequeCommand.getOldChequeId()) && chequeData.getLoanAccId() != null) { + final Long loanId = chequeData.getLoanAccId(); + final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId); + loan.setCheque(newCheque); + this.loanRepositoryWrapper.saveAndFlush(loan); + } + } final String newChequeDescription = "Emitido por sustitución de Desembolso cheque " + oldCheque.getChequeNo(); final String oldChequeDescription = "Cheque anulado por proceso de Reasignación, cheque nuevo " + newCheque.getChequeNo(); final LocalDateTime localDateTime = DateUtils.getLocalDateTimeOfSystem(); @@ -194,7 +218,14 @@ public CommandProcessingResult reassignCheque(final Long chequeId, JsonCommand c newCheque.stampAudit(currentUserId, localDateTime); newCheque.setPrintedDate(localDate); newCheque.setPrintedBy(currentUser); - chequeJpaRepository.saveAll(List.of(oldCheque, newCheque)); + newCheque.setGuaranteeAmount(oldCheque.getGuaranteeAmount()); + newCheque.setRequiredGuaranteeAmount(oldCheque.getRequiredGuaranteeAmount()); + newCheque.setDepositGuaranteeNo(oldCheque.getDepositGuaranteeNo()); + newCheque.setCaseId(oldCheque.getCaseId()); + newCheque.setGuaranteeId(oldCheque.getGuaranteeId()); + newCheque.setGuaranteeName(oldCheque.getGuaranteeName()); + newCheque.setAmountInWords(oldCheque.getAmountInWords()); + this.chequeJpaRepository.saveAll(List.of(oldCheque, newCheque)); return new CommandProcessingResultBuilder().withCommandId(command.commandId()) .withResourceIdAsString(reassignChequeCommand.getOldChequeId().toString()) .withEntityId(reassignChequeCommand.getOldChequeId()).build(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/office/data/OfficeData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/office/data/OfficeData.java index 963096e5dde..4c85eeea2bd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/office/data/OfficeData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/office/data/OfficeData.java @@ -45,8 +45,9 @@ public class OfficeData implements Serializable { private String locale; private String dateFormat; - public static OfficeData importInstance(final String name, final Long parentId, final LocalDate openingDate, final String externalId) { - return new OfficeData(null, name, null, externalId, openingDate, null, parentId, null, null, null); + public static OfficeData importInstance(final String name, final Long parentId, final LocalDate openingDate, final String externalId, + final String officeCode) { + return new OfficeData(null, name, null, externalId, openingDate, null, parentId, null, null, officeCode); } public void setImportFields(final Integer rowIndex, final String locale, final String dateFormat) { 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 f7edac6c345..82e5148ff9e 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 @@ -24,7 +24,6 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import java.io.InputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -44,6 +43,7 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; import org.apache.fineract.commands.domain.CommandWrapper; import org.apache.fineract.commands.service.CommandWrapperBuilder; import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; @@ -63,9 +63,9 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.organisation.agency.data.AgencyData; import org.apache.fineract.organisation.agency.service.AgencyReadPlatformServiceImpl; -import org.apache.fineract.organisation.office.domain.OfficeHierarchyLevel; import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatus; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationType; import org.apache.fineract.organisation.prequalification.service.PrequalificationReadPlatformService; import org.apache.fineract.organisation.prequalification.service.PrequalificationWritePlatformService; import org.apache.fineract.portfolio.group.data.CenterData; @@ -147,7 +147,8 @@ public String retrieveAllBlacklistItems(@Context final UriInfo uriInfo, @QueryParam("status") @Parameter(description = "status") final String status, @QueryParam("type") @Parameter(description = "type") final String type, @QueryParam("searchText") @Parameter(description = "searchText") final String searchText, - @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, + @QueryParam("groupingType") @Parameter(description = "groupingType") final String groupingType) { this.context.authenticatedUser().validateHasViewPermission(this.resourceNameForPermissions); @@ -155,7 +156,7 @@ public String retrieveAllBlacklistItems(@Context final UriInfo uriInfo, String clientName = queryParameters.getFirst("clientName"); SearchParameters searchParameters = SearchParameters.forPrequalification(clientName, status, offset, limit, orderBy, sortOrder, - type, searchText); + type, searchText, groupingType); final Page clientData = this.prequalificationReadPlatformService.retrieveAll(searchParameters); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(queryParameters); @@ -176,17 +177,40 @@ public String newClientIdentifierDetails(@Context final UriInfo uriInfo) { MultivaluedMap queryParameters = uriInfo.getQueryParameters(); String type = queryParameters.getFirst("type"); - Collection centerData = this.centerReadPlatformService - .retrieveAllForDropdown(this.context.authenticatedUser().getOffice().getId()); - - Collection agencies = this.agencyReadPlatformService.retrieveAllByUser(); + String groupingType = queryParameters.getFirst("groupingType"); + Long agencyId = null; + Long centerId = null; + if (queryParameters.getFirst("agencyId") != null) { + agencyId = NumberUtils.toLong(queryParameters.getFirst("agencyId"), Long.MAX_VALUE); + } + if (queryParameters.getFirst("centerId") != null) { + centerId = NumberUtils.toLong(queryParameters.getFirst("centerId"), Long.MAX_VALUE); + } Collection loanProducts = this.loanProductReadPlatformService.retrieveAllLoanProducts(); - final List appUsers = new ArrayList<>( - this.appUserReadPlatformService.retrieveUsersUnderHierarchy(Long.valueOf(OfficeHierarchyLevel.GRUPO.getValue()))); + Integer prequalificationType = null; + if (StringUtils.isNotBlank(groupingType)) { + if (groupingType.equals("group")) { + prequalificationType = PrequalificationType.GROUP.getValue(); + } + + if (groupingType.equals("individual")) { + prequalificationType = PrequalificationType.INDIVIDUAL.getValue(); + } + + if (prequalificationType != null) { + loanProducts = this.loanProductReadPlatformService.retrieveAllLoanProductsForOwner(prequalificationType); + } + } + + final String hierarchy = this.context.authenticatedUser().getOffice().getHierarchy(); + final Collection centerData = this.centerReadPlatformService.retrieveByOfficeHierarchy(hierarchy, agencyId); + final Collection agencies = this.agencyReadPlatformService.retrieveByOfficeHierarchy(hierarchy); + final Collection appUsers = this.appUserReadPlatformService.retrieveByOfficeHierarchy(hierarchy, centerId); List statusOptions = Arrays.asList(status(PrequalificationStatus.CONSENT_ADDED), status(PrequalificationStatus.BLACKLIST_CHECKED), status(PrequalificationStatus.COMPLETED), - status(PrequalificationStatus.HARD_POLICY_CHECKED), status(PrequalificationStatus.TIME_EXPIRED)); + status(PrequalificationStatus.HARD_POLICY_CHECKED), status(PrequalificationStatus.TIME_EXPIRED), + status(PrequalificationStatus.PREQUALIFICATION_UPDATE_REQUESTED)); if (StringUtils.equalsIgnoreCase(type, "analysis")) { statusOptions = Arrays.asList(status(PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL), status(PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS)); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/IndividualPrequalificationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/IndividualPrequalificationApiResource.java index 2996a0c09a6..c701e28efe0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/IndividualPrequalificationApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/IndividualPrequalificationApiResource.java @@ -128,7 +128,8 @@ public String retrieveAllBlacklistItems(@Context final UriInfo uriInfo, @QueryParam("status") @Parameter(description = "status") final String status, @QueryParam("type") @Parameter(description = "type") final String type, @QueryParam("searchText") @Parameter(description = "searchText") final String searchText, - @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { + @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, + @QueryParam("groupingType") @Parameter(description = "groupingType") final String groupingType) { this.context.authenticatedUser().validateHasViewPermission(this.resourceNameForPermissions); @@ -136,7 +137,7 @@ public String retrieveAllBlacklistItems(@Context final UriInfo uriInfo, String clientName = queryParameters.getFirst("clientName"); SearchParameters searchParameters = SearchParameters.forPrequalification(clientName, status, offset, limit, orderBy, sortOrder, - type, searchText); + type, searchText, groupingType); final Page memberData = this.prequalificationReadPlatformService.retrieveAllMembers(searchParameters); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(queryParameters); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/PrequalificationChecklistApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/PrequalificationChecklistApiResource.java index 223b497dfc5..be9178df711 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/PrequalificationChecklistApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/api/PrequalificationChecklistApiResource.java @@ -132,6 +132,9 @@ public String validateHardPolicyChecklist(@PathParam("prequalificationId") final } else if (is(commandParam, "approveanalysis")) { final CommandWrapper validateCommandRequest = builder.processAnalysisRequest(prequalificationId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(validateCommandRequest); + } else if (is(commandParam, "assigntoself")) { + final CommandWrapper validateCommandRequest = builder.assigntoPrequalificationSelf(prequalificationId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(validateCommandRequest); } else { final CommandWrapper commandRequest = builder.processAnalysisRequest(prequalificationId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); 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 460a68f5734..0ceda74b0f0 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 @@ -65,16 +65,22 @@ public void validateForCreate(final String json) { final JsonElement element = this.fromApiJsonHelper.parse(json); - final Long centerId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.centerIdParamName, element); - baseDataValidator.reset().parameter(PrequalificatoinApiConstants.centerIdParamName).value(centerId).notNull().longGreaterThanZero(); + final Boolean individualPrequalification = this.fromApiJsonHelper.extractBooleanNamed("individual", element); - if (this.fromApiJsonHelper.parameterExists(PrequalificatoinApiConstants.groupIdParamName, element)) { - final Long groupId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.groupIdParamName, element); - baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupIdParamName).value(groupId).notNull() + if (!individualPrequalification) { + final Long centerId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.centerIdParamName, element); + baseDataValidator.reset().parameter(PrequalificatoinApiConstants.centerIdParamName).value(centerId).notNull() .longGreaterThanZero(); - } else { - final String groupName = this.fromApiJsonHelper.extractStringNamed(PrequalificatoinApiConstants.groupNameParamName, element); - baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupNameParamName).value(groupName).notBlank(); + + if (this.fromApiJsonHelper.parameterExists(PrequalificatoinApiConstants.groupIdParamName, element)) { + final Long groupId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.groupIdParamName, element); + baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupIdParamName).value(groupId).notNull() + .longGreaterThanZero(); + } else { + final String groupName = this.fromApiJsonHelper.extractStringNamed(PrequalificatoinApiConstants.groupNameParamName, + element); + baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupNameParamName).value(groupName).notBlank(); + } } final JsonArray members = this.fromApiJsonHelper.extractJsonArrayNamed(PrequalificatoinApiConstants.membersParamName, element); @@ -99,16 +105,22 @@ public void validateUpdate(final String json) { final JsonElement element = this.fromApiJsonHelper.parse(json); - final Long centerId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.centerIdParamName, element); - baseDataValidator.reset().parameter(PrequalificatoinApiConstants.centerIdParamName).value(centerId).notNull().longGreaterThanZero(); + final Boolean individualPrequalification = this.fromApiJsonHelper.extractBooleanNamed("individual", element); - if (this.fromApiJsonHelper.parameterExists(PrequalificatoinApiConstants.groupIdParamName, element)) { - final Long groupId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.groupIdParamName, element); - baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupIdParamName).value(groupId).notNull() + if (!individualPrequalification) { + final Long centerId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.centerIdParamName, element); + baseDataValidator.reset().parameter(PrequalificatoinApiConstants.centerIdParamName).value(centerId).notNull() .longGreaterThanZero(); - } else { - final String groupName = this.fromApiJsonHelper.extractStringNamed(PrequalificatoinApiConstants.groupNameParamName, element); - baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupNameParamName).value(groupName).notBlank(); + + if (this.fromApiJsonHelper.parameterExists(PrequalificatoinApiConstants.groupIdParamName, element)) { + final Long groupId = this.fromApiJsonHelper.extractLongNamed(PrequalificatoinApiConstants.groupIdParamName, element); + baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupIdParamName).value(groupId).notNull() + .longGreaterThanZero(); + } else { + final String groupName = this.fromApiJsonHelper.extractStringNamed(PrequalificatoinApiConstants.groupNameParamName, + element); + baseDataValidator.reset().parameter(PrequalificatoinApiConstants.groupNameParamName).value(groupName).notBlank(); + } } final JsonArray members = this.fromApiJsonHelper.extractJsonArrayNamed(PrequalificatoinApiConstants.membersParamName, element); diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/ClientData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/ClientData.java index 9d54943e69e..964b98556ae 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/ClientData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/ClientData.java @@ -27,8 +27,9 @@ @Builder public class ClientData { - private Integer clientId; + private Long clientId; private Integer prequalificationId; + private Long productId; private Integer prequalificationMemberId; private String name; private Date dateOfBirth; @@ -37,4 +38,9 @@ public class ClientData { private String workWithPuente; private Long noOfCompletedCycles; private String gender; + private String clientCategorization; + private String clientArea; + private String recreditCategorization; + private Boolean president; + private Integer buroCheckStatus; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupData.java new file mode 100644 index 00000000000..2bd56bc69c1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupData.java @@ -0,0 +1,35 @@ +/** + * 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.data; + +import java.math.BigDecimal; +import java.util.List; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class GroupData { + + private Long id; + private Long productId; + private BigDecimal requestedAmount; + private Integer numberOfMembers; + private List members; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupPrequalificationData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupPrequalificationData.java index 4169b068d7c..c9ae5002d17 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupPrequalificationData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/GroupPrequalificationData.java @@ -26,6 +26,7 @@ import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData; import org.apache.fineract.infrastructure.core.data.EnumOptionData; import org.apache.fineract.organisation.agency.data.AgencyData; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationSubStatus; import org.apache.fineract.portfolio.group.data.CenterData; import org.apache.fineract.portfolio.loanproduct.data.LoanProductData; import org.apache.fineract.useradministration.data.AppUserData; @@ -56,6 +57,7 @@ public class GroupPrequalificationData { private final String processQuality; private EnumOptionData status; private final String addedBy; + private EnumOptionData prequalificationType; private final String facilitatorName; private final Long facilitatorId; @@ -76,6 +78,9 @@ public class GroupPrequalificationData { private BigDecimal totalRequestedAmount; private BigDecimal totalApprovedAmount; + private PrequalificationSubStatus substatus; + private String assignedUser; + private String assignedUserName; public GroupPrequalificationData(final Long id, final String productName, final String prequalificationNumber, final String agencyName, final String portforlioName, final String centerName, final String groupName, final String addedBy, final LocalDate createdAt, @@ -113,6 +118,9 @@ public GroupPrequalificationData(final Long id, final String productName, final this.processQuality = null; this.totalRequestedAmount = null; this.totalApprovedAmount = null; + this.substatus = null; + this.assignedUser = null; + this.assignedUserName = null; } public GroupPrequalificationData(final Long id, final String productName, final String prequalificationNumber, final String agencyName, @@ -123,7 +131,8 @@ public GroupPrequalificationData(final Long id, final String productName, final final String facilitatorName, Long greenValidationCount, Long yellowValidationCount, Long orangeValidationCount, Long redValidationCount, Long prequalilficationTimespan, EnumOptionData lastPrequalificationStatus, String statusChangedBy, LocalDate statusChangedOn, String processType, String processQuality, BigDecimal totalRequestedAmount, - BigDecimal totalApprovedAmount) { + BigDecimal totalApprovedAmount, EnumOptionData prequalificationType, PrequalificationSubStatus substatus, String assignedUser, + String assignedUserName) { this.id = id; this.productName = productName; this.prequalificationNumber = prequalificationNumber; @@ -158,6 +167,10 @@ public GroupPrequalificationData(final Long id, final String productName, final this.processQuality = processQuality; this.totalRequestedAmount = totalRequestedAmount; this.totalApprovedAmount = totalApprovedAmount; + this.prequalificationType = prequalificationType; + this.substatus = substatus; + this.assignedUser = assignedUser; + this.assignedUserName = assignedUserName; } public static GroupPrequalificationData template(final Collection agencies, Collection centerData, @@ -183,12 +196,20 @@ public static GroupPrequalificationData instance(Long id, String prequalificatio final String facilitatorName, Long greenValidationCount, Long yellowValidationCount, Long orangeValidationCount, Long redValidationCount, Long prequalilficationTimespan, EnumOptionData lastPrequalificationStatus, String statusChangedBy, LocalDate statusChangedOn, String processType, String processQuality, BigDecimal totalRequestedAmount, - BigDecimal totalApprovedAmount) { + BigDecimal totalApprovedAmount, EnumOptionData prequalificationType, PrequalificationSubStatus substatus, String assignedUser, + String assignedUserName) { return new GroupPrequalificationData(id, productName, prequalificationNumber, agencyName, portfolioName, centerName, groupName, addedBy, createdAt, status, comments, groupId, null, null, null, null, null, agencyId, centerId, productId, facilitatorId, facilitatorName, greenValidationCount, yellowValidationCount, orangeValidationCount, redValidationCount, prequalilficationTimespan, lastPrequalificationStatus, statusChangedBy, statusChangedOn, processType, processQuality, - totalRequestedAmount, totalApprovedAmount); + totalRequestedAmount, totalApprovedAmount, prequalificationType, substatus, assignedUser, assignedUserName); + } + + public static GroupPrequalificationData simpeGroupData(Long id, String prequalificationNumber, EnumOptionData status, String groupName, + String productName, String addedBy, LocalDate createdAt) { + + return new GroupPrequalificationData(id, productName, prequalificationNumber, null, null, null, groupName, addedBy, createdAt, + status, null, null, null, null, null, null, null, null, null); } public void updateMembers(Collection groupMembers) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/HardPolicyCategoryData.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/PolicyData.java similarity index 90% rename from fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/HardPolicyCategoryData.java rename to fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/PolicyData.java index f115f2b7af4..79af8273878 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/HardPolicyCategoryData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/data/PolicyData.java @@ -18,14 +18,15 @@ */ package org.apache.fineract.organisation.prequalification.data; +import lombok.Builder; import lombok.Data; -import lombok.RequiredArgsConstructor; @Data -@RequiredArgsConstructor -public class HardPolicyCategoryData { +@Builder +public class PolicyData { private final Integer id; private final String name; + private final String label; private final String description; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/GroupPrequalificationRelationship.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/GroupPrequalificationRelationship.java new file mode 100644 index 00000000000..02663a67310 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/GroupPrequalificationRelationship.java @@ -0,0 +1,61 @@ +/** + * 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.domain; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import lombok.Getter; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.group.domain.Group; +import org.apache.fineract.useradministration.domain.AppUser; + +@Entity +@Getter +@Table(name = "m_group_prequalification_relationship") +public class GroupPrequalificationRelationship extends AbstractPersistableCustom { + + @ManyToOne + @JoinColumn(name = "group_id", nullable = true) + private Group group; + + @ManyToOne + @JoinColumn(name = "prequalification_id", nullable = false) + private PrequalificationGroup prequalificationGroup; + + @ManyToOne + @JoinColumn(name = "created_by", nullable = false) + private AppUser addedBy; + + public GroupPrequalificationRelationship(AppUser appUser, Group group, PrequalificationGroup prequalificationGroup) { + this.addedBy = appUser; + this.group = group; + this.prequalificationGroup = prequalificationGroup; + } + + public static GroupPrequalificationRelationship addRelationship(final AppUser appUser, final Group group, + final PrequalificationGroup prequalificationGroup) { + return new GroupPrequalificationRelationship(appUser, group, prequalificationGroup); + } + + protected GroupPrequalificationRelationship() { + // + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/GroupPrequalificationRelationshipRepository.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/GroupPrequalificationRelationshipRepository.java new file mode 100644 index 00000000000..fe4eaab5835 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/GroupPrequalificationRelationshipRepository.java @@ -0,0 +1,27 @@ +/** + * 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.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface GroupPrequalificationRelationshipRepository + extends JpaRepository, JpaSpecificationExecutor { + // no behaviour +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/HardPolicyCategory.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/HardPolicyCategory.java deleted file mode 100644 index 8eda43898de..00000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/HardPolicyCategory.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * 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.domain; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public enum HardPolicyCategory { - - INVALID(0, "Invalid"), NEW_CLIENT(1, "New Client"), RECURRING_CUSTOMER(2, "Recurring Customer"), INCREASE_PERCENTAGE(3, - "Increase Percentage"), MANDATORY_PHOTO_GRAPH(4, "Mandatory Photographs"), CLIENT_AGE(5, - "Client Age"), NUMBER_OF_MEMBERS_ACCORDING_TO_POLICY(6, - "No. Of Members according To Policy"), MINIMUM_AND_MAXIMUM_AMOUNT(7, - "Minimum and Maximum Amount"), DISPARITY_OF_VALUES(8, - "Disparity of Values"), PERCENTAGE_OF_MEMBERS_STARTING_BUSINESS(9, - "Percent Of Members Starting Business"), PERCENTAGE_OF_MEMBERS_WITH_THEIR_OWN_HOME(10, - " Percent Of Members with their own home"), CHAIRMAN_OF_THE_BC_BOARD_OF_DIRECTORS( - 11, "Chairman of The BC Board Of Directors"), OVERALL_CONDITION(12, - "Overall Condition"), CATEGORIES_OF_CLIENT_TO_ACCEPT(13, - "Categories of clients to accept"), REQUESTED_AMOUNT(14, - "Requested Amount"), ADD_ENDORSEMENT(15, - "add_endorsemnet"), PAYMENTS_OUTSIDE_CURRENT_TERM( - 16, - "Payments Outside Current Term"), PERCENTAGE_OF_MEMBERS_THAT_CAN_HAVE_PRODUCT( - 17, - "Percentage Of members that can have Product"), GENDER( - 18, - "Gender"), NATIONALITY( - 19, - "Nationality"), INTERNAL_CREDIT_HISTORY( - 20, - "Internal Credit History"), EXTERNAL_CREDIT_HISTORY( - 21, - "External Credit History"), CLAIMS_REGISTERED( - 22, - "Claim Registered"), HOUSING_TYPE( - 23, - "Housing Type"), RENTAL_AGE( - 24, - "Rental Age"), AGE_OF_BUSINESS( - 25, - "Age Of Business"), CREDITS( - 26, - "Credits"), CANCELLED_CYCLES_COUNT( - 27, - "Cancelled Cycles Count"), SUBMIT_AGRICULTURAL_TECHNICAL_DIAGNOSIS( - 28, - "Submit agricultural technical diagnosis (Commcare)"), ACCEPTANCE_OF_NEW_CLIENTS( - 29, - "Acceptance of new clients"); - - private final Integer id; - private final String name; - - public static HardPolicyCategory fromInt(final Integer id) { - return switch (id) { - case 1 -> HardPolicyCategory.NEW_CLIENT; - case 2 -> HardPolicyCategory.RECURRING_CUSTOMER; - case 3 -> HardPolicyCategory.INCREASE_PERCENTAGE; - case 4 -> HardPolicyCategory.MANDATORY_PHOTO_GRAPH; - case 5 -> HardPolicyCategory.CLIENT_AGE; - case 6 -> HardPolicyCategory.NUMBER_OF_MEMBERS_ACCORDING_TO_POLICY; - case 7 -> HardPolicyCategory.MINIMUM_AND_MAXIMUM_AMOUNT; - case 8 -> HardPolicyCategory.DISPARITY_OF_VALUES; - case 9 -> HardPolicyCategory.PERCENTAGE_OF_MEMBERS_STARTING_BUSINESS; - case 10 -> HardPolicyCategory.PERCENTAGE_OF_MEMBERS_WITH_THEIR_OWN_HOME; - case 11 -> HardPolicyCategory.CHAIRMAN_OF_THE_BC_BOARD_OF_DIRECTORS; - case 12 -> HardPolicyCategory.OVERALL_CONDITION; - case 13 -> HardPolicyCategory.CATEGORIES_OF_CLIENT_TO_ACCEPT; - case 14 -> HardPolicyCategory.REQUESTED_AMOUNT; - case 15 -> HardPolicyCategory.ADD_ENDORSEMENT; - case 16 -> HardPolicyCategory.PAYMENTS_OUTSIDE_CURRENT_TERM; - case 17 -> HardPolicyCategory.PERCENTAGE_OF_MEMBERS_THAT_CAN_HAVE_PRODUCT; - case 18 -> HardPolicyCategory.GENDER; - case 19 -> HardPolicyCategory.NATIONALITY; - case 20 -> HardPolicyCategory.INTERNAL_CREDIT_HISTORY; - case 21 -> HardPolicyCategory.EXTERNAL_CREDIT_HISTORY; - case 22 -> HardPolicyCategory.CLAIMS_REGISTERED; - case 23 -> HardPolicyCategory.HOUSING_TYPE; - case 24 -> HardPolicyCategory.RENTAL_AGE; - case 25 -> HardPolicyCategory.AGE_OF_BUSINESS; - case 26 -> HardPolicyCategory.CREDITS; - case 27 -> HardPolicyCategory.CANCELLED_CYCLES_COUNT; - case 28 -> HardPolicyCategory.SUBMIT_AGRICULTURAL_TECHNICAL_DIAGNOSIS; - case 29 -> HardPolicyCategory.ACCEPTANCE_OF_NEW_CLIENTS; - default -> HardPolicyCategory.INVALID; - }; - } -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/Policies.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/Policies.java new file mode 100644 index 00000000000..51a114c92a4 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/Policies.java @@ -0,0 +1,74 @@ +/** + * 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.domain; + +import java.util.Arrays; +import java.util.Objects; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum Policies { + + ZERO(0, "Invalid"), ONE(1, "New client categorization"), TWO(2, "Recurring customer categorization"), THREE(3, + "Increase percentage"), FOUR(4, "Mandatory to attach photographs and investment plan"), FIVE(5, "Client age"), SIX(6, + "Number of members according to policy"), SEVEN(7, "Minimum and maximum amount"), EIGHT(8, "Value disparity"), NINE(9, + "Percentage of members starting business"), TEN(10, "Percentage of members with their own home"), ELEVEN(11, + "President of the Board of Directors of the BC"), TWELVE(12, "General condition"), THIRTEEN(13, + "Categories of clients to accept"), FOURTEEN(14, + "Amount requested in relation to the current amount of main products"), FIFTEEN(15, + "Add endorsement"), SIXTEEN(16, + "Payments outside the current term of the main product"), SEVENTEEN(17, + "Percentage of members of the same group who they can have parallel product"), EIGHTEEN( + 18, "Gender"), NINETEEN(19, "Nationality"), TWENTY(20, + "Internal Credit History"), TWENTY_ONE(21, + "External Credit History"), TWENTY_TWO( + 22, + "Do you register any lawsuit?"), TWENTY_THREE( + 23, + "Housing Type"), TWENTY_FOUR( + 24, + "Rental Age"), TWENTY_FIVE( + 25, + "Age Of Business"), TWENTY_SIX( + 26, + "Credits"), TWENTY_SEVEN( + 27, + "Cancelled Cycles Count"), TWENTY_EIGHT( + 28, + "Acceptance of new clients"), TWENTY_NINE( + 29, + "Present agricultural technical diagnosis (Commcare)"), THIRTY( + 30, + "Age"), THIRTY_ONE( + 31, + "Amount"), THIRTY_TWO( + 32, + "Percentage of members with agricultural business"), THIRTY_THREE( + 33, + "Percentage of members with their own business"); + + private final Integer id; + private final String name; + + public static Policies fromInt(final Integer id) { + return Arrays.stream(values()).filter(policy -> Objects.equals(policy.id, id)).findFirst().orElse(ZERO); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationStatusLogRepository.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationStatusLogRepository.java index 5d47aeef40d..8a1e3a18b84 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationStatusLogRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationStatusLogRepository.java @@ -18,10 +18,15 @@ */ package org.apache.fineract.organisation.prequalification.domain; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface PreQualificationStatusLogRepository extends JpaRepository, JpaSpecificationExecutor { - // no behaviour + + @Query("SELECT sl FROM PrequalificationStatusLog sl WHERE sl.prequalificationGroup = :preqGroup AND sl.toStatus = :status ORDER BY sl.id desc") + List groupStatusLogs(@Param("status") Integer status, @Param("preqGroup") PrequalificationGroup preqGroup); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsEnumerations.java index 52172243266..5c9003642f9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PreQualificationsEnumerations.java @@ -75,6 +75,18 @@ public static EnumOptionData status(final PrequalificationStatus status) { PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS.getValue().longValue(), PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS.getCode(), "ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS"); + case PRE_COMMITTEE_D_PENDING_APPROVAL -> new EnumOptionData( + PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL.getValue().longValue(), + PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL.getCode(), "PRE_COMMITTEE_D_PENDING_APPROVAL"); + case PRE_COMMITTEE_B_PENDING_APPROVAL -> new EnumOptionData( + PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL.getValue().longValue(), + PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL.getCode(), "PRE_COMMITTEE_B_PENDING_APPROVAL"); + case PRE_COMMITTEE_C_PENDING_APPROVAL -> new EnumOptionData( + PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL.getValue().longValue(), + PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL.getCode(), "PRE_COMMITTEE_C_PENDING_APPROVAL"); + case PRE_COMMITTEE_A_PENDING_APPROVAL -> new EnumOptionData( + PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL.getValue().longValue(), + PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL.getCode(), "PRE_COMMITTEE_A_PENDING_APPROVAL"); default -> new EnumOptionData(PrequalificationStatus.INVALID.getValue().longValue(), PrequalificationStatus.INVALID.getCode(), "INVALID"); }; @@ -120,4 +132,14 @@ public static List clientTransactionType(final ClientTransaction return optionDatas; } + public static EnumOptionData prequalificationType(final Integer prequalificationTypeId) { + return prequalificationType(PrequalificationType.fromInt(prequalificationTypeId)); + } + + public static EnumOptionData prequalificationType(final PrequalificationType prequalificationType) { + final EnumOptionData optionData = new EnumOptionData(prequalificationType.getValue().longValue(), prequalificationType.getCode(), + prequalificationType.toString()); + return optionData; + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroup.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroup.java index 78363cb9b5d..9f3f35a49c6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroup.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationGroup.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.organisation.prequalification.domain; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.LinkedHashMap; import java.util.List; @@ -172,22 +173,30 @@ public Map update(final JsonCommand command) { final Map actualChanges = new LinkedHashMap<>(7); - if (command.isChangeInStringParameterNamed(PrequalificatoinApiConstants.groupNameParamName, this.groupName)) { - final String newValue = command.stringValueOfParameterNamed(PrequalificatoinApiConstants.groupNameParamName); - actualChanges.put(PrequalificatoinApiConstants.groupNameParamName, newValue); - this.groupName = newValue; - } - - if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.agencyIdParamName, this.agency.getId())) { - final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.agencyIdParamName); - actualChanges.put(PrequalificatoinApiConstants.agencyIdParamName, newValue); - // this.ag = newValue; - } - - if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.centerIdParamName, this.centerId)) { - final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.centerIdParamName); - actualChanges.put(PrequalificatoinApiConstants.centerIdParamName, newValue); - this.centerId = newValue; + final Boolean individualPrequalification = command.booleanPrimitiveValueOfParameterNamed("individual"); + + if (!individualPrequalification) { + if (command.isChangeInStringParameterNamed(PrequalificatoinApiConstants.groupNameParamName, this.groupName)) { + final String newValue = command.stringValueOfParameterNamed(PrequalificatoinApiConstants.groupNameParamName); + actualChanges.put(PrequalificatoinApiConstants.groupNameParamName, newValue); + this.groupName = newValue; + } + + if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.agencyIdParamName, this.agency.getId())) { + final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.agencyIdParamName); + actualChanges.put(PrequalificatoinApiConstants.agencyIdParamName, newValue); + } + + if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.centerIdParamName, this.centerId)) { + final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.centerIdParamName); + actualChanges.put(PrequalificatoinApiConstants.centerIdParamName, newValue); + this.centerId = newValue; + } + + if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.facilitatorParamName, this.facilitator.getId())) { + final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.facilitatorParamName); + actualChanges.put(PrequalificatoinApiConstants.facilitatorParamName, newValue); + } } if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.productIdParamName, this.loanProduct.getId())) { @@ -196,10 +205,6 @@ public Map update(final JsonCommand command) { // this.loanProduct. = newValue; } - if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.facilitatorParamName, this.facilitator.getId())) { - final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.facilitatorParamName); - actualChanges.put(PrequalificatoinApiConstants.facilitatorParamName, newValue); - } if (command.isChangeInLongParameterNamed(PrequalificatoinApiConstants.prequalilficationTimespanParamName, this.prequalificationDuration)) { final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.prequalilficationTimespanParamName); @@ -223,4 +228,16 @@ public Integer getPrequalificationType() { public void setPrequalificationType(Integer prequalificationType) { this.prequalificationType = prequalificationType; } + + public boolean isPrequalificationTypeIndividual() { + return this.prequalificationType.equals(PrequalificationType.INDIVIDUAL.getValue()); + } + + public boolean isPrequalificationTypeGroup() { + return this.prequalificationType.equals(PrequalificationType.GROUP.getValue()); + } + + public BigDecimal getTotalRequestedAmount() { + return this.getMembers().stream().map(PrequalificationGroupMember::getRequestedAmount).reduce(BigDecimal.ZERO, BigDecimal::add); + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatus.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatus.java index 638ea0370a9..13ba7794eb3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatus.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatus.java @@ -38,8 +38,18 @@ public enum PrequalificationStatus { "prequalification.status.pending.approval.exceptions"), ANALYSIS_UNIT_PENDING_APPROVAL( 1001, "prequalification.status.pending.approval.exceptions"), ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS( - 1002, "prequalification.status.pending.approval.exceptions"), INVALID(0, - "prequalification.status.invalid"); + 1002, + "prequalification.status.pending.approval.exceptions"), PRE_COMMITTEE_D_PENDING_APPROVAL( + 1003, + "prequalification.status.pre.committee.d.pending.approval"), PRE_COMMITTEE_C_PENDING_APPROVAL( + 1004, + "prequalification.status.pre.committee.c.pending.approval"), PRE_COMMITTEE_B_PENDING_APPROVAL( + 1005, + "prequalification.status.committee.b.pending.approval"), PRE_COMMITTEE_A_PENDING_APPROVAL( + 1006, + "prequalification.status.committee.a.pending.approval"), INVALID( + 0, + "prequalification.status.invalid"); private final Integer value; private final String code; @@ -93,6 +103,18 @@ public static PrequalificationStatus fromInt(final Integer statusValue) { case 1002: enumeration = PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS; break; + case 1003: + enumeration = PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL; + break; + case 1004: + enumeration = PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL; + break; + case 1005: + enumeration = PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL; + break; + case 1006: + enumeration = PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL; + break; } return enumeration; } @@ -140,6 +162,16 @@ public static PrequalificationStatus fromString(String status) { clientStatus = PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS; } else if (status.equalsIgnoreCase(PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL.toString())) { clientStatus = PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL; + } else if (status.equalsIgnoreCase(PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL.toString())) { + clientStatus = PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL; + } else if (status.equalsIgnoreCase(PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL.toString())) { + clientStatus = PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL; + } else if (status.equalsIgnoreCase(PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL.toString())) { + clientStatus = PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL; + } else if (status.equalsIgnoreCase(PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL.toString())) { + clientStatus = PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL; + } else { + clientStatus = PrequalificationStatus.INVALID; } return clientStatus; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusLog.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusLog.java index c98c7c2b44a..d9ebba2213b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusLog.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusLog.java @@ -54,6 +54,13 @@ public class PrequalificationStatusLog extends AbstractPersistableCustom { @Column(name = "comments", nullable = false) private String comments; + @Column(name = "sub_status", nullable = false) + private Integer subStatus; + + @ManyToOne + @JoinColumn(name = "assigned_to", nullable = false) + private AppUser assignedTo; + protected PrequalificationStatusLog() { // } @@ -72,4 +79,12 @@ public static PrequalificationStatusLog fromJson(final AppUser appUser, final In final String comments, final PrequalificationGroup group) { return new PrequalificationStatusLog(appUser, fromStatus, toStatus, comments, group); } + + public void updateAssignedTo(final AppUser assignedTo) { + this.assignedTo = assignedTo; + } + + public void updateSubStatus(final Integer subStatus) { + this.subStatus = subStatus; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusRange.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusRange.java new file mode 100644 index 00000000000..69b69bb9fa8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusRange.java @@ -0,0 +1,98 @@ +/** + * 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.domain; + +import java.math.BigDecimal; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import lombok.Getter; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; + +@Entity +@Getter +@Table(name = "m_prequalification_status_range") +public class PrequalificationStatusRange extends AbstractPersistableCustom { + + @Column(name = "prequalification_type_enum") + private Integer prequalificationType; + + @Column(name = "min_amount", nullable = false) + private BigDecimal minAmount; + + @Column(name = "max_amount") + private BigDecimal maxAmount; + + @Column(name = "min_error", nullable = false) + private Integer minError; + + @Column(name = "max_error", nullable = false) + private Integer maxError; + + @Column(name = "status", nullable = false) + private Integer status; + + public Integer getPrequalificationType() { + return prequalificationType; + } + + public void setPrequalificationType(Integer prequalificationType) { + this.prequalificationType = prequalificationType; + } + + public BigDecimal getMinAmount() { + return minAmount; + } + + public void setMinAmount(BigDecimal minAmount) { + this.minAmount = minAmount; + } + + public BigDecimal getMaxAmount() { + return maxAmount; + } + + public void setMaxAmount(BigDecimal maxAmount) { + this.maxAmount = maxAmount; + } + + public Integer getMinError() { + return minError; + } + + public void setMinError(Integer minError) { + this.minError = minError; + } + + public Integer getMaxError() { + return maxError; + } + + public void setMaxError(Integer maxError) { + this.maxError = maxError; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusRangeRepository.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusRangeRepository.java new file mode 100644 index 00000000000..56eccbe1800 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationStatusRangeRepository.java @@ -0,0 +1,35 @@ +/** + * 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.domain; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface PrequalificationStatusRangeRepository + extends JpaRepository, JpaSpecificationExecutor { + + @Query("SELECT sr FROM PrequalificationStatusRange sr WHERE sr.prequalificationType = :type AND " + + ":numberOfErrors >= sr.minError AND :numberOfErrors <= sr.maxError ORDER BY sr.minAmount") + List findByPrequalificationTypeAndNumberOfErrors(@Param("type") Integer type, + @Param("numberOfErrors") Integer numberOfErrors); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationSubStatus.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationSubStatus.java new file mode 100644 index 00000000000..56412db794f --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/PrequalificationSubStatus.java @@ -0,0 +1,98 @@ +/** + * 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.domain; + +import org.springframework.util.StringUtils; + +/** + * Enum representation of prequalification status states. + */ +public enum PrequalificationSubStatus { + + PENDING(100, "prequalification.status.pending"), // + IN_PROGRESS(200, "prequalification.status.approved"), // + COMPLETED(300, "prequalification.status.rejected"), INVALID(999, "prequalification.status.rejected"); + + private final Integer value; + private final String code; + + public static PrequalificationSubStatus fromInt(final Integer statusValue) { + + PrequalificationSubStatus enumeration = PrequalificationSubStatus.INVALID; + switch (statusValue) { + case 100: + enumeration = PrequalificationSubStatus.PENDING; + break; + case 200: + enumeration = PrequalificationSubStatus.IN_PROGRESS; + break; + case 300: + enumeration = PrequalificationSubStatus.COMPLETED; + break; + } + return enumeration; + } + + PrequalificationSubStatus(final Integer value, final String code) { + this.value = value; + this.code = code; + } + + public static PrequalificationSubStatus fromString(String status) { + + PrequalificationSubStatus clientStatus = PrequalificationSubStatus.INVALID; + + if (!StringUtils.hasLength(status)) { + return clientStatus; + } + + if (status.equalsIgnoreCase(PrequalificationSubStatus.PENDING.toString())) { + clientStatus = PrequalificationSubStatus.PENDING; + } else if (status.equalsIgnoreCase(PrequalificationSubStatus.IN_PROGRESS.toString())) { + clientStatus = PrequalificationSubStatus.IN_PROGRESS; + } else if (status.equalsIgnoreCase(PrequalificationSubStatus.COMPLETED.toString())) { + clientStatus = PrequalificationSubStatus.COMPLETED; + } else { + clientStatus = PrequalificationSubStatus.INVALID; + } + + return clientStatus; + + } + + public Integer getValue() { + return this.value; + } + + public String getCode() { + return this.code; + } + + public boolean isPending() { + return this.value.equals(PrequalificationSubStatus.PENDING.getValue()); + } + + public boolean isInProgress() { + return this.value.equals(PrequalificationSubStatus.IN_PROGRESS.getValue()); + } + + public boolean isCompleted() { + return this.value.equals(PrequalificationSubStatus.COMPLETED.getValue()); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/ValidationChecklistResult.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/ValidationChecklistResult.java index 8d4837b0950..74dd16e660d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/ValidationChecklistResult.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/domain/ValidationChecklistResult.java @@ -33,8 +33,8 @@ @Table(name = "m_checklist_validation_result") public class ValidationChecklistResult extends AbstractAuditableCustom { - @Column(name = "checklist_category_id") - private Integer categoryId; + @Column(name = "policy_id") + private Integer policyId; @Column(name = "prequalification_id") private Long prequalificationId; @@ -43,7 +43,7 @@ public class ValidationChecklistResult extends AbstractAuditableCustom { private Integer prequalificationMemberId; @Column(name = "client_id") - private Integer clientId; + private Long clientId; @Column(name = "prequalification_type") private Integer prequalificationType; diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationStatusNotCompletedException.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationStatusNotCompletedException.java new file mode 100644 index 00000000000..cebc2ee5e67 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/exception/PrequalificationStatusNotCompletedException.java @@ -0,0 +1,32 @@ +/** + * 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 PrequalificationStatusNotCompletedException extends AbstractPlatformResourceNotFoundException { + + public PrequalificationStatusNotCompletedException(String status) { + super("error.msg.group.prequalification.status.not.complete", + "Existing Group Prequalificaiton was not complete: Status is " + status, status); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/handler/AssignPrequalificationCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/handler/AssignPrequalificationCommandHandler.java new file mode 100644 index 00000000000..a0058456dd9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/handler/AssignPrequalificationCommandHandler.java @@ -0,0 +1,52 @@ +/** + * 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.handler; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.DataIntegrityErrorHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.organisation.prequalification.service.PrequalificationWritePlatformService; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.orm.jpa.JpaSystemException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@CommandType(entity = "PREQUALIFICATIONS", action = "ASSIGN") +public class AssignPrequalificationCommandHandler implements NewCommandSourceHandler { + + private final DataIntegrityErrorHandler dataIntegrityErrorHandler; + private final PrequalificationWritePlatformService prequalificationWritePlatformService; + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + try { + return this.prequalificationWritePlatformService.assignPrequalification(command.entityId(), command); + } catch (final JpaSystemException | DataIntegrityViolationException dve) { + dataIntegrityErrorHandler.handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve, + "error.msg.prequalification.assignment.failed", "Failed to assign Prequalification"); + return CommandProcessingResult.empty(); + } + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/serialization/PrequalificationMemberCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/serialization/PrequalificationMemberCommandFromApiJsonDeserializer.java index 100b79e040f..01b97706333 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/serialization/PrequalificationMemberCommandFromApiJsonDeserializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/serialization/PrequalificationMemberCommandFromApiJsonDeserializer.java @@ -77,6 +77,7 @@ public void validateForCreate(String json) { final String dpi = this.fromApiJsonHelper.extractStringNamed(ClientApiConstants.dpiParamName, element); baseDataValidator.reset().parameter(ClientApiConstants.dpiParamName).value(dpi).notNull().notBlank().notExceedingLengthOf(20); + ClientIdentifierDocumentValidator.checkDPI(dpi, ClientApiConstants.dpiParamName); final BigDecimal requestedAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element); @@ -86,9 +87,7 @@ public void validateForCreate(String json) { final LocalDate dateOfBirth = this.fromApiJsonHelper.extractLocalDateNamed("dob", element); baseDataValidator.reset().parameter("dob").value(dateOfBirth).value(dateOfBirth).notNull() .validateDateBefore(DateUtils.getBusinessLocalDate()); - } - } public void validateForUpdate(String json) { @@ -124,7 +123,6 @@ public void validateForUpdate(String json) { element); baseDataValidator.reset().parameter(PrequalificatoinApiConstants.memberDobParamName).value(dateOfBirth).value(dateOfBirth) .notNull().validateDateBefore(DateUtils.getBusinessLocalDate()); - } final String workWithPuente = this.fromApiJsonHelper.extractStringNamed(PrequalificatoinApiConstants.memberWorkWithPuenteParamName, diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistReadPlatformServiceImpl.java index b5b1225280f..fadd75012e4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationChecklistReadPlatformServiceImpl.java @@ -25,7 +25,7 @@ import org.apache.fineract.infrastructure.core.domain.JdbcSupport; import org.apache.fineract.organisation.prequalification.data.ChecklistValidationResult; import org.apache.fineract.organisation.prequalification.data.GenericValidationResultSet; -import org.apache.fineract.organisation.prequalification.data.HardPolicyCategoryData; +import org.apache.fineract.organisation.prequalification.data.PolicyData; import org.apache.fineract.organisation.prequalification.data.PrequalificationChecklistData; import org.apache.fineract.organisation.prequalification.domain.CheckValidationColor; import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; @@ -62,16 +62,16 @@ public PrequalificationChecklistData retrieveHardPolicyValidationResults(final L PrequalificationGroup prequalificationGroup = this.prequalificationGroupRepositoryWrapper .findOneWithNotFoundDetection(prequalificationId); final Long productId = prequalificationGroup.getLoanProduct().getId(); - final PrequalificationChecklistWritePlatformServiceImpl.CheckCategoryMapper checkCategoryMapper = new PrequalificationChecklistWritePlatformServiceImpl.CheckCategoryMapper(); - final List groupPolicies = this.jdbcTemplate.query(checkCategoryMapper.schema(), checkCategoryMapper, - productId, PrequalificationType.GROUP.getValue()); + final PrequalificationChecklistWritePlatformServiceImpl.PolicyMapper policyMapper = new PrequalificationChecklistWritePlatformServiceImpl.PolicyMapper(); + final List groupPolicies = this.jdbcTemplate.query(policyMapper.schema(), policyMapper, productId, + PrequalificationType.GROUP.name()); final List prequalificationColumnHeaders = new ArrayList<>(List.of("label.heading.prequalification.name")); final List> prequalificationRows = new ArrayList<>(); final String sql = "SELECT " + validationChecklistMapper.schema() + " WHERE mcvr.prequalification_id = ? "; final List validationResults = this.jdbcTemplate.query(sql, validationChecklistMapper, prequalificationId); final List prequalificationRow = new ArrayList<>(List.of(prequalificationGroup.getGroupName())); - for (HardPolicyCategoryData policy : groupPolicies) { + for (PolicyData policy : groupPolicies) { prequalificationColumnHeaders.add(policy.getDescription()); for (ChecklistValidationResult validationResult : validationResults) { if (policy.getId().equals(validationResult.getPolicyId()) @@ -85,8 +85,8 @@ public PrequalificationChecklistData retrieveHardPolicyValidationResults(final L prequalificationRows.add(prequalificationRow); final GenericValidationResultSet groupValidationResultSet = new GenericValidationResultSet(prequalificationColumnHeaders, prequalificationRows); - final List individualPolicies = this.jdbcTemplate.query(checkCategoryMapper.schema(), checkCategoryMapper, - productId, PrequalificationType.INDIVIDUAL.getValue()); + final List individualPolicies = this.jdbcTemplate.query(policyMapper.schema(), policyMapper, productId, + PrequalificationType.INDIVIDUAL.name()); final List memberColumnHeaders = new ArrayList<>( List.of("label.heading.clientid", "label.heading.clientname", "label.heading.dpi")); individualPolicies.forEach(policy -> memberColumnHeaders.add(policy.getDescription())); @@ -96,7 +96,7 @@ public PrequalificationChecklistData retrieveHardPolicyValidationResults(final L String memberId = null; String clientName; String dpi; - for (HardPolicyCategoryData policy : individualPolicies) { + for (PolicyData policy : individualPolicies) { for (ChecklistValidationResult validationResult : validationResults) { if (policy.getId().equals(validationResult.getPolicyId()) && PrequalificationType.INDIVIDUAL.getValue().equals(validationResult.getPrequalificationTypeEnum()) @@ -126,12 +126,12 @@ public GenericValidationResultSet retrieveClientHardPolicyDetails(Long clientId) PrequalificationGroup prequalificationGroup = groupMember.getPrequalificationGroup(); LoanProduct loanProduct = prequalificationGroup.getLoanProduct(); - final PrequalificationChecklistWritePlatformServiceImpl.CheckCategoryMapper checkCategoryMapper = new PrequalificationChecklistWritePlatformServiceImpl.CheckCategoryMapper(); + final PrequalificationChecklistWritePlatformServiceImpl.PolicyMapper policyMapper = new PrequalificationChecklistWritePlatformServiceImpl.PolicyMapper(); final List> memberRows = new ArrayList<>(); final String sql = "SELECT " + validationChecklistMapper.schema() + " WHERE mcvr.prequalification_member_id = ?"; final List validationResults = this.jdbcTemplate.query(sql, validationChecklistMapper, clientId); - final List individualPolicies = this.jdbcTemplate.query(checkCategoryMapper.schema(), checkCategoryMapper, - loanProduct.getId(), PrequalificationType.INDIVIDUAL.getValue()); + final List individualPolicies = this.jdbcTemplate.query(policyMapper.schema(), policyMapper, loanProduct.getId(), + PrequalificationType.INDIVIDUAL.name()); final List memberColumnHeaders = new ArrayList<>( List.of("label.heading.clientid", "label.heading.clientname", "label.heading.dpi")); @@ -141,7 +141,7 @@ public GenericValidationResultSet retrieveClientHardPolicyDetails(Long clientId) String memberId = null; String clientName; String dpi; - for (HardPolicyCategoryData policy : individualPolicies) { + for (PolicyData policy : individualPolicies) { for (ChecklistValidationResult validationResult : validationResults) { if (policy.getId().equals(validationResult.getPolicyId()) && PrequalificationType.INDIVIDUAL.getValue().equals(validationResult.getPrequalificationTypeEnum())) { @@ -166,10 +166,10 @@ private static final class ValidationChecklistMapper implements RowMapper clientDatas = this.jdbcTemplate.query(clientDataMapper.schema(), clientDataMapper, prequalificationId); final Long productId = prequalificationGroup.getLoanProduct().getId(); - + final Integer noOfMembers = prequalificationGroup.getMembers().size(); + final BigDecimal totalAmountRequested = prequalificationGroup.getMembers().stream() + .map(PrequalificationGroupMember::getRequestedAmount).reduce(BigDecimal.ONE, BigDecimal::add); + final GroupData groupData = GroupData.builder().id(prequalificationId).productId(productId).numberOfMembers(noOfMembers) + .requestedAmount(totalAmountRequested).members(clientDatas).build(); Integer fromStatus = prequalificationGroup.getStatus(); - List validationChecklistResults = new ArrayList<>(); - CheckCategoryMapper checkCategoryMapper = new CheckCategoryMapper(); - List groupPolicies = this.jdbcTemplate.query(checkCategoryMapper.schema(), checkCategoryMapper, productId, - PrequalificationType.GROUP.getValue()); - List individualPolicies = this.jdbcTemplate.query(checkCategoryMapper.schema(), checkCategoryMapper, - productId, PrequalificationType.INDIVIDUAL.getValue()); + final List groupPolicies = this.jdbcTemplate.query(this.policyMapper.schema(), this.policyMapper, productId, + PrequalificationType.GROUP.name()); + final List individualPolicies = this.jdbcTemplate.query(policyMapper.schema(), policyMapper, productId, + PrequalificationType.INDIVIDUAL.name()); final String deleteStatement = "DELETE FROM m_checklist_validation_result WHERE prequalification_id = ?"; this.jdbcTemplate.update(deleteStatement, prequalificationId); - BigDecimal totalAmount = prequalificationGroup.getMembers().stream().map(PrequalificationGroupMember::getRequestedAmount) - .reduce(BigDecimal.ONE, BigDecimal::add); - final ClientData groupData = ClientData.builder().requestedAmount(totalAmount).build(); - for (HardPolicyCategoryData policyCategoryData : groupPolicies) { + for (final PolicyData groupPolicy : groupPolicies) { ValidationChecklistResult prequalificationChecklistResult = new ValidationChecklistResult(); prequalificationChecklistResult.setPrequalificationId(prequalificationId); - prequalificationChecklistResult.setCategoryId(policyCategoryData.getId()); + prequalificationChecklistResult.setPolicyId(groupPolicy.getId()); prequalificationChecklistResult.setPrequalificationType(PrequalificationType.GROUP.getValue()); - CheckValidationColor checkValidationColor = this.validateGenericPolicy(HardPolicyCategory.fromInt(policyCategoryData.getId()), - groupData, prequalificationGroup); + CheckValidationColor checkValidationColor = this.validateGenericPolicy(Policies.fromInt(groupPolicy.getId()), null, groupData); prequalificationChecklistResult.setValidationColor(checkValidationColor.getValue()); - AppUser authenticatedUser = platformSecurityContext.authenticatedUser(); + AppUser authenticatedUser = platformSecurityContext.getAuthenticatedUserIfPresent(); final LocalDateTime localDateTime = DateUtils.getLocalDateTimeOfSystem(); - prequalificationChecklistResult.setCreatedBy(authenticatedUser.getId()); - prequalificationChecklistResult.setLastModifiedBy(authenticatedUser.getId()); + if (authenticatedUser != null && authenticatedUser.getId() != null) { + prequalificationChecklistResult.setCreatedBy(authenticatedUser.getId()); + prequalificationChecklistResult.setLastModifiedBy(authenticatedUser.getId()); + } prequalificationChecklistResult.setCreatedDate(localDateTime); prequalificationChecklistResult.setLastModifiedDate(localDateTime); validationChecklistResults.add(prequalificationChecklistResult); } - for (HardPolicyCategoryData policyCategoryData : individualPolicies) { - final ClientDataMapper clientDataMapper = new ClientDataMapper(); - List clientDatas = this.jdbcTemplate.query(clientDataMapper.schema(), clientDataMapper, prequalificationId); + for (PolicyData policyCategoryData : individualPolicies) { for (final ClientData clientData : clientDatas) { + clientData.setProductId(productId); ValidationChecklistResult validationChecklistResult = new ValidationChecklistResult(); validationChecklistResult.setPrequalificationId(prequalificationId); - validationChecklistResult.setCategoryId(policyCategoryData.getId()); + validationChecklistResult.setPolicyId(policyCategoryData.getId()); validationChecklistResult.setClientId(clientData.getClientId()); validationChecklistResult.setPrequalificationMemberId(clientData.getPrequalificationMemberId()); validationChecklistResult.setPrequalificationType(PrequalificationType.INDIVIDUAL.getValue()); - CheckValidationColor checkValidationColor = this - .validateGenericPolicy(HardPolicyCategory.fromInt(policyCategoryData.getId()), clientData, prequalificationGroup); + CheckValidationColor checkValidationColor = this.validateGenericPolicy(Policies.fromInt(policyCategoryData.getId()), + clientData, groupData); validationChecklistResult.setValidationColor(checkValidationColor.getValue()); AppUser authenticatedUser = platformSecurityContext.authenticatedUser(); final LocalDateTime localDateTime = DateUtils.getLocalDateTimeOfSystem(); - validationChecklistResult.setCreatedBy(authenticatedUser.getId()); - validationChecklistResult.setLastModifiedBy(authenticatedUser.getId()); + if (authenticatedUser != null && authenticatedUser.getId() != null) { + validationChecklistResult.setCreatedBy(authenticatedUser.getId()); + validationChecklistResult.setLastModifiedBy(authenticatedUser.getId()); + } validationChecklistResult.setCreatedDate(localDateTime); validationChecklistResult.setLastModifiedDate(localDateTime); validationChecklistResults.add(validationChecklistResult); @@ -149,30 +149,34 @@ public CommandProcessingResult validatePrequalificationHardPolicies(Long prequal PrequalificationStatusLog statusLog = PrequalificationStatusLog.fromJson(appUser, fromStatus, prequalificationGroup.getStatus(), null, prequalificationGroup); - this.preQualificationStatusLogRepository.saveAndFlush(statusLog); - return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(prequalificationId).build(); } - static final class CheckCategoryMapper implements RowMapper { + static final class PolicyMapper implements RowMapper { public String schema() { return """ - SELECT cc.id, cc.name, cc.description \s - FROM checklist_decision_making cdm\s - INNER JOIN checklist_categories cc ON cc.id = cdm.checklist_category_id\s - INNER JOIN m_product_loan mpl ON mpl.id = cdm.product_id\s - WHERE mpl.id = ? AND cdm.validation_type_enum = ? - GROUP BY cc.id"""; + SELECT mp.id AS id,\s + mp.name AS name,\s + mp.label AS label, + mp.description AS description, + mpl.name AS productName + FROM m_policy mp\s + INNER JOIN m_product_policy mpp ON mpp.policy_id = mp.id\s + INNER JOIN m_product_loan mpl ON mpl.id = mpp.product_id\s + WHERE mpl.id = ? AND mpp.evaluation_type = ? + GROUP BY mp.id + """; } @Override - public HardPolicyCategoryData mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException { + public PolicyData mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException { final Integer id = JdbcSupport.getInteger(rs, "id"); final String name = rs.getString("name"); + final String label = rs.getString("label"); final String description = rs.getString("description"); - return new HardPolicyCategoryData(id, name, description); + return PolicyData.builder().id(id).name(name).label(label).description(description).build(); } } @@ -182,7 +186,7 @@ public String schema() { return """ SELECT mc.id AS clientId, mpgm.id AS prequalificationMemberId, IFNULL(mc.display_name,mpgm.name) AS name, mpg.id AS prequalificationId,\s mpgm.requested_amount AS requestedAmount, IFNULL(mc.date_of_birth, mpgm.dob) AS dateOfBirth, IFNULL(mc.dpi, mpgm.dpi) AS dpi, - mpgm.work_with_puente AS workWithPuente, mcv.code_value As gender + mpgm.work_with_puente AS workWithPuente, mcv.code_value As gender, mpgm.is_president AS president, mpgm.buro_check_status buroCheckStatus FROM m_prequalification_group_members mpgm\s LEFT JOIN m_client mc ON mc.dpi = mpgm.dpi\s LEFT JOIN m_code_value mcv ON mcv.id = mc.gender_cv_id @@ -193,10 +197,12 @@ mpgm.requested_amount AS requestedAmount, IFNULL(mc.date_of_birth, mpgm.dob) AS @Override public ClientData mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException { - final Integer clientId = JdbcSupport.getInteger(rs, "clientId"); + final Long clientId = JdbcSupport.getLong(rs, "clientId"); final Integer prequalificationMemberId = JdbcSupport.getInteger(rs, "prequalificationMemberId"); final Integer prequalificationId = JdbcSupport.getInteger(rs, "prequalificationId"); final String name = rs.getString("name"); + final boolean president = rs.getBoolean("president"); + final Integer buroCheckStatus = JdbcSupport.getInteger(rs, "buroCheckStatus"); final Date dateOfBirth = rs.getDate("dateOfBirth"); final String dpi = rs.getString("dpi"); final BigDecimal requestedAmount = rs.getBigDecimal("requestedAmount"); @@ -204,260 +210,658 @@ public ClientData mapRow(@NotNull ResultSet rs, int rowNum) throws SQLException final String gender = rs.getString("gender"); return ClientData.builder().clientId(clientId).prequalificationId(prequalificationId) .prequalificationMemberId(prequalificationMemberId).name(name).dateOfBirth(dateOfBirth).dpi(dpi) - .requestedAmount(requestedAmount).gender(gender).workWithPuente(workWithPuente).build(); + .requestedAmount(requestedAmount).gender(gender).workWithPuente(workWithPuente).president(president) + .buroCheckStatus(buroCheckStatus).build(); } } - private CheckValidationColor validateGenericPolicy(final HardPolicyCategory hardPolicyCategory, final ClientData clientData, - final PrequalificationGroup prequalificationGroup) { + private CheckValidationColor validateGenericPolicy(final Policies policy, final ClientData clientData, final GroupData groupData) { CheckValidationColor checkValidationColor; - switch (hardPolicyCategory) { - case NEW_CLIENT -> checkValidationColor = this.handleNewClientCheck(clientData); - case RECURRING_CUSTOMER -> checkValidationColor = this.handleRecurringClientCheck(clientData, prequalificationGroup); - case INCREASE_PERCENTAGE -> checkValidationColor = this.handleIncreasePercentageCheck(clientData, prequalificationGroup); - case MANDATORY_PHOTO_GRAPH -> checkValidationColor = this.handleMandatoryPhotographCheck(); - case CLIENT_AGE -> checkValidationColor = this.handleClientAgeCheck(clientData); - case NUMBER_OF_MEMBERS_ACCORDING_TO_POLICY -> checkValidationColor = this - .handleNumberOfMembersAccordingToPolicyCheck(prequalificationGroup); - case MINIMUM_AND_MAXIMUM_AMOUNT -> checkValidationColor = this.handleMinAndMaxAmountCheck(prequalificationGroup, clientData); - case DISPARITY_OF_VALUES -> checkValidationColor = this.handleDisparitiesOfValuesCheck(); - case PERCENTAGE_OF_MEMBERS_STARTING_BUSINESS -> checkValidationColor = this.handlePercentageOfMemberStartingBusinessCheck(); - case PERCENTAGE_OF_MEMBERS_WITH_THEIR_OWN_HOME -> checkValidationColor = this.handlePercentageOfMemberWithHomeCheck(); - case CHAIRMAN_OF_THE_BC_BOARD_OF_DIRECTORS -> checkValidationColor = this.handleChairmanBoardOfDirectorsCheck(); - case OVERALL_CONDITION -> checkValidationColor = this.handleOverallConditionCheck(); - case CATEGORIES_OF_CLIENT_TO_ACCEPT -> checkValidationColor = this.handleCategoriesOfClientToAcceptCheck(); - case REQUESTED_AMOUNT -> checkValidationColor = this.handleRequestedAmountCheck(clientData); - case ADD_ENDORSEMENT -> checkValidationColor = this.handleAddEndorsementCheck(); - case PAYMENTS_OUTSIDE_CURRENT_TERM -> checkValidationColor = this.handlePaymentOutsideCurrentTermCheck(); - case PERCENTAGE_OF_MEMBERS_THAT_CAN_HAVE_PRODUCT -> checkValidationColor = this.handPercentageOfProductMemberCheck(); - case GENDER -> checkValidationColor = this.handleGenderCheck(clientData); - case NATIONALITY -> checkValidationColor = this.handleNationalityCheck(); - case INTERNAL_CREDIT_HISTORY -> checkValidationColor = this.handleInternalCreditHistoryCheck(); - case EXTERNAL_CREDIT_HISTORY -> checkValidationColor = this.handleExternalCreditHistoryCheck(); - case CLAIMS_REGISTERED -> checkValidationColor = this.handleClaimedRegisteredCheck(); - case HOUSING_TYPE -> checkValidationColor = this.handleHousingTypeCheck(); - case RENTAL_AGE -> checkValidationColor = this.handleRentalAgeCheck(); - case AGE_OF_BUSINESS -> checkValidationColor = this.handleBusinessAgeCheck(); - case CREDITS -> checkValidationColor = this.handleCreditCheck(); - case CANCELLED_CYCLES_COUNT -> checkValidationColor = this.handleCancelledCyclesCheck(); - case SUBMIT_AGRICULTURAL_TECHNICAL_DIAGNOSIS -> checkValidationColor = this.handleAgriculturalDiagnosisCheck(); - case ACCEPTANCE_OF_NEW_CLIENTS -> checkValidationColor = this.handleAcceptanceOfNewClientCheck(); + switch (policy) { + case ONE -> checkValidationColor = this.runCheck1(); + case TWO -> checkValidationColor = this.runCheck2(); + case THREE -> checkValidationColor = this.runCheck3(clientData); + case FOUR -> checkValidationColor = this.runCheck4(clientData); + case FIVE -> checkValidationColor = this.runCheck5(clientData); + case SIX -> checkValidationColor = this.runCheck6(groupData); + case SEVEN -> checkValidationColor = this.runCheck7(groupData); + case EIGHT -> checkValidationColor = this.runCheck8(groupData); + case NINE -> checkValidationColor = this.runCheck9(); + case TEN -> checkValidationColor = this.runCheck10(groupData); + case ELEVEN -> checkValidationColor = this.runCheck11(groupData); + case TWELVE -> checkValidationColor = this.runCheck12(clientData); + case THIRTEEN -> checkValidationColor = this.runCheck13(clientData); + case FOURTEEN -> checkValidationColor = this.runCheck14(clientData); + case FIFTEEN -> checkValidationColor = this.runCheck15(); + case SIXTEEN -> checkValidationColor = this.runCheck16(clientData); + case SEVENTEEN -> checkValidationColor = this.runCheck17(groupData); + case EIGHTEEN -> checkValidationColor = this.runCheck18(clientData); + case NINETEEN -> checkValidationColor = this.runCheck19(clientData); + case TWENTY -> checkValidationColor = this.runCheck20(clientData); + case TWENTY_ONE -> checkValidationColor = this.runCheck21(clientData); + case TWENTY_TWO -> checkValidationColor = this.runCheck22(); + case TWENTY_THREE -> checkValidationColor = this.runCheck23(clientData); + case TWENTY_FOUR -> checkValidationColor = this.runCheck24(clientData); + case TWENTY_FIVE -> checkValidationColor = this.runCheck25(clientData); + case TWENTY_SIX -> checkValidationColor = this.runCheck26(clientData); + case TWENTY_SEVEN -> checkValidationColor = this.runCheck27(groupData); + case TWENTY_EIGHT -> checkValidationColor = this.runCheck28(groupData); + case TWENTY_NINE -> checkValidationColor = this.runCheck29(); + case THIRTY -> checkValidationColor = this.runCheck30(clientData); + case THIRTY_ONE -> checkValidationColor = this.runCheck31(clientData); + case THIRTY_TWO -> checkValidationColor = this.runCheck32(); + case THIRTY_THREE -> checkValidationColor = this.runCheck33(); default -> checkValidationColor = CheckValidationColor.INVALID; } return checkValidationColor; } - private CheckValidationColor handleNewClientCheck(final ClientData clientData) { - CheckValidationColor checkValidationColor; - final Integer clientId = clientData.getClientId(); - final String loanCycle = "SELECT COALESCE(MAX(ml.loan_counter), 0) FROM m_loan ml WHERE ml.client_id = ?"; - final Integer loanCycleCount = this.jdbcTemplate.queryForObject(loanCycle, Integer.class, clientId); - final String closedLoanCountSql = "SELECT COALESCE(COUNT(*), 0) FROM m_loan ml WHERE ml.loan_status_id IN (700, 600) AND ml.client_id = ? "; - final Integer closedLoanCount = this.jdbcTemplate.queryForObject(closedLoanCountSql, Integer.class, clientId); - final String notActiveSql = "SELECT COALESCE(COUNT(*), 0) FROM m_loan ml WHERE ml.loan_status_id NOT IN (100, 200, 300, 303, 304, 400, 500, 601, 602) AND ml.client_id = ? "; - final Integer notActiveCount = this.jdbcTemplate.queryForObject(notActiveSql, Integer.class, clientId); - if (ObjectUtils.defaultIfNull(loanCycleCount, 0) == 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else if (ObjectUtils.defaultIfNull(closedLoanCount, 0) > 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else if (ObjectUtils.defaultIfNull(notActiveCount, 0) == 1) { - checkValidationColor = CheckValidationColor.GREEN; - } else { - checkValidationColor = CheckValidationColor.RED; - } - return checkValidationColor; + /** + * New client categorization + */ + private CheckValidationColor runCheck1() { + return CheckValidationColor.GREEN; } - private CheckValidationColor handleRecurringClientCheck(final ClientData clientData, - final PrequalificationGroup prequalificationGroup) { - final CheckValidationColor checkValidationColor; - final String loanCycle = "SELECT COALESCE(MAX(ml.loan_counter), 0) FROM m_loan ml WHERE ml.client_id = ?"; - final Integer clientId = clientData.getClientId(); - final Long productId = prequalificationGroup.getLoanProduct().getId(); - final Integer loanCycleCount = this.jdbcTemplate.queryForObject(loanCycle, Integer.class, clientId); - if (List.of(2L, 8L, 9L).contains(productId) && ObjectUtils.defaultIfNull(loanCycleCount, 0) > 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else if (List.of(4L, 5L).contains(productId) && ObjectUtils.defaultIfNull(loanCycleCount, 0) > 3) { - checkValidationColor = CheckValidationColor.GREEN; - } else { - checkValidationColor = CheckValidationColor.RED; - } - return checkValidationColor; + /** + * Recurring customer categorization + */ + private CheckValidationColor runCheck2() { + return CheckValidationColor.GREEN; } - private CheckValidationColor handleIncreasePercentageCheck(final ClientData clientData, - final PrequalificationGroup prequalificationGroup) { - final CheckValidationColor checkValidationColor; - final Integer clientId = clientData.getClientId(); - final Long productId = prequalificationGroup.getLoanProduct().getId(); - BigDecimal requestedAmount = clientData.getRequestedAmount(); - final String principalAmtSql = "SELECT COALESCE(ml.principal_amount, 0) AS principalAmount FROM m_loan ml WHERE ml.client_id = ? " - + "AND ml.loan_status_id IN (700, 600) ORDER BY ml.disbursedon_date DESC"; - final List principalAmounts = jdbcTemplate.queryForList(principalAmtSql, BigDecimal.class, clientId); - BigDecimal previousPrincipalAmount = !principalAmounts.isEmpty() ? principalAmounts.get(0) : BigDecimal.ZERO; - BigDecimal percentageIncrease = BigDecimal.valueOf(100); - final MathContext mc = new MathContext(8, MoneyHelper.getRoundingMode()); - if (previousPrincipalAmount.compareTo(BigDecimal.ZERO) > 0) { - percentageIncrease = requestedAmount.subtract(previousPrincipalAmount).multiply(BigDecimal.valueOf(100)) - .divide(previousPrincipalAmount, mc); + /** + * Increase percentage + */ + private CheckValidationColor runCheck3(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.THREE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${requestedAmount}", String.valueOf(clientData.getRequestedAmount())); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Mandatory to attach photographs and investment plan + */ + private CheckValidationColor runCheck4(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.FOUR.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${requestedAmount}", String.valueOf(clientData.getRequestedAmount())); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Client age check + */ + private CheckValidationColor runCheck5(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.FIVE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + private ClientData retrieveClientParams(final Long clientId, final Long productId) { + final String reportName = "Client Categorization Policy Check"; + Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", String.valueOf(clientId)); + reportParams.put("${loanProductId}", String.valueOf(productId)); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + final List columnHeaders = result.getColumnHeaders(); + List rowDataList = result.getData(); + String clientCategorization = "NEW"; + String clientArea = "RURAL"; + String recreditCategorization = "NUEVO"; + if (!rowDataList.isEmpty()) { + for (int i = 0; i < columnHeaders.size(); i++) { + final ResultsetColumnHeaderData columnHeaderData = columnHeaders.get(i); + if ("clientCategorization".equals(columnHeaderData.getColumnName())) { + List rowList = rowDataList.get(0).getRow(); + clientCategorization = rowList.get(i); + } + if ("clientArea".equals(columnHeaderData.getColumnName())) { + List rowList = rowDataList.get(0).getRow(); + clientArea = rowList.get(i); + } + if ("recreditCategorization".equals(columnHeaderData.getColumnName())) { + List rowList = rowDataList.get(0).getRow(); + recreditCategorization = rowList.get(i); + } + } } - if (List.of(2L, 9L).contains(productId) && percentageIncrease.compareTo(BigDecimal.valueOf(200)) == 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else if (List.of(2L, 9L).contains(productId) && percentageIncrease.compareTo(BigDecimal.valueOf(201)) >= 0 - && percentageIncrease.compareTo(BigDecimal.valueOf(500)) <= 0) { - checkValidationColor = CheckValidationColor.YELLOW; - } else if (List.of(2L, 9L).contains(productId) && percentageIncrease.compareTo(BigDecimal.valueOf(500)) >= 0) { - checkValidationColor = CheckValidationColor.RED; - } else if (List.of(4L, 5L).contains(productId) && percentageIncrease.compareTo(BigDecimal.valueOf(60)) <= 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else if (List.of(4L, 5L).contains(productId) && percentageIncrease.compareTo(BigDecimal.valueOf(60)) > 0) { - checkValidationColor = CheckValidationColor.ORANGE; - } else { - checkValidationColor = CheckValidationColor.RED; + return ClientData.builder().clientArea(clientArea).clientCategorization(clientCategorization) + .recreditCategorization(recreditCategorization).build(); + } + + private CheckValidationColor extractColorFromResultset(final GenericResultsetData resultset) { + final List columnHeaders = resultset.getColumnHeaders(); + final List rowDataList = resultset.getData(); + CheckValidationColor colorResult = CheckValidationColor.RED; + if (!rowDataList.isEmpty()) { + for (int i = 0; i < columnHeaders.size(); i++) { + final ResultsetColumnHeaderData columnHeaderData = columnHeaders.get(i); + if ("color".equals(columnHeaderData.getColumnName())) { + final List rowList = rowDataList.get(0).getRow(); + final String color = rowList.get(i); + if (StringUtils.isNotEmpty(color)) { + colorResult = CheckValidationColor.valueOf(color); + } + + } + } } - return checkValidationColor; - } - - private CheckValidationColor handleMandatoryPhotographCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleClientAgeCheck(final ClientData clientData) { - final CheckValidationColor checkValidationColor; - java.util.Date dateOfBirth = clientData.getDateOfBirth(); // .toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - LocalDate localDate = Instant.ofEpochMilli(dateOfBirth.getTime()).atZone(ZoneId.systemDefault()).toLocalDate(); - LocalDate businessDate = DateUtils.getBusinessLocalDate(); - int age = businessDate.getYear() - localDate.getYear(); - if (age >= 20 && age <= 60) { - checkValidationColor = CheckValidationColor.GREEN; - } else { - checkValidationColor = CheckValidationColor.RED; + return colorResult; + } + + /** + * Number of members according to policy + */ + private CheckValidationColor runCheck6(final GroupData groupData) { + String clientArea = "RURAL"; + String clientCategorization = "NEW"; + String recreditCategorization = "NUEVO"; + if (!CollectionUtils.isEmpty(groupData.getMembers())) { + final ClientData clientData = groupData.getMembers().get(0); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + clientArea = params.getClientArea(); + recreditCategorization = params.getRecreditCategorization(); + clientCategorization = params.getClientCategorization(); } - return checkValidationColor; - } - - private CheckValidationColor handleNumberOfMembersAccordingToPolicyCheck(final PrequalificationGroup prequalificationGroup) { - final CheckValidationColor checkValidationColor; - final int membersCount = prequalificationGroup.getMembers().size(); - if (membersCount > 10) { - checkValidationColor = CheckValidationColor.GREEN; - } else if (membersCount < 4) { - checkValidationColor = CheckValidationColor.ORANGE; - } else { - checkValidationColor = CheckValidationColor.RED; + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.SIX.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final String numberOfMembers = String.valueOf(groupData.getNumberOfMembers()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", clientCategorization); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${recreditCategorization}", recreditCategorization); + reportParams.put("${numberOfMembers}", numberOfMembers); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Minimum and maximum amount + */ + private CheckValidationColor runCheck7(final GroupData groupData) { + String clientArea = "RURAL"; + if (!CollectionUtils.isEmpty(groupData.getMembers())) { + final ClientData clientData = groupData.getMembers().get(0); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + clientArea = params.getClientArea(); } - return checkValidationColor; - } - - private CheckValidationColor handleMinAndMaxAmountCheck(final PrequalificationGroup prequalificationGroup, - final ClientData clientData) { - final CheckValidationColor checkValidationColor; - if (BigDecimal.valueOf(1000).compareTo(ObjectUtils.defaultIfNull(clientData.getRequestedAmount(), BigDecimal.ZERO)) > 0 - && BigDecimal.valueOf(20000).compareTo(ObjectUtils.defaultIfNull(clientData.getRequestedAmount(), BigDecimal.ZERO)) < 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else { - checkValidationColor = CheckValidationColor.RED; + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.SEVEN.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${requestedAmount}", String.valueOf(groupData.getRequestedAmount())); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Value disparity + */ + private CheckValidationColor runCheck8(final GroupData groupData) { + String clientArea = "RURAL"; + String disparityRatio = "1"; + BigDecimal minimumAmount = BigDecimal.ZERO; + BigDecimal maximumAmount = BigDecimal.ZERO; + if (!CollectionUtils.isEmpty(groupData.getMembers())) { + final ClientData clientData = groupData.getMembers().get(0); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + clientArea = params.getClientArea(); + minimumAmount = groupData.getMembers().get(0).getRequestedAmount(); + for (final ClientData memberData : groupData.getMembers()) { + final BigDecimal requestedAmount = memberData.getRequestedAmount(); + if (maximumAmount != null && maximumAmount.compareTo(requestedAmount) < 0) { + maximumAmount = requestedAmount; + } + if (minimumAmount != null && minimumAmount.compareTo(requestedAmount) > 0) { + minimumAmount = requestedAmount; + } + } } - return checkValidationColor; - } - - private CheckValidationColor handleDisparitiesOfValuesCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handlePercentageOfMemberStartingBusinessCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handlePercentageOfMemberWithHomeCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleChairmanBoardOfDirectorsCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleOverallConditionCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleCategoriesOfClientToAcceptCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleRequestedAmountCheck(final ClientData clientData) { - final CheckValidationColor checkValidationColor; - if (BigDecimal.valueOf(3000).compareTo(ObjectUtils.defaultIfNull(clientData.getRequestedAmount(), BigDecimal.ZERO)) <= 0) { - checkValidationColor = CheckValidationColor.GREEN; - } else { - checkValidationColor = CheckValidationColor.RED; + if (maximumAmount != null) { + disparityRatio = String.valueOf(maximumAmount.divide(minimumAmount, MoneyHelper.getRoundingMode())); } - return checkValidationColor; - } - - private CheckValidationColor handleAddEndorsementCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handlePaymentOutsideCurrentTermCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handPercentageOfProductMemberCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleGenderCheck(final ClientData clientData) { - final CheckValidationColor checkValidationColor; - if ("Mujer".equalsIgnoreCase(clientData.getGender())) { - checkValidationColor = CheckValidationColor.GREEN; - } else { - checkValidationColor = CheckValidationColor.ORANGE; + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.EIGHT.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${disparityRatio}", disparityRatio); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Percentage of members starting business + */ + private CheckValidationColor runCheck9() { + return CheckValidationColor.RED; + } + + /** + * Percentage of members with their own home + * + * @param groupData + */ + private CheckValidationColor runCheck10(GroupData groupData) { + final String reportName = Policies.TEN.getName() + " Policy Check"; + + final String prequalificationId = String.valueOf(groupData.getId()); + final String productId = String.valueOf(groupData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * President of the Board of Directors of the BC + */ + private CheckValidationColor runCheck11(final GroupData groupData) { + final List members = groupData.getMembers(); + final Optional presidentOptionalData = members.stream().filter(ClientData::getPresident).findFirst(); + if (presidentOptionalData.isPresent()) { + final ClientData presidentData = presidentOptionalData.get(); + final ClientData params = retrieveClientParams(presidentData.getClientId(), presidentData.getProductId()); + final String clientArea = params.getClientArea(); + final Integer bureauStatus = presidentData.getBuroCheckStatus(); + final BuroCheckClassification buroCheckClassification = BuroCheckClassification.fromInt(bureauStatus); + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.ELEVEN.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${buroCheckClassification}", buroCheckClassification.getLetter()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, + false); + return extractColorFromResultset(result); } - return checkValidationColor; - } - - private CheckValidationColor handleNationalityCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleInternalCreditHistoryCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleExternalCreditHistoryCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleClaimedRegisteredCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleHousingTypeCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleRentalAgeCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleBusinessAgeCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleCreditCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleCancelledCyclesCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleAgriculturalDiagnosisCheck() { - return CheckValidationColor.GREEN; - } - - private CheckValidationColor handleAcceptanceOfNewClientCheck() { - return CheckValidationColor.GREEN; + return CheckValidationColor.RED; + } + + /** + * General condition + */ + private CheckValidationColor runCheck12(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWELVE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Categories of clients to accept + */ + private CheckValidationColor runCheck13(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.THIRTEEN.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Integer bureauStatus = clientData.getBuroCheckStatus(); + final BuroCheckClassification buroCheckClassification = BuroCheckClassification.fromInt(bureauStatus); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + reportParams.put("${buroCheckClassification}", buroCheckClassification.getLetter()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Amount requested in relation to the current amount of main products + */ + private CheckValidationColor runCheck14(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.FOURTEEN.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final String requestedAmount = clientData.getRequestedAmount().toPlainString(); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${requestedAmount}", requestedAmount); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Add endorsement + */ + private CheckValidationColor runCheck15() { + return CheckValidationColor.RED; + } + + /** + * Payments outside the current term of the main product + * + * @param clientData + */ + private CheckValidationColor runCheck16(ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.SIXTEEN.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Percentage of members of the same group who they can have parallel product + */ + private CheckValidationColor runCheck17(final GroupData groupData) { + String clientArea = "RURAL"; + if (!CollectionUtils.isEmpty(groupData.getMembers())) { + final ClientData clientData = groupData.getMembers().get(0); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + clientArea = params.getClientArea(); + } + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.SEVENTEEN.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final String numberOfMembers = String.valueOf(groupData.getNumberOfMembers()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${numberOfMembers}", numberOfMembers); + reportParams.put("${requestedAmount}", String.valueOf(groupData.getRequestedAmount())); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Gender + */ + private CheckValidationColor runCheck18(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.EIGHTEEN.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Nationality + */ + private CheckValidationColor runCheck19(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.NINETEEN.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Internal Credit History + */ + private CheckValidationColor runCheck20(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWENTY.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * External Credit History + */ + private CheckValidationColor runCheck21(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWENTY_ONE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Do you register any lawsuit? + */ + private CheckValidationColor runCheck22() { + return CheckValidationColor.RED; + } + + /** + * Housing Type + */ + private CheckValidationColor runCheck23(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWENTY_THREE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Rental Age + */ + private CheckValidationColor runCheck24(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWENTY_FOUR.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Age Of Business + */ + private CheckValidationColor runCheck25(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWENTY_FIVE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Credits + */ + private CheckValidationColor runCheck26(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.TWENTY_SIX.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Cancelled Cycles Count + */ + private CheckValidationColor runCheck27(final GroupData groupData) { + String clientArea = "RURAL"; + if (!CollectionUtils.isEmpty(groupData.getMembers())) { + final ClientData clientData = groupData.getMembers().get(0); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + clientArea = params.getClientArea(); + } + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.TWENTY_SEVEN.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${requestedAmount}", String.valueOf(groupData.getRequestedAmount())); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Acceptance of new clients + */ + private CheckValidationColor runCheck28(final GroupData groupData) { + String clientArea = "RURAL"; + String clientsRatio = "1"; + int newMembersCount = 0; + int recurringMembersCount = 0; + if (!CollectionUtils.isEmpty(groupData.getMembers())) { + for (final ClientData memberData : groupData.getMembers()) { + final ClientData params = retrieveClientParams(memberData.getClientId(), memberData.getProductId()); + clientArea = params.getClientArea(); + if ("NEW".equals(params.getClientCategorization())) { + newMembersCount++; + } else { + recurringMembersCount++; + } + } + } + if (newMembersCount > 0 && recurringMembersCount > 0) { + final Integer ratio = recurringMembersCount / newMembersCount; + clientsRatio = String.valueOf(ratio); + } + final String prequalificationId = String.valueOf(groupData.getId()); + final String reportName = Policies.TWENTY_EIGHT.getName() + " Policy Check"; + final String productId = Long.toString(groupData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${prequalificationId}", prequalificationId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientArea}", clientArea); + reportParams.put("${clientsRatio}", clientsRatio); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Present agricultural technical diagnosis (Commcare) + */ + private CheckValidationColor runCheck29() { + return CheckValidationColor.RED; + } + + /** + * Age + */ + private CheckValidationColor runCheck30(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.THIRTY.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Amount + */ + private CheckValidationColor runCheck31(final ClientData clientData) { + final String clientId = String.valueOf(clientData.getClientId()); + final String reportName = Policies.THIRTY_ONE.getName() + " Policy Check"; + final String productId = Long.toString(clientData.getProductId()); + final ClientData params = retrieveClientParams(clientData.getClientId(), clientData.getProductId()); + final Map reportParams = new HashMap<>(); + reportParams.put("${clientId}", clientId); + reportParams.put("${loanProductId}", productId); + reportParams.put("${clientCategorization}", params.getClientCategorization()); + reportParams.put("${recreditCategorization}", params.getRecreditCategorization()); + reportParams.put("${requestedAmount}", String.valueOf(clientData.getRequestedAmount())); + final GenericResultsetData result = this.readReportingService.retrieveGenericResultset(reportName, "report", reportParams, false); + return extractColorFromResultset(result); + } + + /** + * Percentage of members with agricultural business + */ + private CheckValidationColor runCheck32() { + return CheckValidationColor.RED; + } + + /** + * Percentage of members with their own business + */ + private CheckValidationColor runCheck33() { + return CheckValidationColor.RED; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformService.java index 291b08c2fb3..83e2a2ff9df 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationReadPlatformService.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.organisation.prequalification.service; +import java.util.Collection; import org.apache.fineract.infrastructure.core.service.Page; import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; @@ -34,4 +35,6 @@ public interface PrequalificationReadPlatformService { Page retrieveAllMembers(SearchParameters searchParameters); MemberPrequalificationData retrieveOneMember(Long clientId); + + Collection retrievePrequalificationGroupsMappings(Long groupId); } 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 43ec6cb08d7..3b9792aeb04 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 @@ -23,9 +23,11 @@ import java.sql.SQLException; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.infrastructure.codes.data.CodeValueData; import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; import org.apache.fineract.infrastructure.core.data.ApiParameterError; import org.apache.fineract.infrastructure.core.data.EnumOptionData; @@ -46,9 +48,12 @@ import org.apache.fineract.organisation.prequalification.domain.PreQualificationsMemberEnumerations; import org.apache.fineract.organisation.prequalification.domain.PrequalificationMemberIndication; import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatus; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationSubStatus; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationType; import org.apache.fineract.portfolio.client.service.ClientChargeWritePlatformServiceJpaRepositoryImpl; import org.apache.fineract.portfolio.client.service.ClientReadPlatformService; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository; +import org.apache.fineract.useradministration.domain.AppUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -71,6 +76,7 @@ public class PrequalificationReadPlatformServiceImpl implements Prequalification private final PaginationHelper paginationHelper; private final ColumnValidator columnValidator; private final PrequalificationsGroupMapper prequalificationsGroupMapper = new PrequalificationsGroupMapper(); + private final PrequalificationsGroupMappingsMapper mappingsMapper = new PrequalificationsGroupMappingsMapper(); private final PrequalificationsMemberMapper prequalificationsMemberMapper = new PrequalificationsMemberMapper(); private final DatabaseSpecificSQLGenerator sqlGenerator; private final PreQualificationMemberRepository preQualificationMemberRepository; @@ -243,8 +249,24 @@ public MemberPrequalificationData retrieveOneMember(Long clientId) { return clientData; } + @Override + public Collection retrievePrequalificationGroupsMappings(Long groupId) { + final String sql = "select " + this.mappingsMapper.schema() + " where GR.group_id = ? "; + Collection prequalificationGroups = this.jdbcTemplate.query(sql, this.mappingsMapper, + new Object[] { groupId }); + return prequalificationGroups; + } + private String buildSqlStringFromBlacklistCriteria(final SearchParameters searchParameters, List paramList, boolean isGroup) { + AppUser appUser = this.context.authenticatedUser(); + String committeeQuery = "select committee_id from m_committee_user where user_id = ? order by committee_id asc limit 1"; + final List committeeIdList = this.jdbcTemplate.queryForList(committeeQuery, Long.class, appUser.getId()); + + CodeValueData committeeValueData = null; + if (!committeeIdList.isEmpty()) { + committeeValueData = this.codeValueReadPlatformService.retrieveCodeValue(committeeIdList.get(0)); + } String sqlSearch = searchParameters.getSqlSearch(); final Long officeId = searchParameters.getOfficeId(); final String dpiNumber = searchParameters.getName(); @@ -252,14 +274,28 @@ private String buildSqlStringFromBlacklistCriteria(final SearchParameters search final String type = searchParameters.getType(); final String groupName = searchParameters.getGroupName(); final String centerName = searchParameters.getCenterName(); + final String groupingType = searchParameters.getGroupingType(); String extraCriteria = ""; + + if (StringUtils.isNotBlank(groupingType)) { + if (groupingType.equals("group")) { + extraCriteria += " and g.prequalification_type_enum = ? "; + paramList.add(PrequalificationType.GROUP.getValue()); + } + + if (groupingType.equals("individual")) { + extraCriteria += " and g.prequalification_type_enum = ? "; + paramList.add(PrequalificationType.INDIVIDUAL.getValue()); + } + } + if (sqlSearch != null && !isGroup) { - extraCriteria = " and (m.name like '%" + sqlSearch + "%' OR m.dpi='" + sqlSearch + "') "; + extraCriteria += " and (m.name like '%" + sqlSearch + "%' OR m.dpi='" + sqlSearch + "') "; } if (sqlSearch != null && isGroup) { - extraCriteria = " and (g.group_name like '%" + sqlSearch + "%' OR pc.display_name='%" + sqlSearch + "%') "; + extraCriteria += " and (g.group_name like '%" + sqlSearch + "%' OR pc.display_name='%" + sqlSearch + "%') "; } if (officeId != null) { @@ -297,9 +333,20 @@ private String buildSqlStringFromBlacklistCriteria(final SearchParameters search } else if (type.equals("analysis")) { extraCriteria += " and g.status IN( " + PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL.getValue().toString() + ", " + PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS.getValue().toString() + ") "; - } else if (type.equals("exceptionsqueue")) { + } else if (type.equals("agency")) { extraCriteria += " and g.status IN( " + PrequalificationStatus.AGENCY_LEAD_PENDING_APPROVAL.getValue().toString() + ", " + PrequalificationStatus.AGENCY_LEAD_PENDING_APPROVAL_WITH_EXCEPTIONS.getValue().toString() + ") "; + } else if (type.equals("exceptionsqueue")) { + extraCriteria += " and g.status IN( " + + PrequalificationStatus.ANALYSIS_UNIT_PENDING_APPROVAL_WITH_EXCEPTIONS.getValue().toString() + ", " + + PrequalificationStatus.AGENCY_LEAD_PENDING_APPROVAL_WITH_EXCEPTIONS.getValue().toString() + ") "; + } else if (type.equals("committeeapprovals")) { + + if (committeeValueData == null) { + extraCriteria += " and g.status IN( " + PrequalificationStatus.INVALID.getValue().toString() + ") "; + } else { + extraCriteria += " and g.status IN( " + resolveCommitteeGroupStatus(committeeValueData) + ") "; + } } } @@ -309,6 +356,23 @@ private String buildSqlStringFromBlacklistCriteria(final SearchParameters search return extraCriteria; } + private String resolveCommitteeGroupStatus(CodeValueData committeeValueData) { + String name = committeeValueData.getName(); + + String statusValues = ""; + switch (name) { + case "A" -> statusValues = PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL.getValue().toString() + ", " + + PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL.getValue().toString(); + case "B" -> statusValues = PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL.getValue().toString() + ", " + + PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL.getValue().toString(); + case "C" -> statusValues = PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL.getValue().toString() + ", " + + PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL.getValue().toString(); + case "D" -> statusValues = PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL.getValue().toString(); + default -> statusValues = PrequalificationStatus.INVALID.getValue().toString(); + } + return statusValues; + } + private static final class PrequalificationsGroupMapper implements RowMapper { private final String schema; @@ -321,7 +385,11 @@ private static final class PrequalificationsGroupMapper implements RowMapper { + + private final String schema; + + PrequalificationsGroupMappingsMapper() { + this.schema = " PG.id AS id, PG.prequalification_number AS prequalificationNumber, PG.group_name AS groupName, " + + "PG.status, LP.name AS productName, " + "PG.created_at, AU.firstname, AU.lastname " + + "from m_group_prequalification_relationship GR " + "inner join m_group MG on MG.id = GR.group_id " + + "inner join m_prequalification_group PG on PG.id = GR.prequalification_id " + + "inner join m_product_loan LP on LP.id = PG.product_id " + "INNER JOIN m_appuser AU ON AU.id = PG.added_by " + ""; + } + + public String schema() { + return this.schema; + } + + @Override + public GroupPrequalificationData mapRow(final ResultSet rs, final int rowNum) throws SQLException { + + final Integer statusEnum = JdbcSupport.getInteger(rs, "status"); + final EnumOptionData status = PreQualificationsEnumerations.status(statusEnum); + + final Long id = JdbcSupport.getLong(rs, "id"); + final String prequalificationNumber = rs.getString("prequalificationNumber"); + String groupName = rs.getString("groupName"); + final String productName = rs.getString("productName"); + final LocalDate createdAt = JdbcSupport.getLocalDate(rs, "created_at"); + + final String addedBy = rs.getString("firstname") + " " + rs.getString("lastname"); + + return GroupPrequalificationData.simpeGroupData(id, prequalificationNumber, status, groupName, productName, addedBy, createdAt); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformService.java index aeb6e55423d..4f948f782db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/prequalification/service/PrequalificationWritePlatformService.java @@ -41,4 +41,6 @@ public interface PrequalificationWritePlatformService { CommandProcessingResult sendToAgency(Long entityId, JsonCommand command); CommandProcessingResult processAnalysisRequest(Long entityId, JsonCommand command); + + CommandProcessingResult assignPrequalification(Long entityId, JsonCommand command); } 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 e6915f8df92..b7ad94dc607 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 @@ -56,7 +56,10 @@ import org.apache.fineract.organisation.prequalification.command.PrequalificationDataValidator; import org.apache.fineract.organisation.prequalification.command.PrequalificatoinApiConstants; import org.apache.fineract.organisation.prequalification.data.GenericValidationResultSet; +import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; import org.apache.fineract.organisation.prequalification.data.PrequalificationChecklistData; +import org.apache.fineract.organisation.prequalification.domain.GroupPrequalificationRelationship; +import org.apache.fineract.organisation.prequalification.domain.GroupPrequalificationRelationshipRepository; import org.apache.fineract.organisation.prequalification.domain.PreQualificationStatusLogRepository; import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroupMember; @@ -65,8 +68,12 @@ import org.apache.fineract.organisation.prequalification.domain.PrequalificationMemberIndication; import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatus; import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatusLog; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatusRange; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationStatusRangeRepository; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationSubStatus; import org.apache.fineract.organisation.prequalification.domain.PrequalificationType; import org.apache.fineract.organisation.prequalification.exception.PrequalificationStatusNotChangedException; +import org.apache.fineract.organisation.prequalification.exception.PrequalificationStatusNotCompletedException; import org.apache.fineract.organisation.prequalification.serialization.PrequalificationMemberCommandFromApiJsonDeserializer; import org.apache.fineract.portfolio.blacklist.domain.BlacklistStatus; import org.apache.fineract.portfolio.client.service.ClientChargeWritePlatformServiceJpaRepositoryImpl; @@ -80,6 +87,7 @@ import org.apache.fineract.useradministration.domain.AppUser; import org.apache.fineract.useradministration.domain.AppUserRepository; import org.apache.fineract.useradministration.exception.UserNotFoundException; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -103,6 +111,7 @@ public class PrequalificationWritePlatformServiceImpl implements Prequalificatio private final PrequalificationChecklistReadPlatformService prequalificationChecklistReadPlatformService; private final PrequalificationGroupMemberRepositoryWrapper preQualificationMemberRepository; private final GroupRepositoryWrapper groupRepositoryWrapper; + private final GroupPrequalificationRelationshipRepository groupPrequalificationRelationshipRepository; private final AppUserRepository appUserRepository; private final AgencyRepositoryWrapper agencyRepositoryWrapper; private final PrequalificationMemberCommandFromApiJsonDeserializer apiJsonDeserializer; @@ -110,6 +119,8 @@ public class PrequalificationWritePlatformServiceImpl implements Prequalificatio private final DocumentRepository documentRepository; private final ContentRepositoryFactory contentRepositoryFactory; private final DocumentReadPlatformService documentReadPlatformService; + private final PrequalificationStatusRangeRepository prequalificationStatusRangeRepository; + private final PrequalificationReadPlatformService prequalificationReadPlatformService; @Autowired public PrequalificationWritePlatformServiceImpl(final PlatformSecurityContext context, @@ -123,7 +134,10 @@ public PrequalificationWritePlatformServiceImpl(final PlatformSecurityContext co final CodeValueReadPlatformService codeValueReadPlatformService, final JdbcTemplate jdbcTemplate, final ContentRepositoryFactory contentRepositoryFactory, final DocumentRepository documentRepository, final DocumentReadPlatformService documentReadPlatformService, - final PrequalificationGroupRepositoryWrapper prequalificationGroupRepositoryWrapper) { + final GroupPrequalificationRelationshipRepository groupPrequalificationRelationshipRepository, + final PrequalificationGroupRepositoryWrapper prequalificationGroupRepositoryWrapper, + final PrequalificationStatusRangeRepository prequalificationStatusRangeRepository, + PrequalificationReadPlatformService prequalificationReadPlatformService) { this.context = context; this.dataValidator = dataValidator; this.loanProductRepository = loanProductRepository; @@ -141,6 +155,9 @@ public PrequalificationWritePlatformServiceImpl(final PlatformSecurityContext co this.contentRepositoryFactory = contentRepositoryFactory; this.documentRepository = documentRepository; this.documentReadPlatformService = documentReadPlatformService; + this.groupPrequalificationRelationshipRepository = groupPrequalificationRelationshipRepository; + this.prequalificationStatusRangeRepository = prequalificationStatusRangeRepository; + this.prequalificationReadPlatformService = prequalificationReadPlatformService; } @Transactional @@ -148,9 +165,6 @@ public PrequalificationWritePlatformServiceImpl(final PlatformSecurityContext co public CommandProcessingResult processPrequalification(JsonCommand command) { final Boolean individualPrequalification = command.booleanPrimitiveValueOfParameterNamed("individual"); - if (individualPrequalification) { - return prequalifyIndividual(command); - } this.dataValidator.validateForCreate(command.json()); final Long productId = command.longValueOfParameterNamed(PrequalificatoinApiConstants.productIdParamName); @@ -160,28 +174,42 @@ public CommandProcessingResult processPrequalification(JsonCommand command) { .longValueOfParameterNamed(PrequalificatoinApiConstants.previousPrequalificationParamName); PrequalificationGroup parentGroup = null; + Group existingGroupParentGroup = null; if (previousPrequalificationId != null) { parentGroup = this.prequalificationGroupRepositoryWrapper.findOneWithNotFoundDetection(previousPrequalificationId); + if (!parentGroup.getStatus().equals(PrequalificationStatus.COMPLETED.getValue()) + && !parentGroup.getStatus().equals(PrequalificationStatus.REJECTED.getValue())) { + throw new PrequalificationStatusNotCompletedException(PrequalificationStatus.fromInt(parentGroup.getStatus()).toString()); + } + existingGroupParentGroup = this.groupRepositoryWrapper.findOneWithPrequalificationIdNotFoundDetection(parentGroup); + } Optional productOption = this.loanProductRepository.findById(productId); if (productOption.isEmpty()) throw new LoanProductNotFoundException(productId); LoanProduct loanProduct = productOption.get(); - String groupName = command.stringValueOfParameterNamed(PrequalificatoinApiConstants.groupNameParamName); + AppUser facilitator = null; + Agency agency = null; Group group = null; - if (centerGroupId != null) { - group = this.groupRepositoryWrapper.findOneWithNotFoundDetection(centerGroupId); - groupName = group.getName(); - } - Agency agency = this.agencyRepositoryWrapper.findOneWithNotFoundDetection(agencyId); + if (!individualPrequalification) { + String groupName = command.stringValueOfParameterNamed(PrequalificatoinApiConstants.groupNameParamName); - AppUser addedBy = this.context.getAuthenticatedUserIfPresent(); - Long facilitatorId = command.longValueOfParameterNamed(PrequalificatoinApiConstants.facilitatorParamName); - AppUser facilitator = null; - if (facilitatorId != null) { - facilitator = this.appUserRepository.findById(facilitatorId).orElseThrow(() -> new UserNotFoundException(facilitatorId)); + if (centerGroupId != null) { + group = this.groupRepositoryWrapper.findOneWithNotFoundDetection(centerGroupId); + groupName = group.getName(); + } + + agency = this.agencyRepositoryWrapper.findOneWithNotFoundDetection(agencyId); + + Long facilitatorId = command.longValueOfParameterNamed(PrequalificatoinApiConstants.facilitatorParamName); + if (facilitatorId != null) { + facilitator = this.appUserRepository.findById(facilitatorId).orElseThrow(() -> new UserNotFoundException(facilitatorId)); + } } + + AppUser addedBy = this.context.getAuthenticatedUserIfPresent(); + PrequalificationGroup prequalificationGroup = PrequalificationGroup.fromJson(addedBy, facilitator, agency, group, loanProduct, parentGroup, command); @@ -189,12 +217,9 @@ public CommandProcessingResult processPrequalification(JsonCommand command) { prequalificationGroup.setPrequalificationType(prequalificationType.getValue()); this.prequalificationGroupRepositoryWrapper.saveAndFlush(prequalificationGroup); - StringBuilder prequalSB = new StringBuilder(); - prequalSB.append("PRECAL-"); - prequalSB.append(agency.getId()).append("-"); - String prequalificationNumber = StringUtils.leftPad(prequalificationGroup.getId().toString(), 4, '0'); - prequalSB.append(prequalificationNumber); - prequalificationGroup.updatePrequalificationNumber(prequalSB.toString()); + + String prequalificationNumberAsString = resolvePrequalificationNumber(individualPrequalification, agency, prequalificationGroup); + prequalificationGroup.updatePrequalificationNumber(prequalificationNumberAsString); List members = assembNewMembers(command, prequalificationGroup, addedBy); prequalificationGroup.updateMembers(members); this.prequalificationGroupRepositoryWrapper.saveAndFlush(prequalificationGroup); @@ -204,6 +229,14 @@ public CommandProcessingResult processPrequalification(JsonCommand command) { this.preQualificationLogRepository.saveAndFlush(statusLog); + if (existingGroupParentGroup != null) { + existingGroupParentGroup.updatePrequalification(prequalificationGroup); + this.groupRepositoryWrapper.saveAndFlush(existingGroupParentGroup); + GroupPrequalificationRelationship relationship = GroupPrequalificationRelationship.addRelationship(addedBy, + existingGroupParentGroup, prequalificationGroup); + this.groupPrequalificationRelationshipRepository.saveAndFlush(relationship); + } + return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withResourceIdAsString(prequalificationGroup.getId().toString()) // @@ -211,6 +244,21 @@ public CommandProcessingResult processPrequalification(JsonCommand command) { .build(); } + @NotNull + private String resolvePrequalificationNumber(Boolean individualPrequalification, Agency agency, + PrequalificationGroup prequalificationGroup) { + StringBuilder prequalSB = new StringBuilder(); + prequalSB.append("PRECAL-"); + String prequalificationNumber = StringUtils.leftPad(prequalificationGroup.getId().toString(), 4, '0'); + + if (!individualPrequalification) { + prequalSB.append(agency.getId()).append("-"); + } + prequalSB.append(prequalificationNumber); + return prequalSB.toString(); + } + + @SuppressWarnings("unused") private CommandProcessingResult prequalifyIndividual(JsonCommand command) { AppUser addedBy = this.context.getAuthenticatedUserIfPresent(); @@ -365,9 +413,6 @@ public Long addCommentsToPrequalification(Long groupId, String comment) { @Override public CommandProcessingResult processUpdatePrequalification(Long groupId, JsonCommand command) { final Boolean individualPrequalification = command.booleanPrimitiveValueOfParameterNamed("individual"); - if (individualPrequalification) { - return prequalifyIndividual(command); - } PrequalificationGroup prequalificationGroup = prequalificationGroupRepositoryWrapper.findOneWithNotFoundDetection(groupId); @@ -375,24 +420,44 @@ public CommandProcessingResult processUpdatePrequalification(Long groupId, JsonC final Map changes = prequalificationGroup.update(command); - if (changes.containsKey(PrequalificatoinApiConstants.agencyIdParamName)) { + if (!individualPrequalification) { + if (changes.containsKey(PrequalificatoinApiConstants.agencyIdParamName)) { - final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.agencyIdParamName); - Agency newAgency = null; - if (newValue != null) { - newAgency = this.agencyRepositoryWrapper.findOneWithNotFoundDetection(newValue); + final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.agencyIdParamName); + Agency newAgency = null; + if (newValue != null) { + newAgency = this.agencyRepositoryWrapper.findOneWithNotFoundDetection(newValue); + } + prequalificationGroup.updateAgency(newAgency); } - prequalificationGroup.updateAgency(newAgency); - } - if (changes.containsKey(PrequalificatoinApiConstants.centerIdParamName)) { + if (changes.containsKey(PrequalificatoinApiConstants.centerIdParamName)) { - final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.centerIdParamName); - Group newCenter = null; - if (newValue != null) { - newCenter = this.groupRepositoryWrapper.findOneWithNotFoundDetection(newValue); + final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.centerIdParamName); + Group newCenter = null; + if (newValue != null) { + newCenter = this.groupRepositoryWrapper.findOneWithNotFoundDetection(newValue); + } + prequalificationGroup.updateCenter(newCenter.getId()); + } + + if (changes.containsKey(PrequalificatoinApiConstants.facilitatorParamName)) { + + final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.facilitatorParamName); + AppUser newFacilitator = null; + if (newValue != null) { + newFacilitator = this.appUserRepository.findById(newValue).orElseThrow(() -> new UserNotFoundException(newValue)); + } + prequalificationGroup.updateFacilitator(newFacilitator); + } + + if (changes.containsKey(PrequalificatoinApiConstants.groupNameParamName)) { + + final String newValue = command.stringValueOfParameterNamed(PrequalificatoinApiConstants.groupNameParamName); + if (newValue != null) { + prequalificationGroup.updateGroupName(newValue); + } } - prequalificationGroup.updateCenter(newCenter.getId()); } if (changes.containsKey(PrequalificatoinApiConstants.productIdParamName)) { @@ -410,23 +475,6 @@ public CommandProcessingResult processUpdatePrequalification(Long groupId, JsonC prequalificationGroup.setPrequalificationType(prequalificationType.getValue()); } - if (changes.containsKey(PrequalificatoinApiConstants.facilitatorParamName)) { - - final Long newValue = command.longValueOfParameterNamed(PrequalificatoinApiConstants.facilitatorParamName); - AppUser newFacilitator = null; - if (newValue != null) { - newFacilitator = this.appUserRepository.findById(newValue).orElseThrow(() -> new UserNotFoundException(newValue)); - } - prequalificationGroup.updateFacilitator(newFacilitator); - } - - if (changes.containsKey(PrequalificatoinApiConstants.groupNameParamName)) { - - final String newValue = command.stringValueOfParameterNamed(PrequalificatoinApiConstants.groupNameParamName); - if (newValue != null) { - prequalificationGroup.updateGroupName(newValue); - } - } Collection prequalificationDocs = this.documentReadPlatformService.retrieveAllDocuments("prequalifications", prequalificationGroup.getId()); if (!prequalificationDocs.isEmpty()) { @@ -767,20 +815,82 @@ public CommandProcessingResult processAnalysisRequest(Long entityId, JsonCommand return sendToAgency(entityId, command); } PrequalificationStatus prequalificationStatus = resolveStatus(action); + + if (prequalificationGroup.isPrequalificationTypeIndividual() && action.equals("approveanalysis")) { + PrequalificationStatusRange statusRange = resolveIndividualStatusRange(prequalificationGroup, action); + prequalificationStatus = PrequalificationStatus.fromInt(statusRange.getStatus()); + + } + if (prequalificationGroup.isPrequalificationTypeIndividual() && action.equals("approveCommittee")) { + prequalificationStatus = resolveCommitteeStatus(prequalificationGroup, action); + } + + // check if status has changed after resolving the new status if (fromStatus.equals(prequalificationStatus.getValue())) { throw new PrequalificationStatusNotChangedException(prequalificationStatus.toString()); } + prequalificationGroup.updateStatus(prequalificationStatus); prequalificationGroup.updateComments(comments); - // this.prequalificationGroupRepositoryWrapper.save(prequalificationGroup); - PrequalificationStatusLog statusLog = PrequalificationStatusLog.fromJson(addedBy, fromStatus, prequalificationGroup.getStatus(), + PrequalificationStatusLog newStatusLog = PrequalificationStatusLog.fromJson(addedBy, fromStatus, prequalificationGroup.getStatus(), comments, prequalificationGroup); - this.preQualificationLogRepository.saveAndFlush(statusLog); + this.preQualificationLogRepository.saveAndFlush(newStatusLog); + + List currentLogs = this.preQualificationLogRepository.groupStatusLogs(fromStatus, prequalificationGroup); + if (!currentLogs.isEmpty()) { + PrequalificationStatusLog currentStatusLog = currentLogs.get(0); + currentStatusLog.updateSubStatus(PrequalificationSubStatus.COMPLETED.getValue()); + this.preQualificationLogRepository.save(currentStatusLog); + } + return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(prequalificationGroup.getId()).build(); + } + + @Override + public CommandProcessingResult assignPrequalification(Long entityId, JsonCommand command) { + final PrequalificationGroup prequalificationGroup = this.prequalificationGroupRepositoryWrapper + .findOneWithNotFoundDetection(entityId); + AppUser currentUser = this.context.getAuthenticatedUserIfPresent(); + + Integer status = prequalificationGroup.getStatus(); + List statusLogList = this.preQualificationLogRepository.groupStatusLogs(status, prequalificationGroup); + if (statusLogList.isEmpty()) + throw new PrequalificationStatusNotCompletedException(PrequalificationStatus.fromInt(status).toString()); + + // retrieve latest log update assignee + PrequalificationStatusLog prequalificationStatusLog = statusLogList.get(0); + prequalificationStatusLog.updateSubStatus(PrequalificationSubStatus.IN_PROGRESS.getValue()); + prequalificationStatusLog.updateAssignedTo(currentUser); + this.preQualificationLogRepository.saveAndFlush(prequalificationStatusLog); return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(prequalificationGroup.getId()).build(); } + private PrequalificationStatus resolveCommitteeStatus(PrequalificationGroup prequalificationGroup, String action) { + // TODO ---CHECK IF THE COMMITTEE IS THE LAST COMMITTEE + PrequalificationStatusRange initialStatusRange = resolveIndividualStatusRange(prequalificationGroup, action); + + PrequalificationStatus initialStatus = PrequalificationStatus.fromInt(initialStatusRange.getStatus()); + PrequalificationStatus currentStatus = PrequalificationStatus.fromInt(prequalificationGroup.getStatus()); + + PrequalificationStatus finalStatus = currentStatus; + if (initialStatus.getValue().equals(currentStatus.getValue())) { + if (currentStatus.equals(PrequalificationStatus.PRE_COMMITTEE_D_PENDING_APPROVAL)) { + finalStatus = PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL; + } else if (currentStatus.equals(PrequalificationStatus.PRE_COMMITTEE_C_PENDING_APPROVAL)) { + finalStatus = PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL; + } else if (currentStatus.equals(PrequalificationStatus.PRE_COMMITTEE_B_PENDING_APPROVAL)) { + finalStatus = PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL; + } else if (currentStatus.equals(PrequalificationStatus.PRE_COMMITTEE_A_PENDING_APPROVAL)) { + finalStatus = PrequalificationStatus.COMPLETED; + } + } else { + finalStatus = PrequalificationStatus.COMPLETED; + } + + return finalStatus; + } + private PrequalificationStatus resolveStatus(String action) { PrequalificationStatus status = null; if (action.equalsIgnoreCase("sendtoagency")) { @@ -797,6 +907,36 @@ private PrequalificationStatus resolveStatus(String action) { return status; } + private PrequalificationStatusRange resolveIndividualStatusRange(PrequalificationGroup prequalificationGroup, String action) { + PrequalificationStatusRange finalRange = null; + + if (action.equalsIgnoreCase("approveanalysis") || action.equalsIgnoreCase("approveCommittee")) { + + GroupPrequalificationData prequalificationData = prequalificationReadPlatformService.retrieveOne(prequalificationGroup.getId()); + int numberOfErrors = prequalificationData.getRedValidationCount() > 0 + ? Math.toIntExact(prequalificationData.getRedValidationCount()) + : 0; + + BigDecimal amount = prequalificationGroup.getTotalRequestedAmount(); + + List statusRangeList = this.prequalificationStatusRangeRepository + .findByPrequalificationTypeAndNumberOfErrors(prequalificationGroup.getPrequalificationType(), numberOfErrors); + + for (PrequalificationStatusRange statusRange : statusRangeList) { + if (amount.compareTo(statusRange.getMinAmount()) >= 0 + && (statusRange.getMaxAmount() != null && amount.compareTo(statusRange.getMaxAmount()) <= 0)) { + finalRange = statusRange; + break; + } else if (amount.compareTo(statusRange.getMinAmount()) >= 0 && statusRange.getMaxAmount() == null) { + finalRange = statusRange; + break; + } + } + } + + return finalRange; + } + private PrequalificationType resolvePrequalificationType(LoanProduct loanProduct) { if (loanProduct.getOwnerType() != null) { LoanProductOwnerType ownerType = LoanProductOwnerType.fromInt(loanProduct.getOwnerType()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java index 2778ccffb80..e8b49685a1e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java @@ -68,7 +68,8 @@ public class ChargesApiResource { "chargeAppliesTo", "chargeTimeType", "chargeCalculationType", "chargeCalculationTypeOptions", "chargeAppliesToOptions", "chargeTimeTypeOptions", "currencyOptions", "loanChargeCalculationTypeOptions", "loanChargeTimeTypeOptions", "savingsChargeCalculationTypeOptions", "savingsChargeTimeTypeOptions", "incomeAccount", "clientChargeCalculationTypeOptions", - "clientChargeTimeTypeOptions", "adminFeeRanges", "chargeDisbursementType", "chargeDisbursementTypeOptions")); + "clientChargeTimeTypeOptions", "adminFeeRanges", "chargeDisbursementType", "chargeDisbursementTypeOptions", + "chargeInstallmentFeeType", "chargeInstallmentFeeTypeOptions")); private final String resourceNameForPermissions = "CHARGE"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java index 5706d017476..060f8ea9729 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/data/ChargeData.java @@ -66,6 +66,7 @@ public final class ChargeData implements Comparable, Serializable { private final GLAccountData incomeOrLiabilityAccount; private final TaxGroupData taxGroup; private final EnumOptionData chargeDisbursementType; + private final EnumOptionData chargeInstallmentFeeType; private final Collection currencyOptions; private final List chargeCalculationTypeOptions;// @@ -92,6 +93,7 @@ public final class ChargeData implements Comparable, Serializable { private final List assetAccountOptions; private List chargeRanges; private final List chargeDisbursementTypeOptions; + private final List chargeInstallmentFeeTypeOptions; public static ChargeData template(final Collection currencyOptions, final List chargeCalculationTypeOptions, final List chargeAppliesToOptions, @@ -103,7 +105,7 @@ public static ChargeData template(final Collection currencyOptions final Collection taxGroupOptions, final List shareChargeCalculationTypeOptions, final List shareChargeTimeTypeOptions, String accountMappingForChargeConfig, List expenseAccountOptions, List assetAccountOptions, - final List chargeDisbursementTypeOptions) { + final List chargeDisbursementTypeOptions, final List chargeInstallmentFeeTypeOptions) { final GLAccountData account = null; final TaxGroupData taxGroupData = null; @@ -113,7 +115,8 @@ public static ChargeData template(final Collection currencyOptions savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, null, null, null, null, null, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, - expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions, null, null); + expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions, null, null, chargeInstallmentFeeTypeOptions, + null); } public static ChargeData withTemplate(final ChargeData charge, final ChargeData template) { @@ -128,7 +131,8 @@ public static ChargeData withTemplate(final ChargeData charge, final ChargeData charge.incomeOrLiabilityAccount, template.incomeOrLiabilityAccountOptions, template.taxGroupOptions, template.shareChargeCalculationTypeOptions, template.shareChargeTimeTypeOptions, template.accountMappingForChargeConfig, template.expenseAccountOptions, template.assetAccountOptions, template.chargeDisbursementTypeOptions, - charge.chargeDisbursementType, charge.chargeRanges); + charge.chargeDisbursementType, charge.chargeRanges, template.chargeInstallmentFeeTypeOptions, + charge.chargeInstallmentFeeType); } public static ChargeData instance(final Long id, final String name, final BigDecimal amount, final CurrencyData currency, @@ -137,7 +141,7 @@ public static ChargeData instance(final Long id, final String name, final BigDec final boolean active, final boolean freeWithdrawal, final Integer freeWithdrawalChargeFrequency, final Integer restartFrequency, final Integer restartFrequencyEnum, final boolean isPaymentType, final PaymentTypeData paymentTypeOptions, final BigDecimal minCap, final BigDecimal maxCap, final EnumOptionData feeFrequency, final GLAccountData accountData, - TaxGroupData taxGroupData, final EnumOptionData chargeDisbursementType) { + TaxGroupData taxGroupData, final EnumOptionData chargeDisbursementType, final EnumOptionData chargeInstallmentFeeType) { final Collection currencyOptions = null; final List chargeCalculationTypeOptions = null; @@ -159,6 +163,7 @@ public static ChargeData instance(final Long id, final String name, final BigDec final List expenseAccountOptions = null; final List assetAccountOptions = null; final List chargeDisbursementTypeOptions = null; + final List chargeInstallmentFeeTypeOptions = null; return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode, penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType, @@ -168,7 +173,7 @@ public static ChargeData instance(final Long id, final String name, final BigDec clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, accountData, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions, - chargeDisbursementType, null); + chargeDisbursementType, null, chargeInstallmentFeeTypeOptions, chargeInstallmentFeeType); } public static ChargeData lookup(final Long id, final String name, final boolean isPenalty) { @@ -179,6 +184,7 @@ public static ChargeData lookup(final Long id, final String name, final boolean final EnumOptionData chargeCalculationType = null; final EnumOptionData chargePaymentMode = null; final EnumOptionData chargeDisbursementType = null; + final EnumOptionData chargeInstallmentFeeType = null; final MonthDay feeOnMonthDay = null; final Integer feeInterval = null; final Boolean penalty = isPenalty; @@ -215,6 +221,7 @@ public static ChargeData lookup(final Long id, final String name, final boolean final List assetAccountOptions = null; final List chargeDisbursementTypeOptions = null; final List chargeRanges = null; + final List chargeInstallmentFeeTypeOptions = null; return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentMode, penalty, active, freeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType, @@ -224,7 +231,7 @@ public static ChargeData lookup(final Long id, final String name, final boolean clientChargeTimeTypeOptions, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, feeFrequencyOptions, account, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions, - chargeDisbursementType, chargeRanges); + chargeDisbursementType, chargeRanges, chargeInstallmentFeeTypeOptions, chargeInstallmentFeeType); } private ChargeData(final Long id, final String name, final BigDecimal amount, final CurrencyData currency, @@ -244,7 +251,8 @@ private ChargeData(final Long id, final String name, final BigDecimal amount, fi final List shareChargeCalculationTypeOptions, final List shareChargeTimeTypeOptions, final String accountMappingForChargeConfig, final List expenseAccountOptions, final List assetAccountOptions, final List chargeDisbursementTypeOptions, - final EnumOptionData chargeDisbursementType, final List chargeRanges) { + final EnumOptionData chargeDisbursementType, final List chargeRanges, + final List chargeInstallmentFeeTypeOptions, final EnumOptionData chargeInstallmentFeeType) { this.id = id; this.name = name; this.amount = amount; @@ -266,6 +274,7 @@ private ChargeData(final Long id, final String name, final BigDecimal amount, fi this.minCap = minCap; this.maxCap = maxCap; this.chargeDisbursementType = chargeDisbursementType; + this.chargeInstallmentFeeType = chargeInstallmentFeeType; this.currencyOptions = currencyOptions; this.chargeCalculationTypeOptions = chargeCalculationTypeOptions; this.chargeAppliesToOptions = chargeAppliesToOptions; @@ -290,6 +299,7 @@ private ChargeData(final Long id, final String name, final BigDecimal amount, fi this.expenseAccountOptions = expenseAccountOptions; this.chargeDisbursementTypeOptions = chargeDisbursementTypeOptions; this.chargeRanges = chargeRanges; + this.chargeInstallmentFeeTypeOptions = chargeInstallmentFeeTypeOptions; } @Override diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java index 9c13ecb90ea..a054c132569 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java @@ -149,6 +149,9 @@ public class Charge extends AbstractPersistableCustom { @Column(name = "charge_disbursement_type_enum", nullable = false) private Integer chargeDisbursementType; + @Column(name = "charge_installment_fee_type_enum", nullable = false) + private Integer chargeInstallmentFeeType; + @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL, mappedBy = "charge") private List chargeRanges; @@ -195,9 +198,13 @@ public static Charge fromJson(final JsonCommand command, final GLAccount account final ChargeDisbursementType chargeDisbursementType = ChargeDisbursementType .fromInt(command.integerValueOfParameterNamed("chargeDisbursementType")); + final ChargeInstallmentFeeType chargeInstallmentFeeType = ChargeInstallmentFeeType + .fromInt(command.integerValueOfParameterNamed("chargeInstallmentFeeType")); + Charge charge = new Charge(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculationType, penalty, active, paymentMode, feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, enableFreeWithdrawalCharge, freeWithdrawalFrequency, - restartCountFrequency, countFrequencyType, account, taxGroup, enablePaymentType, paymentType, chargeDisbursementType); + restartCountFrequency, countFrequencyType, account, taxGroup, enablePaymentType, paymentType, chargeDisbursementType, + chargeInstallmentFeeType); setChargeRanges(charge, command); @@ -234,7 +241,7 @@ private Charge(final String name, final BigDecimal amount, final String currency final BigDecimal maxCap, final Integer feeFrequency, final boolean enableFreeWithdrawalCharge, final Integer freeWithdrawalFrequency, final Integer restartFrequency, final PeriodFrequencyType restartFrequencyEnum, final GLAccount account, final TaxGroup taxGroup, final boolean enablePaymentType, final PaymentType paymentType, - final ChargeDisbursementType chargeDisbursementType) { + final ChargeDisbursementType chargeDisbursementType, final ChargeInstallmentFeeType chargeInstallmentFeeType) { this.name = name; this.amount = amount; this.currencyCode = currencyCode; @@ -247,6 +254,7 @@ private Charge(final String name, final BigDecimal amount, final String currency this.taxGroup = taxGroup; this.chargePaymentMode = paymentMode == null ? null : paymentMode.getValue(); this.chargeDisbursementType = chargeDisbursementType == null ? null : chargeDisbursementType.getValue(); + this.chargeInstallmentFeeType = chargeInstallmentFeeType == null ? null : chargeInstallmentFeeType.getValue(); final List dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charges"); @@ -601,6 +609,14 @@ public Map update(final JsonCommand command) { actualChanges.put("locale", localeAsInput); this.chargeDisbursementType = ChargeDisbursementType.fromInt(newValue).getValue(); } + + final String chargeInstallmentFeeTypeParamName = "chargeInstallmentFeeType"; + if (command.isChangeInIntegerParameterNamed(chargeInstallmentFeeTypeParamName, this.chargeInstallmentFeeType)) { + final Integer newValue = command.integerValueOfParameterNamed(chargeInstallmentFeeTypeParamName); + actualChanges.put(chargeInstallmentFeeTypeParamName, newValue); + actualChanges.put("locale", localeAsInput); + this.chargeInstallmentFeeType = ChargeInstallmentFeeType.fromInt(newValue).getValue(); + } } if (command.hasParameter("feeOnMonthDay")) { @@ -719,6 +735,7 @@ public ChargeData toData() { final EnumOptionData chargePaymentmode = ChargeEnumerations.chargePaymentMode(this.chargePaymentMode); final EnumOptionData feeFrequencyType = ChargeEnumerations.chargePaymentMode(this.feeFrequency); final EnumOptionData chargeDisbursementType = ChargeEnumerations.chargePaymentMode(this.chargePaymentMode); + final EnumOptionData chargeInstallmentFeeType = ChargeEnumerations.chargePaymentMode(this.chargePaymentMode); GLAccountData accountData = null; if (account != null) { accountData = new GLAccountData(account.getId(), account.getName(), account.getGlCode()); @@ -737,7 +754,7 @@ public ChargeData toData() { return ChargeData.instance(getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType, chargePaymentmode, getFeeOnMonthDay(), this.feeInterval, this.penalty, this.active, this.enableFreeWithdrawal, this.freeWithdrawalFrequency, this.restartFrequency, this.restartFrequencyEnum, this.enablePaymentType, paymentTypeData, - this.minCap, this.maxCap, feeFrequencyType, accountData, taxGroupData, chargeDisbursementType); + this.minCap, this.maxCap, feeFrequencyType, accountData, taxGroupData, chargeDisbursementType, chargeInstallmentFeeType); } public Integer getChargePaymentMode() { @@ -809,6 +826,14 @@ public boolean isAddOnDisbursementType() { return ChargeDisbursementType.fromInt(this.chargeDisbursementType).equals(ChargeDisbursementType.ADD_ON); } + public boolean isInstallmentFeeCharge() { + return ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.INSTALMENT_FEE); + } + + public boolean isAddOnInstallmentFeeType() { + return ChargeInstallmentFeeType.fromInt(this.chargeInstallmentFeeType).equals(ChargeInstallmentFeeType.ADD_ON); + } + public TaxGroup getTaxGroup() { return this.taxGroup; } @@ -821,6 +846,10 @@ public Integer getChargeDisbursementType() { return chargeDisbursementType; } + public Integer getChargeInstallmentFeeType() { + return chargeInstallmentFeeType; + } + public List getChargeRanges() { return chargeRanges; } @@ -838,7 +867,8 @@ public Pair getAddOnDisbursementChargeRate(LocalDate disbur final Comparator orderByMinDay = Comparator.comparing(ChargeRange::getMinDay); Collections.sort(this.chargeRanges, orderByMinDay); - if (isDisbursementCharge() && isAddOnDisbursementType() && this.chargeRanges != null && !this.chargeRanges.isEmpty()) { + if (((isDisbursementCharge() && isAddOnDisbursementType()) || (isInstallmentFeeCharge() && isAddOnInstallmentFeeType())) + && this.chargeRanges != null && !this.chargeRanges.isEmpty()) { // calculate days since disbursement date int numberOfDays = Math.toIntExact(daysBetween(disbursementDate, firstRepaymentDate)); if (numberOfDays > defaultDays) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeInstallmentFeeType.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeInstallmentFeeType.java new file mode 100644 index 00000000000..4a40d48f026 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/ChargeInstallmentFeeType.java @@ -0,0 +1,67 @@ +/** + * 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.charge.domain; + +public enum ChargeInstallmentFeeType { + + INVALID(0, "chargeInstallmentFeeType.invalid"), // + REGULAR(1, "chargeInstallmentFeeType.regular"), // + ADD_ON(2, "chargeInstallmentFeeType.addOn"); + + private final Integer value; + private final String code; + + ChargeInstallmentFeeType(final Integer value, final String code) { + this.value = value; + this.code = code; + } + + public Integer getValue() { + return this.value; + } + + public String getCode() { + return this.code; + } + + public static ChargeInstallmentFeeType fromInt(final Integer chargeCalculation) { + ChargeInstallmentFeeType chargeCalculationType = ChargeInstallmentFeeType.INVALID; + if (chargeCalculation != null) { + switch (chargeCalculation) { + case 1: + chargeCalculationType = REGULAR; + break; + case 2: + chargeCalculationType = ADD_ON; + break; + default: + chargeCalculationType = REGULAR; + } + } + return chargeCalculationType; + } + + public boolean isRegular() { + return this.value.equals(ChargeInstallmentFeeType.REGULAR.getValue()); + } + + public boolean isAddOn() { + return this.value.equals(ChargeInstallmentFeeType.ADD_ON.getValue()); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java index 2c428d5146a..4fdb2da5079 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java @@ -45,6 +45,7 @@ import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; import org.apache.fineract.portfolio.charge.domain.ChargeDisbursementType; +import org.apache.fineract.portfolio.charge.domain.ChargeInstallmentFeeType; import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode; import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; import org.springframework.beans.factory.annotation.Autowired; @@ -61,7 +62,7 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer { "active", "chargePaymentMode", "feeOnMonthDay", "feeInterval", "monthDayFormat", "minCap", "maxCap", "feeFrequency", "enableFreeWithdrawalCharge", "freeWithdrawalFrequency", "restartCountFrequency", "countFrequencyType", "paymentTypeId", "enablePaymentType", ChargesApiConstants.glAccountIdParamName, ChargesApiConstants.taxGroupIdParamName, "adminFeeRanges", - "chargeDisbursementType", "chargeDisbursementTypeOptions")); + "chargeDisbursementType", "chargeDisbursementTypeOptions", "chargeInstallmentFeeType", "chargeInstallmentFeeTypeOptions")); private final FromJsonHelper fromApiJsonHelper; @@ -140,6 +141,9 @@ public void validateForCreate(final String json) { final ChargeDisbursementType chargeDisbursementType = ChargeDisbursementType .fromInt(this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeDisbursementType", element)); + final ChargeInstallmentFeeType chargeInstallmentFeeType = ChargeInstallmentFeeType + .fromInt(this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeInstallmentFeeType", element)); + if (appliesTo.isLoanCharge()) { // loan applicable validation final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeTimeType", element); @@ -275,7 +279,7 @@ public void validateForCreate(final String json) { baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).value(taxGroupId).notNull().longGreaterThanZero(); } - if (appliesTo.isLoanCharge() && chargeDisbursementType.isAddOn()) { + if (appliesTo.isLoanCharge() && (chargeDisbursementType.isAddOn() || chargeInstallmentFeeType.isAddOn())) { this.validateChargeLimits(false, dataValidationErrors, baseDataValidator, element); } @@ -447,7 +451,9 @@ public void validateForUpdate(final String json) { } final ChargeDisbursementType chargeDisbursementType = ChargeDisbursementType .fromInt(this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeDisbursementType", element)); - if (appliesTo != null && appliesTo.isLoanCharge() && chargeDisbursementType.isAddOn()) { + final ChargeInstallmentFeeType chargeInstallmentFeeType = ChargeInstallmentFeeType + .fromInt(this.fromApiJsonHelper.extractIntegerSansLocaleNamed("chargeInstallmentFeeType", element)); + if (appliesTo != null && appliesTo.isLoanCharge() && (chargeDisbursementType.isAddOn() || chargeInstallmentFeeType.isAddOn())) { this.validateChargeLimits(false, dataValidationErrors, baseDataValidator, element); } throwExceptionIfValidationWarningsExist(dataValidationErrors); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformService.java index 31628ba136d..ae3cd6ea821 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformService.java @@ -49,4 +49,6 @@ public interface ChargeDropdownReadPlatformService { List retrieveDisbursementTypeOptions(); + List retrieveInstallmentFeeTypeOptions(); + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java index 4b3a09468b7..38f85358258 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeDropdownReadPlatformServiceImpl.java @@ -20,6 +20,7 @@ import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargeCalculationType; import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargeDisbursementType; +import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargeInstallmentFeeType; import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargePaymentMode; import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargeTimeType; @@ -30,6 +31,7 @@ import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; import org.apache.fineract.portfolio.charge.domain.ChargeDisbursementType; +import org.apache.fineract.portfolio.charge.domain.ChargeInstallmentFeeType; import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode; import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; import org.springframework.stereotype.Service; @@ -134,4 +136,10 @@ public List retrieveDisbursementTypeOptions() { return Arrays.asList(chargeDisbursementType(ChargeDisbursementType.REGULAR), chargeDisbursementType(ChargeDisbursementType.ADD_ON)); } + @Override + public List retrieveInstallmentFeeTypeOptions() { + return Arrays.asList(chargeInstallmentFeeType(ChargeInstallmentFeeType.REGULAR), + chargeInstallmentFeeType(ChargeInstallmentFeeType.ADD_ON)); + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeEnumerations.java index 8b1a40f3f94..db79573e2c4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeEnumerations.java @@ -22,6 +22,7 @@ import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; import org.apache.fineract.portfolio.charge.domain.ChargeDisbursementType; +import org.apache.fineract.portfolio.charge.domain.ChargeInstallmentFeeType; import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode; import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; @@ -215,4 +216,27 @@ public static EnumOptionData chargeDisbursementType(final ChargeDisbursementType return optionData; } + public static EnumOptionData chargeInstallmentFeeType(final int id) { + return chargeInstallmentFeeType(ChargeInstallmentFeeType.fromInt(id)); + } + + public static EnumOptionData chargeInstallmentFeeType(final ChargeInstallmentFeeType type) { + EnumOptionData optionData = null; + switch (type) { + case REGULAR: + optionData = new EnumOptionData(ChargeInstallmentFeeType.REGULAR.getValue().longValue(), + ChargeInstallmentFeeType.REGULAR.getCode(), "Regular"); + break; + case ADD_ON: + optionData = new EnumOptionData(ChargeInstallmentFeeType.ADD_ON.getValue().longValue(), + ChargeInstallmentFeeType.ADD_ON.getCode(), "Add-on"); + break; + default: + optionData = new EnumOptionData(ChargeInstallmentFeeType.INVALID.getValue().longValue(), + ChargeInstallmentFeeType.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java index 1818f1ee27e..f2edf7e9830 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformServiceImpl.java @@ -170,13 +170,15 @@ public ChargeData retrieveNewChargeDetails() { final List expenseAccountOptions = this.accountingDropdownReadPlatformService.retrieveExpenseAccountOptions(); final List assetAccountOptions = this.accountingDropdownReadPlatformService.retrieveAssetAccountOptions(); final List chargeDisbursementTypeOptions = this.chargeDropdownReadPlatformService.retrieveDisbursementTypeOptions(); + final List chargeInstallmentFeeTypeOptions = this.chargeDropdownReadPlatformService + .retrieveInstallmentFeeTypeOptions(); return ChargeData.template(currencyOptions, allowedChargeCalculationTypeOptions, allowedChargeAppliesToOptions, allowedChargeTimeOptions, chargePaymentOptions, loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, accountMappingForChargeConfig, expenseAccountOptions, - assetAccountOptions, chargeDisbursementTypeOptions); + assetAccountOptions, chargeDisbursementTypeOptions, chargeInstallmentFeeTypeOptions); } @Override @@ -301,6 +303,7 @@ public String chargeSchema() { + "c.is_active as active, c.is_free_withdrawal as isFreeWithdrawal, c.free_withdrawal_charge_frequency as freeWithdrawalChargeFrequency, " + "c.restart_frequency as restartFrequency, c.restart_frequency_enum as restartFrequencyEnum, " + "c.charge_disbursement_type_enum as chargeDisbursementType, " + + "c.charge_installment_fee_type_enum as chargeInstallmentFeeType, " + "oc.name as currencyName, oc.decimal_places as currencyDecimalPlaces, " + "oc.currency_multiplesof as inMultiplesOf, oc.display_symbol as currencyDisplaySymbol, " + "oc.internationalized_name_code as currencyNameCode, oc.int_code as intCode, c.fee_on_day as feeOnDay, c.fee_on_month as feeOnMonth, " @@ -350,6 +353,9 @@ public ChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final i final int chargeDisbursementTypeId = rs.getInt("chargeDisbursementType"); final EnumOptionData chargeDisbursementType = ChargeEnumerations.chargeDisbursementType(chargeDisbursementTypeId); + final int chargeInstallmentFeeTypeId = rs.getInt("chargeInstallmentFeeType"); + final EnumOptionData chargeInstallmentFeeType = ChargeEnumerations.chargeInstallmentFeeType(chargeInstallmentFeeTypeId); + final int chargeCalculation = rs.getInt("chargeCalculation"); final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation); @@ -407,7 +413,7 @@ public ChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final i return ChargeData.instance(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType, chargePaymentMode, feeOnMonthDay, feeInterval, penalty, active, isFreeWithdrawal, freeWithdrawalChargeFrequency, restartFrequency, restartFrequencyEnum, isPaymentType, paymentTypeData, minCap, maxCap, feeFrequencyType, glAccountData, - taxGroupData, chargeDisbursementType); + taxGroupData, chargeDisbursementType, chargeInstallmentFeeType); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientContactInformation.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientContactInformation.java index 7fda30de5f7..ad64c41ce33 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientContactInformation.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientContactInformation.java @@ -90,7 +90,7 @@ public class ClientContactInformation extends AbstractPersistableCustom { private String streetNumber; @Column(name = "years_of_community") - private String communityYears; + private Integer communityYears; protected ClientContactInformation() { // @@ -99,7 +99,7 @@ protected ClientContactInformation() { public ClientContactInformation(Integer area, Integer housingType, Integer yearsOfResidence, Integer departmentId, Integer municipalityId, String village, String referenceHousingData, String street, String avenue, String houseNumber, String colony, String sector, String batch, String square, String zone, String lightMeterNumber, String homePhone, - Client newClient, final String streetNumber, final String communityYears) { + Client newClient, final String streetNumber, final Integer communityYears) { this.area = area; this.housingType = housingType; this.yearsOfResidence = yearsOfResidence; @@ -142,7 +142,7 @@ public static ClientContactInformation fromJson(Client newClient, JsonCommand co final String lightMeterNumber = command.stringValueOfParameterNamed(ClientApiConstants.lightDeviceNumberParamName); final String homePhone = command.stringValueOfParameterNamed(ClientApiConstants.homeNumberParamName); final String streetNumber = command.stringValueOfParameterNamed(ClientApiConstants.STREET_NUMBER); - final String communityYears = command.stringValueOfParameterNamed(ClientApiConstants.COMMUNITY_YEARS); + final Integer communityYears = command.integerValueOfParameterNamed(ClientApiConstants.COMMUNITY_YEARS); return new ClientContactInformation(area, housingType, yearsOfResidence, departmentId, municipalityId, village, referenceHousingData, street, avenue, houseNumber, colony, sector, batch, square, zone, lightMeterNumber, homePhone, newClient, streetNumber, communityYears); @@ -167,7 +167,7 @@ public static ClientContactInformation updateJson(ClientContactInformation conta final String lightMeterNumber = command.stringValueOfParameterNamed(ClientApiConstants.lightDeviceNumberParamName); final String homePhone = command.stringValueOfParameterNamed(ClientApiConstants.homeNumberParamName); final String streetNumber = command.stringValueOfParameterNamed(ClientApiConstants.STREET_NUMBER); - final String communityYears = command.stringValueOfParameterNamed(ClientApiConstants.COMMUNITY_YEARS); + final Integer communityYears = command.integerValueOfParameterNamed(ClientApiConstants.COMMUNITY_YEARS); contactInformation.area = area; contactInformation.housingType = housingType; contactInformation.yearsOfResidence = yearsOfResidence; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java index a3b965d2b91..107f58cb5c1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java @@ -73,6 +73,8 @@ import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum; import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; +import org.apache.fineract.organisation.prequalification.service.PrequalificationReadPlatformService; import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData; import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService; import org.apache.fineract.portfolio.calendar.data.CalendarData; @@ -111,6 +113,7 @@ public class GroupsApiResource { private final PlatformSecurityContext context; private final GroupReadPlatformService groupReadPlatformService; + private final PrequalificationReadPlatformService prequalificationReadPlatformService; private final CenterReadPlatformService centerReadPlatformService; private final ClientReadPlatformService clientReadPlatformService; private final ToApiJsonSerializer toApiJsonSerializer; @@ -150,6 +153,7 @@ public GroupsApiResource(final PlatformSecurityContext context, final GroupReadP final BulkImportWorkbookService bulkImportWorkbookService, final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService, final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService, + final PrequalificationReadPlatformService prequalificationReadPlatformService, final GSIMReadPlatformService gsimReadPlatformService) { this.context = context; this.groupReadPlatformService = groupReadPlatformService; @@ -173,6 +177,7 @@ public GroupsApiResource(final PlatformSecurityContext context, final GroupReadP this.bulkImportWorkbookService = bulkImportWorkbookService; this.glimAccountInfoReadPlatformService = glimAccountInfoReadPlatformService; this.gsimReadPlatformService = gsimReadPlatformService; + this.prequalificationReadPlatformService = prequalificationReadPlatformService; } @@ -281,6 +286,7 @@ public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("groupId") Collection groupRoles = null; GroupRoleData selectedRole = null; Collection calendars = null; + Collection prequalificationData = null; CalendarData collectionMeetingCalendar = null; if (!associationParameters.isEmpty()) { @@ -355,7 +361,11 @@ public String retrieveOne(@Context final UriInfo uriInfo, @PathParam("groupId") staffInSelectedOfficeOnly); group = GroupGeneralData.withTemplate(templateGroup, group); } + prequalificationData = this.prequalificationReadPlatformService.retrievePrequalificationGroupsMappings(groupId); + if (!prequalificationData.isEmpty()) { + group.setPrequalificationGroups(prequalificationData); + } return this.groupGeneralApiJsonSerializer.serialize(settings, group, GroupingTypesApiConstants.GROUP_RESPONSE_DATA_PARAMETERS); } 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 8a7d0d04dab..fe35cc61621 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 @@ -173,6 +173,36 @@ public static CenterData withTemplate(final CenterData templateCenter, final Cen return mapDTO(center, centerWithTemplate); } + public static CenterData instance(final Long id, final String name) { + final String accountNo = null; + final String externalId = null; + final EnumOptionData status = null; + final LocalDate activationDate = null; + final Long officeId = null; + final String officeName = null; + final Long staffId = null; + final String staffName = null; + final String hierarchy = null; + final Collection groupMembers = null; + final Collection officeOptions = null; + final Collection staffOptions = null; + final Collection groupMembersOptions = null; + final CalendarData collectionMeetingCalendar = null; + final GroupTimelineData timeline = null; + final BigDecimal totalCollected = null; + final BigDecimal totalOverdue = null; + final BigDecimal totaldue = null; + final BigDecimal installmentDue = null; + final Collection cityOptions = null; + final Collection stateOptions = null; + final Collection typeOptions = null; + final Collection meetingDayOptions = null; + final Collection closureReasons = null; + return new CenterData(id, accountNo, name, externalId, status, activationDate, officeId, officeName, staffId, staffName, hierarchy, + groupMembers, officeOptions, staffOptions, groupMembersOptions, collectionMeetingCalendar, closureReasons, timeline, + totalCollected, totalOverdue, totaldue, installmentDue, cityOptions, stateOptions, typeOptions, meetingDayOptions); + } + 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, 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 31c3d830497..c3d7eb37b23 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 @@ -31,6 +31,7 @@ import org.apache.fineract.infrastructure.dataqueries.data.DatatableData; import org.apache.fineract.organisation.office.data.OfficeData; import org.apache.fineract.organisation.portfolioCenter.data.PortfolioCenterData; +import org.apache.fineract.organisation.prequalification.data.GroupPrequalificationData; import org.apache.fineract.organisation.staff.data.StaffData; import org.apache.fineract.portfolio.calendar.data.CalendarData; import org.apache.fineract.portfolio.client.data.ClientData; @@ -110,6 +111,7 @@ public class GroupGeneralData implements Serializable { private String referencePoint; private String prequalificationNumber; private EnumOptionData prequalificationStatus; + private Collection prequalificationGroups; private Long prequalificationId; // import fields @@ -645,4 +647,8 @@ public void setPrequalificationId(Long prequalificationId) { public void setPrequalificationStatus(EnumOptionData prequalificationStatus) { this.prequalificationStatus = prequalificationStatus; } + + public void setPrequalificationGroups(Collection prequalificationData) { + this.prequalificationGroups = prequalificationData; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepository.java index fdf6c5a6359..c422f1db64f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepository.java @@ -20,6 +20,8 @@ import java.time.LocalDate; import java.util.Collection; +import java.util.Optional; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; @@ -29,6 +31,10 @@ public interface GroupRepository extends JpaRepository, JpaSpecific Collection findByParentId(Long parentId); + Optional findByPrequalificationGroup(PrequalificationGroup prequalificationGroup); + + // Collection findByPrequalificationGroup(PrequalificationGroup prequalificationGroup); + String RETRIEVE_SUBMITTED_ON_DATE = "select g.submittedOnDate from Group g where g.id = :groupId"; @Query(RETRIEVE_SUBMITTED_ON_DATE) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepositoryWrapper.java index e06899f17fb..2931f5374ad 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepositoryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/GroupRepositoryWrapper.java @@ -20,6 +20,7 @@ import java.time.LocalDate; import org.apache.fineract.organisation.office.domain.Office; +import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; import org.apache.fineract.portfolio.group.exception.GroupNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -43,6 +44,12 @@ public Group findOneWithNotFoundDetection(final Long id) { return this.repository.findById(id).orElseThrow(() -> new GroupNotFoundException(id)); } + public Group findOneWithPrequalificationIdNotFoundDetection(final PrequalificationGroup prequalificationGroup) { + return this.repository.findByPrequalificationGroup(prequalificationGroup) + .orElseThrow(() -> new GroupNotFoundException(prequalificationGroup.getId())); + + } + public Group findByOfficeWithNotFoundDetection(final Long id, final Office office) { final Group group = findOneWithNotFoundDetection(id); if (!group.getOffice().getId().equals(office.getId())) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformService.java index ee243c436f8..82e29231999 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/CenterReadPlatformService.java @@ -35,6 +35,8 @@ public interface CenterReadPlatformService { Collection retrieveAllForDropdown(Long officeId); + Collection retrieveByOfficeHierarchy(final String hierarchy, final Long agencyId); + Page retrievePagedAll(SearchParameters searchParameters, PaginationParameters parameters); Collection retrieveAll(SearchParameters searchParameters, PaginationParameters parameters); 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 da56bd50265..ac132a6cdb0 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 @@ -511,6 +511,37 @@ public Collection retrieveAllForDropdown(final Long officeId) { return this.jdbcTemplate.query(sql, this.centerMapper, new Object[] { officeId, GroupTypes.CENTER.getId(), hierarchySearchString }); // NOSONAR } + @Override + public Collection retrieveByOfficeHierarchy(final String hierarchy, final Long agencyId) { + String sql = """ + SELECT + center.id AS id, + center.display_name AS name + FROM + m_office mo + INNER JOIN m_office office_under ON office_under.hierarchy LIKE CONCAT(mo.hierarchy, '%')AND office_under.hierarchy LIKE CONCAT(?, '%') + INNER JOIN m_appuser agency_responsible_user ON agency_responsible_user.office_id = office_under.id + INNER JOIN m_office agency_responsible_user_office ON agency_responsible_user_office.id = agency_responsible_user.office_id + INNER JOIN m_agency ma ON ma.responsible_user_id = agency_responsible_user.id + INNER JOIN m_office agency_office_under ON agency_office_under.hierarchy LIKE CONCAT(agency_responsible_user_office.hierarchy, '%') + INNER JOIN m_appuser supervison_responsible_user ON agency_responsible_user.office_id = agency_office_under.id + INNER JOIN m_office supervision_responsible_user_office ON supervision_responsible_user_office.id = supervison_responsible_user.office_id + INNER JOIN m_supervision ms ON ms.responsible_user_id = supervison_responsible_user.id + INNER JOIN m_office supervison_office_under ON supervison_office_under.hierarchy LIKE CONCAT(supervision_responsible_user_office.hierarchy, '%') + INNER JOIN m_appuser portfolio_responsible_user ON portfolio_responsible_user.office_id = supervison_office_under.id + INNER JOIN m_portfolio mp ON mp.responsible_user_id = portfolio_responsible_user.id + INNER JOIN m_group center ON center.portfolio_id = mp.id + WHERE center.parent_id IS NULL AND center.level_id = 1 + """; + List params = new ArrayList<>(List.of(hierarchy)); + if (agencyId != null) { + sql = sql + " AND ma.id = ?"; + params.add(agencyId); + } + sql = sql + " GROUP BY center.id"; + return this.jdbcTemplate.query(sql, (rs, rowNum) -> CenterData.instance(rs.getLong("id"), rs.getString("name")), params.toArray()); + } + @Override public CenterData retrieveTemplate(final Long officeId, final boolean staffInSelectedOfficeOnly) { 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 b00ff5ba06b..372041f0d8e 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 @@ -66,6 +66,8 @@ import org.apache.fineract.organisation.portfolio.domain.Portfolio; import org.apache.fineract.organisation.portfolio.domain.PortfolioRepositoryWrapper; import org.apache.fineract.organisation.portfolioCenter.service.PortfolioCenterConstants; +import org.apache.fineract.organisation.prequalification.domain.GroupPrequalificationRelationship; +import org.apache.fineract.organisation.prequalification.domain.GroupPrequalificationRelationshipRepository; import org.apache.fineract.organisation.prequalification.domain.PreQualificationGroupRepository; import org.apache.fineract.organisation.prequalification.domain.PrequalificationGroup; import org.apache.fineract.organisation.prequalification.exception.GroupPreQualificationNotFound; @@ -150,6 +152,7 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group private final GroupReadPlatformService groupReadPlatformService; private final JdbcTemplate jdbcTemplate; private final PreQualificationGroupRepository prequalificationGroupRepository; + private final GroupPrequalificationRelationshipRepository groupPrequalificationRelationshipRepository; private CommandProcessingResult createGroupingType(final JsonCommand command, final GroupTypes groupingType, final Long centerId) { try { @@ -314,6 +317,10 @@ private CommandProcessingResult createGroupingType(final JsonCommand command, fi // pre-save to generate id for use in group hierarchy this.groupRepository.saveAndFlush(newGroup); + GroupPrequalificationRelationship relationship = GroupPrequalificationRelationship.addRelationship(currentUser, newGroup, + prequalificationGroup); + + this.groupPrequalificationRelationshipRepository.save(relationship); /* * Generate hierarchy for a new center/group and all the child groups if they exist */ @@ -483,7 +490,7 @@ public CommandProcessingResult updateGroup(final Long groupId, final JsonCommand private CommandProcessingResult updateGroupingType(final Long groupId, final JsonCommand command, final GroupTypes groupingType) { try { - this.context.authenticatedUser(); + AppUser appUser = this.context.authenticatedUser(); final Group groupForUpdate = this.groupRepository.findOneWithNotFoundDetection(groupId); final Long officeId = groupForUpdate.officeId(); final Office groupOffice = groupForUpdate.getOffice(); @@ -519,6 +526,9 @@ private CommandProcessingResult updateGroupingType(final Long groupId, final Jso .orElseThrow(() -> new GroupPreQualificationNotFound(newValue)); groupForUpdate.updatePrequalification(prequalificationGroup); + GroupPrequalificationRelationship relationship = GroupPrequalificationRelationship.addRelationship(appUser, groupForUpdate, + prequalificationGroup); + this.groupPrequalificationRelationshipRepository.save(relationship); } final GroupLevel groupLevel = this.groupLevelRepository.findById(groupForUpdate.getGroupLevel().getId()).orElse(null); 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 edb19c3d8a9..643f77a6878 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 @@ -63,6 +63,7 @@ import javax.persistence.UniqueConstraint; import javax.persistence.Version; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.fineract.infrastructure.codes.domain.CodeValue; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.ApiParameterError; @@ -5002,11 +5003,20 @@ public List generateInstallmentLoanCharges(final LoanChar continue; } BigDecimal amount = BigDecimal.ZERO; + // FBR-369: Apply Administrative Fee as Installment Fee + BigDecimal chargeRate = loanCharge.getPercentage(); + + if (loanCharge.getCharge().isAddOnInstallmentFeeType()) { + LocalDate firstRepaymentDate = this.fetchRepaymentScheduleInstallment(1).getDueDate(); + Pair addOnDaysAndRate = loanCharge.getCharge() + .getAddOnDisbursementChargeRate(this.getDisbursementDate(), firstRepaymentDate); + chargeRate = addOnDaysAndRate.getRight(); + } + if (loanCharge.getChargeCalculation().isFlat()) { amount = loanCharge.amountOrPercentage(); } else { - amount = calculateInstallmentChargeAmount(loanCharge.getChargeCalculation(), loanCharge.getPercentage(), installment) - .getAmount(); + amount = calculateInstallmentChargeAmount(loanCharge.getChargeCalculation(), chargeRate, installment).getAmount(); } final LoanInstallmentCharge loanInstallmentCharge = new LoanInstallmentCharge(amount, loanCharge, installment); installment.getInstallmentCharges().add(loanInstallmentCharge); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java index 1c626a491bc..a7e9a6b5955 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java @@ -48,6 +48,7 @@ import org.apache.fineract.portfolio.charge.domain.Charge; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; import org.apache.fineract.portfolio.charge.domain.ChargeDisbursementType; +import org.apache.fineract.portfolio.charge.domain.ChargeInstallmentFeeType; import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode; import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; import org.apache.fineract.portfolio.charge.exception.LoanChargeWithoutMandatoryFieldException; @@ -129,6 +130,9 @@ public class LoanCharge extends AbstractPersistableCustom { @Column(name = "charge_disbursement_type_enum", nullable = false) private Integer chargeDisbursementType; + @Column(name = "charge_installment_fee_type_enum", nullable = false) + private Integer chargeInstallmentFeeType; + @OneToOne(mappedBy = "loancharge", cascade = CascadeType.ALL, optional = true, orphanRemoval = true, fetch = FetchType.EAGER) private LoanOverdueInstallmentCharge overdueInstallmentCharge; @@ -211,6 +215,7 @@ public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeD final String externalId = command.stringValueOfParameterNamedAllowingNull("externalId"); newLoanCharge.setExternalId(externalId); newLoanCharge.setChargeDisbursementType(chargeDefinition.getChargeDisbursementType()); + newLoanCharge.setChargeInstallmentFeeType(chargeDefinition.getChargeInstallmentFeeType()); return newLoanCharge; } @@ -235,9 +240,10 @@ public LoanCharge(final Loan loan, final Charge chargeDefinition, final BigDecim this.charge = chargeDefinition; this.penaltyCharge = chargeDefinition.isPenalty(); this.minCap = chargeDefinition.getMinCap(); + this.minCap = chargeDefinition.getMinCap(); this.maxCap = chargeDefinition.getMaxCap(); this.chargeDisbursementType = chargeDefinition.getChargeDisbursementType(); - + this.chargeInstallmentFeeType = chargeDefinition.getChargeInstallmentFeeType(); this.chargeTime = chargeDefinition.getChargeTimeType(); if (chargeTime != null) { this.chargeTime = chargeTime.getValue(); @@ -1102,8 +1108,20 @@ public void setChargeDisbursementType(Integer chargeDisbursementType) { this.chargeDisbursementType = chargeDisbursementType; } + public Integer getChargeInstallmentFeeType() { + return chargeInstallmentFeeType; + } + + public void setChargeInstallmentFeeType(Integer chargeInstallmentFeeType) { + this.chargeInstallmentFeeType = chargeInstallmentFeeType; + } + public boolean isAddOnDisbursementType() { return ChargeDisbursementType.fromInt(this.chargeDisbursementType).equals(ChargeDisbursementType.ADD_ON); } + public boolean isAddOnInstallmentFeeType() { + return ChargeInstallmentFeeType.fromInt(this.chargeInstallmentFeeType).equals(ChargeInstallmentFeeType.ADD_ON); + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java index 2b6ff390b37..0d3f78da3ee 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java @@ -636,7 +636,7 @@ public LoanScheduleModel assembleLoanScheduleFrom(final LoanApplicationTerms loa final List holidays, final WorkingDays workingDays, final JsonElement element, List disbursementDetails) { - final Set loanCharges = this.loanChargeAssembler.fromParsedJson(element, disbursementDetails); + final Set loanCharges = this.loanChargeAssembler.fromParsedJson(element, disbursementDetails, loanApplicationTerms); final RoundingMode roundingMode = MoneyHelper.getRoundingMode(); final MathContext mc = new MathContext(8, roundingMode); 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 fb89292fbe5..c0dcf05cbc4 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 @@ -453,8 +453,8 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { // contract number generation StringBuilder contractBuilder = new StringBuilder(); - String countLoansSql = "select count(*) from m_loan where product_id = ? "; - Long productLoansCount = this.jdbcTemplate.queryForObject(countLoansSql, Long.class, loanProduct.getId()); + String countLoansSql = "select count(*) from m_loan where product_id = ? and client_id =? and approvedon_date is not null"; + Long productLoansCount = this.jdbcTemplate.queryForObject(countLoansSql, Long.class, loanProduct.getId(), clientId); contractBuilder.append(loanProduct.getShortName()); if (clientId != null) { contractBuilder.append(StringUtils.leftPad(clientId.toString(), 8, '0')); @@ -878,8 +878,10 @@ public CommandProcessingResult modifyApplication(final Long loanId, final JsonCo /** * Stores all charges which are passed in during modify loan application **/ + //TODO: FBR-369 we need the expected disbursement date and first repayment date. This is hack to get hose but should be considered for improvement + final LoanApplicationTerms loanApplicationTermsCharges = this.loanScheduleAssembler.assembleLoanTerms(command.parsedJson()); final Set possiblyModifedLoanCharges = this.loanChargeAssembler.fromParsedJson(command.parsedJson(), - disbursementDetails); + disbursementDetails, loanApplicationTermsCharges); /** Boolean determines if any charge has been modified **/ boolean isChargeModified = false; 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 c57433d22f7..8a3d502ca0e 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 @@ -250,7 +250,10 @@ private Loan assembleApplication(final JsonElement element, final Long clientId, } } - final Set loanCharges = this.loanChargeAssembler.fromParsedJson(element, disbursementDetails); + //TODO: FBR-369 get range rate and generate charge + LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element); + + final Set loanCharges = this.loanChargeAssembler.fromParsedJson(element, disbursementDetails, loanApplicationTerms); for (final LoanCharge loanCharge : loanCharges) { if (!loanProduct.hasCurrencyCodeOf(loanCharge.currencyCode())) { final String errorMessage = "Charge and Loan must have the same currency."; @@ -338,7 +341,8 @@ private Loan assembleApplication(final JsonElement element, final Long clientId, } } - final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element); + loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element); + loanApplicationTerms.getCalculatedRepaymentsStartingFromLocalDate(); final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled(); final List holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loanApplication.getOfficeId(), loanApplicationTerms.getExpectedDisbursementDate(), HolidayStatusType.ACTIVE.getValue()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java index b6567d62627..5e682b76d09 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeAssembler.java @@ -29,6 +29,9 @@ import java.util.List; import java.util.Locale; import java.util.Set; + +import com.google.gson.JsonPrimitive; +import org.apache.commons.lang3.tuple.Pair; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.portfolio.charge.domain.Charge; import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; @@ -41,6 +44,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge; +import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository; import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException; @@ -64,7 +68,7 @@ public LoanChargeAssembler(final FromJsonHelper fromApiJsonHelper, final ChargeR this.loanProductRepository = loanProductRepository; } - public Set fromParsedJson(final JsonElement element, List disbursementDetails) { + public Set fromParsedJson(JsonElement element, List disbursementDetails, final LoanApplicationTerms loanApplicationTermsCharges) { JsonArray jsonDisbursement = this.fromApiJsonHelper.extractJsonArrayNamed("disbursementData", element); List disbursementChargeIds = new ArrayList<>(); @@ -109,7 +113,7 @@ public Set fromParsedJson(final JsonElement element, List fromParsedJson(final JsonElement element, List fromParsedJson(final JsonElement element, List fromParsedJson(final JsonElement element, List addOnDaysAndRate = charge.getAddOnDisbursementChargeRate(loanApplicationTermsCharges.getExpectedDisbursementDate(), + loanApplicationTermsCharges.getRepaymentStartFromDate()); + rate = addOnDaysAndRate.getRight(); + loanChargeElement.add("amount", new JsonPrimitive(rate)); + } + } + return rate; + } + public Set getNewLoanTrancheCharges(final JsonElement element) { final Set associatedChargesForLoan = new HashSet<>(); if (element.isJsonObject()) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java index 952f96f4015..67131c60dc7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java @@ -143,6 +143,7 @@ public ChargeData retrieveLoanChargeTemplate() { final List clientChargeCalculationTypeOptions = null; final List clientChargeTimeTypeOptions = null; final List chargeDisbursementTypeOptions = null; + final List chargeInstallmentFeeTypeOptions = null; final List feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); // this field is applicable only for client charges @@ -159,7 +160,8 @@ public ChargeData retrieveLoanChargeTemplate() { loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, - accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions); + accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions, + chargeInstallmentFeeTypeOptions); } @Override 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 59caefe1a09..18785789a25 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 @@ -23,6 +23,7 @@ import com.google.gson.JsonObject; import java.math.BigDecimal; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; @@ -60,6 +61,9 @@ import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException; import org.apache.fineract.infrastructure.jobs.service.JobName; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.organisation.bankcheque.domain.BankChequeStatus; +import org.apache.fineract.organisation.bankcheque.domain.Cheque; +import org.apache.fineract.organisation.bankcheque.domain.ChequeJpaRepository; import org.apache.fineract.organisation.holiday.domain.Holiday; import org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper; import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency; @@ -273,6 +277,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final PostDatedChecksRepository postDatedChecksRepository; private final LumaAccountingProcessorForLoan lumaAccountingProcessorForLoan; private final BitaCoraMasterRepository bitaCoraMasterRepository; + private final ChequeJpaRepository chequeJpaRepository; private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { final List allowedLoanStatuses = Arrays.asList(LoanStatus.values()); @@ -849,6 +854,18 @@ public CommandProcessingResult undoLoanDisbursal(final Long loanId, final JsonCo BigDecimal netDisbursalAmount = loan.getApprovedPrincipal().subtract(loanOutstanding); loan.adjustNetDisbursalAmount(netDisbursalAmount); } + + if (loan.getCheque() != null) { + Long userId = currentUser.getId(); + final LocalDateTime localDateTime = DateUtils.getLocalDateTimeOfSystem(); + LocalDate localDate = DateUtils.getBusinessLocalDate(); + Cheque cheque = loan.getCheque(); + cheque.setStatus(BankChequeStatus.VOIDED.getValue()); + cheque.stampAudit(userId, localDateTime); + cheque.setVoidedBy(currentUser); + cheque.setVoidedDate(localDate); + this.chequeJpaRepository.saveAndFlush(cheque); + } saveAndFlushLoanWithDataIntegrityViolationChecks(loan); this.accountTransfersWritePlatformService.reverseAllTransactions(loanId, PortfolioAccountType.LOAN); String noteText = null; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java index 54df64fc75d..db8e3e97935 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java @@ -47,4 +47,6 @@ public interface LoanProductReadPlatformService { Collection retrieveLoanProductBorrowerCycleVariations(Long loanProductId); LoanProductData retrieveLoanProductFloatingDetails(Long loanProductId); + + Collection retrieveAllLoanProductsForOwner(Integer ownerType); } 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 897c2bb6598..554697e9b5c 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 @@ -658,6 +658,25 @@ public Collection retrieveAllowedProductsForMix(final Long prod return this.jdbcTemplate.query(sql, rm, new Object[] { productId, productId }); // NOSONAR } + @Override + public Collection retrieveAllLoanProductsForOwner(Integer ownerType) { + this.context.authenticatedUser(); + + final LoanProductMapper rm = new LoanProductMapper(null, null, null); + + String sql = "select " + rm.loanProductSchema() + " where lp.owner_type_enum= ? "; + + // Check if branch specific products are enabled. If yes, fetch only + // products mapped to current user's office + String inClause = fineractEntityAccessUtil + .getSQLWhereClauseForProductIDsForUserOffice_ifGlobalConfigEnabled(FineractEntityType.LOAN_PRODUCT); + if (inClause != null && !inClause.trim().isEmpty()) { + sql += " and id in (" + inClause + ") "; + } + + return this.jdbcTemplate.query(sql, rm, new Object[] { ownerType }); // NOSONAR + } + @Override public LoanProductData retrieveLoanProductFloatingDetails(final Long loanProductId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java index 0404b8a54e6..6be8681063b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountChargeReadPlatformServiceImpl.java @@ -167,6 +167,7 @@ public ChargeData retrieveSavingsAccountChargeTemplate() { final List clientChargeCalculationTypeOptions = null; final List clientChargeTimeTypeOptions = null; final List chargeDisbursementTypeOptions = null; + final List chargeInstallmentFeeTypeOptions = null; final List feeFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions(); // this field is applicable only for client charges @@ -184,7 +185,8 @@ public ChargeData retrieveSavingsAccountChargeTemplate() { loansChargeCalculationTypeOptions, loansChargeTimeTypeOptions, savingsChargeCalculationTypeOptions, savingsChargeTimeTypeOptions, clientChargeCalculationTypeOptions, clientChargeTimeTypeOptions, feeFrequencyOptions, incomeOrLiabilityAccountOptions, taxGroupOptions, shareChargeCalculationTypeOptions, shareChargeTimeTypeOptions, - accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions); + accountMappingForChargeConfig, expenseAccountOptions, assetAccountOptions, chargeDisbursementTypeOptions, + chargeInstallmentFeeTypeOptions); } @Override diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/data/AppUserData.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/data/AppUserData.java index 49f4ca698e2..b52a277f050 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/data/AppUserData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/data/AppUserData.java @@ -112,6 +112,20 @@ public static AppUserData instance(final Long id, final String username, final S selectedRoles, null, staff, passwordNeverExpire, isSelfServiceUser); } + public static AppUserData instance(final Long id, final String username, String firstname, final String lastname) { + final Long officeId = null; + final String officeName = null; + final String email = null; + final Boolean passwordNeverExpires = null; + final Collection availableRoles = null; + final Collection selfServiceRoles = null; + final Collection selectedRoles = null; + final StaffData staff = null; + final Boolean isSelfServiceUser = null; + return new AppUserData(id, username, email, officeId, officeName, firstname, lastname, availableRoles, selfServiceRoles, + selectedRoles, null, staff, passwordNeverExpires, isSelfServiceUser); + } + private AppUserData(final Long id, final String username, final String email, final Long officeId, final String officeName, final String firstname, final String lastname, final Collection availableRoles, final Collection selfServiceRoles, final Collection selectedRoles, diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java index b0d348c5e4d..06f0fa6936d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java @@ -35,5 +35,7 @@ public interface AppUserReadPlatformService { Collection retrieveUsersUnderHierarchy(Long hierarchyLevel); + Collection retrieveByOfficeHierarchy(final String hierarchy, final Long centerId); + Collection retrieveUsersForCommittees(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java index d9115f16497..e2309095f47 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.apache.fineract.infrastructure.core.domain.JdbcSupport; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; @@ -302,4 +303,33 @@ private void findUserWithRoleLike(Collection usersDataList, Collect } } + @Override + public Collection retrieveByOfficeHierarchy(String hierarchy, final Long centerId) { + String sql = """ + SELECT + facilitator.id AS id, + facilitator.username AS username, + facilitator.firstname AS firstname, + facilitator.lastname AS lastname, + facilitator.email AS email, + facilitator.office_id AS officeId, + mo.name AS officeName, + facilitator.is_self_service_user AS isSelfServiceUser + FROM m_office mo + INNER JOIN m_office office_under ON office_under.hierarchy LIKE CONCAT(mo.hierarchy, '%')AND office_under.hierarchy LIKE CONCAT(?, '%') + LEFT JOIN m_group center ON center.office_id = office_under.id + LEFT JOIN m_office center_office ON center_office.id = center.office_id + LEFT JOIN m_office center_office_under ON center_office_under.hierarchy LIKE CONCAT(center_office.hierarchy, '%') + LEFT JOIN m_appuser facilitator ON facilitator.office_id = center_office_under.id + WHERE facilitator.is_deleted = FALSE AND center.parent_id IS NULL AND center.level_id = 1 + """; + final List params = new ArrayList<>(List.of(hierarchy)); + if (centerId != null) { + sql = sql + " AND center.id = ? "; + params.add(centerId); + } + sql = sql + " GROUP BY facilitator.id ORDER BY facilitator.username"; + return this.jdbcTemplate.query(sql, (rs, rowNum) -> AppUserData.instance(rs.getLong("id"), rs.getString("username"), + rs.getString("firstname"), rs.getString("lastname")), params.toArray()); + } } 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 c59efe611e9..4fcfe186ee3 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 @@ -114,5 +114,13 @@ + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/insert_initial_policy_data.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/insert_initial_policy_data.sql new file mode 100644 index 00000000000..52d30e47ed2 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/insert_initial_policy_data.sql @@ -0,0 +1,159 @@ +-- +-- 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 */; + +-- Drop previous tables -- +DROP TABLE IF EXISTS checklist_decision_making; +DROP TABLE IF EXISTS checklist_categories; + + +-- Insert policy names -- +INSERT INTO m_policy (id, name, label, description) VALUES(1, 'New client categorization', 'label.category.newclient', 'Categorización de clienta nueva'); +INSERT INTO m_policy (id, name, label, description) VALUES(2, 'Recurring customer categorization', 'label.category.recurringcustomer', 'Categoríazación de clienta recurruente'); +INSERT INTO m_policy (id, name, label, description) VALUES(3, 'Increase percentage', 'label.category.increasepercentage', 'Porcentaje de incremento'); +INSERT INTO m_policy (id, name, label, description) VALUES(4, 'Mandatory to attach photographs and investment plan', 'label.category.mandatoryphotos', 'Obligatorio adjuntar fotografías y plan de inversión'); +INSERT INTO m_policy (id, name, label, description) VALUES(5, 'Client age', 'label.category.clientage', 'Edad de la cliente'); +INSERT INTO m_policy (id, name, label, description) VALUES(6, 'Number of members according to policy', 'label.category.memberspolicycount', 'Cantidad de integrantes según política'); +INSERT INTO m_policy (id, name, label, description) VALUES(7, 'Minimum and maximum amount', 'label.category.minmaxamount', 'Monto mínimo y máximo'); +INSERT INTO m_policy (id, name, label, description) VALUES(8, 'Value disparity', 'label.category.disparity', 'Disparidad de valores'); +INSERT INTO m_policy (id, name, label, description) VALUES(9, 'Percentage of members starting business', 'label.category.startingbusiness', 'Porcentaje de integrantes iniciando negocio'); +INSERT INTO m_policy (id, name, label, description) VALUES(10, 'Percentage of members with their own home', 'label.category.ownhome', 'Porcentaje de integrantes con vivienda propia'); +INSERT INTO m_policy (id, name, label, description) VALUES(11, 'President of the Board of Directors of the BC', 'label.category.boardofdirectors', 'Presidente de Junta Directiva del BC'); +INSERT INTO m_policy (id, name, label, description) VALUES(12, 'General condition', 'label.category.overallcondition', 'Condición general'); +INSERT INTO m_policy (id, name, label, description) VALUES(13, 'Categories of clients to accept', 'label.category.clientcategories', 'Categorías de clientes a aceptar'); +INSERT INTO m_policy (id, name, label, description) VALUES(14, 'Amount requested in relation to the current amount of main products', 'label.category.requestedamount', 'Monto solicitado en relación al monto que tiene vigente en productos principales'); +INSERT INTO m_policy (id, name, label, description) VALUES(15, 'Add endorsement', 'label.category.addendorsement', 'Agregar aval'); +INSERT INTO m_policy (id, name, label, description) VALUES(16, 'Payments outside the current term of the main product', 'label.category.outsidetermpayents', 'Pagos fuera del plazo vigente del producto principal'); +INSERT INTO m_policy (id, name, label, description) VALUES(17, 'Percentage of members of the same group who they can have parallel product', 'label.category.canhaveproduct', 'Porcentaje de integrantes del mismo grupo que pueden llegar a tener producto Paralelo'); +INSERT INTO m_policy (id, name, label, description) VALUES(18, 'Gender', 'label.category.gender', 'Género'); +INSERT INTO m_policy (id, name, label, description) VALUES(19, 'Nationality', 'label.category.nationality', 'Nacionalidad'); +INSERT INTO m_policy (id, name, label, description) VALUES(20, 'Internal Credit History', 'label.category.internalcredithistory', 'Historial crédito INTERNO'); +INSERT INTO m_policy (id, name, label, description) VALUES(21, 'External Credit History', 'label.category.externalcredithistory', 'Historial crédito EXTERNO'); +INSERT INTO m_policy (id, name, label, description) VALUES(22, 'Do you register any lawsuit?', 'label.category.claimregistered', 'Do you register any lawsuit?'); +INSERT INTO m_policy (id, name, label, description) VALUES(23, 'Housing Type', 'label.category.housingtype', 'Tipo de vivienda'); +INSERT INTO m_policy (id, name, label, description) VALUES(24, 'Rental Age', 'label.category.rentalage', 'Antigüedad de alquiler'); +INSERT INTO m_policy (id, name, label, description) VALUES(25, 'Age Of Business', 'label.category.businessage', 'Antigüedad del negocio'); +INSERT INTO m_policy (id, name, label, description) VALUES(26, 'Credits', 'label.category.credits', 'Recréditos'); +INSERT INTO m_policy (id, name, label, description) VALUES(27, 'Cancelled Cycles Count', 'label.category.cyclescount', 'Cantidade ciclos cancelados como grupo'); +INSERT INTO m_policy (id, name, label, description) VALUES(28, ' Acceptance of new clients', 'label.category.newclientsacceptance', 'Aceptación de clientas nuevas'); +INSERT INTO m_policy (id, name, label, description) VALUES(29, 'Present agricultural technical diagnosis (Commcare)', 'label.category.agricultural.diagnosis', 'Presentar diagnótico técnico agrícola (Commcare)'); +INSERT INTO m_policy (id, name, label, description) VALUES(30, 'Age', 'label.category.clientage', 'Edad'); +INSERT INTO m_policy (id, name, label, description) VALUES(31, 'Amount', 'label.category.amount', 'Monto'); +INSERT INTO m_policy (id, name, label, description) VALUES(32, 'Percentage of members with agricultural business', 'label.agribusiness.percentage', 'Porcentaje de integrantes con negocio agrícola'); +INSERT INTO m_policy (id, name, label, description) VALUES(33, 'Percentage of members with their own business', 'label.own.business.percentage', 'Porcentaje de integrantes con negocio propia'); + +-- Insert product policy data -- +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'INDIVIDUAL', 1); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'INDIVIDUAL', 1); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 1); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'INDIVIDUAL', 1); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 1); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(3, 'INDIVIDUAL', 2); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'INDIVIDUAL', 3); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'INDIVIDUAL', 3); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 3); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'INDIVIDUAL', 3); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 3); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'INDIVIDUAL', 5); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'INDIVIDUAL', 5); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 5); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'INDIVIDUAL', 5); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 5); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'GROUP', 6); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'GROUP', 6); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'GROUP', 6); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'GROUP', 6); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'GROUP', 6); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'GROUP', 7); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'GROUP', 7); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'GROUP', 7); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'GROUP', 7); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'GROUP', 7); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'GROUP', 8); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'GROUP', 8); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'GROUP', 8); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'GROUP', 9); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'GROUP', 10); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'GROUP', 10); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(2, 'GROUP', 11); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'GROUP', 11); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'GROUP', 11); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'GROUP', 11); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'GROUP', 11); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 12); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(3, 'INDIVIDUAL', 12); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 13); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(3, 'INDIVIDUAL', 13); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 14); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(3, 'INDIVIDUAL', 14); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 15); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 16); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 17); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 18); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 19); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 20); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 21); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 22); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 23); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 24); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 25); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 26); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(9, 'GROUP', 27); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(7, 'INDIVIDUAL', 4); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'GROUP', 28); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 29); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(8, 'INDIVIDUAL', 29); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'INDIVIDUAL', 29); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 30); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(6, 'INDIVIDUAL', 31); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(5, 'GROUP', 32); +INSERT INTO m_product_policy (product_id, evaluation_type, policy_id) VALUES(4, 'GROUP', 33); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_10.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_10.sql new file mode 100644 index 00000000000..8ff10751ae5 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_10.sql @@ -0,0 +1,57 @@ +-- +-- 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 */; + +-- Percentage of members with their own home -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Percentage of members with their own home Policy Check", "Table", "Prequalification", +"SELECT + housing_type.owner_percent, + CASE + WHEN (${loanProductId} = 2) AND (housing_type.owner_percent <=50) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (housing_type.owner_percent >50) THEN 'YELLOW' + + WHEN (${loanProductId} = 8) AND (housing_type.owner_percent <=50) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (housing_type.owner_percent >50) THEN 'YELLOW' + + END AS color + FROM m_prequalification_group mpg + INNER JOIN ( select (((select count(*) from m_prequalification_group_members mpm INNER JOIN m_client mc on mc.dpi = mpm.dpi + INNER JOIN m_client_contact_info mcinf on mcinf.client_id = mc.id INNER JOIN m_code_value mcv on mcv.id = mcinf.housing_type where mcv.code_value = 'Propia' and mpm.group_id = ${prequalificationId})/ + (select count(*) from m_prequalification_group_members mpg where mpg.group_id = ${prequalificationId}))*100) as owner_percent, ${prequalificationId} as grp_id ) + housing_type ON housing_type.grp_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "Percentage of members with their own home Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_11.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_11.sql new file mode 100644 index 00000000000..e65887c04fa --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_11.sql @@ -0,0 +1,76 @@ +-- +-- 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 */; + +-- External Credit History Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("President of the Board of Directors of the BC Policy Check", "Table", "Prequalification", +"SELECT + prequalification_details.recreditCategorization, + CASE + WHEN (${loanProductId} = 2) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 2) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 2) AND ('${buroCheckClassification}' = 'C') THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + + WHEN (${loanProductId} = 9) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 9) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 9) AND ('${buroCheckClassification}' = 'C') THEN 'YELLOW' + WHEN (${loanProductId} = 9) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + + WHEN (${loanProductId} = 8) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 8) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 8) AND ('${buroCheckClassification}' = 'C') THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + + WHEN (${loanProductId} = 4) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 4) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 4) AND ('${buroCheckClassification}' = 'C') THEN 'YELLOW' + WHEN (${loanProductId} = 4) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + + WHEN (${loanProductId} = 5) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 5) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 5) AND ('${buroCheckClassification}' = 'C') THEN 'YELLOW' + WHEN (${loanProductId} = 5) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + END AS color + FROM m_prequalification_group mpg + INNER JOIN ( + SELECT p.id AS prequalification_id, + (CASE WHEN p.previous_prequalification IS NOT NULL THEN 'RECREDITO' ELSE 'NUEVO' END) AS recreditCategorization + FROM m_prequalification_group p + ) prequalification_details ON prequalification_details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "President of the Board of Directors of the BC Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_12.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_12.sql new file mode 100644 index 00000000000..ce0dcf22945 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_12.sql @@ -0,0 +1,56 @@ +-- +-- 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 */; + +-- General condition Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("General condition Policy Check", "Table", "Prequalification", +"SELECT + client_details.number_of_principal_loans, + CASE + WHEN ('${loanProductId}' = 7) AND (client_details.number_of_principal_loans >= 1) THEN 'GREEN' + WHEN ('${loanProductId}' = 3) AND (client_details.number_of_principal_loans >= 1) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mc.id AS client_id, COUNT(DISTINCT ml.id) AS number_of_principal_loans + FROM m_client mc + LEFT JOIN m_loan ml ON ml.client_id = mc.id + WHERE ml.product_id IN (2, 4) AND (ml.loan_status_id = 300) + GROUP BY mc.id + )client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "General condition Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_13.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_13.sql new file mode 100644 index 00000000000..ea691ec02bc --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_13.sql @@ -0,0 +1,56 @@ +-- +-- 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 */; + +-- Categories of clients to accept Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Categories of clients to accept Policy Check", "Table", "Prequalification", +"SELECT + CASE + WHEN (${loanProductId} = 7) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 7) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 7) AND ('${buroCheckClassification}' = 'C') THEN 'ORANGE' + WHEN (${loanProductId} = 7) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + + WHEN (${loanProductId} = 3) AND ('${buroCheckClassification}' = 'A') THEN 'GREEN' + WHEN (${loanProductId} = 3) AND ('${buroCheckClassification}' = 'B') THEN 'GREEN' + WHEN (${loanProductId} = 3) AND ('${buroCheckClassification}' = 'C') THEN 'ORANGE' + WHEN (${loanProductId} = 3) AND ('${buroCheckClassification}' = 'D') THEN 'ORANGE' + END AS color + FROM m_client mc + WHERE mc.id = ${clientId} +", "Categories of clients to accept Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_14.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_14.sql new file mode 100644 index 00000000000..f017d06379f --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_14.sql @@ -0,0 +1,56 @@ +-- +-- 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 */; + +-- Amount requested in relation to the current amount of main products -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Amount requested in relation to the current amount of main products Policy Check", "Table", "Prequalification", + "SELECT + client_details.current_loan_amount, + CASE + WHEN ('${loanProductId}' = 7) AND ((client_details.current_loan_amount)/${requestedAmount} <= 4) THEN 'GREEN' + WHEN ('${loanProductId}' = 7) AND ((client_details.current_loan_amount)/${requestedAmount} = 5) THEN 'GREEN' + WHEN ('${loanProductId}' = 7) AND ((client_details.current_loan_amount)/${requestedAmount} >= 6) THEN 'GREEN' + WHEN ('${loanProductId}' = 3) AND (${requestedAmount} <= 3000) THEN 'GREEN' + WHEN ('${loanProductId}' = 3) AND (${requestedAmount} > client_details.current_loan_amount) THEN 'RED' + WHEN ('${loanProductId}' = 3) AND (${requestedAmount} > 3000) THEN 'RED' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mc.id AS client_id, (select COALESCE(ml.principal_amount,0) from m_loan ml where ml.client_id = mc.id and ml.product_id = ${loanProductId} and ml.loan_status_id = 300 ORDER BY id desc limit 1 ) as current_loan_amount FROM m_client mc + )client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Amount requested in relation to the current amount of main products Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_16.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_16.sql new file mode 100644 index 00000000000..28888c902d4 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_16.sql @@ -0,0 +1,59 @@ +-- +-- 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 */; + +-- Payments outside the current term of the main product -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Payments outside the current term of the main product Policy Check", "Table", "Prequalification", +"SELECT + client_details.number_of_pending_installments, + CASE + WHEN ('${loanProductId}' = 7) AND (client_details.number_of_pending_installments = 4) THEN 'GREEN' + WHEN ('${loanProductId}' = 7) AND (client_details.number_of_pending_installments > 4) THEN 'ORANGE' + WHEN ('${loanProductId}' = 3) AND (client_details.number_of_pending_installments = 4) THEN 'GREEN' + WHEN ('${loanProductId}' = 3) AND (client_details.number_of_pending_installments > 4) THEN 'ORANGE' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mc.id AS client_id, COUNT(DISTINCT RS.id) AS number_of_pending_installments + FROM m_client mc + LEFT JOIN m_loan ml ON ml.client_id = mc.id + LEFT JOIN m_loan_repayment_schedule RS ON RS.loan_id = ml.id + WHERE ml.product_id IN (2, 4) AND (ml.loan_status_id = 300) AND RS.completed_derived =0 + GROUP BY mc.id + )client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Payments outside the current term of the main product Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_17.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_17.sql new file mode 100644 index 00000000000..1916ce59aab --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_17.sql @@ -0,0 +1,64 @@ +-- +-- 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 */; + +-- Percentage of members of the same group who they can have parallel product -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Percentage of members of the same group who they can have parallel product Policy Check", "Table", "Prequalification", +"SELECT + COALESCE(prequalification_details.percentage, 0) AS percentage, + CASE + WHEN (${loanProductId} = 7) AND ((COALESCE(prequalification_details.percentage, 0)) <= 50) THEN 'GREEN' + END AS color + FROM m_prequalification_group pg + INNER JOIN ( + SELECT + mpg.id AS prequalification_id, ((COUNT(DISTINCT details.client_id) * 100) / (${numberOfMembers})) AS percentage + FROM m_prequalification_group mpg + LEFT JOIN ( + SELECT mpg.id AS prequalification_id, mc.id AS client_id + FROM m_prequalification_group mpg + LEFT JOIN m_prequalification_group_members mpgm ON mpgm.group_id = mpg.id + LEFT JOIN m_client mc ON mc.dpi = mpgm.dpi + LEFT JOIN m_loan ml ON ml.client_id = mc.id + WHERE ml.loan_status_id = 300 AND ml.product_id = ${loanProductId} + GROUP BY ml.id, mpg.id + ) details ON details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId} + GROUP BY mpg.id + ) prequalification_details ON prequalification_details.prequalification_id = pg.id + WHERE pg.id = ${prequalificationId}", "Percentage of members of the same group who they can have parallel product Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_18.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_18.sql new file mode 100644 index 00000000000..b8dc3c56610 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_18.sql @@ -0,0 +1,55 @@ +-- +-- 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 */; + +-- Nationality -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Gender Policy Check", "Table", "Prequalification", +"SELECT mc.id, + client_details.client_gender, + CASE + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND ('MUJER' = UPPER(COALESCE(client_details.client_gender, ''))) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND ('MUJER' = UPPER(COALESCE(client_details.client_gender, ''))) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mct.id AS client_id, client_gender.code_value AS client_gender + FROM m_client mct + LEFT JOIN m_code_value client_gender ON mct.gender_cv_id = client_gender.id + ) client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Gender Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_19.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_19.sql new file mode 100644 index 00000000000..767497b7eda --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_19.sql @@ -0,0 +1,52 @@ +-- +-- 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 */; + +-- Nationality -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Nationality Policy Check", "Table", "Prequalification", +"SELECT mc.id, + UPPER(COALESCE(mc.nationality, '')) AS client_nationality, + CASE + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND ('GUATEMALA' = UPPER(COALESCE(mc.nationality, ''))) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND ('GUATEMALA' <> UPPER(COALESCE(mc.nationality, ''))) THEN 'RED' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND ('GUATEMALA' = UPPER(COALESCE(mc.nationality, ''))) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND ('GUATEMALA' <> UPPER(COALESCE(mc.nationality, ''))) THEN 'RED' + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + WHERE mc.id = ${clientId}", "Nationality Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_1_2.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_1_2.sql new file mode 100644 index 00000000000..572edcf1eed --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_1_2.sql @@ -0,0 +1,122 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Client Categorization Policy Check", "Table", "Prequalification", +"SELECT CASE + WHEN (${loanProductId} = 2) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) > 0) THEN 'RECURRING' + WHEN (${loanProductId} = 2) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 2) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1 OR IFNULL(client_loan_details.number_of_closed_loans, 0) <= 2) THEN 'NEW' + + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) > 0) THEN 'RECURRING' + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) > 0) THEN 'RECURRING' + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 3) THEN 'RECURRING' + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 3) THEN 'RECURRING' + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 7) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 3) THEN 'RECURRING' + WHEN (${loanProductId} = 7) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) = 2) THEN 'RECURRING' + WHEN (${loanProductId} = 7) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) < 2) THEN 'RECURRING' + + WHEN (${loanProductId} = 3) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 1) THEN 'RECURRING' + WHEN (${loanProductId} = 3) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) = 0) THEN 'RECURRING' + + ELSE 'NEW' + END AS clientCategorization, + 'GREEN' AS color, + CASE + WHEN client_area.code_value = 'Urbana' THEN 'URBANA' + WHEN client_area.code_value = 'Rural' THEN 'RURAL' + WHEN client_area.code_value = 'PeriUrbana' THEN 'PERI_URBANA' + ELSE 'RURAL' + END AS clientArea, + CASE + WHEN COALESCE(client_loan_details.number_of_submitted_loans, 0) > 0 THEN 'RECREDITO' + ELSE 'NUEVO' + END AS recreditCategorization, + client_loan_details.submittedon_years, + client_loan_details.rejoining_years, + client_loan_details.number_of_loan_cycles, + client_loan_details.number_of_closed_loans, + client_loan_details.number_of_submitted_loans + FROM m_client mc + INNER JOIN ( + SELECT mcl.id AS client_id, + TIMESTAMPDIFF(YEAR, mcl.submittedon_date, CURDATE()) AS submittedon_years, + IFNULL(TIMESTAMPDIFF(YEAR, mcl.submittedon_date, mcl.reactivated_on_date), 0) AS rejoining_years, + COALESCE((SELECT COUNT(*) FROM m_loan WHERE client_id = ${clientId} AND approvedon_date IS NOT NULL), 0) AS number_of_loan_cycles, + COALESCE((SELECT COUNT(*) FROM m_loan WHERE client_id = ${clientId} AND loan_status_id >= 600), 0) AS number_of_closed_loans, + COALESCE((SELECT COUNT(*) FROM m_loan WHERE client_id = ${clientId} AND loan_status_id = 100), 0) AS number_of_submitted_loans + FROM m_client mcl + )client_loan_details ON client_loan_details.client_id = mc.id + LEFT JOIN m_client_contact_info mcci ON mcci.client_id = mc.id + LEFT JOIN m_code_value client_area ON client_area.id = mcci.area + WHERE mc.id = ${clientId} + GROUP BY mc.id", "Client Categorization Policy Check", 0, 0, 0); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client Categorization Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "clientIdSelectAll"), "clientId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client Categorization Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "loanProductIdSelectAll"), "loanProductId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client Categorization Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "OfficeIdSelectOne"), "officeId"); + + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client Categorization Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "currencyIdSelectAll"), "currencyId"); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_20.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_20.sql new file mode 100644 index 00000000000..0fa7100b024 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_20.sql @@ -0,0 +1,48 @@ +-- +-- 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 */; + +-- Internal Credit History Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Internal Credit History Policy Check", "Table", "Prequalification", +"SELECT + mc.id AS client_id, + CASE + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + WHERE mc.id = ${clientId}", "Internal Credit History Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_21.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_21.sql new file mode 100644 index 00000000000..af2df39683a --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_21.sql @@ -0,0 +1,48 @@ +-- +-- 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 */; + +-- External Credit History Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("External Credit History Policy Check", "Table", "Prequalification", +"SELECT + mc.id AS client_id, + CASE + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + WHERE mc.id = ${clientId}", "External Credit History Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_23.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_23.sql new file mode 100644 index 00000000000..02e78fdc7b8 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_23.sql @@ -0,0 +1,61 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Housing Type Policy Check", "Table", "Prequalification", +"SELECT + client_details.housing_type, + CASE + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.housing_type = 'OWN') THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.housing_type = 'RENTED') THEN 'YELLOW' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.housing_type = 'OWN') THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.housing_type = 'OWN') THEN 'YELLOW' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.housing_type = 'RENTED') THEN 'ORANGE' + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT + mct.id AS client_id, + (CASE WHEN housing_type.code_value = 'Propia' THEN 'OWN' ELSE 'RENTED' END) AS housing_type + FROM m_client mct + LEFT JOIN m_client_contact_info mcci ON mcci.client_id = mct.id + LEFT JOIN m_code_value housing_type ON housing_type.id = mcci.housing_type + ) client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Housing Typed Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_24.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_24.sql new file mode 100644 index 00000000000..39139e0c354 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_24.sql @@ -0,0 +1,60 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Rental Age Policy Check", "Table", "Prequalification", +"SELECT + client_details.years_of_residence, + CASE + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.years_of_residence >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.years_of_residence < 3) THEN 'YELLOW' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.years_of_residence >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.years_of_residence < 3) THEN 'YELLOW' + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT + mct.id AS client_id, + COALESCE(mcci.years_of_residence, 0) AS years_of_residence + FROM m_client mct + LEFT JOIN m_client_contact_info mcci ON mcci.client_id = mct.id + LEFT JOIN m_code_value housing_type ON housing_type.id = mcci.housing_type + ) client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Rental Age Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_25.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_25.sql new file mode 100644 index 00000000000..e61b0c3e0d2 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_25.sql @@ -0,0 +1,62 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Age Of Business Policy Check", "Table", "Prequalification", +"SELECT + client_details.years_of_business, + CASE + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.years_of_business >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.years_of_business BETWEEN 1.5 AND 3) THEN 'YELLOW' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (client_details.years_of_business < 1.5) THEN 'RED' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.years_of_business >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.years_of_business BETWEEN 1.5 AND 3) THEN 'YELLOW' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (client_details.years_of_business < 1.5) THEN 'RED' + WHEN (${loanProductId} = 6) AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT + mct.id AS client_id, + COALESCE(mcci.years_of_residence, 0) AS years_of_business + FROM m_client mct + LEFT JOIN m_client_contact_info mcci ON mcci.client_id = mct.id + LEFT JOIN m_code_value housing_type ON housing_type.id = mcci.housing_type + ) client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Age Of Business Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_26.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_26.sql new file mode 100644 index 00000000000..6f04c3ba704 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_26.sql @@ -0,0 +1,56 @@ +-- +-- 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 */; + +-- Credits Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Credits Policy Check", "Table", "Prequalification", +"SELECT + COALESCE(client_details.principal_paid_percentage, 0) AS principal_paid_percentage, + CASE + WHEN ('${loanProductId}' = 7) AND ( COALESCE(client_details.principal_paid_percentage, 0) >= 50) THEN 'GREEN' + WHEN ('${loanProductId}' = 3) AND ( COALESCE(client_details.principal_paid_percentage, 0) >= 50) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mc.id AS client_id, (100 * SUM(ml.principal_repaid_derived)/SUM(ml.principal_disbursed_derived)) AS principal_paid_percentage + FROM m_client mc + LEFT JOIN m_loan ml ON ml.client_id = mc.id + WHERE ml.loan_status_id = 300 AND COALESCE(ml.principal_disbursed_derived, 0) > 0 + GROUP BY mc.id + )client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Credits Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_27.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_27.sql new file mode 100644 index 00000000000..903463b9e3e --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_27.sql @@ -0,0 +1,62 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Cancelled Cycles Count Policy Check", "Table", "Prequalification", +"SELECT + prequalification_details.recreditCategorization, + COALESCE(prequalification_details.number_of_completed_loans, 0) AS number_of_completed_loans, + CASE + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (COALESCE(prequalification_details.number_of_completed_loans, 0) >= 1) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (COALESCE(prequalification_details.number_of_completed_loans, 0) >= 1) THEN 'GREEN' + END AS color + FROM m_prequalification_group mpg + LEFT JOIN ( + SELECT p.id AS prequalification_id, + (CASE WHEN p.previous_prequalification IS NOT NULL THEN 'RECREDITO' ELSE 'NUEVO' END) AS recreditCategorization, + (SELECT COUNT(*) + FROM m_prequalification_group mp + LEFT JOIN m_group_prequalification_relationship mgpr ON mgpr.prequalification_id = mp.id + LEFT JOIN m_group mg ON (mg.prequalification_id = mp.id OR mg.id = mgpr.group_id) + LEFT JOIN m_loan ml ON ml.group_id = mg.id + WHERE ml.loan_status_id >= 600 AND mg.status_enum = 300 AND mp.id = ${prequalificationId} + GROUP BY mp.id) AS number_of_completed_loans + FROM m_prequalification_group p + )prequalification_details ON prequalification_details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "Cancelled Cycles Count Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_28.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_28.sql new file mode 100644 index 00000000000..31ad4bb9427 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_28.sql @@ -0,0 +1,54 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Acceptance of new clients Policy Check", "Table", "Prequalification", +"SELECT + prequalification_details.recreditCategorization, + CASE + WHEN (${loanProductId} = 4) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${clientsRatio} >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${clientsRatio} >= 3) THEN 'GREEN' + END AS color + FROM m_prequalification_group mpg + LEFT JOIN ( + SELECT p.id AS prequalification_id, + (CASE WHEN p.previous_prequalification IS NULL THEN 'RECREDITO' ELSE 'NUEVO' END) AS recreditCategorization + FROM m_prequalification_group p + )prequalification_details ON prequalification_details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "Acceptance of new clients Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_30.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_30.sql new file mode 100644 index 00000000000..574fd142ddb --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_30.sql @@ -0,0 +1,56 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Age Policy Check", "Table", "Prequalification", +"SELECT mc.id, + COALESCE(client_details.client_age, 0) AS client_age, + mc.date_of_birth AS date_of_birth, + CASE + -- CREDITO INDIVIDUAL + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (COALESCE(client_details.client_age, 0) BETWEEN 20 AND 60) THEN 'GREEN' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (COALESCE(client_details.client_age, 0) NOT BETWEEN 20 AND 60) THEN 'RED' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mct.id AS client_id, mct.date_of_birth AS date_of_birth, IFNULL(TIMESTAMPDIFF(YEAR, mct.date_of_birth, CURDATE()), 0) AS client_age + FROM m_client mct + ) client_details ON client_details.client_id = mc.id + WHERE mc.id = ${clientId}", "Age Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_31.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_31.sql new file mode 100644 index 00000000000..8e5fef044bc --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_31.sql @@ -0,0 +1,50 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Amount Policy Check", "Table", "Prequalification", +"SELECT + CASE + -- CREDITO INDIVIDUAL + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'NUEVO') AND (${requestedAmount} NOT BETWEEN 10000 AND 200000) THEN 'RED' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (${requestedAmount} NOT BETWEEN 10000 AND 200000) THEN 'RED' + WHEN (${loanProductId} = 6) AND ('${recreditCategorization}' = 'RECREDITO') AND (mc.status_enum = 300) THEN 'GREEN' + END AS color + FROM m_client mc + WHERE mc.id = ${clientId}", "Amount Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_3_.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_3_.sql new file mode 100644 index 00000000000..e9d238da8bd --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_3_.sql @@ -0,0 +1,82 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Increase percentage Policy Check", "Table", "Prequalification", +"SELECT + CASE + WHEN (${loanProductId} = 2) AND (IFNULL(previous_loans.percentage_increase, 0) = 200) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (IFNULL(previous_loans.percentage_increase, 0) BETWEEN 201 AND 500) THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND (IFNULL(previous_loans.percentage_increase, 0) > 500) THEN 'RED' + WHEN (${loanProductId} = 9) AND (IFNULL(previous_loans.percentage_increase, 0) = 200) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (IFNULL(previous_loans.percentage_increase, 0) BETWEEN 201 AND 500) THEN 'YELLOW' + WHEN (${loanProductId} = 9) AND (IFNULL(previous_loans.percentage_increase, 0) > 500) THEN 'RED' + WHEN (${loanProductId} = 8) AND (IFNULL(previous_loans.percentage_increase, 0) = 200) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (IFNULL(previous_loans.percentage_increase, 0) BETWEEN 201 AND 500) THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND (IFNULL(previous_loans.percentage_increase, 0) > 500) THEN 'RED' + WHEN (${loanProductId} = 4) AND (IFNULL(previous_loans.percentage_increase, 0) <= 60) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND (IFNULL(previous_loans.percentage_increase, 0) > 60) THEN 'ORANGE' + WHEN (${loanProductId} = 5) AND (IFNULL(previous_loans.percentage_increase, 0) <= 60) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND (IFNULL(previous_loans.percentage_increase, 0) > 60) THEN 'ORANGE' + END AS color, + IFNULL(previous_loans.percentage_increase, 0) AS percentage_increase, + IFNULL(previous_loans.principal_disbursed_derived, 0) AS principal_disbursed_derived + FROM m_client mc + LEFT JOIN ( + SELECT (100 *(${requestedAmount} - mln.principal_disbursed_derived) / mln.principal_disbursed_derived) AS percentage_increase, COALESCE(mln.principal_disbursed_derived, 0) AS principal_disbursed_derived, mln.client_id AS client_id, MAX(mln.disbursedon_date) AS disbursedon_date FROM m_loan mln WHERE mln.loan_status_id IN (700, 600, 601, 602) GROUP BY mln.id ORDER BY mln.disbursedon_date DESC + ) previous_loans ON previous_loans.client_id = mc.id + WHERE mc.id = ${clientId} + GROUP BY mc.id", "Increase percentage Policy Check", 0, 0, 0); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Increase percentage Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "clientIdSelectAll"), "clientId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Increase percentage Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "loanProductIdSelectAll"), "loanProductId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Increase percentage Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "OfficeIdSelectOne"), "officeId"); + + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Increase percentage Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "currencyIdSelectAll"), "currencyId"); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_4.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_4.sql new file mode 100644 index 00000000000..d4ce69b9187 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_4.sql @@ -0,0 +1,106 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Mandatory to attach photographs and investment plan Policy Check", "Table", "Prequalification", +"SELECT CASE + -- Banco Comunal + WHEN (${loanProductId} = 2) AND (IFNULL(client_cycles.number_of_loan_cycles, 0) = 0) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (IFNULL(client_years.rejoining_years, 0) >= 1) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (IFNULL(client_closed_loans.number_of_closed_loans, 0) > 0) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (${requestedAmount} > 6000) THEN 'GREEN' + + -- Banco Comunal temporal + WHEN (${loanProductId} = 9) AND (IFNULL(client_cycles.number_of_loan_cycles, 0) = 0) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (IFNULL(client_years.rejoining_years, 0) >= 1) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (IFNULL(client_closed_loans.number_of_closed_loans, 0) > 0) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (${requestedAmount} > 6000) THEN 'GREEN' + + -- Banco Comunal Agricola + WHEN (${loanProductId} = 8) AND (IFNULL( client_years.number_of_documents, 0) > 0) THEN 'GREEN' + + -- Grupo Solidario + WHEN (${loanProductId} = 4) AND (IFNULL( client_years.number_of_documents, 0) > 0) THEN 'GREEN' + + -- Grupo Solidario Agricola + WHEN (${loanProductId} = 5) AND (IFNULL( client_years.number_of_documents, 0) > 0) THEN 'GREEN' + + -- Paralelo + WHEN (${loanProductId} = 7) AND (IFNULL( client_years.number_of_documents, 0) >= 4) THEN 'GREEN' + + ELSE 'RED' + END AS color, + client_years.submittedon_years, + client_years.rejoining_years, + client_cycles.number_of_loan_cycles, + client_closed_loans.number_of_closed_loans, + client_years.number_of_documents + FROM m_client mc + LEFT JOIN ( + SELECT mcl.id AS client_id, + TIMESTAMPDIFF(YEAR, mcl.submittedon_date, CURDATE()) AS submittedon_years, + IFNULL(TIMESTAMPDIFF(YEAR, mcl.submittedon_date, mcl.reactivated_on_date), 0) AS rejoining_years, + (SELECT COUNT(*) FROM m_document md WHERE md.parent_entity_id = ${clientId} AND md.parent_entity_type ='clients') AS number_of_documents + FROM m_client mcl + )client_years ON client_years.client_id = mc.id + LEFT JOIN ( + SELECT COALESCE(MAX(mcl.loan_counter), 0) AS number_of_loan_cycles , mcl.client_id AS client_id FROM m_loan mcl GROUP BY mcl.client_id + )client_cycles ON client_cycles.client_id = mc.id + LEFT JOIN ( + SELECT COALESCE(COUNT(*), 0) AS number_of_closed_loans, mln.client_id AS client_id FROM m_loan mln WHERE mln.loan_status_id IN (700, 600, 602, 601) GROUP BY mln.client_id + ) client_closed_loans ON client_closed_loans.client_id = mc.id + WHERE mc.id = ${clientId} + GROUP BY mc.id", "Mandatory to attach photographs and investment plan Policy Check", 0, 0, 0); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Mandatory to attach photographs and investment plan Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "clientIdSelectAll"), "clientId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Mandatory to attach photographs and investment plan Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "loanProductIdSelectAll"), "loanProductId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Mandatory to attach photographs and investment plan Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "OfficeIdSelectOne"), "officeId"); + + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Mandatory to attach photographs and investment plan Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "currencyIdSelectAll"), "currencyId"); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_5.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_5.sql new file mode 100644 index 00000000000..486764a3716 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_5.sql @@ -0,0 +1,118 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Client age Policy Check", "Table", "Prequalification", +"SELECT mc.id, + client_age.client_age AS client_age, + mc.date_of_birth AS date_of_birth, + CASE + -- Banco Comunal normal + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + -- Banco Comunal temporal + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + + -- Banco Comunal Agricola + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + + -- Grupo Solidario + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + + -- Grupo Solidario Agricola + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + ELSE 'GREEN' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mct.id AS client_id, mct.date_of_birth AS date_of_birth, IFNULL(TIMESTAMPDIFF(YEAR, mct.date_of_birth, CURDATE()), 0) AS client_age + FROM m_client mct + ) client_age ON client_age.client_id = mc.id + WHERE mc.id = ${clientId}", "Client Age Hard Policy Check", 0, 0, 0); + +INSERT INTO stretchy_parameter +(parameter_name, parameter_variable, parameter_label, parameter_displayType, parameter_FormatType, parameter_default, special, selectOne, selectAll, parameter_sql, parent_id) +VALUES('clientCategorization', 'clientCategorization', 'Client Categorization', 'select', 'string', 'NEW', NULL, 'Y', NULL, 'SELECT ''NEW'' AS id, ''New'' AS name +UNION ALL +SELECT ''RECURRING'' AS id, ''Recurring'' AS name', NULL); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client age Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "clientCategorization"), "clientCategorization"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client age Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "clientIdSelectAll"), "clientId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client age Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "loanProductIdSelectAll"), "loanProductId"); + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client age Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "OfficeIdSelectOne"), "officeId"); + + +INSERT INTO stretchy_report_parameter +(report_id, parameter_id, report_parameter_name) +VALUES((SELECT sr.id FROM stretchy_report sr WHERE sr.report_name = "Client age Policy Check"), (SELECT p.id FROM stretchy_parameter p WHERE parameter_name = "currencyIdSelectAll"), "currencyId"); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_6.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_6.sql new file mode 100644 index 00000000000..59d73ca7d27 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_6.sql @@ -0,0 +1,77 @@ +-- +-- 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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Number of members according to policy Policy Check", "Table", "Prequalification", +"SELECT + prequalification_details.recreditCategorization, + mpg.previous_prequalification, + CASE + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 7) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 7) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 10) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 10) THEN 'GREEN' + + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 4) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} < 4) THEN 'ORANGE' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 4) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} < 4) THEN 'ORANGE' + + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 7) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} < 7) THEN 'ORANGE' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 7) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} < 7) THEN 'ORANGE' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 10) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} < 10) THEN 'ORANGE' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 10) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} < 10) THEN 'ORANGE' + + WHEN (${loanProductId} = 4) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 4) THEN 'GREEN' + + WHEN (${loanProductId} = 5) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${numberOfMembers} >= 3) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${numberOfMembers} >= 4) THEN 'GREEN' + END AS color + FROM m_prequalification_group mpg + INNER JOIN ( + SELECT p.id AS prequalification_id, + (CASE WHEN p.previous_prequalification IS NOT NULL THEN 'RECREDITO' ELSE 'NUEVO' END) AS recreditCategorization + FROM m_prequalification_group p + ) prequalification_details ON prequalification_details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "Client Age Hard Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_7.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_7.sql new file mode 100644 index 00000000000..68921e9d2a2 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_7.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 */; + +-- Client Age Hard Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Minimum and maximum amount Policy Check", "Table", "Prequalification", +"SELECT + prequalification_details.recreditCategorization, + CASE + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 1500 AND 5000) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 1500 AND 15000) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 1500 AND 5000) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 1500 AND 15000) THEN 'GREEN' + + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 1500 AND 15000) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 1500 AND 15000) THEN 'GREEN' + + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 1000 AND 4999) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 1000 AND 20000) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 1000 AND 4999) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 1000 AND 20000) THEN 'GREEN' + + WHEN (${loanProductId} = 4) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 6000 AND 20000) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 6000 AND 20000) THEN 'GREEN' + + WHEN (${loanProductId} = 5) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${requestedAmount} BETWEEN 5000 AND 20000) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${requestedAmount} BETWEEN 5000 AND 20000) THEN 'GREEN' + END AS color + FROM m_prequalification_group mpg + INNER JOIN ( + SELECT p.id AS prequalification_id, + (CASE WHEN p.previous_prequalification IS NOT NULL THEN 'RECREDITO' ELSE 'NUEVO' END) AS recreditCategorization + FROM m_prequalification_group p + ) prequalification_details ON prequalification_details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "Client Age Hard Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_8.sql b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_8.sql new file mode 100644 index 00000000000..ddf416f99db --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/commands/policy_run_8.sql @@ -0,0 +1,74 @@ +-- +-- 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 */; + +-- External Credit History Policy Check -- +INSERT INTO stretchy_report (report_name,report_type,report_category,report_sql,description,core_report,use_report,self_service_user_report) +VALUES ("Value disparity Policy Check", "Table", "Prequalification", +"SELECT + prequalification_details.recreditCategorization, + CASE + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} > 3) THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} BETWEEN 1 AND 4) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} > 4) THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} > 3) THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} BETWEEN 1 AND 4) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} > 4) THEN 'YELLOW' + + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} > 3) THEN 'YELLOW' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} > 3) THEN 'YELLOW' + + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} > 3) THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'URBAN') AND (${disparityRatio} > 3) THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'NUEVO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} > 3) THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} BETWEEN 1 AND 3) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND (prequalification_details.recreditCategorization = 'RECREDITO') AND ('${clientArea}' = 'RURAL') AND (${disparityRatio} > 3) THEN 'YELLOW' + END AS color + FROM m_prequalification_group mpg + INNER JOIN ( + SELECT p.id AS prequalification_id, + (CASE WHEN p.previous_prequalification IS NOT NULL THEN 'RECREDITO' ELSE 'NUEVO' END) AS recreditCategorization + FROM m_prequalification_group p + ) prequalification_details ON prequalification_details.prequalification_id = mpg.id + WHERE mpg.id = ${prequalificationId}", "Value disparity Policy Check", 0, 0, 0); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0094_FBR_327_Add_committees_permissions.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0094_FBR_327_Add_committees_permissions.xml index 25444508ec7..459da5e5a5c 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0094_FBR_327_Add_committees_permissions.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0094_FBR_327_Add_committees_permissions.xml @@ -52,4 +52,14 @@ + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0098_Alter_table_prequalification_group.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0098_Alter_table_prequalification_group.xml new file mode 100644 index 00000000000..67bbceaf3c9 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0098_Alter_table_prequalification_group.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0099_Create_Groups_and_Prequalification_Relationship.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0099_Create_Groups_and_Prequalification_Relationship.xml new file mode 100644 index 00000000000..8cd358c73aa --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0099_Create_Groups_and_Prequalification_Relationship.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0100_FBR_348_create_prequalification_status_range.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0100_FBR_348_create_prequalification_status_range.xml new file mode 100644 index 00000000000..68b142abf74 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0100_FBR_348_create_prequalification_status_range.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO m_prequalification_status_range(prequalification_type_enum, min_amount, max_amount, min_error, max_error, status) + VALUES (1, 0, 20000.00, 0, 0, 1003) + + + INSERT INTO m_prequalification_status_range(prequalification_type_enum, min_amount, max_amount, min_error, max_error, status) + VALUES (1, 20000.00, 75000.00, 0, 0, 1004) + + + INSERT INTO m_prequalification_status_range(prequalification_type_enum, min_amount, min_error, max_error, status) + VALUES (1, 75000.00, 0, 0, 1005) + + + INSERT INTO m_prequalification_status_range(prequalification_type_enum, min_amount, max_amount, min_error, max_error, status) + VALUES (1, 0.00, 75000.00, 1, 1, 1004) + + + INSERT INTO m_prequalification_status_range(prequalification_type_enum, min_amount, min_error, max_error, status) + VALUES (1, 75000.00, 1, 1, 1005) + + + INSERT INTO m_prequalification_status_range(prequalification_type_enum, min_amount, max_amount, min_error, max_error, status) + VALUES (1, 0.00, 0.00, 2, 999, 1005) + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0101_FBR-352-group_client_collection_reports.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0101_FBR-352-group_client_collection_reports.xml index 643852682f9..d4d88b42962 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0101_FBR-352-group_client_collection_reports.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0101_FBR-352-group_client_collection_reports.xml @@ -103,7 +103,6 @@ ) client_loan ON client_loan.client_id = ml.client_id WHERE (ml.submittedon_date BETWEEN ''${submittedOnStartDate}'' AND ''${submittedOnEndDate}'') AND (ml.fund_id = ''${fundId}'' OR ''-1'' = ''${fundId}'') AND (mgc.client_id IS NOT NULL) GROUP BY group_client.id - UNION ALL SELECT mc.id AS clientId, diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0102_FBR_366_Add_sub_status_prequalifications.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0102_FBR_366_Add_sub_status_prequalifications.xml new file mode 100644 index 00000000000..dc3fdc1d4bd --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0102_FBR_366_Add_sub_status_prequalifications.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0103_FBR_372_hard_policy_check_sql_redesign.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0103_FBR_372_hard_policy_check_sql_redesign.xml new file mode 100644 index 00000000000..34bb5399d14 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0103_FBR_372_hard_policy_check_sql_redesign.xml @@ -0,0 +1,499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPDATE stretchy_report SET report_sql = "SELECT mc.id, + client_age.client_age AS client_age, + mc.date_of_birth AS date_of_birth, + CASE + -- Banco Comunal normal + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 2) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + -- Banco Comunal temporal + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 9) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + + -- Banco Comunal Agricola + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 8) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + + -- Grupo Solidario + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 4) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + + + -- Grupo Solidario Agricola + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 70) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) BETWEEN 71 AND 75) THEN 'YELLOW' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'NEW') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) BETWEEN 18 AND 75) THEN 'GREEN' + WHEN (${loanProductId} = 5) AND ('${clientCategorization}' = 'RECURRING') AND (IFNULL(client_age.client_age, 0) NOT BETWEEN 18 AND 75) THEN 'RED' + END AS color + FROM m_client mc + INNER JOIN ( + SELECT mct.id AS client_id, mct.date_of_birth AS date_of_birth, IFNULL(TIMESTAMPDIFF(YEAR, mct.date_of_birth, CURDATE()), 0) AS client_age + FROM m_client mct + ) client_age ON client_age.client_id = mc.id + WHERE mc.id = ${clientId}" WHERE report_name = "Client age Policy Check"; + + + + + + id='22' + + + + + + + + + + + + + + + + + + + + + + + + + + 0) THEN 'RECURRING' + WHEN (${loanProductId} = 2) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 2) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1 OR IFNULL(client_loan_details.number_of_closed_loans, 0) <= 2) THEN 'NEW' + + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) > 0) THEN 'RECURRING' + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 9) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) > 0) THEN 'RECURRING' + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 8) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 3) THEN 'RECURRING' + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 4) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 3) THEN 'RECURRING' + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.number_of_loan_cycles, 0) = 0) THEN 'NEW' + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.rejoining_years, 0) >= 1) THEN 'NEW' + WHEN (${loanProductId} = 5) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) > 0) THEN 'NEW' + + WHEN (${loanProductId} = 7) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 3) THEN 'RECURRING' + WHEN (${loanProductId} = 7) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) = 2) THEN 'RECURRING' + WHEN (${loanProductId} = 7) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) < 2) THEN 'RECURRING' + + WHEN (${loanProductId} = 3) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) >= 1) THEN 'RECURRING' + WHEN (${loanProductId} = 3) AND (IFNULL(client_loan_details.number_of_closed_loans, 0) = 0) THEN 'RECURRING' + + ELSE 'NEW' + END AS clientCategorization, + 'GREEN' AS color, + CASE + WHEN client_area.code_value = 'Urbana' THEN 'URBANA' + WHEN client_area.code_value = 'Rural' THEN 'RURAL' + WHEN client_area.code_value = 'PeriUrbana' THEN 'PERI_URBANA' + ELSE 'RURAL' + END AS clientArea, + CASE + WHEN COALESCE(client_loan_details.number_of_submitted_loans, 0) > 0 THEN 'RECREDITO' + ELSE 'NUEVO' + END AS recreditCategorization, + client_loan_details.submittedon_years, + client_loan_details.rejoining_years, + client_loan_details.number_of_loan_cycles, + client_loan_details.number_of_closed_loans, + client_loan_details.number_of_submitted_loans + FROM m_client mc + INNER JOIN ( + SELECT mcl.id AS client_id, + TIMESTAMPDIFF(YEAR, mcl.submittedon_date, CURDATE()) AS submittedon_years, + IFNULL(TIMESTAMPDIFF(YEAR, mcl.submittedon_date, mcl.reactivated_on_date), 0) AS rejoining_years, + COALESCE((SELECT COUNT(*) FROM m_loan WHERE client_id = mcl.id AND approvedon_date IS NOT NULL), 0) AS number_of_loan_cycles, + COALESCE((SELECT COUNT(*) FROM m_loan WHERE client_id = mcl.id AND loan_status_id >= 600), 0) AS number_of_closed_loans, + COALESCE((SELECT COUNT(*) FROM m_loan WHERE client_id = mcl.id AND loan_status_id = 100), 0) AS number_of_submitted_loans + FROM m_client mcl + )client_loan_details ON client_loan_details.client_id = mc.id + LEFT JOIN m_client_contact_info mcci ON mcci.client_id = mc.id + LEFT JOIN m_code_value client_area ON client_area.id = mcci.area + WHERE mc.id = ${clientId} + GROUP BY mc.id" WHERE report_name = "Client Categorization Policy Check"; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0104_FBR_369_create_charge_admin_fee_configurations.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0104_FBR_369_create_charge_admin_fee_configurations.xml new file mode 100644 index 00000000000..65cfb373f3b --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0104_FBR_369_create_charge_admin_fee_configurations.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0105_FBR_395_alter_bank_table.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0105_FBR_395_alter_bank_table.xml new file mode 100644 index 00000000000..7b21c9a72ec --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0105_FBR_395_alter_bank_table.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0106_Add_Prequalification_Permissions.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0106_Add_Prequalification_Permissions.xml new file mode 100644 index 00000000000..4ea8cc58360 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0106_Add_Prequalification_Permissions.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + +