| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.fineract.portfolio.loanaccount.api; |
| |
| import static org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations.interestType; |
| |
| import com.google.gson.JsonElement; |
| import io.swagger.v3.oas.annotations.Operation; |
| import io.swagger.v3.oas.annotations.Parameter; |
| import io.swagger.v3.oas.annotations.media.Content; |
| import io.swagger.v3.oas.annotations.media.Schema; |
| import io.swagger.v3.oas.annotations.parameters.RequestBody; |
| import io.swagger.v3.oas.annotations.responses.ApiResponse; |
| import io.swagger.v3.oas.annotations.responses.ApiResponses; |
| import io.swagger.v3.oas.annotations.tags.Tag; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import javax.ws.rs.Consumes; |
| import javax.ws.rs.DELETE; |
| import javax.ws.rs.DefaultValue; |
| import javax.ws.rs.GET; |
| import javax.ws.rs.POST; |
| import javax.ws.rs.PUT; |
| import javax.ws.rs.Path; |
| import javax.ws.rs.PathParam; |
| import javax.ws.rs.Produces; |
| import javax.ws.rs.QueryParam; |
| import javax.ws.rs.core.Context; |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.UriInfo; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.fineract.commands.domain.CommandWrapper; |
| import org.apache.fineract.commands.service.CommandWrapperBuilder; |
| import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService; |
| import org.apache.fineract.infrastructure.bulkimport.data.GlobalEntityType; |
| import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookPopulatorService; |
| import org.apache.fineract.infrastructure.bulkimport.service.BulkImportWorkbookService; |
| import org.apache.fineract.infrastructure.codes.data.CodeValueData; |
| import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService; |
| import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; |
| import org.apache.fineract.infrastructure.core.api.ApiParameterHelper; |
| import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper; |
| 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.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.Page; |
| import org.apache.fineract.infrastructure.core.service.SearchParameters; |
| import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant; |
| import org.apache.fineract.infrastructure.dataqueries.data.DatatableData; |
| import org.apache.fineract.infrastructure.dataqueries.data.EntityTables; |
| import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum; |
| import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService; |
| import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; |
| import org.apache.fineract.organisation.monetary.data.CurrencyData; |
| import org.apache.fineract.organisation.staff.data.StaffData; |
| import org.apache.fineract.portfolio.account.PortfolioAccountType; |
| import org.apache.fineract.portfolio.account.data.PortfolioAccountDTO; |
| import org.apache.fineract.portfolio.account.data.PortfolioAccountData; |
| import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService; |
| import org.apache.fineract.portfolio.account.service.PortfolioAccountReadPlatformService; |
| import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData; |
| import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService; |
| import org.apache.fineract.portfolio.calendar.data.CalendarData; |
| import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType; |
| import org.apache.fineract.portfolio.calendar.service.CalendarReadPlatformService; |
| import org.apache.fineract.portfolio.charge.data.ChargeData; |
| import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; |
| import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService; |
| import org.apache.fineract.portfolio.client.data.ClientData; |
| import org.apache.fineract.portfolio.collateral.data.CollateralData; |
| import org.apache.fineract.portfolio.collateral.service.CollateralReadPlatformService; |
| import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData; |
| import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService; |
| import org.apache.fineract.portfolio.creditscorecard.data.CreditScorecardData; |
| import org.apache.fineract.portfolio.creditscorecard.data.CreditScorecardFeatureData; |
| import org.apache.fineract.portfolio.creditscorecard.provider.ScorecardServiceProvider; |
| import org.apache.fineract.portfolio.creditscorecard.service.CreditScorecardReadPlatformService; |
| import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData; |
| import org.apache.fineract.portfolio.fund.data.FundData; |
| import org.apache.fineract.portfolio.fund.service.FundReadPlatformService; |
| import org.apache.fineract.portfolio.group.data.GroupGeneralData; |
| import org.apache.fineract.portfolio.group.service.GroupReadPlatformService; |
| import org.apache.fineract.portfolio.loanaccount.data.CollectionData; |
| import org.apache.fineract.portfolio.loanaccount.data.DisbursementData; |
| import org.apache.fineract.portfolio.loanaccount.data.GlimRepaymentTemplate; |
| import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; |
| import org.apache.fineract.portfolio.loanaccount.data.LoanApprovalData; |
| import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData; |
| import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData; |
| import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData; |
| import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData; |
| import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData; |
| import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; |
| import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType; |
| 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; |
| import org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorReadPlatformService; |
| import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData; |
| import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel; |
| import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService; |
| import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryReadPlatformService; |
| import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformService; |
| import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService; |
| import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService; |
| import org.apache.fineract.portfolio.loanproduct.LoanProductConstants; |
| import org.apache.fineract.portfolio.loanproduct.data.LoanProductData; |
| import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData; |
| import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod; |
| import org.apache.fineract.portfolio.loanproduct.service.LoanDropdownReadPlatformService; |
| import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService; |
| import org.apache.fineract.portfolio.note.data.NoteData; |
| import org.apache.fineract.portfolio.note.domain.NoteType; |
| import org.apache.fineract.portfolio.note.service.NoteReadPlatformService; |
| import org.apache.fineract.portfolio.rate.data.RateData; |
| import org.apache.fineract.portfolio.rate.service.RateReadService; |
| import org.apache.fineract.portfolio.savings.DepositAccountType; |
| import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType; |
| import org.glassfish.jersey.media.multipart.FormDataContentDisposition; |
| import org.glassfish.jersey.media.multipart.FormDataParam; |
| import org.springframework.context.annotation.Scope; |
| import org.springframework.stereotype.Component; |
| import org.springframework.util.CollectionUtils; |
| |
| @Path("/loans") |
| @Component |
| @Scope("singleton") |
| @Tag(name = "Loans", description = "The API concept of loans models the loan application process and the loan contract/monitoring process.\n" |
| + "\n" + "Field Descriptions\n" + "accountNo\n" |
| + "The account no. associated with this loan. Is auto generated if not provided at loan application creation time.\n" |
| + "externalId\n" + "A place to put an external reference for this loan e.g. The ID another system uses.\n" |
| + "If provided, it must be unique.\n" + "fundId\n" + "Optional: For associating a loan with a given fund.\n" + "loanOfficerId\n" |
| + "Optional: For associating a loan with a given staff member who is a loan officer.\n" + "loanPurposeId\n" |
| + "Optional: For marking a loan with a given loan purpose option. Loan purposes are configurable and can be setup by system admin through code/code values screens.\n" |
| + "principal\n" + "The loan amount to be disbursed to through loan.\n" + "loanTermFrequency\n" + "The length of loan term\n" |
| + "Used like: loanTermFrequency loanTermFrequencyType\n" + "e.g. 12 Months\n" + "loanTermFrequencyType\n" |
| + "The loan term period to use. Used like: loanTermFrequency loanTermFrequencyType\n" |
| + "e.g. 12 Months Example Values: 0=Days, 1=Weeks, 2=Months, 3=Years\n" + "numberOfRepayments\n" |
| + "Number of installments to repay.\n" + "Used like: numberOfRepayments Every repaymentEvery repaymentFrequencyType\n" |
| + "e.g. 10 (repayments) Every 12 Weeks\n" + "repaymentEvery\n" |
| + "Used like: numberOfRepayments Every repaymentEvery repaymentFrequencyType\n" + "e.g. 10 (repayments) Every 12 Weeks\n" |
| + "repaymentFrequencyType\n" + "Used like: numberOfRepayments Every repaymentEvery repaymentFrequencyType\n" |
| + "e.g. 10 (repayments) Every 12 Weeks \n" + "Example Values: 0=Days, 1=Weeks, 2=Months\n" + "interestRatePerPeriod\n" |
| + "Interest Rate.\n" + "Used like: interestRatePerPeriod % interestRateFrequencyType - interestType\n" |
| + "e.g. 12.0000% Per year - Declining Balance\n" + "interestRateFrequencyType\n" |
| + "Used like: interestRatePerPeriod% interestRateFrequencyType - interestType\n" + "e.g. 12.0000% Per year - Declining Balance \n" |
| + "Example Values: 2=Per month, 3=Per year\n" + "graceOnPrincipalPayment\n" |
| + "Optional: Integer - represents the number of repayment periods that grace should apply to the principal component of a repayment period.\n" |
| + "graceOnInterestPayment\n" |
| + "Optional: Integer - represents the number of repayment periods that grace should apply to the interest component of a repayment period. Interest is still calculated but offset to later repayment periods.\n" |
| + "graceOnInterestCharged\n" + "Optional: Integer - represents the number of repayment periods that should be interest-free.\n" |
| + "graceOnArrearsAgeing\n" |
| + "Optional: Integer - Used in Arrears calculation to only take into account loans that are more than graceOnArrearsAgeing days overdue.\n" |
| + "interestChargedFromDate\n" + "Optional: Date - The date from with interest is to start being charged.\n" |
| + "expectedDisbursementDate\n" + "The proposed disbursement date of the loan so a proposed repayment schedule can be provided.\n" |
| + "submittedOnDate\n" + "The date the loan application was submitted by applicant.\n" + "linkAccountId\n" |
| + "The Savings Account id for linking with loan account for payments.\n" + "amortizationType\n" |
| + "Example Values: 0=Equal principle payments, 1=Equal installments\n" + "interestType\n" |
| + "Used like: interestRatePerPeriod% interestRateFrequencyType - interestType\n" + "e.g. 12.0000% Per year - Declining Balance \n" |
| + "Example Values: 0=Declining Balance, 1=Flat\n" + "interestCalculationPeriodType\n" |
| + "Example Values: 0=Daily, 1=Same as repayment period\n" + "allowPartialPeriodInterestCalcualtion\n" |
| + "This value will be supported along with interestCalculationPeriodType as Same as repayment period to calculate interest for partial periods. Example: Interest charged from is 5th of April , Principal is 10000 and interest is 1% per month then the interest will be (10000 * 1%)* (25/30) , it calculates for the month first then calculates exact periods between start date and end date(can be a decimal)\n" |
| + "inArrearsTolerance\n" + "The amount that can be 'waived' at end of all loan payments because it is too small to worry about.\n" |
| + "This is also the tolerance amount assessed when determining if a loan is in arrears.\n" + "transactionProcessingStrategyId\n" |
| + "An enumeration that indicates the type of transaction processing strategy to be used. This relates to functionality that is also known as Payment Application Logic.\n" |
| + "A number of out of the box approaches exist, some are custom to specific MFIs, some are more general and indicate the order in which payments are processed.\n" |
| + "\n" |
| + "Refer to the Payment Application Logic / Transaction Processing Strategy section in the appendix for more detailed overview of each available payment application logic provided out of the box.\n" |
| + "\n" + "List of current approaches:\n" + "1 = Mifos style (Similar to Old Mifos)\n" + "2 = Heavensfamily (Custom MFI approach)\n" |
| + "3 = Creocore (Custom MFI approach)\n" + "4 = RBI (India)\n" + "5 = Principal Interest Penalties Fees Order\n" |
| + "6 = Interest Principal Penalties Fees Order\n" + "7 = Early Payment Strategy\n" + "loanType\n" |
| + "To represent different type of loans.\n" + "At present there are three type of loans are supported. \n" |
| + "Available loan types:\n" + "individual: Loan given to individual member\n" + "group: Loan given to group as a whole\n" |
| + "jlg: Joint liability group loan given to members in a group on individual basis. JLG loan can be given to one or more members in a group.\n" |
| + "recalculationRestFrequencyDate\n" |
| + "Specifies rest frequency start date for interest recalculation. This date must be before or equal to disbursement date\n" |
| + "recalculationCompoundingFrequencyDate\n" |
| + "Specifies compounding frequency start date for interest recalculation. This date must be equal to disbursement date") |
| public class LoansApiResource { |
| |
| private final Set<String> loanDataParameters = new HashSet<>(Arrays.asList("id", "accountNo", "status", "externalId", "clientId", |
| "group", "loanProductId", "loanProductName", "loanProductDescription", "isLoanProductLinkedToFloatingRate", "fundId", |
| "fundName", "loanPurposeId", "loanPurposeName", "loanOfficerId", "loanOfficerName", "currency", "principal", "totalOverpaid", |
| "inArrearsTolerance", "termFrequency", "termPeriodFrequencyType", "numberOfRepayments", "repaymentEvery", |
| "interestRatePerPeriod", "annualInterestRate", "repaymentFrequencyType", "transactionProcessingStrategyId", |
| "transactionProcessingStrategyName", "interestRateFrequencyType", "amortizationType", "interestType", |
| "interestCalculationPeriodType", LoanProductConstants.ALLOW_PARTIAL_PERIOD_INTEREST_CALCUALTION_PARAM_NAME, |
| "expectedFirstRepaymentOnDate", "graceOnPrincipalPayment", "recurringMoratoriumOnPrincipalPeriods", "graceOnInterestPayment", |
| "graceOnInterestCharged", "interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", "summary", |
| "repaymentSchedule", "transactions", "charges", "collateral", "guarantors", "meeting", "productOptions", |
| "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", |
| "repaymentFrequencyNthDayTypeOptions", "repaymentFrequencyDaysOfWeekTypeOptions", "termFrequencyTypeOptions", |
| "interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions", "loanOfficerOptions", |
| "loanPurposeOptions", "loanCollateralOptions", "chargeTemplate", "calendarOptions", "syncDisbursementWithMeeting", |
| "loanCounter", "loanProductCounter", "notes", "accountLinkingOptions", "linkedAccount", "interestRateDifferential", |
| "isFloatingInterestRate", "interestRatesPeriods", LoanApiConstants.canUseForTopup, LoanApiConstants.isTopup, |
| LoanApiConstants.loanIdToClose, LoanApiConstants.topupAmount, LoanApiConstants.clientActiveLoanOptions, |
| LoanApiConstants.datatables, LoanProductConstants.RATES_PARAM_NAME)); |
| |
| private final Set<String> loanApprovalDataParameters = new HashSet<>(Arrays.asList("approvalDate", "approvalAmount")); |
| final Set<String> glimAccountsDataParameters = new HashSet<>(Arrays.asList("glimId", "groupId", "clientId", "parentLoanAccountNo", |
| "parentPrincipalAmount", "childLoanAccountNo", "childPrincipalAmount", "clientName")); |
| private final String resourceNameForPermissions = "LOAN"; |
| |
| private final PlatformSecurityContext context; |
| private final LoanReadPlatformService loanReadPlatformService; |
| private final LoanProductReadPlatformService loanProductReadPlatformService; |
| private final LoanDropdownReadPlatformService dropdownReadPlatformService; |
| private final FundReadPlatformService fundReadPlatformService; |
| private final ChargeReadPlatformService chargeReadPlatformService; |
| private final LoanChargeReadPlatformService loanChargeReadPlatformService; |
| private final CollateralReadPlatformService loanCollateralReadPlatformService; |
| private final LoanScheduleCalculationPlatformService calculationPlatformService; |
| private final GuarantorReadPlatformService guarantorReadPlatformService; |
| private final CodeValueReadPlatformService codeValueReadPlatformService; |
| private final GroupReadPlatformService groupReadPlatformService; |
| private final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer; |
| private final DefaultToApiJsonSerializer<LoanApprovalData> loanApprovalDataToApiJsonSerializer; |
| private final DefaultToApiJsonSerializer<LoanScheduleData> loanScheduleToApiJsonSerializer; |
| private final ApiRequestParameterHelper apiRequestParameterHelper; |
| private final FromJsonHelper fromJsonHelper; |
| private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; |
| private final CalendarReadPlatformService calendarReadPlatformService; |
| private final NoteReadPlatformService noteReadPlatformService; |
| private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService; |
| private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService; |
| private final LoanScheduleHistoryReadPlatformService loanScheduleHistoryReadPlatformService; |
| private final AccountDetailsReadPlatformService accountDetailsReadPlatformService; |
| private final EntityDatatableChecksReadService entityDatatableChecksReadService; |
| private final BulkImportWorkbookService bulkImportWorkbookService; |
| private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService; |
| private final RateReadService rateReadService; |
| private final ConfigurationDomainService configurationDomainService; |
| private final DefaultToApiJsonSerializer<GlimRepaymentTemplate> glimTemplateToApiJsonSerializer; |
| private final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService; |
| private final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService; |
| private final ScorecardServiceProvider scorecardServiceProvider; |
| |
| public LoansApiResource(final PlatformSecurityContext context, final LoanReadPlatformService loanReadPlatformService, |
| final LoanProductReadPlatformService loanProductReadPlatformService, |
| final LoanDropdownReadPlatformService dropdownReadPlatformService, final FundReadPlatformService fundReadPlatformService, |
| final ChargeReadPlatformService chargeReadPlatformService, final LoanChargeReadPlatformService loanChargeReadPlatformService, |
| final CollateralReadPlatformService loanCollateralReadPlatformService, |
| final LoanScheduleCalculationPlatformService calculationPlatformService, |
| final GuarantorReadPlatformService guarantorReadPlatformService, |
| final CodeValueReadPlatformService codeValueReadPlatformService, final GroupReadPlatformService groupReadPlatformService, |
| final DefaultToApiJsonSerializer<LoanAccountData> toApiJsonSerializer, |
| final DefaultToApiJsonSerializer<LoanApprovalData> loanApprovalDataToApiJsonSerializer, |
| final DefaultToApiJsonSerializer<LoanScheduleData> loanScheduleToApiJsonSerializer, |
| final ApiRequestParameterHelper apiRequestParameterHelper, final FromJsonHelper fromJsonHelper, |
| final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, |
| final CalendarReadPlatformService calendarReadPlatformService, final NoteReadPlatformService noteReadPlatformService, |
| final PortfolioAccountReadPlatformService portfolioAccountReadPlatformServiceImpl, |
| final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService, |
| final LoanScheduleHistoryReadPlatformService loanScheduleHistoryReadPlatformService, |
| final AccountDetailsReadPlatformService accountDetailsReadPlatformService, |
| final EntityDatatableChecksReadService entityDatatableChecksReadService, |
| final BulkImportWorkbookService bulkImportWorkbookService, |
| final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService, final RateReadService rateReadService, |
| final ConfigurationDomainService configurationDomainService, |
| final DefaultToApiJsonSerializer<GlimRepaymentTemplate> glimTemplateToApiJsonSerializer, |
| final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService, |
| final LoanCollateralManagementReadPlatformService loanCollateralManagementReadPlatformService, |
| final ScorecardServiceProvider scorecardServiceProvider) { |
| this.context = context; |
| this.loanReadPlatformService = loanReadPlatformService; |
| this.loanProductReadPlatformService = loanProductReadPlatformService; |
| this.dropdownReadPlatformService = dropdownReadPlatformService; |
| this.fundReadPlatformService = fundReadPlatformService; |
| this.chargeReadPlatformService = chargeReadPlatformService; |
| this.loanChargeReadPlatformService = loanChargeReadPlatformService; |
| this.loanCollateralReadPlatformService = loanCollateralReadPlatformService; |
| this.calculationPlatformService = calculationPlatformService; |
| this.guarantorReadPlatformService = guarantorReadPlatformService; |
| this.codeValueReadPlatformService = codeValueReadPlatformService; |
| this.groupReadPlatformService = groupReadPlatformService; |
| this.toApiJsonSerializer = toApiJsonSerializer; |
| this.loanApprovalDataToApiJsonSerializer = loanApprovalDataToApiJsonSerializer; |
| this.loanScheduleToApiJsonSerializer = loanScheduleToApiJsonSerializer; |
| this.apiRequestParameterHelper = apiRequestParameterHelper; |
| this.fromJsonHelper = fromJsonHelper; |
| this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; |
| this.calendarReadPlatformService = calendarReadPlatformService; |
| this.noteReadPlatformService = noteReadPlatformService; |
| this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformServiceImpl; |
| this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService; |
| this.loanScheduleHistoryReadPlatformService = loanScheduleHistoryReadPlatformService; |
| this.accountDetailsReadPlatformService = accountDetailsReadPlatformService; |
| this.entityDatatableChecksReadService = entityDatatableChecksReadService; |
| this.rateReadService = rateReadService; |
| this.bulkImportWorkbookService = bulkImportWorkbookService; |
| this.bulkImportWorkbookPopulatorService = bulkImportWorkbookPopulatorService; |
| this.configurationDomainService = configurationDomainService; |
| this.glimTemplateToApiJsonSerializer = glimTemplateToApiJsonSerializer; |
| this.glimAccountInfoReadPlatformService = glimAccountInfoReadPlatformService; |
| this.loanCollateralManagementReadPlatformService = loanCollateralManagementReadPlatformService; |
| this.scorecardServiceProvider = scorecardServiceProvider; |
| } |
| |
| /* |
| * This template API is used for loan approval, ideally this should be invoked on loan that are pending for |
| * approval. But system does not validate the status of the loan, it returns the template irrespective of loan |
| * status |
| */ |
| |
| @GET |
| @Path("{loanId}/template") |
| @Consumes({ MediaType.APPLICATION_JSON }) |
| @Produces({ MediaType.APPLICATION_JSON }) |
| public String retrieveApprovalTemplate(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId, |
| @QueryParam("templateType") @Parameter(description = "templateType") final String templateType, |
| @Context final UriInfo uriInfo) { |
| |
| this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); |
| |
| 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, this.loanApprovalDataParameters); |
| |
| } |
| |
| @GET |
| @Path("template") |
| @Consumes({ MediaType.APPLICATION_JSON }) |
| @Produces({ MediaType.APPLICATION_JSON }) |
| @Operation(summary = "Retrieve Loan Details Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n" |
| + "\n" + "Field Defaults\n" + "Allowed description Lists\n" + "Example Requests:\n" + "\n" |
| + "loans/template?templateType=individual&clientId=1\n" + "\n" + "\n" |
| + "loans/template?templateType=individual&clientId=1&productId=1") |
| @ApiResponses({ |
| @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.GetLoansTemplateResponse.class))) }) |
| public String template(@QueryParam("clientId") @Parameter(description = "clientId") final Long clientId, |
| @QueryParam("groupId") @Parameter(description = "groupId") final Long groupId, |
| @QueryParam("productId") @Parameter(description = "productId") final Long productId, |
| @QueryParam("templateType") @Parameter(description = "templateType") final String templateType, |
| @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly, |
| @DefaultValue("false") @QueryParam("activeOnly") @Parameter(description = "activeOnly") final boolean onlyActive, |
| @Context final UriInfo uriInfo) { |
| |
| this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); |
| |
| // template |
| final Collection<LoanProductData> productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup(onlyActive); |
| |
| // options |
| Collection<StaffData> allowedLoanOfficers = null; |
| Collection<CodeValueData> loanCollateralOptions = null; |
| Collection<CalendarData> calendarOptions = null; |
| LoanAccountData newLoanAccount = null; |
| Long officeId = null; |
| Collection<PortfolioAccountData> accountLinkingOptions = null; |
| boolean isRatesEnabled = this.configurationDomainService.isSubRatesEnabled(); |
| |
| if (productId != null) { |
| newLoanAccount = this.loanReadPlatformService.retrieveLoanProductDetailsTemplate(productId, clientId, groupId); |
| } |
| |
| if (templateType == null) { |
| final String errorMsg = "Loan template type must be provided"; |
| throw new LoanTemplateTypeRequiredException(errorMsg); |
| } else if (templateType.equals("collateral")) { |
| loanCollateralOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanCollateral"); |
| newLoanAccount = LoanAccountData.collateralTemplate(loanCollateralOptions); |
| } else { |
| // for JLG loan both client and group details are required |
| if (templateType.equals("individual") || templateType.equals("jlg")) { |
| |
| if (clientId == null) { |
| newLoanAccount = newLoanAccount == null ? LoanAccountData.emptyTemplate() : newLoanAccount; |
| } else { |
| final LoanAccountData loanAccountClientDetails = this.loanReadPlatformService.retrieveClientDetailsTemplate(clientId); |
| |
| officeId = loanAccountClientDetails.officeId(); |
| newLoanAccount = newLoanAccount == null ? loanAccountClientDetails |
| : LoanAccountData.populateClientDefaults(newLoanAccount, loanAccountClientDetails); |
| } |
| |
| // if it's JLG loan add group details |
| if (templateType.equals("jlg")) { |
| final GroupGeneralData group = this.groupReadPlatformService.retrieveOne(groupId); |
| newLoanAccount = LoanAccountData.associateGroup(newLoanAccount, group); |
| calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId); |
| } |
| |
| } else if (templateType.equals("group")) { |
| |
| final LoanAccountData loanAccountGroupData = this.loanReadPlatformService.retrieveGroupDetailsTemplate(groupId); |
| officeId = loanAccountGroupData.groupOfficeId(); |
| calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId); |
| newLoanAccount = newLoanAccount == null ? loanAccountGroupData |
| : LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData); |
| accountLinkingOptions = getaccountLinkingOptions(newLoanAccount, clientId, groupId); |
| |
| } else if (templateType.equals("jlgbulk")) { |
| // get group details along with members in that group |
| final LoanAccountData loanAccountGroupData = this.loanReadPlatformService.retrieveGroupAndMembersDetailsTemplate(groupId); |
| officeId = loanAccountGroupData.groupOfficeId(); |
| calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId); |
| newLoanAccount = newLoanAccount == null ? loanAccountGroupData |
| : LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData); |
| if (productId != null) { |
| Map<Long, Integer> memberLoanCycle = new HashMap<>(); |
| Collection<ClientData> members = loanAccountGroupData.groupData().clientMembers(); |
| accountLinkingOptions = new ArrayList<>(); |
| if (members != null) { |
| for (ClientData clientData : members) { |
| Integer loanCounter = this.loanReadPlatformService.retriveLoanCounter(clientData.id(), productId); |
| memberLoanCycle.put(clientData.id(), loanCounter); |
| accountLinkingOptions.addAll(getaccountLinkingOptions(newLoanAccount, clientData.id(), groupId)); |
| } |
| } |
| |
| newLoanAccount = LoanAccountData.associateMemberVariations(newLoanAccount, memberLoanCycle); |
| } |
| |
| } else { |
| final String errorMsg = "Loan template type '" + templateType + "' is not supported"; |
| throw new NotSupportedLoanTemplateTypeException(errorMsg, templateType); |
| } |
| |
| allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(officeId, staffInSelectedOfficeOnly); |
| |
| if (clientId != null) { |
| accountLinkingOptions = getaccountLinkingOptions(newLoanAccount, clientId, groupId); |
| } |
| |
| CreditScorecardData scorecard = null; |
| |
| final String serviceName = "CreditScorecardReadPlatformService"; |
| final CreditScorecardReadPlatformService scorecardService = (CreditScorecardReadPlatformService) scorecardServiceProvider |
| .getScorecardService(serviceName); |
| |
| if (scorecardService != null) { |
| scorecard = scorecardService.loanScorecardTemplate(); |
| } |
| |
| // add product options, allowed loan officers and calendar options |
| // (calendar options will be null in individual loan) |
| newLoanAccount = LoanAccountData.associationsAndTemplate(newLoanAccount, productOptions, allowedLoanOfficers, calendarOptions, |
| accountLinkingOptions, isRatesEnabled, scorecard); |
| } |
| final List<DatatableData> datatableTemplates = this.entityDatatableChecksReadService |
| .retrieveTemplates(StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getName(), productId); |
| newLoanAccount.setDatatables(datatableTemplates); |
| |
| final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); |
| return this.toApiJsonSerializer.serialize(settings, newLoanAccount, this.loanDataParameters); |
| } |
| |
| private Collection<PortfolioAccountData> getaccountLinkingOptions(final LoanAccountData newLoanAccount, final Long clientId, |
| final Long groupId) { |
| final CurrencyData currencyData = newLoanAccount.currency(); |
| String currencyCode = null; |
| if (currencyData != null) { |
| currencyCode = currencyData.code(); |
| } |
| final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() }; |
| final PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(), clientId, |
| currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue()); |
| if (groupId != null) { |
| portfolioAccountDTO.setGroupId(groupId); |
| } |
| return this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO); |
| } |
| |
| @GET |
| @Path("{loanId}") |
| @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/1\n" + "\n" + "\n" + "loans/1?fields=id,principal,annualInterestRate\n" + "\n" + "\n" |
| + "loans/1?associations=all\n" + "\n" + "loans/1?associations=all&exclude=guarantors\n" + "\n" + "\n" |
| + "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, |
| @DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") @Parameter(description = "staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly, |
| @Context final UriInfo uriInfo) { |
| this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); |
| |
| LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId); |
| |
| CreditScorecardData scorecard = null; |
| |
| final String serviceName = "CreditScorecardReadPlatformService"; |
| final CreditScorecardReadPlatformService scorecardService = (CreditScorecardReadPlatformService) scorecardServiceProvider |
| .getScorecardService(serviceName); |
| |
| if (scorecardService != null) { |
| scorecard = scorecardService.retrieveCreditScorecard(loanBasicDetails.getScorecardId()); |
| } |
| |
| loanBasicDetails = LoanAccountData.populateScorecardDetails(loanBasicDetails, scorecard); |
| |
| 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.isMonthlyRepaymentFrequencyType()) { |
| 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; |
| Collection<CollateralData> collateral = null; |
| CalendarData meeting = null; |
| Collection<NoteData> notes = null; |
| PortfolioAccountData linkedAccount = null; |
| Collection<DisbursementData> disbursementData = null; |
| Collection<LoanTermVariationsData> emiAmountVariations = null; |
| Collection<LoanCollateralResponseData> loanCollateralManagements = null; |
| Collection<LoanCollateralManagementData> loanCollateralManagementData = new ArrayList<>(); |
| CollectionData collectionData = CollectionData.template(); |
| |
| final Set<String> mandatoryResponseParameters = new HashSet<>(); |
| final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); |
| 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(uriInfo.getQueryParameters(), 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); |
| final Collection<LoanTransactionData> currentLoanRepayments = this.loanReadPlatformService.retrieveLoanTransactions(loanId); |
| 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.repaymentScheduleRelatedData(); |
| repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, repaymentScheduleRelatedData, |
| disbursementData, loanBasicDetails.isInterestRecalculationEnabled(), loanBasicDetails.getTotalPaidFeeCharges()); |
| |
| if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName) |
| && loanBasicDetails.isInterestRecalculationEnabled()) { |
| mandatoryResponseParameters.add(DataTableApiConstant.futureScheduleAssociateParamName); |
| this.calculationPlatformService.updateFutureSchedule(repaymentSchedule, loanId); |
| } |
| |
| if (associationParameters.contains(DataTableApiConstant.originalScheduleAssociateParamName) |
| && loanBasicDetails.isInterestRecalculationEnabled() && loanBasicDetails.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 (CollectionUtils.isEmpty(loanCollateralManagements)) { |
| loanCollateralManagements = null; |
| } |
| } |
| |
| 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.loanReadPlatformService.retrieveLoanCollectionData(loanId); |
| } |
| } |
| } |
| |
| Collection<LoanProductData> productOptions = null; |
| LoanProductData product = null; |
| 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 = null; |
| Collection<LoanAccountSummaryData> clientActiveLoanOptions = null; |
| |
| final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters()); |
| if (template) { |
| productOptions = this.loanProductReadPlatformService.retrieveAllLoanProductsForLookup(); |
| product = this.loanProductReadPlatformService.retrieveLoanProduct(loanBasicDetails.loanProductId()); |
| 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 = Arrays.asList(interestType(InterestMethod.DECLINING_BALANCE)); |
| } else { |
| interestTypeOptions = this.dropdownReadPlatformService.retrieveLoanInterestTypeOptions(); |
| } |
| interestCalculationPeriodTypeOptions = this.dropdownReadPlatformService.retrieveLoanInterestRateCalculatedInPeriodOptions(); |
| |
| fundOptions = this.fundReadPlatformService.retrieveAllFunds(); |
| repaymentStrategyOptions = this.dropdownReadPlatformService.retreiveTransactionProcessingStrategies(); |
| 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(); |
| |
| allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(loanBasicDetails.officeId(), |
| staffInSelectedOfficeOnly); |
| |
| loanPurposeOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanPurpose"); |
| loanCollateralOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanCollateral"); |
| final CurrencyData currencyData = loanBasicDetails.currency(); |
| String currencyCode = null; |
| if (currencyData != null) { |
| currencyCode = currencyData.code(); |
| } |
| final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() }; |
| PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(PortfolioAccountType.SAVINGS.getValue(), |
| loanBasicDetails.clientId(), 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.groupId() != null) { |
| calendarOptions = this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.groupId()); |
| } |
| |
| if (loanBasicDetails.product().canUseForTopup() && loanBasicDetails.clientId() != null) { |
| clientActiveLoanOptions = this.accountDetailsReadPlatformService |
| .retrieveClientActiveLoanAccountSummary(loanBasicDetails.clientId()); |
| } |
| |
| } |
| |
| Collection<ChargeData> overdueCharges = this.chargeReadPlatformService.retrieveLoanProductCharges(loanBasicDetails.loanProductId(), |
| 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); |
| } |
| |
| final Collection<CreditScorecardFeatureData> scorecardFeatures = null; |
| |
| final Collection<CreditScorecardFeatureData> scorecardFeatureOptions = null; |
| |
| CreditScorecardData scorecardWithTemplate = null; |
| |
| if (scorecardService != null) { |
| scorecardWithTemplate = scorecardService.loanScorecardTemplate(scorecard); |
| } |
| |
| 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, |
| scorecardFeatures, scorecardFeatureOptions, scorecardWithTemplate); |
| |
| final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(), |
| mandatoryResponseParameters); |
| return this.toApiJsonSerializer.serialize(settings, loanAccount, this.loanDataParameters); |
| } |
| |
| @GET |
| @Consumes({ MediaType.APPLICATION_JSON }) |
| @Produces({ MediaType.APPLICATION_JSON }) |
| @Operation(summary = "List Loans", description = "The list capability of loans can support pagination and sorting.\n" |
| + "Example Requests:\n" + "\n" + "loans\n" + "\n" + "loans?fields=accountNo\n" + "\n" + "loans?offset=10&limit=50\n" + "\n" |
| + "loans?orderBy=accountNo&sortOrder=DESC") |
| @ApiResponses({ |
| @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.GetLoansResponse.class))) }) |
| public String retrieveAll(@Context final UriInfo uriInfo, |
| @QueryParam("sqlSearch") @Parameter(description = "sqlSearch") final String sqlSearch, |
| @QueryParam("externalId") @Parameter(description = "externalId") final String externalId, |
| // @QueryParam("underHierarchy") final String hierarchy, |
| @QueryParam("offset") @Parameter(description = "offset") final Integer offset, |
| @QueryParam("limit") @Parameter(description = "limit") final Integer limit, |
| @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, |
| @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder, |
| @QueryParam("accountNo") @Parameter(description = "accountNo") final String accountNo) { |
| |
| this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); |
| |
| final SearchParameters searchParameters = SearchParameters.forLoans(sqlSearch, externalId, offset, limit, orderBy, sortOrder, |
| accountNo); |
| |
| final Page<LoanAccountData> loanBasicDetails = this.loanReadPlatformService.retrieveAll(searchParameters); |
| |
| final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); |
| return this.toApiJsonSerializer.serialize(settings, loanBasicDetails, this.loanDataParameters); |
| } |
| |
| @POST |
| @Consumes({ MediaType.APPLICATION_JSON }) |
| @Produces({ MediaType.APPLICATION_JSON }) |
| @Operation(summary = "Calculate loan repayment schedule | Submit a new Loan Application", description = "It calculates the loan repayment Schedule\n" |
| + "Submits a new loan application\n" |
| + "Mandatory Fields: clientId, productId, principal, loanTermFrequency, loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyId, expectedDisbursementDate, submittedOnDate, loanType\n" |
| + "Optional Fields: graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, linkAccountId, allowPartialPeriodInterestCalcualtion, fixedEmiAmount, maxOutstandingLoanBalance, disbursementData, graceOnArrearsAgeing, createStandingInstructionAtDisbursement (requires linkedAccountId if set to true)\n" |
| + "Additional Mandatory Fields if interest recalculation is enabled for product and Rest frequency not same as repayment period: recalculationRestFrequencyDate\n" |
| + "Additional Mandatory Fields if interest recalculation with interest/fee compounding is enabled for product and compounding frequency not same as repayment period: recalculationCompoundingFrequencyDate\n" |
| + "Additional Mandatory Field if Entity-Datatable Check is enabled for the entity of type loan: datatables") |
| @RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PostLoansRequest.class))) |
| @ApiResponses({ |
| @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoansApiResourceSwagger.PostLoansResponse.class))) }) |
| public String calculateLoanScheduleOrSubmitLoanApplication( |
| @QueryParam("command") @Parameter(description = "command") final String commandParam, @Context final UriInfo uriInfo, |
| @Parameter(hidden = true) final String apiRequestBodyAsJson) { |
| |
| if (is(commandParam, "calculateLoanSchedule")) { |
| |
| final JsonElement parsedQuery = this.fromJsonHelper.parse(apiRequestBodyAsJson); |
| final JsonQuery query = JsonQuery.from(apiRequestBodyAsJson, parsedQuery, this.fromJsonHelper); |
| |
| final LoanScheduleModel loanSchedule = this.calculationPlatformService.calculateLoanSchedule(query, true); |
| |
| final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); |
| return this.loanScheduleToApiJsonSerializer.serialize(settings, loanSchedule.toData(), new HashSet<String>()); |
| } |
| |
| final CommandWrapper commandRequest = new CommandWrapperBuilder().createLoanApplication().withJson(apiRequestBodyAsJson).build(); |
| |
| final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| |
| return this.toApiJsonSerializer.serialize(result); |
| } |
| |
| @PUT |
| @Path("{loanId}") |
| @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("loanId") @Parameter(description = "loanId") final Long loanId, |
| @Parameter(hidden = true) final String apiRequestBodyAsJson) { |
| |
| final CommandWrapper commandRequest = new CommandWrapperBuilder().updateLoanApplication(loanId).withJson(apiRequestBodyAsJson) |
| .build(); |
| |
| final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| |
| return this.toApiJsonSerializer.serialize(result); |
| } |
| |
| @DELETE |
| @Path("{loanId}") |
| @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("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); |
| } |
| |
| @POST |
| @Path("{loanId}") |
| @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("loanId") @Parameter(description = "loanId") final Long loanId, |
| @QueryParam("command") @Parameter(description = "command") final String commandParam, |
| @Parameter(hidden = true) final String apiRequestBodyAsJson) { |
| |
| final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson); |
| |
| CommandProcessingResult result = null; |
| |
| if (is(commandParam, "reject")) { |
| final CommandWrapper commandRequest = builder.rejectLoanApplication(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "withdrawnByApplicant")) { |
| final CommandWrapper commandRequest = builder.withdrawLoanApplication(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "approve")) { |
| final CommandWrapper commandRequest = builder.approveLoanApplication(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "disburse")) { |
| final CommandWrapper commandRequest = builder.disburseLoanApplication(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "disburseToSavings")) { |
| final CommandWrapper commandRequest = builder.disburseLoanToSavingsApplication(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } |
| |
| if (is(commandParam, "undoapproval")) { |
| final CommandWrapper commandRequest = builder.undoLoanApplicationApproval(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "undodisbursal")) { |
| final CommandWrapper commandRequest = builder.undoLoanApplicationDisbursal(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "undolastdisbursal")) { |
| final CommandWrapper commandRequest = builder.undoLastDisbursalLoanApplication(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } |
| |
| if (is(commandParam, "assignloanofficer")) { |
| final CommandWrapper commandRequest = builder.assignLoanOfficer(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "unassignloanofficer")) { |
| final CommandWrapper commandRequest = builder.unassignLoanOfficer(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "recoverGuarantees")) { |
| final CommandWrapper commandRequest = new CommandWrapperBuilder().recoverFromGuarantor(loanId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } |
| |
| if (result == null) { |
| throw new UnrecognizedQueryParamException("command", commandParam); |
| } |
| |
| return this.toApiJsonSerializer.serialize(result); |
| } |
| |
| private boolean is(final String commandParam, final String commandValue) { |
| return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); |
| } |
| |
| @GET |
| @Path("downloadtemplate") |
| @Produces("application/vnd.ms-excel") |
| public Response getLoansTemplate(@QueryParam("officeId") final Long officeId, @QueryParam("staffId") final Long staffId, |
| @QueryParam("dateFormat") final String dateFormat) { |
| return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.LOANS.toString(), officeId, staffId, dateFormat); |
| } |
| |
| @GET |
| @Path("glimAccount/{glimId}") |
| @Consumes({ MediaType.APPLICATION_JSON }) |
| @Produces({ MediaType.APPLICATION_JSON }) |
| public String getGlimRepaymentTemplate(@PathParam("glimId") final Long glimId, @Context final UriInfo uriInfo) { |
| this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); |
| Collection<GlimRepaymentTemplate> glimRepaymentTemplate = this.glimAccountInfoReadPlatformService.findglimRepaymentTemplate(glimId); |
| final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); |
| return this.glimTemplateToApiJsonSerializer.serialize(settings, glimRepaymentTemplate, this.glimAccountsDataParameters); |
| } |
| |
| @POST |
| @Path("glimAccount/{glimId}") |
| @Consumes({ MediaType.APPLICATION_JSON }) |
| @Produces({ MediaType.APPLICATION_JSON }) |
| @Operation(summary = "Approve GLIM Application | Undo GLIM Application Approval | Reject GLIM Application | Disburse Loan Disburse Loan To Savings Account | Undo Loan Disbursal", description = "Approve GLIM Application:\n" |
| + "Mandatory Fields: approvedOnDate\n" + "Optional Fields: approvedLoanAmount and expectedDisbursementDate\n" |
| + "Approves the GLIM application\n\n" + "Undo GLIM Application Approval:\n" + "Undoes the GLIM Application Approval\n\n" |
| + "Reject GLIM Application:\n" + "Mandatory Fields: rejectedOnDate\n" + "Allows you to reject the GLIM 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") |
| @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 glimStateTransitions(@PathParam("glimId") final Long glimId, @QueryParam("command") final String commandParam, |
| final String apiRequestBodyAsJson) { |
| |
| final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson); |
| |
| CommandProcessingResult result = null; |
| |
| if (is(commandParam, "reject")) { |
| final CommandWrapper commandRequest = builder.rejectGLIMApplication(glimId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "approve")) { |
| final CommandWrapper commandRequest = builder.approveGLIMLoanApplication(glimId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "disburse")) { |
| final CommandWrapper commandRequest = builder.disburseGlimLoanApplication(glimId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "glimrepayment")) { |
| final CommandWrapper commandRequest = builder.repaymentGlimLoanApplication(glimId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "undodisbursal")) { |
| final CommandWrapper commandRequest = builder.undoGLIMLoanDisbursal(glimId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } else if (is(commandParam, "undoapproval")) { |
| final CommandWrapper commandRequest = builder.undoGLIMLoanApproval(glimId).build(); |
| result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); |
| } |
| |
| if (result == null) { |
| throw new UnrecognizedQueryParamException("command", commandParam); |
| } |
| |
| return this.toApiJsonSerializer.serialize(result); |
| } |
| |
| @GET |
| @Path("repayments/downloadtemplate") |
| @Produces("application/vnd.ms-excel") |
| public Response getLoanRepaymentTemplate(@QueryParam("officeId") final Long officeId, |
| @QueryParam("dateFormat") final String dateFormat) { |
| return bulkImportWorkbookPopulatorService.getTemplate(GlobalEntityType.LOAN_TRANSACTIONS.toString(), officeId, null, dateFormat); |
| } |
| |
| @POST |
| @Path("uploadtemplate") |
| @Consumes(MediaType.MULTIPART_FORM_DATA) |
| @RequestBody(description = "Upload Loan template", content = { |
| @Content(mediaType = MediaType.MULTIPART_FORM_DATA, schema = @Schema(implementation = UploadRequest.class)) }) |
| public String postLoanTemplate(@FormDataParam("file") InputStream uploadedInputStream, |
| @FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("locale") final String locale, |
| @FormDataParam("dateFormat") final String dateFormat) { |
| final Long importDocumentId = this.bulkImportWorkbookService.importWorkbook(GlobalEntityType.LOANS.toString(), uploadedInputStream, |
| fileDetail, locale, dateFormat); |
| return this.toApiJsonSerializer.serialize(importDocumentId); |
| } |
| |
| @POST |
| @Path("repayments/uploadtemplate") |
| @Consumes(MediaType.MULTIPART_FORM_DATA) |
| @RequestBody(description = "Upload Loan repayments template", content = { |
| @Content(mediaType = MediaType.MULTIPART_FORM_DATA, schema = @Schema(implementation = UploadRequest.class)) }) |
| public String postLoanRepaymentTemplate(@FormDataParam("file") InputStream uploadedInputStream, |
| @FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("locale") final String locale, |
| @FormDataParam("dateFormat") final String dateFormat) { |
| final Long importDocumentId = this.bulkImportWorkbookService.importWorkbook(GlobalEntityType.LOAN_TRANSACTIONS.toString(), |
| uploadedInputStream, fileDetail, locale, dateFormat); |
| return this.toApiJsonSerializer.serialize(importDocumentId); |
| } |
| } |