FINERACT-1760: Enhanced external id support for loan
This commit is contained in:
+3
-1
@@ -42,7 +42,9 @@ import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.DateSe
|
||||
import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOptionDataValueSerializer;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData;
|
||||
@@ -140,7 +142,7 @@ public class LoanImportHandler implements ImportHandler {
|
||||
|
||||
private LoanAccountData readLoan(final Workbook workbook, final Row row, final List<String> statuses, final String locale,
|
||||
final String dateFormat) {
|
||||
String externalId = ImportHandlerUtils.readAsString(LoanConstants.EXTERNAL_ID_COL, row);
|
||||
ExternalId externalId = ExternalIdFactory.produce(ImportHandlerUtils.readAsString(LoanConstants.EXTERNAL_ID_COL, row));
|
||||
String status = ImportHandlerUtils.readAsString(LoanConstants.STATUS_COL, row);
|
||||
String productName = ImportHandlerUtils.readAsString(LoanConstants.PRODUCT_COL, row);
|
||||
Long productId = ImportHandlerUtils.getIdByName(workbook.getSheet(TemplatePopulateImportConstants.PRODUCT_SHEET_NAME), productName);
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class LoanDelinquencyRangeChangeBusinessEventSerializer extends AbstractB
|
||||
LoanAccountData data = service.retrieveOne(event.get().getId());
|
||||
Long id = data.getId();
|
||||
String accountNumber = data.getAccountNo();
|
||||
String externalId = data.getExternalId();
|
||||
String externalId = data.getExternalId().getValue();
|
||||
DelinquencyRangeDataV1 delinquencyRange = mapper.map(data.getDelinquencyRange());
|
||||
return new LoanAccountDelinquencyRangeDataV1(id, accountNumber, externalId, delinquencyRange);
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class LoanRepaymentBusinessEventSerializer extends AbstractBusinessEventS
|
||||
Loan loan = repaymentInstallment.getLoan();
|
||||
Long id = loan.getId();
|
||||
String accountNo = loan.getAccountNumber();
|
||||
String externalId = loan.getExternalId();
|
||||
String externalId = loan.getExternalId().getValue();
|
||||
String dueDate = dataTimeMapper.mapLocalDate(repaymentInstallment.getDueDate());
|
||||
MonetaryCurrency loanCurrency = loan.getCurrency();
|
||||
CurrencyDataV1 currency = CurrencyDataV1.newBuilder().setCode(loanCurrency.getCode())
|
||||
|
||||
+2
-1
@@ -163,7 +163,8 @@ public class DelinquencyWritePlatformServiceImpl implements DelinquencyWritePlat
|
||||
final CollectionData collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan);
|
||||
changes = lookUpDelinquencyRange(loan, delinquencyBucket, collectionData.getDelinquentDays());
|
||||
}
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loan.getId()).with(changes).build();
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loan.getId())
|
||||
.withEntityExternalId(loan.getExternalId()).with(changes).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -560,7 +560,7 @@ public class LoanChargesApiResource {
|
||||
Long resolvedLoanId = loanId;
|
||||
if (resolvedLoanId == null) {
|
||||
loanExternalId.throwExceptionIfEmpty();
|
||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId.getValue());
|
||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
||||
if (resolvedLoanId == null) {
|
||||
throw new LoanNotFoundException(loanExternalId);
|
||||
}
|
||||
|
||||
+1
-1
@@ -587,7 +587,7 @@ public class LoanTransactionsApiResource {
|
||||
Long resolvedLoanId = loanId;
|
||||
if (resolvedLoanId == null) {
|
||||
loanExternalId.throwExceptionIfEmpty();
|
||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId.getValue());
|
||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
||||
if (resolvedLoanId == null) {
|
||||
throw new LoanNotFoundException(loanExternalId);
|
||||
}
|
||||
|
||||
+504
-354
@@ -73,11 +73,13 @@ import org.apache.fineract.infrastructure.core.api.JsonQuery;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.data.UploadRequest;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.CommandParameterUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant;
|
||||
@@ -127,6 +129,7 @@ import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTemplateTypeRequiredException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.NotSupportedLoanTemplateTypeException;
|
||||
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
|
||||
@@ -282,24 +285,12 @@ public class LoansApiResource {
|
||||
@Path("{loanId}/template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveApprovalTemplate(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.GetLoansApprovalTemplateResponse.class))) })
|
||||
public String retrieveApprovalTemplate(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@QueryParam("templateType") @Parameter(description = "templateType") final String templateType,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
LoanApprovalData loanApprovalTemplate = null;
|
||||
|
||||
if (templateType == null) {
|
||||
final String errorMsg = "Loan template type must be provided";
|
||||
throw new LoanTemplateTypeRequiredException(errorMsg);
|
||||
} else if (templateType.equals("approval")) {
|
||||
loanApprovalTemplate = this.loanReadPlatformService.retrieveApprovalTemplate(loanId);
|
||||
}
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.loanApprovalDataToApiJsonSerializer.serialize(settings, loanApprovalTemplate, LOAN_APPROVAL_DATA_PARAMETERS);
|
||||
|
||||
return retrieveApprovalTemplate(loanId, null, templateType, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -376,7 +367,7 @@ public class LoansApiResource {
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
|
||||
newLoanAccount = newLoanAccount == null ? loanAccountGroupData
|
||||
: LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData);
|
||||
accountLinkingOptions = getaccountLinkingOptions(newLoanAccount, clientId, groupId);
|
||||
accountLinkingOptions = getAccountLinkingOptions(newLoanAccount, clientId, groupId);
|
||||
|
||||
} else if (templateType.equals("jlgbulk")) {
|
||||
// get group details along with members in that group
|
||||
@@ -393,7 +384,7 @@ public class LoansApiResource {
|
||||
for (ClientData clientData : members) {
|
||||
Integer loanCounter = this.loanReadPlatformService.retriveLoanCounter(clientData.getId(), productId);
|
||||
memberLoanCycle.put(clientData.getId(), loanCounter);
|
||||
accountLinkingOptions.addAll(getaccountLinkingOptions(newLoanAccount, clientData.getId(), groupId));
|
||||
accountLinkingOptions.addAll(getAccountLinkingOptions(newLoanAccount, clientData.getId(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +399,7 @@ public class LoansApiResource {
|
||||
allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(officeId, staffInSelectedOfficeOnly);
|
||||
|
||||
if (clientId != null) {
|
||||
accountLinkingOptions = getaccountLinkingOptions(newLoanAccount, clientId, groupId);
|
||||
accountLinkingOptions = getAccountLinkingOptions(newLoanAccount, clientId, groupId);
|
||||
}
|
||||
|
||||
// add product options, allowed loan officers and calendar options
|
||||
@@ -424,7 +415,7 @@ public class LoansApiResource {
|
||||
return this.toApiJsonSerializer.serialize(settings, newLoanAccount, LOAN_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
private Collection<PortfolioAccountData> getaccountLinkingOptions(final LoanAccountData newLoanAccount, final Long clientId,
|
||||
private Collection<PortfolioAccountData> getAccountLinkingOptions(final LoanAccountData newLoanAccount, final Long clientId,
|
||||
final Long groupId) {
|
||||
final CurrencyData currencyData = newLoanAccount.getCurrency();
|
||||
String currencyCode = null;
|
||||
@@ -450,289 +441,14 @@ public class LoansApiResource {
|
||||
+ "loans/1?fields=id,principal,annualInterestRate&associations=repaymentSchedule,transactions")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.GetLoansLoanIdResponse.class))) })
|
||||
public String retrieveLoan(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
public String retrieveLoan(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
|
||||
@DefaultValue("all") @QueryParam("associations") @Parameter(in = ParameterIn.QUERY, name = "associations", description = "Loan object relations to be included in the response", required = false, examples = {
|
||||
@ExampleObject(value = "all"), @ExampleObject(value = "repaymentSchedule,transactions") }) final String associations,
|
||||
@QueryParam("exclude") @Parameter(in = ParameterIn.QUERY, name = "exclude", description = "Optional Loan object relation list to be filtered in the response", required = false, example = "guarantors,futureSchedule") final String exclude,
|
||||
@QueryParam("fields") @Parameter(in = ParameterIn.QUERY, name = "fields", description = "Optional Loan attribute list to be in the response", required = false, example = "id,principal,annualInterestRate") final String fields,
|
||||
@Context final UriInfo uriInfo) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId);
|
||||
if (loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||
Collection<CalendarData> interestRecalculationCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(
|
||||
loanBasicDetails.getInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue(),
|
||||
null);
|
||||
CalendarData calendarData = null;
|
||||
if (!CollectionUtils.isEmpty(interestRecalculationCalendarDatas)) {
|
||||
calendarData = interestRecalculationCalendarDatas.iterator().next();
|
||||
}
|
||||
|
||||
Collection<CalendarData> interestRecalculationCompoundingCalendarDatas = this.calendarReadPlatformService
|
||||
.retrieveCalendarsByEntity(loanBasicDetails.getInterestRecalculationDetailId(),
|
||||
CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue(), null);
|
||||
CalendarData compoundingCalendarData = null;
|
||||
if (!CollectionUtils.isEmpty(interestRecalculationCompoundingCalendarDatas)) {
|
||||
compoundingCalendarData = interestRecalculationCompoundingCalendarDatas.iterator().next();
|
||||
}
|
||||
loanBasicDetails = LoanAccountData.withInterestRecalculationCalendarData(loanBasicDetails, calendarData,
|
||||
compoundingCalendarData);
|
||||
}
|
||||
if (loanBasicDetails.getRepaymentFrequencyType() != null
|
||||
&& loanBasicDetails.getRepaymentFrequencyType().getId().intValue() == PeriodFrequencyType.MONTHS.getValue()) {
|
||||
Collection<CalendarData> loanCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(loanId,
|
||||
CalendarEntityType.LOANS.getValue(), null);
|
||||
CalendarData calendarData = null;
|
||||
if (!CollectionUtils.isEmpty(loanCalendarDatas)) {
|
||||
calendarData = loanCalendarDatas.iterator().next();
|
||||
}
|
||||
if (calendarData != null) {
|
||||
loanBasicDetails = LoanAccountData.withLoanCalendarData(loanBasicDetails, calendarData);
|
||||
}
|
||||
}
|
||||
Collection<InterestRatePeriodData> interestRatesPeriods = this.loanReadPlatformService
|
||||
.retrieveLoanInterestRatePeriodData(loanBasicDetails);
|
||||
Collection<LoanTransactionData> loanRepayments = null;
|
||||
LoanScheduleData repaymentSchedule = null;
|
||||
Collection<LoanChargeData> charges = null;
|
||||
Collection<GuarantorData> guarantors = null;
|
||||
CalendarData meeting = null;
|
||||
Collection<NoteData> notes = null;
|
||||
PortfolioAccountData linkedAccount = null;
|
||||
Collection<DisbursementData> disbursementData = null;
|
||||
Collection<LoanTermVariationsData> emiAmountVariations = null;
|
||||
Collection<LoanCollateralResponseData> loanCollateralManagements;
|
||||
Collection<LoanCollateralManagementData> loanCollateralManagementData = new ArrayList<>();
|
||||
CollectionData collectionData = CollectionData.template();
|
||||
|
||||
final Set<String> mandatoryResponseParameters = new HashSet<>();
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
final Collection<LoanTransactionData> currentLoanRepayments = this.loanReadPlatformService.retrieveLoanTransactions(loanId);
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains(DataTableApiConstant.allAssociateParamName)) {
|
||||
associationParameters.addAll(Arrays.asList(DataTableApiConstant.repaymentScheduleAssociateParamName,
|
||||
DataTableApiConstant.futureScheduleAssociateParamName, DataTableApiConstant.originalScheduleAssociateParamName,
|
||||
DataTableApiConstant.transactionsAssociateParamName, DataTableApiConstant.chargesAssociateParamName,
|
||||
DataTableApiConstant.guarantorsAssociateParamName, DataTableApiConstant.collateralAssociateParamName,
|
||||
DataTableApiConstant.notesAssociateParamName, DataTableApiConstant.linkedAccountAssociateParamName,
|
||||
DataTableApiConstant.multiDisburseDetailsAssociateParamName, DataTableApiConstant.collectionAssociateParamName));
|
||||
}
|
||||
|
||||
ApiParameterHelper.excludeAssociationsForResponseIfProvided(exclude, associationParameters);
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.guarantorsAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.guarantorsAssociateParamName);
|
||||
guarantors = this.guarantorReadPlatformService.retrieveGuarantorsForLoan(loanId);
|
||||
if (CollectionUtils.isEmpty(guarantors)) {
|
||||
guarantors = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.transactionsAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.transactionsAssociateParamName);
|
||||
if (!CollectionUtils.isEmpty(currentLoanRepayments)) {
|
||||
loanRepayments = currentLoanRepayments;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.multiDisburseDetailsAssociateParamName)
|
||||
|| associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.multiDisburseDetailsAssociateParamName);
|
||||
disbursementData = this.loanReadPlatformService.retrieveLoanDisbursementDetails(loanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.emiAmountVariationsAssociateParamName)
|
||||
|| associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.emiAmountVariationsAssociateParamName);
|
||||
emiAmountVariations = this.loanReadPlatformService.retrieveLoanTermVariations(loanId,
|
||||
LoanTermVariationType.EMI_AMOUNT.getValue());
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.repaymentScheduleAssociateParamName);
|
||||
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.getTimeline()
|
||||
.repaymentScheduleRelatedData(loanBasicDetails.getCurrency(), loanBasicDetails.getPrincipal(),
|
||||
loanBasicDetails.getApprovedPrincipal(), loanBasicDetails.getInArrearsTolerance(),
|
||||
loanBasicDetails.getFeeChargesAtDisbursementCharged());
|
||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, repaymentScheduleRelatedData,
|
||||
disbursementData, loanBasicDetails.isInterestRecalculationEnabled(),
|
||||
loanBasicDetails.getSummary() != null ? loanBasicDetails.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName)
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.futureScheduleAssociateParamName);
|
||||
this.calculationPlatformService.updateFutureSchedule(repaymentSchedule, loanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.originalScheduleAssociateParamName)
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled()
|
||||
&& LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName);
|
||||
LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService.retrieveRepaymentArchiveSchedule(loanId,
|
||||
repaymentScheduleRelatedData, disbursementData);
|
||||
loanBasicDetails = LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData);
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.chargesAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.chargesAssociateParamName);
|
||||
charges = this.loanChargeReadPlatformService.retrieveLoanCharges(loanId);
|
||||
if (CollectionUtils.isEmpty(charges)) {
|
||||
charges = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.collateralAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.collateralAssociateParamName);
|
||||
loanCollateralManagements = this.loanCollateralManagementReadPlatformService.getLoanCollateralResponseDataList(loanId);
|
||||
for (LoanCollateralResponseData loanCollateralManagement : loanCollateralManagements) {
|
||||
loanCollateralManagementData.add(loanCollateralManagement.toCommand());
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.meetingAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.meetingAssociateParamName);
|
||||
meeting = this.calendarReadPlatformService.retrieveLoanCalendar(loanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.notesAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.notesAssociateParamName);
|
||||
notes = this.noteReadPlatformService.retrieveNotesByResource(loanId, NoteType.LOAN.getValue());
|
||||
if (CollectionUtils.isEmpty(notes)) {
|
||||
notes = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.linkedAccountAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName);
|
||||
linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.collectionAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.collectionAssociateParamName);
|
||||
if (loanBasicDetails.isActive()) {
|
||||
collectionData = this.delinquencyReadPlatformService.calculateLoanCollectionData(loanId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<LoanProductData> productOptions = null;
|
||||
LoanProductData product;
|
||||
Collection<EnumOptionData> loanTermFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> repaymentFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> repaymentFrequencyNthDayTypeOptions = null;
|
||||
Collection<EnumOptionData> repaymentFrequencyDayOfWeekTypeOptions = null;
|
||||
Collection<TransactionProcessingStrategyData> repaymentStrategyOptions = null;
|
||||
Collection<EnumOptionData> interestRateFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> amortizationTypeOptions = null;
|
||||
Collection<EnumOptionData> interestTypeOptions = null;
|
||||
Collection<EnumOptionData> interestCalculationPeriodTypeOptions = null;
|
||||
Collection<FundData> fundOptions = null;
|
||||
Collection<StaffData> allowedLoanOfficers = null;
|
||||
Collection<ChargeData> chargeOptions = null;
|
||||
ChargeData chargeTemplate = null;
|
||||
Collection<CodeValueData> loanPurposeOptions = null;
|
||||
Collection<CodeValueData> loanCollateralOptions = null;
|
||||
Collection<CalendarData> calendarOptions = null;
|
||||
Collection<PortfolioAccountData> accountLinkingOptions = null;
|
||||
PaidInAdvanceData paidInAdvanceTemplate;
|
||||
Collection<LoanAccountSummaryData> clientActiveLoanOptions = null;
|
||||
|
||||
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
if (template) {
|
||||
productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup();
|
||||
product = this.loanProductReadPlatformService.retrieveLoanProduct(loanBasicDetails.getLoanProductId());
|
||||
loanBasicDetails.setProduct(product);
|
||||
loanTermFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
|
||||
repaymentFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
|
||||
repaymentFrequencyNthDayTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyOptionsForNthDayOfMonth();
|
||||
repaymentFrequencyDayOfWeekTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyOptionsForDaysOfWeek();
|
||||
interestRateFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions();
|
||||
|
||||
amortizationTypeOptions = this.dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions();
|
||||
if (product.isLinkedToFloatingInterestRates()) {
|
||||
interestTypeOptions = Collections.singletonList(interestType(InterestMethod.DECLINING_BALANCE));
|
||||
} else {
|
||||
interestTypeOptions = this.dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
|
||||
}
|
||||
interestCalculationPeriodTypeOptions = this.dropdownReadPlatformService.retrieveLoanInterestRateCalculatedInPeriodOptions();
|
||||
|
||||
fundOptions = this.fundReadPlatformService.retrieveAllFunds();
|
||||
repaymentStrategyOptions = this.dropdownReadPlatformService.retrieveTransactionProcessingStrategies();
|
||||
if (product.getMultiDisburseLoan()) {
|
||||
chargeOptions = this.chargeReadPlatformService.retrieveLoanAccountApplicableCharges(loanId,
|
||||
new ChargeTimeType[] { ChargeTimeType.OVERDUE_INSTALLMENT });
|
||||
} else {
|
||||
chargeOptions = this.chargeReadPlatformService.retrieveLoanAccountApplicableCharges(loanId,
|
||||
new ChargeTimeType[] { ChargeTimeType.OVERDUE_INSTALLMENT, ChargeTimeType.TRANCHE_DISBURSEMENT });
|
||||
}
|
||||
chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate();
|
||||
|
||||
Long officeId = loanBasicDetails.getClientOfficeId();
|
||||
|
||||
if (officeId == null && loanBasicDetails.getGroup() != null) {
|
||||
officeId = loanBasicDetails.getGroup().getOfficeId();
|
||||
}
|
||||
allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(officeId, staffInSelectedOfficeOnly);
|
||||
|
||||
loanPurposeOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanPurpose");
|
||||
loanCollateralOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanCollateral");
|
||||
final CurrencyData currencyData = loanBasicDetails.getCurrency();
|
||||
String currencyCode = null;
|
||||
if (currencyData != null) {
|
||||
currencyCode = currencyData.getCode();
|
||||
}
|
||||
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
|
||||
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(),
|
||||
loanBasicDetails.getClientId(), currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue());
|
||||
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
|
||||
|
||||
if (!associationParameters.contains(DataTableApiConstant.linkedAccountAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName);
|
||||
linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId);
|
||||
}
|
||||
if (loanBasicDetails.getGroup() != null && loanBasicDetails.getGroup().getId() != null) {
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.getGroup().getId());
|
||||
}
|
||||
|
||||
if (loanBasicDetails.getProduct().isCanUseForTopup() && loanBasicDetails.getClientId() != null) {
|
||||
clientActiveLoanOptions = this.accountDetailsReadPlatformService
|
||||
.retrieveClientActiveLoanAccountSummary(loanBasicDetails.getClientId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Collection<ChargeData> overdueCharges = this.chargeReadPlatformService
|
||||
.retrieveLoanProductCharges(loanBasicDetails.getLoanProductId(), ChargeTimeType.OVERDUE_INSTALLMENT);
|
||||
|
||||
paidInAdvanceTemplate = this.loanReadPlatformService.retrieveTotalPaidInAdvance(loanId);
|
||||
|
||||
// Get rates from Loan
|
||||
boolean isRatesEnabled = this.configurationDomainService.isSubRatesEnabled();
|
||||
List<RateData> rates = null;
|
||||
if (isRatesEnabled) {
|
||||
rates = this.rateReadService.retrieveLoanRates(loanId);
|
||||
}
|
||||
|
||||
// updating summary with transaction amounts summary
|
||||
if (loanBasicDetails.getSummary() != null) {
|
||||
loanBasicDetails
|
||||
.setSummary(LoanSummaryData.withTransactionAmountsSummary(loanBasicDetails.getSummary(), currentLoanRepayments));
|
||||
}
|
||||
|
||||
final LoanAccountData loanAccount = LoanAccountData.associationsAndTemplate(loanBasicDetails, repaymentSchedule, loanRepayments,
|
||||
charges, loanCollateralManagementData, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions,
|
||||
repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions,
|
||||
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
|
||||
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions,
|
||||
loanCollateralOptions, calendarOptions, notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations,
|
||||
overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled,
|
||||
collectionData);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
|
||||
mandatoryResponseParameters);
|
||||
return this.toApiJsonSerializer.serialize(settings, loanAccount, LOAN_DATA_PARAMETERS);
|
||||
return retrieveLoan(loanId, null, staffInSelectedOfficeOnly, exclude, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -807,20 +523,10 @@ public class LoansApiResource {
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PutLoansLoanIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PutLoansLoanIdResponse.class))) })
|
||||
public String modifyLoanApplication(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
public String modifyLoanApplication(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
CommandWrapper commandRequest = null;
|
||||
if (CommandParameterUtil.is(commandParam, LoanApiConstants.MARK_AS_FRAUD_COMMAND)) {
|
||||
commandRequest = builder.markAsFraud(loanId).build();
|
||||
} else {
|
||||
commandRequest = builder.updateLoanApplication(loanId).build();
|
||||
}
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
return modifyLoanApplication(loanId, null, commandParam, apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@@ -830,13 +536,8 @@ public class LoansApiResource {
|
||||
@Operation(summary = "Delete a Loan Application", description = "Note: Only loans in \"Submitted and awaiting approval\" status can be deleted.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.DeleteLoansLoanIdResponse.class))) })
|
||||
public String deleteLoanApplication(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteLoanApplication(loanId).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
public String deleteLoanApplication(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId) {
|
||||
return deleteLoanApplication(loanId, null);
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -858,44 +559,10 @@ public class LoansApiResource {
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PostLoansLoanIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PostLoansLoanIdResponse.class))) })
|
||||
public String stateTransitions(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
public String stateTransitions(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
CommandWrapper commandRequest = null;
|
||||
if (CommandParameterUtil.is(commandParam, "reject")) {
|
||||
commandRequest = builder.rejectLoanApplication(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "withdrawnByApplicant")) {
|
||||
commandRequest = builder.withdrawLoanApplication(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "approve")) {
|
||||
commandRequest = builder.approveLoanApplication(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburse")) {
|
||||
commandRequest = builder.disburseLoanApplication(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburseToSavings")) {
|
||||
commandRequest = builder.disburseLoanToSavingsApplication(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undoapproval")) {
|
||||
commandRequest = builder.undoLoanApplicationApproval(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undodisbursal")) {
|
||||
commandRequest = builder.undoLoanApplicationDisbursal(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undolastdisbursal")) {
|
||||
commandRequest = builder.undoLastDisbursalLoanApplication(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "assignloanofficer")) {
|
||||
commandRequest = builder.assignLoanOfficer(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "unassignloanofficer")) {
|
||||
commandRequest = builder.unassignLoanOfficer(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "recoverGuarantees")) {
|
||||
commandRequest = new CommandWrapperBuilder().recoverFromGuarantor(loanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "assigndelinquency")) {
|
||||
commandRequest = builder.assignDelinquency(loanId).build();
|
||||
}
|
||||
|
||||
if (commandRequest == null) {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
}
|
||||
CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
return stateTransitions(loanId, null, commandParam, apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -1001,12 +668,495 @@ public class LoansApiResource {
|
||||
@Operation(summary = "Retrieve the Loan Delinquency Tag history using the Loan Id", description = "")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = DelinquencyApiResourceSwagger.GetDelinquencyTagHistoryResponse.class)))) })
|
||||
public String getDelinquencyTagHistory(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
public String getDelinquencyTagHistory(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return getDelinquencyTagHistory(loanId, null, uriInfo);
|
||||
}
|
||||
|
||||
// External id related APIs
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.GetLoansApprovalTemplateResponse.class))) })
|
||||
public String retrieveApprovalTemplate(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@QueryParam("templateType") @Parameter(description = "templateType") final String templateType,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveApprovalTemplate(null, loanExternalId, templateType, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Loan", description = "Note: template=true parameter doesn't apply to this resource."
|
||||
+ "Example Requests:\n" + "\n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854\n" + "\n" + "\n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854?fields=id,principal,annualInterestRate\n" + "\n" + "\n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854?associations=all\n" + "\n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854?associations=all&exclude=guarantors\n" + "\n" + "\n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854?fields=id,principal,annualInterestRate&associations=repaymentSchedule,transactions")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.GetLoansLoanIdResponse.class))) })
|
||||
public String retrieveLoan(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
|
||||
@DefaultValue("all") @QueryParam("associations") @Parameter(in = ParameterIn.QUERY, name = "associations", description = "Loan object relations to be included in the response", required = false, examples = {
|
||||
@ExampleObject(value = "all"), @ExampleObject(value = "repaymentSchedule,transactions") }) final String associations,
|
||||
@QueryParam("exclude") @Parameter(in = ParameterIn.QUERY, name = "exclude", description = "Optional Loan object relation list to be filtered in the response", required = false, example = "guarantors,futureSchedule") final String exclude,
|
||||
@QueryParam("fields") @Parameter(in = ParameterIn.QUERY, name = "fields", description = "Optional Loan attribute list to be in the response", required = false, example = "id,principal,annualInterestRate") final String fields,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return retrieveLoan(null, loanExternalId, staffInSelectedOfficeOnly, exclude, uriInfo);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("external-id/{loanExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Modify a loan application", description = "Loan application can only be modified when in 'Submitted and pending approval' state. Once the application is approved, the details cannot be changed using this method.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PutLoansLoanIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PutLoansLoanIdResponse.class))) })
|
||||
public String modifyLoanApplication(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
return modifyLoanApplication(null, loanExternalId, commandParam, apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("external-id/{loanExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Delete a Loan Application", description = "Note: Only loans in \"Submitted and awaiting approval\" status can be deleted.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.DeleteLoansLoanIdResponse.class))) })
|
||||
public String deleteLoanApplication(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId) {
|
||||
return deleteLoanApplication(null, loanExternalId);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("external-id/{loanExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Approve Loan Application | Recover Loan Guarantee | Undo Loan Application Approval | Assign a Loan Officer | Unassign a Loan Officer | Reject Loan Application | Applicant Withdraws from Loan Application | Disburse Loan Disburse Loan To Savings Account | Undo Loan Disbursal", description = "Approve Loan Application:\n"
|
||||
+ "Mandatory Fields: approvedOnDate\n" + "Optional Fields: approvedLoanAmount and expectedDisbursementDate\n"
|
||||
+ "Approves the loan application\n\n" + "Recover Loan Guarantee:\n" + "Recovers the loan guarantee\n\n"
|
||||
+ "Undo Loan Application Approval:\n" + "Undoes the Loan Application Approval\n\n" + "Assign a Loan Officer:\n"
|
||||
+ "Allows you to assign Loan Officer for existing Loan.\n\n" + "Unassign a Loan Officer:\n"
|
||||
+ "Allows you to unassign the Loan Officer.\n\n" + "Reject Loan Application:\n" + "Mandatory Fields: rejectedOnDate\n"
|
||||
+ "Allows you to reject the loan application\n\n" + "Applicant Withdraws from Loan Application:\n"
|
||||
+ "Mandatory Fields: withdrawnOnDate\n" + "Allows the applicant to withdraw the loan application\n\n" + "Disburse Loan:\n"
|
||||
+ "Mandatory Fields: actualDisbursementDate\n" + "Optional Fields: transactionAmount and fixedEmiAmount\n"
|
||||
+ "Disburses the Loan\n\n" + "Disburse Loan To Savings Account:\n" + "Mandatory Fields: actualDisbursementDate\n"
|
||||
+ "Optional Fields: transactionAmount and fixedEmiAmount\n" + "Disburses the loan to Saving Account\n\n"
|
||||
+ "Undo Loan Disbursal:\n" + "Undoes the Loan Disbursal\n" + "Showing request and response for Assign a Loan Officer")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PostLoansLoanIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PostLoansLoanIdResponse.class))) })
|
||||
public String stateTransitions(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
return stateTransitions(null, loanExternalId, commandParam, apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/delinquencytags")
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Retrieve the Loan Delinquency Tag history using the Loan Id", description = "")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = DelinquencyApiResourceSwagger.GetDelinquencyTagHistoryResponse.class)))) })
|
||||
public String getDelinquencyTagHistory(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
return getDelinquencyTagHistory(null, loanExternalId, uriInfo);
|
||||
}
|
||||
|
||||
private String retrieveApprovalTemplate(final Long loanId, final String loanExternalIdStr, final String templateType,
|
||||
final UriInfo uriInfo) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
LoanApprovalData loanApprovalTemplate = null;
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
if (templateType == null) {
|
||||
final String errorMsg = "Loan template type must be provided";
|
||||
throw new LoanTemplateTypeRequiredException(errorMsg);
|
||||
} else if (templateType.equals("approval")) {
|
||||
loanApprovalTemplate = this.loanReadPlatformService.retrieveApprovalTemplate(resolvedLoanId);
|
||||
}
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.loanApprovalDataToApiJsonSerializer.serialize(settings, loanApprovalTemplate, LOAN_APPROVAL_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
private String retrieveLoan(final Long loanId, final String loanExternalIdStr, boolean staffInSelectedOfficeOnly, final String exclude,
|
||||
final UriInfo uriInfo) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(resolvedLoanId);
|
||||
if (loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||
Collection<CalendarData> interestRecalculationCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(
|
||||
loanBasicDetails.getInterestRecalculationDetailId(), CalendarEntityType.LOAN_RECALCULATION_REST_DETAIL.getValue(),
|
||||
null);
|
||||
CalendarData calendarData = null;
|
||||
if (!CollectionUtils.isEmpty(interestRecalculationCalendarDatas)) {
|
||||
calendarData = interestRecalculationCalendarDatas.iterator().next();
|
||||
}
|
||||
|
||||
Collection<CalendarData> interestRecalculationCompoundingCalendarDatas = this.calendarReadPlatformService
|
||||
.retrieveCalendarsByEntity(loanBasicDetails.getInterestRecalculationDetailId(),
|
||||
CalendarEntityType.LOAN_RECALCULATION_COMPOUNDING_DETAIL.getValue(), null);
|
||||
CalendarData compoundingCalendarData = null;
|
||||
if (!CollectionUtils.isEmpty(interestRecalculationCompoundingCalendarDatas)) {
|
||||
compoundingCalendarData = interestRecalculationCompoundingCalendarDatas.iterator().next();
|
||||
}
|
||||
loanBasicDetails = LoanAccountData.withInterestRecalculationCalendarData(loanBasicDetails, calendarData,
|
||||
compoundingCalendarData);
|
||||
}
|
||||
if (loanBasicDetails.getRepaymentFrequencyType() != null
|
||||
&& loanBasicDetails.getRepaymentFrequencyType().getId().intValue() == PeriodFrequencyType.MONTHS.getValue()) {
|
||||
Collection<CalendarData> loanCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(resolvedLoanId,
|
||||
CalendarEntityType.LOANS.getValue(), null);
|
||||
CalendarData calendarData = null;
|
||||
if (!CollectionUtils.isEmpty(loanCalendarDatas)) {
|
||||
calendarData = loanCalendarDatas.iterator().next();
|
||||
}
|
||||
if (calendarData != null) {
|
||||
loanBasicDetails = LoanAccountData.withLoanCalendarData(loanBasicDetails, calendarData);
|
||||
}
|
||||
}
|
||||
Collection<InterestRatePeriodData> interestRatesPeriods = this.loanReadPlatformService
|
||||
.retrieveLoanInterestRatePeriodData(loanBasicDetails);
|
||||
Collection<LoanTransactionData> loanRepayments = null;
|
||||
LoanScheduleData repaymentSchedule = null;
|
||||
Collection<LoanChargeData> charges = null;
|
||||
Collection<GuarantorData> guarantors = null;
|
||||
CalendarData meeting = null;
|
||||
Collection<NoteData> notes = null;
|
||||
PortfolioAccountData linkedAccount = null;
|
||||
Collection<DisbursementData> disbursementData = null;
|
||||
Collection<LoanTermVariationsData> emiAmountVariations = null;
|
||||
Collection<LoanCollateralResponseData> loanCollateralManagements;
|
||||
Collection<LoanCollateralManagementData> loanCollateralManagementData = new ArrayList<>();
|
||||
CollectionData collectionData = CollectionData.template();
|
||||
|
||||
final Set<String> mandatoryResponseParameters = new HashSet<>();
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
final Collection<LoanTransactionData> currentLoanRepayments = this.loanReadPlatformService.retrieveLoanTransactions(resolvedLoanId);
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains(DataTableApiConstant.allAssociateParamName)) {
|
||||
associationParameters.addAll(Arrays.asList(DataTableApiConstant.repaymentScheduleAssociateParamName,
|
||||
DataTableApiConstant.futureScheduleAssociateParamName, DataTableApiConstant.originalScheduleAssociateParamName,
|
||||
DataTableApiConstant.transactionsAssociateParamName, DataTableApiConstant.chargesAssociateParamName,
|
||||
DataTableApiConstant.guarantorsAssociateParamName, DataTableApiConstant.collateralAssociateParamName,
|
||||
DataTableApiConstant.notesAssociateParamName, DataTableApiConstant.linkedAccountAssociateParamName,
|
||||
DataTableApiConstant.multiDisburseDetailsAssociateParamName, DataTableApiConstant.collectionAssociateParamName));
|
||||
}
|
||||
|
||||
ApiParameterHelper.excludeAssociationsForResponseIfProvided(exclude, associationParameters);
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.guarantorsAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.guarantorsAssociateParamName);
|
||||
guarantors = this.guarantorReadPlatformService.retrieveGuarantorsForLoan(resolvedLoanId);
|
||||
if (CollectionUtils.isEmpty(guarantors)) {
|
||||
guarantors = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.transactionsAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.transactionsAssociateParamName);
|
||||
if (!CollectionUtils.isEmpty(currentLoanRepayments)) {
|
||||
loanRepayments = currentLoanRepayments;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.multiDisburseDetailsAssociateParamName)
|
||||
|| associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.multiDisburseDetailsAssociateParamName);
|
||||
disbursementData = this.loanReadPlatformService.retrieveLoanDisbursementDetails(resolvedLoanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.emiAmountVariationsAssociateParamName)
|
||||
|| associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.emiAmountVariationsAssociateParamName);
|
||||
emiAmountVariations = this.loanReadPlatformService.retrieveLoanTermVariations(resolvedLoanId,
|
||||
LoanTermVariationType.EMI_AMOUNT.getValue());
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.repaymentScheduleAssociateParamName);
|
||||
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.getTimeline()
|
||||
.repaymentScheduleRelatedData(loanBasicDetails.getCurrency(), loanBasicDetails.getPrincipal(),
|
||||
loanBasicDetails.getApprovedPrincipal(), loanBasicDetails.getInArrearsTolerance(),
|
||||
loanBasicDetails.getFeeChargesAtDisbursementCharged());
|
||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(resolvedLoanId, repaymentScheduleRelatedData,
|
||||
disbursementData, loanBasicDetails.isInterestRecalculationEnabled(),
|
||||
loanBasicDetails.getSummary() != null ? loanBasicDetails.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName)
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.futureScheduleAssociateParamName);
|
||||
this.calculationPlatformService.updateFutureSchedule(repaymentSchedule, resolvedLoanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.originalScheduleAssociateParamName)
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled()
|
||||
&& LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName);
|
||||
LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService
|
||||
.retrieveRepaymentArchiveSchedule(resolvedLoanId, repaymentScheduleRelatedData, disbursementData);
|
||||
loanBasicDetails = LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData);
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.chargesAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.chargesAssociateParamName);
|
||||
charges = this.loanChargeReadPlatformService.retrieveLoanCharges(resolvedLoanId);
|
||||
if (CollectionUtils.isEmpty(charges)) {
|
||||
charges = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.collateralAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.collateralAssociateParamName);
|
||||
loanCollateralManagements = this.loanCollateralManagementReadPlatformService
|
||||
.getLoanCollateralResponseDataList(resolvedLoanId);
|
||||
for (LoanCollateralResponseData loanCollateralManagement : loanCollateralManagements) {
|
||||
loanCollateralManagementData.add(loanCollateralManagement.toCommand());
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.meetingAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.meetingAssociateParamName);
|
||||
meeting = this.calendarReadPlatformService.retrieveLoanCalendar(resolvedLoanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.notesAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.notesAssociateParamName);
|
||||
notes = this.noteReadPlatformService.retrieveNotesByResource(resolvedLoanId, NoteType.LOAN.getValue());
|
||||
if (CollectionUtils.isEmpty(notes)) {
|
||||
notes = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.linkedAccountAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName);
|
||||
linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(resolvedLoanId);
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.collectionAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.collectionAssociateParamName);
|
||||
if (loanBasicDetails.isActive()) {
|
||||
collectionData = this.delinquencyReadPlatformService.calculateLoanCollectionData(resolvedLoanId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection<LoanProductData> productOptions = null;
|
||||
LoanProductData product;
|
||||
Collection<EnumOptionData> loanTermFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> repaymentFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> repaymentFrequencyNthDayTypeOptions = null;
|
||||
Collection<EnumOptionData> repaymentFrequencyDayOfWeekTypeOptions = null;
|
||||
Collection<TransactionProcessingStrategyData> repaymentStrategyOptions = null;
|
||||
Collection<EnumOptionData> interestRateFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> amortizationTypeOptions = null;
|
||||
Collection<EnumOptionData> interestTypeOptions = null;
|
||||
Collection<EnumOptionData> interestCalculationPeriodTypeOptions = null;
|
||||
Collection<FundData> fundOptions = null;
|
||||
Collection<StaffData> allowedLoanOfficers = null;
|
||||
Collection<ChargeData> chargeOptions = null;
|
||||
ChargeData chargeTemplate = null;
|
||||
Collection<CodeValueData> loanPurposeOptions = null;
|
||||
Collection<CodeValueData> loanCollateralOptions = null;
|
||||
Collection<CalendarData> calendarOptions = null;
|
||||
Collection<PortfolioAccountData> accountLinkingOptions = null;
|
||||
PaidInAdvanceData paidInAdvanceTemplate;
|
||||
Collection<LoanAccountSummaryData> clientActiveLoanOptions = null;
|
||||
|
||||
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
if (template) {
|
||||
productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup();
|
||||
product = this.loanProductReadPlatformService.retrieveLoanProduct(loanBasicDetails.getLoanProductId());
|
||||
loanBasicDetails.setProduct(product);
|
||||
loanTermFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions();
|
||||
repaymentFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions();
|
||||
repaymentFrequencyNthDayTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyOptionsForNthDayOfMonth();
|
||||
repaymentFrequencyDayOfWeekTypeOptions = this.dropdownReadPlatformService.retrieveRepaymentFrequencyOptionsForDaysOfWeek();
|
||||
interestRateFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions();
|
||||
|
||||
amortizationTypeOptions = this.dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions();
|
||||
if (product.isLinkedToFloatingInterestRates()) {
|
||||
interestTypeOptions = Collections.singletonList(interestType(InterestMethod.DECLINING_BALANCE));
|
||||
} else {
|
||||
interestTypeOptions = this.dropdownReadPlatformService.retrieveLoanInterestTypeOptions();
|
||||
}
|
||||
interestCalculationPeriodTypeOptions = this.dropdownReadPlatformService.retrieveLoanInterestRateCalculatedInPeriodOptions();
|
||||
|
||||
fundOptions = this.fundReadPlatformService.retrieveAllFunds();
|
||||
repaymentStrategyOptions = this.dropdownReadPlatformService.retrieveTransactionProcessingStrategies();
|
||||
if (product.getMultiDisburseLoan()) {
|
||||
chargeOptions = this.chargeReadPlatformService.retrieveLoanAccountApplicableCharges(resolvedLoanId,
|
||||
new ChargeTimeType[] { ChargeTimeType.OVERDUE_INSTALLMENT });
|
||||
} else {
|
||||
chargeOptions = this.chargeReadPlatformService.retrieveLoanAccountApplicableCharges(resolvedLoanId,
|
||||
new ChargeTimeType[] { ChargeTimeType.OVERDUE_INSTALLMENT, ChargeTimeType.TRANCHE_DISBURSEMENT });
|
||||
}
|
||||
chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate();
|
||||
|
||||
Long officeId = loanBasicDetails.getClientOfficeId();
|
||||
|
||||
if (officeId == null && loanBasicDetails.getGroup() != null) {
|
||||
officeId = loanBasicDetails.getGroup().getOfficeId();
|
||||
}
|
||||
allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(officeId, staffInSelectedOfficeOnly);
|
||||
|
||||
loanPurposeOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanPurpose");
|
||||
loanCollateralOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanCollateral");
|
||||
final CurrencyData currencyData = loanBasicDetails.getCurrency();
|
||||
String currencyCode = null;
|
||||
if (currencyData != null) {
|
||||
currencyCode = currencyData.getCode();
|
||||
}
|
||||
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
|
||||
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(),
|
||||
loanBasicDetails.getClientId(), currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue());
|
||||
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
|
||||
|
||||
if (!associationParameters.contains(DataTableApiConstant.linkedAccountAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName);
|
||||
linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(resolvedLoanId);
|
||||
}
|
||||
if (loanBasicDetails.getGroup() != null && loanBasicDetails.getGroup().getId() != null) {
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.getGroup().getId());
|
||||
}
|
||||
|
||||
if (loanBasicDetails.getProduct().isCanUseForTopup() && loanBasicDetails.getClientId() != null) {
|
||||
clientActiveLoanOptions = this.accountDetailsReadPlatformService
|
||||
.retrieveClientActiveLoanAccountSummary(loanBasicDetails.getClientId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Collection<ChargeData> overdueCharges = this.chargeReadPlatformService
|
||||
.retrieveLoanProductCharges(loanBasicDetails.getLoanProductId(), ChargeTimeType.OVERDUE_INSTALLMENT);
|
||||
|
||||
paidInAdvanceTemplate = this.loanReadPlatformService.retrieveTotalPaidInAdvance(resolvedLoanId);
|
||||
|
||||
// Get rates from Loan
|
||||
boolean isRatesEnabled = this.configurationDomainService.isSubRatesEnabled();
|
||||
List<RateData> rates = null;
|
||||
if (isRatesEnabled) {
|
||||
rates = this.rateReadService.retrieveLoanRates(resolvedLoanId);
|
||||
}
|
||||
|
||||
// updating summary with transaction amounts summary
|
||||
if (loanBasicDetails.getSummary() != null) {
|
||||
loanBasicDetails
|
||||
.setSummary(LoanSummaryData.withTransactionAmountsSummary(loanBasicDetails.getSummary(), currentLoanRepayments));
|
||||
}
|
||||
|
||||
final LoanAccountData loanAccount = LoanAccountData.associationsAndTemplate(loanBasicDetails, repaymentSchedule, loanRepayments,
|
||||
charges, loanCollateralManagementData, guarantors, meeting, productOptions, loanTermFrequencyTypeOptions,
|
||||
repaymentFrequencyTypeOptions, repaymentFrequencyNthDayTypeOptions, repaymentFrequencyDayOfWeekTypeOptions,
|
||||
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
|
||||
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions,
|
||||
loanCollateralOptions, calendarOptions, notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations,
|
||||
overdueCharges, paidInAdvanceTemplate, interestRatesPeriods, clientActiveLoanOptions, rates, isRatesEnabled,
|
||||
collectionData);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
|
||||
mandatoryResponseParameters);
|
||||
return this.toApiJsonSerializer.serialize(settings, loanAccount, LOAN_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
private String modifyLoanApplication(final Long loanId, final String loanExternalIdStr, final String commandParam,
|
||||
final String apiRequestBodyAsJson) {
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
CommandWrapper commandRequest;
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
if (CommandParameterUtil.is(commandParam, LoanApiConstants.MARK_AS_FRAUD_COMMAND)) {
|
||||
commandRequest = builder.markAsFraud(resolvedLoanId).build();
|
||||
} else {
|
||||
commandRequest = builder.updateLoanApplication(resolvedLoanId).build();
|
||||
}
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private String deleteLoanApplication(final Long loanId, final String loanExternalIdStr) {
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteLoanApplication(resolvedLoanId).build();
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private String stateTransitions(final Long loanId, final String loanExternalIdStr, final String commandParam,
|
||||
final String apiRequestBodyAsJson) {
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
CommandWrapper commandRequest = null;
|
||||
if (CommandParameterUtil.is(commandParam, "reject")) {
|
||||
commandRequest = builder.rejectLoanApplication(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "withdrawnByApplicant")) {
|
||||
commandRequest = builder.withdrawLoanApplication(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "approve")) {
|
||||
commandRequest = builder.approveLoanApplication(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburse")) {
|
||||
commandRequest = builder.disburseLoanApplication(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburseToSavings")) {
|
||||
commandRequest = builder.disburseLoanToSavingsApplication(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undoapproval")) {
|
||||
commandRequest = builder.undoLoanApplicationApproval(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undodisbursal")) {
|
||||
commandRequest = builder.undoLoanApplicationDisbursal(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undolastdisbursal")) {
|
||||
commandRequest = builder.undoLastDisbursalLoanApplication(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "assignloanofficer")) {
|
||||
commandRequest = builder.assignLoanOfficer(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "unassignloanofficer")) {
|
||||
commandRequest = builder.unassignLoanOfficer(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "recoverGuarantees")) {
|
||||
commandRequest = new CommandWrapperBuilder().recoverFromGuarantor(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "assigndelinquency")) {
|
||||
commandRequest = builder.assignDelinquency(resolvedLoanId).build();
|
||||
}
|
||||
|
||||
if (commandRequest == null) {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
}
|
||||
CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private String getDelinquencyTagHistory(final Long loanId, final String loanExternalIdStr, final UriInfo uriInfo) {
|
||||
context.authenticatedUser().validateHasReadPermission("DELINQUENCY_TAGS");
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
final Collection<LoanDelinquencyTagHistoryData> loanDelinquencyTagHistoryData = this.delinquencyReadPlatformService
|
||||
.retrieveDelinquencyRangeHistory(loanId);
|
||||
.retrieveDelinquencyRangeHistory(resolvedLoanId);
|
||||
return this.jsonSerializerTagHistory.serialize(loanDelinquencyTagHistoryData);
|
||||
}
|
||||
|
||||
private Long getResolvedLoanId(final Long loanId, final ExternalId loanExternalId) {
|
||||
Long resolvedLoanId = loanId;
|
||||
if (resolvedLoanId == null) {
|
||||
loanExternalId.throwExceptionIfEmpty();
|
||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId);
|
||||
if (resolvedLoanId == null) {
|
||||
throw new LoanNotFoundException(loanExternalId);
|
||||
}
|
||||
}
|
||||
return resolvedLoanId;
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -32,6 +32,19 @@ final class LoansApiResourceSwagger {
|
||||
|
||||
private LoansApiResourceSwagger() {}
|
||||
|
||||
@Schema(description = "GetLoansApprovalTemplateResponse")
|
||||
public static final class GetLoansApprovalTemplateResponse {
|
||||
|
||||
private GetLoansApprovalTemplateResponse() {}
|
||||
|
||||
@Schema(example = "[2012, 4, 3]")
|
||||
public LocalDate approvalDate;
|
||||
@Schema(example = "200.000000")
|
||||
public Double approvalAmount;
|
||||
@Schema(example = "200.000000")
|
||||
public Double netDisbursalAmount;
|
||||
}
|
||||
|
||||
@Schema(description = "GetLoansTemplateResponse")
|
||||
public static final class GetLoansTemplateResponse {
|
||||
|
||||
@@ -935,6 +948,8 @@ final class LoansApiResourceSwagger {
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String externalId;
|
||||
@Schema(example = "000000001")
|
||||
public Long accountNo;
|
||||
public GetLoansLoanIdStatus status;
|
||||
@@ -1302,6 +1317,8 @@ final class LoansApiResourceSwagger {
|
||||
public Integer loanId;
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String resourceExternalId;
|
||||
public PutLoansLoanIdChanges changes;
|
||||
}
|
||||
|
||||
@@ -1318,6 +1335,8 @@ final class LoansApiResourceSwagger {
|
||||
public Integer loanId;
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String resourceExternalId;
|
||||
}
|
||||
|
||||
@Schema(description = "PostLoansLoanIdRequest")
|
||||
@@ -1339,6 +1358,9 @@ final class LoansApiResourceSwagger {
|
||||
public Integer toLoanOfficerId;
|
||||
@Schema(example = "02 September 2014")
|
||||
public String assignmentDate;
|
||||
|
||||
@Schema(example = "02 September 2014")
|
||||
public String unassignedDate;
|
||||
@Schema(example = "en")
|
||||
public String locale;
|
||||
@Schema(example = "dd MMMM yyyy")
|
||||
@@ -1361,6 +1383,10 @@ final class LoansApiResourceSwagger {
|
||||
public String approvedLoanAmount;
|
||||
@Schema(example = "28 June 2022")
|
||||
public String expectedDisbursementDate;
|
||||
@Schema(example = "28 June 2022")
|
||||
public String rejectedOnDate;
|
||||
@Schema(example = "28 June 2022")
|
||||
public String withdrawnOnDate;
|
||||
@Schema(description = "List of PostLoansLoanIdDisbursementData")
|
||||
public List<PostLoansLoanIdDisbursementData> disbursementData;
|
||||
}
|
||||
@@ -1422,6 +1448,8 @@ final class LoansApiResourceSwagger {
|
||||
public Integer loanId;
|
||||
@Schema(example = "3")
|
||||
public Integer resourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String resourceExternalId;
|
||||
@Schema(description = "PostLoansLoanIdChanges")
|
||||
public PostLoansLoanIdChanges changes;
|
||||
}
|
||||
|
||||
+21
-19
@@ -33,6 +33,7 @@ import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||
@@ -65,7 +66,7 @@ public class LoanAccountData {
|
||||
// identity
|
||||
private Long id;
|
||||
private String accountNo;
|
||||
private String externalId;
|
||||
private ExternalId externalId = ExternalId.empty();
|
||||
|
||||
// status
|
||||
private LoanStatusEnumData status;
|
||||
@@ -260,7 +261,7 @@ public class LoanAccountData {
|
||||
EnumOptionData amortizationEnumOption, EnumOptionData interestMethodEnum, EnumOptionData interestCalculationPeriodTypeEnum,
|
||||
BigDecimal inArrearsTolerance, String transactionProcessingStrategyCode, Integer graceOnPrincipalPayment,
|
||||
Integer graceOnInterestPayment, Integer graceOnInterestCharged, LocalDate interestChargedFromDate,
|
||||
LocalDate repaymentsStartingFromDate, Integer rowIndex, String externalId, Long groupId, Collection<LoanChargeData> charges,
|
||||
LocalDate repaymentsStartingFromDate, Integer rowIndex, ExternalId externalId, Long groupId, Collection<LoanChargeData> charges,
|
||||
String linkAccountId, String locale, String dateFormat, List<LoanCollateralManagementData> loanCollateralManagementData) {
|
||||
|
||||
return new LoanAccountData().setLoanType(loanTypeEnumOption).setClientId(clientId).setProductId(productId)
|
||||
@@ -285,7 +286,7 @@ public class LoanAccountData {
|
||||
EnumOptionData interestMethodEnum, EnumOptionData interestCalculationPeriodEnum, BigDecimal arrearsTolerance,
|
||||
String transactionProcessingStrategyCode, Integer graceOnPrincipalPayment, Integer graceOnInterestPayment,
|
||||
Integer graceOnInterestCharged, LocalDate interestChargedFromDate, LocalDate repaymentsStartingFromDate, Integer rowIndex,
|
||||
String externalId, String linkAccountId, String locale, String dateFormat) {
|
||||
ExternalId externalId, String linkAccountId, String locale, String dateFormat) {
|
||||
|
||||
return new LoanAccountData().setLoanType(loanTypeEnumOption).setGroupId(groupIdforGroupLoan).setProductId(productId)
|
||||
.setLoanOfficerId(loanOfficerId).setSubmittedOnDate(submittedOnDate).setFundId(fundId).setPrincipal(principal)
|
||||
@@ -626,22 +627,23 @@ public class LoanAccountData {
|
||||
* Used to send back loan account data with the basic details coming from query.
|
||||
*/
|
||||
public static LoanAccountData basicLoanDetails(final Long id, final String accountNo, final LoanStatusEnumData status,
|
||||
final String externalId, final Long clientId, final String clientAccountNo, final String clientName, final Long clientOfficeId,
|
||||
final String clientExternalId, final GroupGeneralData group, final EnumOptionData loanType, final Long loanProductId,
|
||||
final String loanProductName, final String loanProductDescription, final boolean isLoanProductLinkedToFloatingRate,
|
||||
final Long fundId, final String fundName, final Long loanPurposeId, final String loanPurposeName, final Long loanOfficerId,
|
||||
final String loanOfficerName, final CurrencyData currencyData, final BigDecimal proposedPrincipal, final BigDecimal principal,
|
||||
final BigDecimal approvedPrincipal, final BigDecimal netDisbursalAmount, final BigDecimal totalOverpaid,
|
||||
final BigDecimal inArrearsTolerance, final Integer termFrequency, final EnumOptionData termPeriodFrequencyType,
|
||||
final Integer numberOfRepayments, final Integer repaymentEvery, final EnumOptionData repaymentFrequencyType,
|
||||
EnumOptionData repaymentFrequencyNthDayType, EnumOptionData repaymentFrequencyDayOfWeekType, final String transactionStrategy,
|
||||
final String transactionStrategyName, final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod,
|
||||
final EnumOptionData interestRateFrequencyType, final BigDecimal annualInterestRate, final EnumOptionData interestType,
|
||||
final boolean isFloatingInterestRate, final BigDecimal interestRateDifferential,
|
||||
final EnumOptionData interestCalculationPeriodType, Boolean allowPartialPeriodInterestCalcualtion,
|
||||
final LocalDate expectedFirstRepaymentOnDate, final Integer graceOnPrincipalPayment,
|
||||
final Integer recurringMoratoriumOnPrincipalPeriods, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged,
|
||||
final LocalDate interestChargedFromDate, final LoanApplicationTimelineData timeline, final LoanSummaryData loanSummary,
|
||||
final ExternalId externalId, final Long clientId, final String clientAccountNo, final String clientName,
|
||||
final Long clientOfficeId, final String clientExternalId, final GroupGeneralData group, final EnumOptionData loanType,
|
||||
final Long loanProductId, final String loanProductName, final String loanProductDescription,
|
||||
final boolean isLoanProductLinkedToFloatingRate, final Long fundId, final String fundName, final Long loanPurposeId,
|
||||
final String loanPurposeName, final Long loanOfficerId, final String loanOfficerName, final CurrencyData currencyData,
|
||||
final BigDecimal proposedPrincipal, final BigDecimal principal, final BigDecimal approvedPrincipal,
|
||||
final BigDecimal netDisbursalAmount, final BigDecimal totalOverpaid, final BigDecimal inArrearsTolerance,
|
||||
final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, final Integer numberOfRepayments,
|
||||
final Integer repaymentEvery, final EnumOptionData repaymentFrequencyType, EnumOptionData repaymentFrequencyNthDayType,
|
||||
EnumOptionData repaymentFrequencyDayOfWeekType, final String transactionStrategy, final String transactionStrategyName,
|
||||
final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType,
|
||||
final BigDecimal annualInterestRate, final EnumOptionData interestType, final boolean isFloatingInterestRate,
|
||||
final BigDecimal interestRateDifferential, final EnumOptionData interestCalculationPeriodType,
|
||||
Boolean allowPartialPeriodInterestCalcualtion, final LocalDate expectedFirstRepaymentOnDate,
|
||||
final Integer graceOnPrincipalPayment, final Integer recurringMoratoriumOnPrincipalPeriods,
|
||||
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate,
|
||||
final LoanApplicationTimelineData timeline, final LoanSummaryData loanSummary,
|
||||
final BigDecimal feeChargesDueAtDisbursementCharged, final Boolean syncDisbursementWithMeeting, final Integer loanCounter,
|
||||
final Integer loanProductCounter, final Boolean multiDisburseLoan, Boolean canDefineInstallmentAmount,
|
||||
final BigDecimal fixedEmiAmont, final BigDecimal outstandingLoanBalance, final Boolean inArrears,
|
||||
|
||||
+11
-10
@@ -38,7 +38,7 @@ public class LoanTransactionData {
|
||||
|
||||
private final Long id;
|
||||
private final Long loanId;
|
||||
private final String externalLoanId;
|
||||
private final ExternalId externalLoanId;
|
||||
private final Long officeId;
|
||||
private final String officeName;
|
||||
|
||||
@@ -115,7 +115,7 @@ public class LoanTransactionData {
|
||||
this.type = null;
|
||||
this.id = null;
|
||||
this.loanId = null;
|
||||
this.externalLoanId = null;
|
||||
this.externalLoanId = ExternalId.empty();
|
||||
this.officeId = null;
|
||||
this.officeName = null;
|
||||
this.currency = null;
|
||||
@@ -163,7 +163,7 @@ public class LoanTransactionData {
|
||||
this.locale = locale;
|
||||
this.id = null;
|
||||
this.loanId = null;
|
||||
this.externalLoanId = null;
|
||||
this.externalLoanId = ExternalId.empty();
|
||||
this.officeId = null;
|
||||
this.officeName = null;
|
||||
this.type = null;
|
||||
@@ -216,7 +216,7 @@ public class LoanTransactionData {
|
||||
final BigDecimal netDisbursalAmount, final BigDecimal principalPortion, final BigDecimal interestPortion,
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
final ExternalId externalId, final AccountTransferData transfer, BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
final BigDecimal unrecognizedIncomePortion, final boolean manuallyReversed, Long loanId, String externalLoanId) {
|
||||
final BigDecimal unrecognizedIncomePortion, final boolean manuallyReversed, Long loanId, ExternalId externalLoanId) {
|
||||
this(id, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, netDisbursalAmount, principalPortion,
|
||||
interestPortion, feeChargesPortion, penaltyChargesPortion, overpaymentPortion, unrecognizedIncomePortion, null, externalId,
|
||||
transfer, fixedEmiAmount, outstandingLoanBalance, manuallyReversed, loanId, externalLoanId);
|
||||
@@ -228,7 +228,7 @@ public class LoanTransactionData {
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
BigDecimal unrecognizedIncomePortion, final Collection<PaymentTypeData> paymentTypeOptions, final ExternalId externalId,
|
||||
final AccountTransferData transfer, final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
boolean manuallyReversed, Long loanId, String externalLoanId) {
|
||||
boolean manuallyReversed, Long loanId, ExternalId externalLoanId) {
|
||||
this(id, externalLoanId, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, netDisbursalAmount,
|
||||
principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion, overpaymentPortion, unrecognizedIncomePortion,
|
||||
paymentTypeOptions, externalId, transfer, fixedEmiAmount, outstandingLoanBalance, null, manuallyReversed,
|
||||
@@ -241,14 +241,14 @@ public class LoanTransactionData {
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
final BigDecimal unrecognizedIncomePortion, final ExternalId externalId, final AccountTransferData transfer,
|
||||
BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance, LocalDate submittedOnDate, final boolean manuallyReversed,
|
||||
final ExternalId reversalExternalId, final LocalDate reversedOnDate, Long loanId, String externalLoanId) {
|
||||
final ExternalId reversalExternalId, final LocalDate reversedOnDate, Long loanId, ExternalId externalLoanId) {
|
||||
this(id, externalLoanId, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, netDisbursalAmount,
|
||||
principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion, overpaymentPortion, unrecognizedIncomePortion,
|
||||
null, externalId, transfer, fixedEmiAmount, outstandingLoanBalance, submittedOnDate, manuallyReversed, reversalExternalId,
|
||||
reversedOnDate, loanId);
|
||||
}
|
||||
|
||||
public LoanTransactionData(final Long id, final String externalLoanId, final Long officeId, final String officeName,
|
||||
public LoanTransactionData(final Long id, final ExternalId externalLoanId, final Long officeId, final String officeName,
|
||||
final LoanTransactionEnumData transactionType, final PaymentDetailData paymentDetailData, final CurrencyData currency,
|
||||
final LocalDate date, final BigDecimal amount, final BigDecimal netDisbursalAmount, final BigDecimal principalPortion,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
@@ -288,7 +288,8 @@ public class LoanTransactionData {
|
||||
public LoanTransactionData(Long id, LoanTransactionEnumData transactionType, LocalDate date, BigDecimal totalAmount,
|
||||
BigDecimal netDisbursalAmount, BigDecimal principalPortion, BigDecimal interestPortion, BigDecimal feeChargesPortion,
|
||||
BigDecimal penaltyChargesPortion, BigDecimal overpaymentPortion, BigDecimal unrecognizedIncomePortion,
|
||||
BigDecimal outstandingLoanBalance, final boolean manuallyReversed, ExternalId externalId, Long loanId, String externalLoanId) {
|
||||
BigDecimal outstandingLoanBalance, final boolean manuallyReversed, ExternalId externalId, Long loanId,
|
||||
ExternalId externalLoanId) {
|
||||
this(id, externalLoanId, null, null, transactionType, null, null, date, totalAmount, netDisbursalAmount, principalPortion,
|
||||
interestPortion, feeChargesPortion, penaltyChargesPortion, overpaymentPortion, unrecognizedIncomePortion, null, externalId,
|
||||
null, null, outstandingLoanBalance, null, manuallyReversed, ExternalId.empty(), null, loanId);
|
||||
@@ -300,7 +301,7 @@ public class LoanTransactionData {
|
||||
final LocalDate possibleNextRepaymentDate) {
|
||||
final Long id = null;
|
||||
final Long loanId = null;
|
||||
final String externalLoanId = null;
|
||||
final ExternalId externalLoanId = ExternalId.empty();
|
||||
final Long officeId = null;
|
||||
final String officeName = null;
|
||||
final PaymentDetailData paymentDetailData = null;
|
||||
@@ -331,7 +332,7 @@ public class LoanTransactionData {
|
||||
BigDecimal unrecognizedIncomePortion, Collection<PaymentTypeData> paymentOptions, final AccountTransferData transfer,
|
||||
final ExternalId externalId, final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
final LocalDate submittedOnDate, final boolean manuallyReversed, final LocalDate possibleNextRepaymentDate, Long loanId,
|
||||
String externalLoanId) {
|
||||
ExternalId externalLoanId) {
|
||||
this.id = id;
|
||||
this.loanId = loanId;
|
||||
this.externalLoanId = externalLoanId;
|
||||
|
||||
+13
-8
@@ -69,6 +69,7 @@ import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.security.service.RandomPasswordGenerator;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.holiday.service.HolidayUtil;
|
||||
@@ -194,7 +195,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
private String accountNumber;
|
||||
|
||||
@Column(name = "external_id")
|
||||
private String externalId;
|
||||
private ExternalId externalId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "client_id", nullable = true)
|
||||
@@ -1440,10 +1441,14 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
this.createStandingInstructionAtDisbursement = valueAsInput;
|
||||
}
|
||||
|
||||
if (command.isChangeInStringParameterNamed(EXTERNAL_ID, this.externalId)) {
|
||||
if (command.isChangeInStringParameterNamed(EXTERNAL_ID, this.externalId.getValue())) {
|
||||
final String newValue = command.stringValueOfParameterNamed(EXTERNAL_ID);
|
||||
actualChanges.put(EXTERNAL_ID, newValue);
|
||||
this.externalId = StringUtils.defaultIfEmpty(newValue, null);
|
||||
ExternalId externalId = ExternalIdFactory.produce(newValue);
|
||||
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
actualChanges.put(EXTERNAL_ID, externalId);
|
||||
this.externalId = externalId;
|
||||
}
|
||||
|
||||
// add clientId, groupId and loanType changes to actual changes
|
||||
@@ -2055,7 +2060,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
public void loanApplicationSubmittal(final LoanScheduleModel loanSchedule, final LoanApplicationTerms loanApplicationTerms,
|
||||
final LoanLifecycleStateMachine lifecycleStateMachine, final LocalDate submittedOn, final String externalId,
|
||||
final LoanLifecycleStateMachine lifecycleStateMachine, final LocalDate submittedOn, final ExternalId externalId,
|
||||
final boolean allowTransactionsOnHoliday, final List<Holiday> holidays, final WorkingDays workingDays,
|
||||
final boolean allowTransactionsOnNonWorkingDay) {
|
||||
|
||||
@@ -3793,7 +3798,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||
|
||||
ExternalId externalId = StringUtils.isBlank(txnExternalId) ? ExternalId.empty() : new ExternalId(txnExternalId);
|
||||
ExternalId externalId = ExternalIdFactory.produce(txnExternalId);
|
||||
|
||||
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
@@ -3887,7 +3892,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||
|
||||
ExternalId externalId = StringUtils.isBlank(txnExternalId) ? ExternalId.empty() : new ExternalId(txnExternalId);
|
||||
ExternalId externalId = ExternalIdFactory.produce(txnExternalId);
|
||||
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
@@ -6033,7 +6038,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return this.accountNumber;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
public ExternalId getExternalId() {
|
||||
return this.externalId;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -83,7 +83,8 @@ public interface LoanAccountDomainService {
|
||||
|
||||
void saveLoanWithDataIntegrityViolationChecks(Loan loan);
|
||||
|
||||
Map<String, Object> foreCloseLoan(Loan loan, LocalDate foreClourseDate, String noteText, ExternalId externalId);
|
||||
LoanTransaction foreCloseLoan(Loan loan, LocalDate foreClourseDate, String noteText, ExternalId externalId,
|
||||
Map<String, Object> changes);
|
||||
|
||||
/**
|
||||
* Disables all standing instructions linked to a closed loan
|
||||
|
||||
+3
-6
@@ -22,7 +22,6 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -708,11 +707,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> foreCloseLoan(final Loan loan, final LocalDate foreClosureDate, final String noteText,
|
||||
final ExternalId externalId) {
|
||||
public LoanTransaction foreCloseLoan(final Loan loan, final LocalDate foreClosureDate, final String noteText,
|
||||
final ExternalId externalId, Map<String, Object> changes) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanForeClosurePreBusinessEvent(loan));
|
||||
MonetaryCurrency currency = loan.getCurrency();
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
List<LoanTransaction> newTransactions = new ArrayList<>();
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
@@ -808,8 +806,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds, false);
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanForeClosurePostBusinessEvent(payment));
|
||||
return changes;
|
||||
|
||||
return payment;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
@@ -167,13 +168,13 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
@Query(FIND_BY_ACCOUNT_NUMBER)
|
||||
Loan findLoanAccountByAccountNumber(@Param("accountNumber") String accountNumber);
|
||||
|
||||
boolean existsByExternalId(@Param("externalId") String externalId);
|
||||
boolean existsByExternalId(@Param("externalId") ExternalId externalId);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED)
|
||||
List<Long> findAllNonClosedLoanIds();
|
||||
|
||||
@Query(FIND_ID_BY_EXTERNAL_ID)
|
||||
Long findIdByExternalId(@Param("externalId") String externalId);
|
||||
Long findIdByExternalId(@Param("externalId") ExternalId externalId);
|
||||
|
||||
@Query(FIND_ALL_NON_CLOSED_ONE_DAY_BEHIND)
|
||||
List<Long> findAllNonClosedLoanIdsOneDayBehind(@Param("last_closed_business_date") LocalDate businessDate);
|
||||
|
||||
+3
-2
@@ -23,6 +23,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
@@ -238,7 +239,7 @@ public class LoanRepositoryWrapper {
|
||||
return this.repository.findNonClosedLoanByAccountNumber(accountNumber);
|
||||
}
|
||||
|
||||
public boolean existLoanByExternalId(final String externalId) {
|
||||
public boolean existLoanByExternalId(final ExternalId externalId) {
|
||||
return this.repository.existsByExternalId(externalId);
|
||||
}
|
||||
|
||||
@@ -252,7 +253,7 @@ public class LoanRepositoryWrapper {
|
||||
return loan;
|
||||
}
|
||||
|
||||
public Long findIdByExternalId(String externalId) {
|
||||
public Long findIdByExternalId(ExternalId externalId) {
|
||||
return this.repository.findIdByExternalId(externalId);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-2
@@ -48,10 +48,12 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
|
||||
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
|
||||
@@ -217,8 +219,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json(), isMeetingMandatoryForJLGLoans, loanProduct);
|
||||
|
||||
// Validate If the externalId is already registered
|
||||
final String externalId = this.fromJsonHelper.extractStringNamed("externalId", command.parsedJson());
|
||||
if (StringUtils.isNotBlank(externalId)) {
|
||||
final String externalIdStr = this.fromJsonHelper.extractStringNamed("externalId", command.parsedJson());
|
||||
ExternalId externalId = ExternalIdFactory.produce(externalIdStr);
|
||||
if (!externalId.isEmpty()) {
|
||||
final boolean existByExternalId = this.loanRepositoryWrapper.existLoanByExternalId(externalId);
|
||||
if (existByExternalId) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.with.externalId.already.used",
|
||||
@@ -518,6 +521,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newLoanApplication.getId()) //
|
||||
.withEntityExternalId(newLoanApplication.getExternalId()) //
|
||||
.withOfficeId(newLoanApplication.getOfficeId()) //
|
||||
.withClientId(newLoanApplication.getClientId()) //
|
||||
.withGroupId(newLoanApplication.getGroupId()) //
|
||||
@@ -1165,6 +1169,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(loanId) //
|
||||
.withEntityExternalId(existingLoanApplication.getExternalId()) //
|
||||
.withOfficeId(existingLoanApplication.getOfficeId()) //
|
||||
.withClientId(existingLoanApplication.getClientId()) //
|
||||
.withGroupId(existingLoanApplication.getGroupId()) //
|
||||
@@ -1239,6 +1244,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(loanId) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1408,6 +1414,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1486,6 +1493,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1554,6 +1562,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1605,6 +1614,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
|
||||
+5
-1
@@ -33,7 +33,9 @@ import org.apache.fineract.infrastructure.codes.domain.CodeValueRepositoryWrappe
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.organisation.holiday.domain.Holiday;
|
||||
import org.apache.fineract.organisation.holiday.domain.HolidayRepository;
|
||||
import org.apache.fineract.organisation.holiday.domain.HolidayStatusType;
|
||||
@@ -107,6 +109,7 @@ public class LoanAssembler {
|
||||
private final LoanUtilService loanUtilService;
|
||||
private final RateAssembler rateAssembler;
|
||||
private final LoanLifecycleStateMachine defaultLoanLifecycleStateMachine;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
|
||||
public Loan assembleFrom(final Long accountId) {
|
||||
final Loan loanAccount = this.loanRepository.findOneWithNotFoundDetection(accountId, true);
|
||||
@@ -287,7 +290,8 @@ public class LoanAssembler {
|
||||
loanApplication.updateTransactionProcessingStrategy(transactionProcessingStrategyCode, transactionProcessingStrategyName);
|
||||
}
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
final String externalIdStr = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
ExternalId externalId = externalIdFactory.create(externalIdStr);
|
||||
final LocalDate submittedOnDate = this.fromApiJsonHelper.extractLocalDateNamed("submittedOnDate", element);
|
||||
|
||||
if (loanApplication == null) {
|
||||
|
||||
+2
-1
@@ -631,7 +631,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanChargeId) //
|
||||
.withEntityExternalId(loanCharge.getExternalId()) //
|
||||
.withSubEntityId(loanTransaction.getId()).withSubEntityExternalId(loanTransaction.getExternalId())
|
||||
.withSubEntityId(loanTransaction.getId()) //
|
||||
.withSubEntityExternalId(loanTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
|
||||
+1
-1
@@ -158,5 +158,5 @@ public interface LoanReadPlatformService {
|
||||
|
||||
Long retrieveLoanTransactionIdByExternalId(ExternalId externalId);
|
||||
|
||||
Long retrieveLoanIdByExternalId(String externalId);
|
||||
Long retrieveLoanIdByExternalId(ExternalId externalId);
|
||||
}
|
||||
|
||||
+9
-7
@@ -696,7 +696,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
final String externalIdStr = rs.getString("externalId");
|
||||
final ExternalId externalId = ExternalIdFactory.produce(externalIdStr);
|
||||
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientAccountNo = rs.getString("clientAccountNo");
|
||||
@@ -1345,7 +1346,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final Long loanId = rs.getLong("loanId");
|
||||
final String externalLoanId = rs.getString("externalLoanId");
|
||||
final String externalLoanIdStr = rs.getString("externalLoanId");
|
||||
final ExternalId externalLoanId = ExternalIdFactory.produce(externalLoanIdStr);
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final int transactionTypeInt = JdbcSupport.getInteger(rs, "transactionType");
|
||||
@@ -2033,7 +2035,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final Long loanId = rs.getLong("loanId");
|
||||
final String externalLoanId = rs.getString("externalLoanId");
|
||||
final String externalLoanIdStr = rs.getString("externalLoanId");
|
||||
final ExternalId externalLoanId = ExternalIdFactory.produce(externalLoanIdStr);
|
||||
final int transactionTypeInt = JdbcSupport.getInteger(rs, "transactionType");
|
||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(transactionTypeInt);
|
||||
|
||||
@@ -2186,7 +2189,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
private LoanTransactionData retrieveRefundTemplate(Long loanId, LoanTransactionType loanTransactionType,
|
||||
Collection<PaymentTypeData> paymentOptions, MonetaryCurrency currency, BigDecimal transactionAmount, BigDecimal netDisbursal,
|
||||
String externalLoanId) {
|
||||
ExternalId externalLoanId) {
|
||||
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||
|
||||
@@ -2365,7 +2368,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final BigDecimal netDisbursalAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "netDisbursalAmount");
|
||||
final Long id = null;
|
||||
final Long loanId = null;
|
||||
final String externalLoanId = null;
|
||||
final Long officeId = null;
|
||||
final String officeName = null;
|
||||
boolean manuallyReversed = false;
|
||||
@@ -2374,7 +2376,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final BigDecimal fixedEmiAmount = null;
|
||||
return new LoanTransactionData(id, officeId, officeName, transactionType, paymentDetailData, currencyData, date, totalDue,
|
||||
netDisbursalAmount, principalPortion, interestDue, feeDue, penaltyDue, overPaymentPortion, ExternalId.empty(), transfer,
|
||||
fixedEmiAmount, outstandingLoanBalance, unrecognizedIncomePortion, manuallyReversed, loanId, externalLoanId);
|
||||
fixedEmiAmount, outstandingLoanBalance, unrecognizedIncomePortion, manuallyReversed, loanId, ExternalId.empty());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2419,7 +2421,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveLoanIdByExternalId(String externalId) {
|
||||
public Long retrieveLoanIdByExternalId(ExternalId externalId) {
|
||||
return loanRepositoryWrapper.findIdByExternalId(externalId);
|
||||
}
|
||||
|
||||
|
||||
+21
-6
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -506,11 +507,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanDisbursalBusinessEvent(loan));
|
||||
|
||||
Long entityId = loan.getId();
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
ExternalId externalId = loan.getExternalId();
|
||||
|
||||
// During a disbursement, the entityId should be the disbursement transaction id
|
||||
if (!isAccountTransfer) {
|
||||
LoanTransaction disbursalTransaction = loan.getLoanTransactions().get(loan.getLoanTransactions().size() - 1);
|
||||
// If accounting is not periodic accrual, the last transaction might be the accrual not the disbursement
|
||||
LoanTransaction disbursalTransaction = Lists.reverse(loan.getLoanTransactions()).stream()
|
||||
.filter(e -> LoanTransactionType.DISBURSEMENT.equals(e.getTypeOf())).findFirst().orElseThrow();
|
||||
entityId = disbursalTransaction.getId();
|
||||
externalId = disbursalTransaction.getExternalId();
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanDisbursalTransactionBusinessEvent(disbursalTransaction));
|
||||
@@ -859,6 +862,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1556,6 +1560,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
result = new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanId) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1616,6 +1621,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanId) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1785,6 +1791,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanId) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -1862,6 +1869,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanId) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -2353,7 +2361,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public CommandProcessingResult recoverFromGuarantor(final Long loanId) {
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
this.guarantorDomainService.transferFundsFromGuarantor(loan);
|
||||
return new CommandProcessingResultBuilder().withLoanId(loanId).build();
|
||||
return new CommandProcessingResultBuilder().withLoanId(loanId).withEntityId(loanId).withEntityExternalId(loan.getExternalId())
|
||||
.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@@ -2476,6 +2485,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -2585,6 +2595,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loan.getId()) //
|
||||
.withEntityExternalId(loan.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -2603,7 +2614,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
this.loanEventApiJsonValidator.validateLoanForeclosure(command.json());
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionDate", transactionDate);
|
||||
// Got changed to match with the rest of the APIs
|
||||
changes.put("dateFormat", command.dateFormat());
|
||||
changes.put("transactionDate", command.stringValueOfParameterNamed(LoanApiConstants.transactionDateParamName));
|
||||
changes.put("externalId", externalId);
|
||||
|
||||
String noteText = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParamName, element);
|
||||
@@ -2619,12 +2632,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.getRepaymentScheduleInstallments(), loan,
|
||||
loanRescheduleRequest);
|
||||
|
||||
final Map<String, Object> modifications = this.loanAccountDomainService.foreCloseLoan(loan, transactionDate, noteText, externalId);
|
||||
changes.putAll(modifications);
|
||||
LoanTransaction foreclosureTransaction = this.loanAccountDomainService.foreCloseLoan(loan, transactionDate, noteText, externalId,
|
||||
changes);
|
||||
|
||||
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
|
||||
return commandProcessingResultBuilder //
|
||||
.withLoanId(loanId) //
|
||||
.withEntityId(foreclosureTransaction.getId()) //
|
||||
.withEntityExternalId(foreclosureTransaction.getExternalId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
|
||||
+2
-1
@@ -37,6 +37,7 @@ import org.apache.fineract.avro.loan.v1.RepaymentDueDataV1;
|
||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentDueBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper;
|
||||
@@ -87,7 +88,7 @@ public class LoanRepaymentBusinessEventSerializerTest {
|
||||
|
||||
when(loanForProcessing.getId()).thenReturn(1L);
|
||||
when(loanForProcessing.getAccountNumber()).thenReturn("0001");
|
||||
when(loanForProcessing.getExternalId()).thenReturn("externalId");
|
||||
when(loanForProcessing.getExternalId()).thenReturn(ExternalIdFactory.produce("externalId"));
|
||||
when(loanForProcessing.getLoanSummary()).thenReturn(loanSummary);
|
||||
when(loanSummary.getTotalOutstanding()).thenReturn(BigDecimal.valueOf(0.0));
|
||||
when(loanForProcessing.getCurrency()).thenReturn(loanCurrency);
|
||||
|
||||
+247
-1
@@ -31,18 +31,29 @@ import io.restassured.specification.ResponseSpecification;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.apache.fineract.client.models.BusinessDateRequest;
|
||||
import org.apache.fineract.client.models.DeleteLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyTagHistoryResponse;
|
||||
import org.apache.fineract.client.models.GetLoansApprovalTemplateResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdChargesTemplateResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
|
||||
import org.apache.fineract.client.models.PostClientsResponse;
|
||||
import org.apache.fineract.client.models.PostDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.models.PostDelinquencyRangeResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
|
||||
@@ -50,8 +61,12 @@ import org.apache.fineract.client.models.PutChargeTransactionChangesRequest;
|
||||
import org.apache.fineract.client.models.PutChargeTransactionChangesResponse;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdChargesChargeIdRequest;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.util.CallFailedRuntimeException;
|
||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||
import org.apache.fineract.integrationtests.client.IntegrationTest;
|
||||
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
@@ -61,6 +76,9 @@ import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
|
||||
import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
|
||||
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
|
||||
import org.apache.fineract.integrationtests.common.products.DelinquencyRangesHelper;
|
||||
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -827,13 +845,241 @@ public class ExternalIdSupportIntegrationTest extends IntegrationTest {
|
||||
assertTrue(exception.getMessage().contains("error.msg.loanCharge.external.id.invalid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loan() {
|
||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, 50, true);
|
||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
|
||||
new BusinessDateHelper().updateBusinessDate(new BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
|
||||
.date("2022.10.10").dateFormat("yyyy.MM.dd").locale("en"));
|
||||
try {
|
||||
ArrayList<Integer> rangeIds = new ArrayList<>();
|
||||
// First Range
|
||||
String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
PostDelinquencyRangeResponse delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec,
|
||||
responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
|
||||
|
||||
GetDelinquencyRangesResponse range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
|
||||
delinquencyRangeResponse.getResourceId());
|
||||
|
||||
// Second Range
|
||||
delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
|
||||
String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
|
||||
PostDelinquencyBucketResponse delinquencyBucketResponse = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
|
||||
responseSpec, jsonBucket);
|
||||
|
||||
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth()
|
||||
.withRepaymentAfterEvery("1").withNumberOfRepayments("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0")
|
||||
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment()
|
||||
.withInterestTypeAsDecliningBalance().withAccountingRuleAsNone()
|
||||
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withDaysInMonth("30").withDaysInYear("365")
|
||||
.withMoratorium("0", "0").withDelinquencyBucket(delinquencyBucketResponse.getResourceId())
|
||||
.withInArrearsTolerance("1001").withMultiDisburse().withDisallowExpectedDisbursements(true).build(null);
|
||||
final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||
|
||||
final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
|
||||
|
||||
String loanExternalIdStr = UUID.randomUUID().toString();
|
||||
final HashMap loan = applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr);
|
||||
Integer loanId = (Integer) loan.get("resourceId");
|
||||
String resourceExternalId = (String) loan.get("resourceExternalId");
|
||||
assertEquals(loanExternalIdStr, resourceExternalId);
|
||||
|
||||
LocalDate actualDate = LocalDate.of(2022, 10, 10);
|
||||
|
||||
GetLoansApprovalTemplateResponse loanApprovalResult = this.loanTransactionHelper.getLoanApprovalTemplate(loanExternalIdStr);
|
||||
assertEquals(actualDate, loanApprovalResult.getApprovalDate());
|
||||
assertEquals(1000.0, loanApprovalResult.getApprovalAmount());
|
||||
assertEquals(1000.0, loanApprovalResult.getNetDisbursalAmount());
|
||||
|
||||
GetLoansLoanIdResponse loanDetailsResult = this.loanTransactionHelper.getLoanDetails(loanExternalIdStr);
|
||||
assertEquals(loanExternalIdStr, loanDetailsResult.getExternalId());
|
||||
|
||||
this.loanTransactionHelper.approveLoan("02 September 2022", loanId);
|
||||
String txnExternalIdStr = UUID.randomUUID().toString();
|
||||
final HashMap disbursedLoanResult = this.loanTransactionHelper.disburseLoan("03 September 2022", loanId, "1000",
|
||||
txnExternalIdStr);
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
assertEquals(txnExternalIdStr, disbursedLoanResult.get("resourceExternalId"));
|
||||
|
||||
String txnExternalIdStr2 = UUID.randomUUID().toString();
|
||||
final HashMap disbursedLoanResult2 = this.loanTransactionHelper.disburseLoan("04 September 2022", loanId, "1000",
|
||||
txnExternalIdStr2);
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
assertEquals(txnExternalIdStr2, disbursedLoanResult2.get("resourceExternalId"));
|
||||
|
||||
PutLoansLoanIdResponse markLoanAsFraudResult = this.loanTransactionHelper.modifyLoanApplication(loanExternalIdStr,
|
||||
"markAsFraud", new PutLoansLoanIdRequest().fraud(true));
|
||||
assertEquals(loanExternalIdStr, markLoanAsFraudResult.getResourceExternalId());
|
||||
|
||||
List<GetDelinquencyTagHistoryResponse> delinquencyTagHistoryResponseResult = this.loanTransactionHelper
|
||||
.getLoanDelinquencyTags(loanExternalIdStr);
|
||||
assertEquals(1, delinquencyTagHistoryResponseResult.size());
|
||||
assertEquals((long) loanId, delinquencyTagHistoryResponseResult.get(0).getLoanId());
|
||||
|
||||
String loanExternalIdStr2 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr2);
|
||||
|
||||
PutLoansLoanIdResponse modifyLoanApplicationResult = this.loanTransactionHelper.modifyLoanApplication(loanExternalIdStr2,
|
||||
"modify",
|
||||
new PutLoansLoanIdRequest().submittedOnDate("31 August 2022").dateFormat("dd MMMM yyyy").locale("en")
|
||||
.loanType("individual").productId(loanProductID).clientId(client.getClientId()).interestType(0)
|
||||
.interestCalculationPeriodType(1).interestRatePerPeriod(0).isEqualAmortization(false).loanTermFrequency(30)
|
||||
.loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1).principal(10000L)
|
||||
.repaymentEvery(30).repaymentFrequencyType(0).transactionProcessingStrategyCode("mifos-standard-strategy")
|
||||
.expectedDisbursementDate("2 September 2022").amortizationType(1));
|
||||
|
||||
assertEquals(loanExternalIdStr2, modifyLoanApplicationResult.getResourceExternalId());
|
||||
DeleteLoansLoanIdResponse deleteLoanApplicationResult = this.loanTransactionHelper.deleteLoanApplication(loanExternalIdStr2);
|
||||
assertEquals(loanExternalIdStr2, deleteLoanApplicationResult.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr3 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr3);
|
||||
PostLoansLoanIdResponse result = this.loanTransactionHelper.rejectLoan(loanExternalIdStr3,
|
||||
new PostLoansLoanIdRequest().rejectedOnDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr3, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr4 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr4);
|
||||
result = this.loanTransactionHelper.withdrawnByApplicantLoan(loanExternalIdStr4,
|
||||
new PostLoansLoanIdRequest().withdrawnOnDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr4, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr5 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr5);
|
||||
this.loanTransactionHelper.approveLoan(loanExternalIdStr5, new PostLoansLoanIdRequest().approvedOnDate("2 September 2022")
|
||||
.approvedLoanAmount("1000").expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
result = this.loanTransactionHelper.disburseLoan(loanExternalIdStr5, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("2 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
// It's commented out for now, till it got fixed to return the loan externalId as well
|
||||
// assertEquals(loanExternalIdStr5, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr6 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr6);
|
||||
this.loanTransactionHelper.approveLoan(loanExternalIdStr6, new PostLoansLoanIdRequest().approvedOnDate("2 September 2022")
|
||||
.approvedLoanAmount("1000").expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
result = this.loanTransactionHelper.undoApprovalLoan(loanExternalIdStr6, new PostLoansLoanIdRequest());
|
||||
assertEquals(loanExternalIdStr6, result.getResourceExternalId());
|
||||
|
||||
final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec,
|
||||
client.getClientId().intValue(), "10000.0");
|
||||
|
||||
String loanExternalIdStr7 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr7, savingsId.toString());
|
||||
this.loanTransactionHelper.approveLoan(loanExternalIdStr7, new PostLoansLoanIdRequest().approvedOnDate("2 September 2022")
|
||||
.approvedLoanAmount("1000").expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
result = this.loanTransactionHelper.disburseToSavingsLoan(loanExternalIdStr7, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("2 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr7, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr8 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr8);
|
||||
this.loanTransactionHelper.approveLoan(loanExternalIdStr8, new PostLoansLoanIdRequest().approvedOnDate("2 September 2022")
|
||||
.approvedLoanAmount("1000").expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
this.loanTransactionHelper.disburseLoan(loanExternalIdStr8, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("2 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
result = this.loanTransactionHelper.undoDisbursalLoan(loanExternalIdStr8, new PostLoansLoanIdRequest());
|
||||
assertEquals(loanExternalIdStr8, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr9 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr9);
|
||||
this.loanTransactionHelper.approveLoan(loanExternalIdStr9, new PostLoansLoanIdRequest().approvedOnDate("2 September 2022")
|
||||
.approvedLoanAmount("1000").expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
this.loanTransactionHelper.disburseLoan(loanExternalIdStr9, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("2 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
this.loanTransactionHelper.disburseLoan(loanExternalIdStr9, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("3 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
result = this.loanTransactionHelper.undoLastDisbursalLoan(loanExternalIdStr9, new PostLoansLoanIdRequest());
|
||||
assertEquals(loanExternalIdStr9, result.getResourceExternalId());
|
||||
|
||||
Integer loanOfficerId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
|
||||
String loanExternalIdStr10 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr10);
|
||||
result = this.loanTransactionHelper.assignLoanOfficerLoan(loanExternalIdStr10, new PostLoansLoanIdRequest()
|
||||
.assignmentDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy").toLoanOfficerId(loanOfficerId));
|
||||
assertEquals(loanExternalIdStr10, result.getResourceExternalId());
|
||||
result = this.loanTransactionHelper.unassignLoanOfficerLoan(loanExternalIdStr10,
|
||||
new PostLoansLoanIdRequest().unassignedDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr10, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr11 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr11);
|
||||
result = this.loanTransactionHelper.recoverGuaranteesLoan(loanExternalIdStr11, new PostLoansLoanIdRequest());
|
||||
assertEquals(loanExternalIdStr11, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr12 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr12);
|
||||
result = this.loanTransactionHelper.assignDelinquencyLoan(loanExternalIdStr12, new PostLoansLoanIdRequest());
|
||||
assertEquals(loanExternalIdStr12, result.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr13 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr13);
|
||||
result = this.loanTransactionHelper.approveLoan(loanExternalIdStr13,
|
||||
new PostLoansLoanIdRequest().approvedOnDate("2 September 2022").approvedLoanAmount("1000")
|
||||
.expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr13, result.getResourceExternalId());
|
||||
|
||||
PostLoansLoanIdTransactionsResponse closeRescheduleResult = this.loanTransactionHelper.closeRescheduledLoan(loanExternalIdStr13,
|
||||
new PostLoansLoanIdTransactionsRequest().transactionDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr13, closeRescheduleResult.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr14 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr14);
|
||||
String transactionExternalId = UUID.randomUUID().toString();
|
||||
result = this.loanTransactionHelper.approveLoan(loanExternalIdStr14,
|
||||
new PostLoansLoanIdRequest().approvedOnDate("2 September 2022").approvedLoanAmount("1000")
|
||||
.expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr14, result.getResourceExternalId());
|
||||
this.loanTransactionHelper.disburseLoan(loanExternalIdStr14, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("2 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
PostLoansLoanIdTransactionsResponse closeResult = this.loanTransactionHelper.closeLoan(loanExternalIdStr14,
|
||||
new PostLoansLoanIdTransactionsRequest().transactionDate("3 September 2022").locale("en").dateFormat("dd MMMM yyyy")
|
||||
.externalId(transactionExternalId));
|
||||
assertEquals(transactionExternalId, closeResult.getResourceExternalId());
|
||||
|
||||
String loanExternalIdStr15 = UUID.randomUUID().toString();
|
||||
String transactionExternalId2 = UUID.randomUUID().toString();
|
||||
applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr15);
|
||||
result = this.loanTransactionHelper.approveLoan(loanExternalIdStr15,
|
||||
new PostLoansLoanIdRequest().approvedOnDate("2 September 2022").approvedLoanAmount("1000")
|
||||
.expectedDisbursementDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
this.loanTransactionHelper.disburseLoan(loanExternalIdStr15, new PostLoansLoanIdRequest()
|
||||
.actualDisbursementDate("2 September 2022").transactionAmount("1000").locale("en").dateFormat("dd MMMM yyyy"));
|
||||
assertEquals(loanExternalIdStr15, result.getResourceExternalId());
|
||||
PostLoansLoanIdTransactionsResponse forecloseResult = this.loanTransactionHelper.forecloseLoan(loanExternalIdStr15,
|
||||
new PostLoansLoanIdTransactionsRequest().transactionDate("2 September 2022").locale("en").dateFormat("dd MMMM yyyy")
|
||||
.externalId(transactionExternalId2));
|
||||
assertEquals(transactionExternalId2, forecloseResult.getResourceExternalId());
|
||||
|
||||
} finally {
|
||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
|
||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, 50, false);
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String externalId,
|
||||
final String linkAccountId) {
|
||||
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
|
||||
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1")
|
||||
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance()
|
||||
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
|
||||
.withExpectedDisbursementDate("03 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual")
|
||||
.withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), linkAccountId);
|
||||
return (HashMap) this.loanTransactionHelper.createLoanAccount(loanApplicationJSON, "");
|
||||
}
|
||||
|
||||
private HashMap applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String externalId) {
|
||||
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
|
||||
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1")
|
||||
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance()
|
||||
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
|
||||
.withExpectedDisbursementDate("03 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual")
|
||||
.withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null);
|
||||
.withInArrearsTolerance("1001").withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null);
|
||||
return (HashMap) this.loanTransactionHelper.createLoanAccount(loanApplicationJSON, "");
|
||||
}
|
||||
}
|
||||
|
||||
+20
@@ -79,6 +79,8 @@ public class LoanApplicationTestBuilder {
|
||||
private List<Map<String, Object>> approvalFormData = null;
|
||||
private String fixedPrincipalPercentagePerInstallment;
|
||||
private String interestChargedFromDate;
|
||||
private String linkAccountId;
|
||||
private String inArrearsTolerance;
|
||||
|
||||
public String build(final String clientID, final String groupID, final String loanProductId, final String savingsID) {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
@@ -169,6 +171,14 @@ public class LoanApplicationTestBuilder {
|
||||
map.put("linkAccountId", savingsID);
|
||||
}
|
||||
|
||||
if (this.linkAccountId != null) {
|
||||
map.put("linkAccountId", this.linkAccountId);
|
||||
}
|
||||
|
||||
if (this.inArrearsTolerance != null) {
|
||||
map.put("inArrearsTolerance", this.inArrearsTolerance);
|
||||
}
|
||||
|
||||
if (graceOnPrincipalPayment != null) {
|
||||
map.put("graceOnPrincipalPayment", graceOnPrincipalPayment);
|
||||
}
|
||||
@@ -210,6 +220,11 @@ public class LoanApplicationTestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanApplicationTestBuilder withLinkedAccount(String linkAccountId) {
|
||||
this.linkAccountId = linkAccountId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanApplicationTestBuilder withLoanTermFrequencyAsMonths() {
|
||||
this.loanTermFrequencyType = MONTHS;
|
||||
return this;
|
||||
@@ -398,4 +413,9 @@ public class LoanApplicationTestBuilder {
|
||||
this.interestChargedFromDate = interestChargedFromDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanApplicationTestBuilder withInArrearsTolerance(String amount) {
|
||||
this.inArrearsTolerance = amount;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -136,6 +136,7 @@ public class LoanProductTestBuilder {
|
||||
private String fixedPrincipalPercentagePerInstallment;
|
||||
private String installmentAmountInMultiplesOf;
|
||||
private boolean canDefineInstallmentAmount;
|
||||
private Integer delinquencyBucketId;
|
||||
|
||||
public String build(final String chargeId) {
|
||||
final HashMap<String, Object> map = build(chargeId, null);
|
||||
@@ -254,6 +255,10 @@ public class LoanProductTestBuilder {
|
||||
map.put("delinquencyBucketId", delinquencyBucketId);
|
||||
}
|
||||
|
||||
if (this.delinquencyBucketId != null) {
|
||||
map.put("delinquencyBucketId", this.delinquencyBucketId);
|
||||
}
|
||||
|
||||
if (this.feeToIncomeAccountMappings != null) {
|
||||
map.put("feeToIncomeAccountMappings", this.feeToIncomeAccountMappings);
|
||||
}
|
||||
@@ -269,6 +274,11 @@ public class LoanProductTestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanProductTestBuilder withDelinquencyBucket(Integer delinquencyBucketId) {
|
||||
this.delinquencyBucketId = delinquencyBucketId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanProductTestBuilder withMinPrincipal(final String minPrincipal) {
|
||||
this.minPrincipal = minPrincipal;
|
||||
return this;
|
||||
|
||||
+84
@@ -43,8 +43,10 @@ import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.client.models.DeleteLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyTagHistoryResponse;
|
||||
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansApprovalTemplateResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdChargesTemplateResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdCollectionData;
|
||||
@@ -59,6 +61,7 @@ import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
@@ -67,6 +70,7 @@ import org.apache.fineract.client.models.PutChargeTransactionChangesRequest;
|
||||
import org.apache.fineract.client.models.PutChargeTransactionChangesResponse;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdChargesChargeIdRequest;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
import org.apache.fineract.integrationtests.client.IntegrationTest;
|
||||
@@ -178,6 +182,11 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return GSON.fromJson(response, PutLoansLoanIdResponse.class);
|
||||
}
|
||||
|
||||
public PutLoansLoanIdResponse modifyLoanApplication(final String loanExternalId, final String command,
|
||||
final PutLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.modifyLoanApplication1(loanExternalId, request, command));
|
||||
}
|
||||
|
||||
public ArrayList getLoanRepaymentSchedule(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer loanID) {
|
||||
final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=repaymentSchedule&" + Utils.TENANT_IDENTIFIER;
|
||||
@@ -920,6 +929,10 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return ok(fineract().loans.retrieveLoan(loanId, false, "all", null, null));
|
||||
}
|
||||
|
||||
public GetLoansLoanIdResponse getLoanDetails(final String loanExternalId) {
|
||||
return ok(fineract().loans.retrieveLoan1(loanExternalId, false, "all", null, null));
|
||||
}
|
||||
|
||||
public GetLoansLoanIdTransactionsTransactionIdResponse getLoanTransaction(final Integer loanId, final Integer txnId) {
|
||||
final String GET_LOAN_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/transactions/" + txnId + "?"
|
||||
+ Utils.TENANT_IDENTIFIER;
|
||||
@@ -1626,4 +1639,75 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, command, dateFormat, transactionDate, locale));
|
||||
}
|
||||
|
||||
public GetLoansApprovalTemplateResponse getLoanApprovalTemplate(String loanExternalIdStr) {
|
||||
return ok(fineract().loans.retrieveApprovalTemplate1(loanExternalIdStr, "approval"));
|
||||
}
|
||||
|
||||
public DeleteLoansLoanIdResponse deleteLoanApplication(String loanExternalId) {
|
||||
return ok(fineract().loans.deleteLoanApplication1(loanExternalId));
|
||||
}
|
||||
|
||||
public List<GetDelinquencyTagHistoryResponse> getLoanDelinquencyTags(String loanExternalId) {
|
||||
return ok(fineract().loans.getDelinquencyTagHistory1(loanExternalId));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse approveLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "approve"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse rejectLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "reject"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse withdrawnByApplicantLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "withdrawnByApplicant"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse disburseLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "disburse"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse disburseToSavingsLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "disburseToSavings"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse undoApprovalLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "undoapproval"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse undoDisbursalLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "undodisbursal"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse undoLastDisbursalLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "undolastdisbursal"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse assignLoanOfficerLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "assignloanofficer"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse unassignLoanOfficerLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "unassignloanofficer"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse recoverGuaranteesLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "recoverGuarantees"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdResponse assignDelinquencyLoan(String loanExternalId, PostLoansLoanIdRequest request) {
|
||||
return ok(fineract().loans.stateTransitions1(loanExternalId, request, "assigndelinquency"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse closeRescheduledLoan(String loanExternalId, PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "close-rescheduled"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse closeLoan(String loanExternalId, PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "close"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse forecloseLoan(String loanExternalId, PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "foreclosure"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user