From 51d8faac6d88c0f7fac59d7b7a378198b61658c7 Mon Sep 17 00:00:00 2001 From: rrpawar96 Date: Sat, 17 Nov 2018 11:26:01 -0500 Subject: [PATCH] GLIM_GSIM enhancement (FINERACT-603) --- .../ClientSavingsIntegrationTest.java | 2 + .../GroupLoanIntegrationTest.java | 148 ++++++- .../GroupSavingsIntegrationTest.java | 255 +++++++++++- .../integrationtests/common/GroupHelper.java | 93 +++-- .../loans/LoanApplicationTestBuilder.java | 51 ++- .../common/loans/LoanStatusChecker.java | 4 + .../common/loans/LoanTransactionHelper.java | 113 +++-- .../common/savings/SavingsAccountHelper.java | 185 +++++++-- .../SavingsApplicationTestBuilder.java | 39 +- .../common/savings/SavingsProductHelper.java | 20 +- .../service/CommandWrapperBuilder.java | 123 ++++++ .../infrastructure/core/api/JsonCommand.java | 7 + .../core/data/CommandProcessingResult.java | 22 +- .../data/CommandProcessingResultBuilder.java | 14 +- ...ountTransfersWritePlatformServiceImpl.java | 17 +- .../data/AccountSummaryCollectionData.java | 17 +- .../data/LoanAccountSummaryData.java | 23 ++ .../data/SavingsAccountSummaryData.java | 8 + .../data/SavingsSummaryCustom.java | 83 ++++ .../accountdetails/domain/AccountType.java | 18 +- .../AccountDetailsReadPlatformService.java | 5 + ...sReadPlatformServiceJpaRepositoryImpl.java | 57 ++- .../service/AccountEnumerations.java | 3 + .../service/CalendarReadPlatformService.java | 2 + .../group/api/GroupsApiResource.java | 87 +++- .../portfolio/group/domain/Group.java | 4 + .../GroupMemberNotFoundInGSIMException.java | 30 ++ .../loanaccount/api/LoanApiConstants.java | 6 + .../loanaccount/api/LoansApiResource.java | 62 ++- .../loanaccount/data/GLIMContainer.java | 73 ++++ .../data/GlimRepaymentTemplate.java | 105 +++++ ...upLoanIndividualMonitoringAccountData.java | 103 +++++ .../domain/GLIMAccountInfoRepository.java | 34 ++ .../GroupLoanIndividualMonitoringAccount.java | 146 +++++++ .../portfolio/loanaccount/domain/Loan.java | 36 ++ .../loanaccount/domain/LoanRepository.java | 4 + .../domain/LoanRepositoryWrapper.java | 1 + .../service/GuarantorReadPlatformService.java | 1 + .../GuarantorReadPlatformServiceImpl.java | 1 + ...LIMApplicationRejectionCommandHandler.java | 49 +++ .../GLIMBulkRepaymentCommandHandler.java | 49 +++ ...LoanApplicationApprovalCommandHandler.java | 49 +++ ...LoanApplicationDisburseCommandHandler.java | 52 +++ .../UndoGLIMLoanApplicationApproval.java | 49 +++ .../UndoGLIMLoanDisbursalCommandHandler.java | 49 +++ ...oanScheduleCalculationPlatformService.java | 1 + ...cheduleCalculationPlatformServiceImpl.java | 1 + ...anApplicationCommandFromApiJsonHelper.java | 8 +- ...ApplicationTransitionApiJsonValidator.java | 2 +- .../LoanEventApiJsonValidator.java | 2 +- .../GLIMAccountInfoReadPlatformService.java | 44 ++ ...LIMAccountInfoReadPlatformServiceImpl.java | 262 ++++++++++++ .../GLIMAccountInfoWritePlatformService.java | 36 ++ ...IMAccountInfoWritePlatformServiceImpl.java | 94 +++++ .../LoanApplicationWritePlatformService.java | 6 + ...WritePlatformServiceJpaRepositoryImpl.java | 309 +++++++++++++- .../loanaccount/service/LoanAssembler.java | 1 + .../service/LoanReadPlatformService.java | 3 +- .../service/LoanReadPlatformServiceImpl.java | 17 + .../service/LoanWritePlatformService.java | 6 + ...WritePlatformServiceJpaRepositoryImpl.java | 102 ++++- .../savings/SavingsApiConstants.java | 13 +- ...SavingsAccountTransactionsApiResource.java | 5 + .../api/SavingsAccountsApiResource.java | 90 ++++ .../portfolio/savings/data/GSIMContainer.java | 75 ++++ ...avingsIndividualMonitoringAccountData.java | 125 ++++++ .../savings/data/SavingsAccountConstant.java | 8 +- .../savings/domain/GSIMRepositoy.java | 32 ++ .../GroupSavingsIndividualMonitoring.java | 140 +++++++ .../savings/domain/SavingsAccount.java | 33 +- .../domain/SavingsAccountAssembler.java | 15 + .../domain/SavingsAccountDomainService.java | 1 + .../SavingsAccountDomainServiceJpa.java | 2 +- .../domain/SavingsAccountRepository.java | 3 + .../SavingsAccountRepositoryWrapper.java | 4 + .../domain/SavingsAccountTransaction.java | 8 + .../handler/CloseGSIMCommandHandler.java | 51 +++ .../GSIMAccountActivationCommandHandler.java | 48 +++ ...GSIMApplicationApprovalCommandHandler.java | 49 +++ ...ApplicationModificationCommandHandler.java | 49 +++ .../GSIMApplicationRejectionHandler.java | 51 +++ ...SIMApplicationSubmittalCommandHandler.java | 49 +++ .../handler/GSIMDepositCommandHandler.java | 49 +++ .../GSIMUndoApprovalCommandHandler.java | 51 +++ .../service/GSIMReadPlatformService.java | 48 +++ .../service/GSIMReadPlatformServiceImpl.java | 389 ++++++++++++++++++ ...ividualMonitoringWritePlatformService.java | 37 ++ ...ualMonitoringWritePlatformServiceImpl.java | 88 ++++ .../SavingsAccountWritePlatformService.java | 6 + ...WritePlatformServiceJpaRepositoryImpl.java | 115 +++++- ...pplicationProcessWritePlatformService.java | 10 + ...WritePlatformServiceJpaRepositoryImpl.java | 215 +++++++++- .../data/SelfSavingsDataValidator.java | 123 +++--- .../core_db/V356__GSIM_migration_script.sql | 63 +++ .../core_db/V357__GLIM_migration_script.sql | 58 +++ 95 files changed, 5068 insertions(+), 228 deletions(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsSummaryCustom.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMemberNotFoundInGSIMException.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GLIMContainer.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GlimRepaymentTemplate.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GroupLoanIndividualMonitoringAccountData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GLIMAccountInfoRepository.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GroupLoanIndividualMonitoringAccount.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMApplicationRejectionCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMBulkRepaymentCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMLoanApplicationApprovalCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GlimLoanApplicationDisburseCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanApplicationApproval.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanDisbursalCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GSIMContainer.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GroupSavingsIndividualMonitoringAccountData.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GSIMRepositoy.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GroupSavingsIndividualMonitoring.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CloseGSIMCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMAccountActivationCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationApprovalCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationModificationCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationRejectionHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationSubmittalCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMDepositCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMUndoApprovalCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/resources/sql/migrations/core_db/V356__GSIM_migration_script.sql create mode 100644 fineract-provider/src/main/resources/sql/migrations/core_db/V357__GLIM_migration_script.sql diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index d2678ba8463..3ca12bc150e 100755 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -68,6 +68,7 @@ public class ClientSavingsIntegrationTest { public static final String WITHDRAW_AMOUNT_ADJUSTED = "500"; public static final String MINIMUM_OPENING_BALANCE = "1000.0"; public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL"; + public static final String DATE_FORMAT = "dd MMMM yyyy"; private ResponseSpecification responseSpec; private RequestSpecification requestSpec; @@ -2294,4 +2295,5 @@ public void testAccountBalanceAfterTransactionReversal() { assertEquals("Verifying opening Balance is -300", balance, summary.get("accountBalance")); } + } \ No newline at end of file diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java index fb00f87e774..9bab83f9a50 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupLoanIntegrationTest.java @@ -28,14 +28,21 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.GroupHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; +import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Group Loan Integration Test for checking Loan Application Repayment Schedule. @@ -46,6 +53,7 @@ public class GroupLoanIntegrationTest { private ResponseSpecification responseSpec; private RequestSpecification requestSpec; private LoanTransactionHelper loanTransactionHelper; + private final static Logger LOG = LoggerFactory.getLogger(GroupLoanIntegrationTest.class); @Before public void setup() { @@ -66,13 +74,121 @@ public void checkGroupLoanCreateAndDisburseFlow() { final Integer loanProductID = createLoanProduct(); final Integer loanID = applyForLoanApplication(groupID, loanProductID); final ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, - loanID); + loanID); verifyLoanRepaymentSchedule(loanSchedule); + } + + @Test + public void checkGlimAccountCommands() { + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + final Integer loanProductID = createLoanProduct(); + + HashMap glim = applyForGlimApplication(clientID, groupID, loanProductID); + LOG.info("Glim Loan Application: {} ", glim); + + final Integer glimId=glim.get("glimId"); + LOG.info("GlimId : {} ", glimId); + + final Integer loanId=glim.get("loanId"); + LOG.info("LoanId : {} ", loanId); + + List> approvalFormData = new ArrayList<>(); + approvalFormData.add(approvalFormData(loanId,"22 September 2011")); + + HashMap loanStatusHashMap = this.loanTransactionHelper.approveGlimAccount(this.requestSpec, this.responseSpec, + approvalFormData, glimId); + LOG.info("glim approval loanSchedule: {} ", loanStatusHashMap); + LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.disburseGlimAccount("25 September 2011", glimId); + LOG.info("glim disbursement loanSchedule: {} ", loanStatusHashMap); + LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.undoDisburseGlimAccount(glimId); + LOG.info("glim undodisbursement loanSchedule: {} ", loanStatusHashMap); + LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.undoApprovalGlimAccount(glimId); + LOG.info("glim undoApproval loanSchedule: {} ", loanStatusHashMap); + LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.rejectGlimAccount("22 September 2011",glimId); + LOG.info("glim reject loanSchedule: {} ", loanStatusHashMap); + LoanStatusChecker.verifyLoanAccountRejected(loanStatusHashMap); + } + + @Test + public void getGlimAccountByGroupId() { + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final Integer loanProductID = createLoanProduct(); + Assert.assertNotNull(loanProductID); + + HashMap glim = applyForGlimApplication(clientID, groupID, loanProductID); + LOG.info("Glim Loan Application: {} ", glim); + + final Integer glimId=glim.get("glimId"); + LOG.info("GlimId: {} ", glimId); + + final Integer loanId=glim.get("loanId"); + LOG.info("LoanId: {} ", loanId); + final List retrievedGlimId=GroupHelper.verifyRetrieveGlimAccountsByGroupId(this.requestSpec, this.responseSpec, groupID); + Assert.assertNotNull(retrievedGlimId.toString()); + } + + @Test + public void getGlimAccountByGlimId() { + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final Integer loanProductID = createLoanProduct(); + Assert.assertNotNull(loanProductID); + + HashMap glim = applyForGlimApplication(clientID, groupID, loanProductID); + LOG.info("Glim Loan Application: {} ", glim); + + final Integer glimId=glim.get("glimId"); + LOG.info("GlimId: {} ", glimId); + + final Integer loanId=glim.get("loanId"); + LOG.info("LoanId: {} ", loanId); + + final List retrievedGlimAccountId=GroupHelper.verifyRetrieveGlimAccountsByGlimId(this.requestSpec, this.responseSpec, glimId); + Assert.assertNotNull(retrievedGlimAccountId); + } + + private Map approvalFormData(final Integer loanId, final String approvedOnDate) { + Map map = new HashMap<>(); + map.put("loanId", loanId); + map.put("approvedOnDate", approvedOnDate); + map.put("dateFormat", CommonConstants.dateFormat); + map.put("locale", "en"); + return map; } private Integer createLoanProduct() { - System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); + LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); final String loanProductJSON = new LoanProductTestBuilder() // .withPrincipal("12,000.00") // .withNumberOfRepayments("4") // @@ -87,7 +203,7 @@ private Integer createLoanProduct() { } private Integer applyForLoanApplication(final Integer groupID, final Integer loanProductID) { - System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); final String loanApplicationJSON = new LoanApplicationTestBuilder() // .withPrincipal("12,000.00") // .withLoanTermFrequency("4") // @@ -102,12 +218,34 @@ private Integer applyForLoanApplication(final Integer groupID, final Integer loa .withExpectedDisbursementDate("20 September 2011") // .withSubmittedOnDate("20 September 2011") // .withLoanType("group").build(groupID.toString(), loanProductID.toString(), null); - System.out.println(loanApplicationJSON); + LOG.info(loanApplicationJSON); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + private HashMap applyForGlimApplication(final Integer clientID, final Integer groupID, final Integer loanProductID) { + LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + final String GlimApplicationJSON = new LoanApplicationTestBuilder() // + .withPrincipal("12,000.00") // + .withLoanTermFrequency("4") // + .withLoanTermFrequencyAsMonths() // + .withNumberOfRepayments("4") // + .withRepaymentEveryAfter("1") // + .withRepaymentFrequencyTypeAsMonths() // + .withInterestRatePerPeriod("2") // + .withAmortizationTypeAsEqualInstallments() // + .withInterestTypeAsDecliningBalance() // + .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // + .withExpectedDisbursementDate("20 September 2011") // + .withSubmittedOnDate("20 September 2011") + .withLoanType("glim") + .withtotalLoan("10000") + .withParentAccount("1").build(clientID.toString(), groupID.toString(), loanProductID.toString(), null); + LOG.info(GlimApplicationJSON); + return this.loanTransactionHelper.getGlimId(GlimApplicationJSON); + } + private void verifyLoanRepaymentSchedule(final ArrayList loanSchedule) { - System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------"); + LOG.info("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------"); assertEquals("Checking for Due Date for 1st Month", new ArrayList<>(Arrays.asList(2011, 10, 20)), loanSchedule.get(1).get("dueDate")); diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java index 1a2f2dfede3..7905bad81cd 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/GroupSavingsIntegrationTest.java @@ -33,9 +33,11 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CommonConstants; import org.apache.fineract.integrationtests.common.GroupHelper; +import org.apache.fineract.integrationtests.common.PaymentTypeHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.charges.ChargesHelper; import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper; @@ -45,6 +47,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Group Savings Integration Test for checking Savings Application. @@ -61,6 +65,7 @@ public class GroupSavingsIntegrationTest { private ResponseSpecification responseSpec; private RequestSpecification requestSpec; private SavingsAccountHelper savingsAccountHelper; + private final static Logger LOG = LoggerFactory.getLogger(GroupSavingsIntegrationTest.class); @Before public void setup() { @@ -115,6 +120,7 @@ public void testSavingsAccount() { Assert.assertFalse(summaryBefore.equals(summary)); final Object savingsInterest = this.savingsAccountHelper.getSavingsInterest(savingsId); + } @SuppressWarnings("unchecked") @@ -164,6 +170,7 @@ public void testSavingsAccount_CLOSE_APPLICATION() { withdrawBalance = "true"; savingsStatusHashMap = this.savingsAccountHelper.closeSavingsAccount(savingsId, withdrawBalance); SavingsStatusChecker.verifySavingsAccountIsClosed(savingsStatusHashMap); + } @SuppressWarnings("unchecked") @@ -214,6 +221,226 @@ public void testSavingsAccount_DELETE_APPLICATION() { } + //gsimcommands testing + @SuppressWarnings("unchecked") + @Test + public void testGsimSavingsAccount_REJECT_APPLICATION() { + + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec, + new ResponseSpecBuilder().build()); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = null; + final String enforceMinRequiredBalance = "false"; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance); + Assert.assertNotNull(savingsProductID); + + List> clientArray = new ArrayList<>(); + clientArray.add(clientArray(clientID, groupID, savingsProductID,"08 January 2013")); + + final Integer gsimID = this.savingsAccountHelper.applyForGsimApplication(clientArray); + + HashMap savingsStatusHashMap = this.savingsAccountHelper.approveGsimSavings(gsimID); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + List error1 = savingsAccountHelperValidationError.rejectGsimApplicationWithErrorCode(gsimID, + SavingsAccountHelper.CREATED_DATE_PLUS_ONE); + assertEquals("validation.msg.savingsaccount.reject.not.in.submittedandpendingapproval.state", + error1.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + + savingsStatusHashMap = this.savingsAccountHelper.undoApprovalGsimSavings(gsimID); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + error1 = savingsAccountHelperValidationError.rejectGsimApplicationWithErrorCode(gsimID, SavingsAccountHelper.getFutureDate()); + assertEquals("validation.msg.savingsaccount.reject.cannot.be.a.future.date", + error1.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + + error1 = savingsAccountHelperValidationError.rejectGsimApplicationWithErrorCode(gsimID, SavingsAccountHelper.CREATED_DATE_MINUS_ONE); + assertEquals("validation.msg.savingsaccount.reject.cannot.be.before.submittal.date", + error1.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + + savingsStatusHashMap = this.savingsAccountHelper.rejectGsimApplication(gsimID); + SavingsStatusChecker.verifySavingsIsRejected(savingsStatusHashMap); + + } + + @Test + public void testGsimSavingsAccount_DEPOSIT_APPLICATION() { + + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = null; + final String enforceMinRequiredBalance = "false"; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance); + Assert.assertNotNull(savingsProductID); + + List> clientArray = new ArrayList<>(); + clientArray.add(clientArray(clientID, groupID, savingsProductID,"08 January 2013")); + LOG.info("client Array : {} ", clientArray); + + final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(groupID, savingsProductID, ACCOUNT_TYPE_GROUP); + Assert.assertNotNull(savingsId); + + String name = PaymentTypeHelper.randomNameGenerator("P_T", 5); + String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 15); + Boolean isCashPayment = true; + Integer position = 1; + + Integer paymentTypeId = PaymentTypeHelper.createPaymentType(requestSpec, responseSpec, name, description, isCashPayment, position); + Assert.assertNotNull(paymentTypeId); + + List> savingsArray = new ArrayList<>(); + final Integer transactionAmount=2500; + savingsArray.add(savingsArray(paymentTypeId, savingsId, transactionAmount, "10 March 2013")); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + final Integer depositId = this.savingsAccountHelper.depositGsimApplication(savingsId, savingsArray); + Assert.assertNotNull(depositId); + + } + + @SuppressWarnings("unchecked") + @Test + public void testGsimSavingsAccount_CLOSE_APPLICATION() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build(); + final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = "1000.0"; + final String enforceMinRequiredBalance = "true"; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance); + Assert.assertNotNull(savingsProductID); + + List> clientArray = new ArrayList<>(); + clientArray.add(clientArray(clientID, groupID, savingsProductID,"08 January 2013")); + + final Integer gsimID = this.savingsAccountHelper.applyForGsimApplication(clientArray); + + HashMap savingsStatusHashMap = this.savingsAccountHelper.approveGsimSavings(gsimID); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateGsimSavings(gsimID); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); + Calendar todaysDate = Calendar.getInstance(); + final String CLOSEDON_DATE = dateFormat.format(todaysDate.getTime()); + String withdrawBalance = "false"; + ArrayList savingsAccountErrorData = (ArrayList) validationErrorHelper.closeGsimSavingsAccountAndGetBackRequiredField(gsimID, withdrawBalance, CommonConstants.RESPONSE_ERROR, CLOSEDON_DATE); + assertEquals("validation.msg.savingsaccount.close.results.in.balance.not.zero", + savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + + withdrawBalance = "true"; + savingsStatusHashMap = this.savingsAccountHelper.closeGsimSavingsAccount(gsimID, withdrawBalance); + SavingsStatusChecker.verifySavingsAccountIsClosed(savingsStatusHashMap); + + } + + @SuppressWarnings("unchecked") + @Test + public void testGsimSavingsAccount_UPDATE_APPLICATION() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build(); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = "1000.0"; + final String enforceMinRequiredBalance = "true"; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance); + Assert.assertNotNull(savingsProductID); + + List> clientArray = new ArrayList<>(); + clientArray.add(clientArray(clientID, groupID, savingsProductID,"08 January 2013")); + + final Integer gsimID = this.savingsAccountHelper.applyForGsimApplication(clientArray); + + HashMap savingsStatusHashMap = this.savingsAccountHelper.updateGsimApplication(gsimID, clientID, groupID, savingsProductID); + LOG.info("savingsStatusHashMap: {} ",savingsStatusHashMap); + Assert.assertTrue(savingsStatusHashMap.containsKey("savingsId")); + + } + + @Test + public void getGsimAccount() { + + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(400).build(); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + + Integer groupID = GroupHelper.createGroup(this.requestSpec, this.responseSpec, true); + Assert.assertNotNull(groupID); + + groupID = GroupHelper.associateClient(this.requestSpec, this.responseSpec, groupID.toString(), clientID.toString()); + Assert.assertNotNull(groupID); + + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = "1000.0"; + final String enforceMinRequiredBalance = "true"; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance); + Assert.assertNotNull(savingsProductID); + + List> clientArray = new ArrayList<>(); + clientArray.add(clientArray(clientID, groupID, savingsProductID,"08 January 2013")); + final Integer gsimID = this.savingsAccountHelper.applyForGsimApplication(clientArray); + + final List retrievedGsimId=GroupHelper.verifyRetrieveGsimAccounts(this.requestSpec, this.responseSpec, groupID); + Assert.assertNotNull(retrievedGsimId.toString()); + } + @SuppressWarnings("unchecked") @Test public void testSavingsAccount_REJECT_APPLICATION() { @@ -266,6 +493,7 @@ public void testSavingsAccount_REJECT_APPLICATION() { savingsStatusHashMap = this.savingsAccountHelper.rejectApplication(savingsId); SavingsStatusChecker.verifySavingsIsRejected(savingsStatusHashMap); + } @Test @@ -536,7 +764,7 @@ public void testSavingsAccountCharges() { public static Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String minOpenningBalance, final String minBalanceForInterestCalculation, final String minRequiredBalance, final String enforceMinRequiredBalance) { - System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); + LOG.info("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); SavingsProductHelper savingsProductHelper = new SavingsProductHelper(); final String savingsProductJSON = savingsProductHelper // .withInterestCompoundingPeriodTypeAsDaily() // @@ -548,4 +776,29 @@ public static Integer createSavingsProduct(final RequestSpecification requestSpe .withMinimumOpenningBalance(minOpenningBalance).build(); return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec); } + + private Map clientArray(final Integer clientId, final Integer groupId, final Integer productId, final String submittedOnDate) { + Map map = new HashMap<>(); + map.put("clientId", clientId); + map.put("groupId", groupId); + map.put("productId", productId); + map.put("submittedOnDate", submittedOnDate); + map.put("dateFormat", CommonConstants.dateFormat); + map.put("locale", "en"); + map.put("isParentAccount", "1"); + map.put("isGSIM", "true"); + return map; + } + + private Map savingsArray(final Integer paymentId, final Integer savingsId, final Integer transactionAmount, final String transactionDate) { + Map map = new HashMap<>(); + map.put("transactionDate", transactionDate); + map.put("dateFormat", CommonConstants.dateFormat); + map.put("locale", "en"); + map.put("transactionAmount",transactionAmount); + map.put("paymentTypeId", paymentId); + map.put("childAccountId", savingsId); + return map; + } + } diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/GroupHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/GroupHelper.java index b0920065810..7a286b63fd7 100755 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/GroupHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/GroupHelper.java @@ -29,11 +29,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class GroupHelper { private final RequestSpecification requestSpec; private final ResponseSpecification responseSpec; + private final static Logger LOG = LoggerFactory.getLogger(GroupHelper.class); private static final String CREATE_GROUP_URL = "/fineract-provider/api/v1/groups?" + Utils.TENANT_IDENTIFIER; public static final String DATE_FORMAT = "dd MMMM yyyy"; @@ -46,30 +49,30 @@ public GroupHelper(final RequestSpecification requestSpec, final ResponseSpecifi public static Integer createGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, @SuppressWarnings("unused") final boolean active) { - System.out.println("---------------------------------CREATING A GROUP---------------------------------------------"); + LOG.info("---------------------------------CREATING A GROUP---------------------------------------------"); return createGroup(requestSpec, responseSpec, "04 March 2011"); } public static Integer createGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String activationDate) { - System.out.println("---------------------------------CREATING A GROUP---------------------------------------------"); + LOG.info("---------------------------------CREATING A GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, CREATE_GROUP_URL, getTestGroupAsJSON(true, activationDate), "groupId"); } public static Integer createGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { - System.out.println("---------------------------------CREATING A GROUP---------------------------------------------"); + LOG.info("---------------------------------CREATING A GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, CREATE_GROUP_URL, getTestGroupAsJSON(false, ""), "groupId"); } public Object createGroupWithError(final String jsonAttributeToGetBack) { - System.out.println("---------------------------------CREATING A GROUP WITH ERROR---------------------------------------------"); + LOG.info("---------------------------------CREATING A GROUP WITH ERROR---------------------------------------------"); return Utils.performServerPost(this.requestSpec, this.responseSpec, CREATE_GROUP_URL, getTestGroupAsJSON(false, ""), jsonAttributeToGetBack); } public static Integer createGroupPendingWithDatatable(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String registeredTableName) { - System.out.println("-------------------------- CREATING A GROUP WITH DATATABLES --------------------------------"); + LOG.info("-------------------------- CREATING A GROUP WITH DATATABLES --------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, CREATE_GROUP_URL, getTestGroupWithDatatableAsJson(registeredTableName), "groupId"); } @@ -78,7 +81,7 @@ public static Integer associateClient(final RequestSpecification requestSpec, fi final String groupId, final String clientMember) { final String GROUP_ASSOCIATE_URL = "/fineract-provider/api/v1/groups/" + groupId + "?command=associateClients&" + Utils.TENANT_IDENTIFIER; - System.out.println("---------------------------------Associate Client To A GROUP---------------------------------------------"); + LOG.info("---------------------------------Associate Client To A GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, associateClientAsJSON(clientMember), "groupId"); } @@ -86,39 +89,38 @@ public static Integer disAssociateClient(final RequestSpecification requestSpec, final String groupId, final String clientMember) { final String GROUP_ASSOCIATE_URL = "/fineract-provider/api/v1/groups/" + groupId + "?command=disassociateClients&" + Utils.TENANT_IDENTIFIER; - System.out.println("---------------------------------Disassociate Client To A GROUP---------------------------------------------"); + LOG.info("---------------------------------Disassociate Client To A GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, associateClientAsJSON(clientMember), "groupId"); } public static Integer activateGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String groupId) { final String GROUP_ASSOCIATE_URL = "/fineract-provider/api/v1/groups/" + groupId + "?command=activate&" + Utils.TENANT_IDENTIFIER; - System.out.println("---------------------------------Activate A GROUP---------------------------------------------"); + LOG.info("---------------------------------Activate A GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, activateGroupAsJSON(""), "groupId"); } public static Integer updateGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String name, final String groupId) { final String GROUP_ASSOCIATE_URL = "/fineract-provider/api/v1/groups/" + groupId + "?" + Utils.TENANT_IDENTIFIER; - System.out.println("---------------------------------UPDATE GROUP---------------------------------------------"); + LOG.info("---------------------------------UPDATE GROUP---------------------------------------------"); return Utils.performServerPut(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, updateGroupAsJSON(name), "groupId"); } public static Integer deleteGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String groupId) { final String GROUP_ASSOCIATE_URL = "/fineract-provider/api/v1/groups/" + groupId + "?" + Utils.TENANT_IDENTIFIER; - System.out.println("---------------------------------DELETE GROUP---------------------------------------------"); + LOG.info("---------------------------------DELETE GROUP---------------------------------------------"); return Utils.performServerDelete(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, "groupId"); } - public static Object assignStaff(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String groupId,final Long staffId){ final String GROUP_ASSIGN_STAFF_URL = "/fineract-provider/api/v1/groups/" + groupId + "?" + Utils.TENANT_IDENTIFIER + "&command=assignStaff"; - System.out.println("---------------------------------DELETE GROUP---------------------------------------------"); + LOG.info("---------------------------------DELETE GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSIGN_STAFF_URL,assignStaffAsJSON(staffId),"changes"); } public static Object assignStaffInheritStaffForClientAccounts(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String groupId,final String staffId){ final String GROUP_ASSIGN_STAFF_URL = "/fineract-provider/api/v1/groups/" + groupId + "?" + Utils.TENANT_IDENTIFIER + "&command=assignStaff"; - System.out.println("---------------------------------DELETE GROUP---------------------------------------------"); + LOG.info("---------------------------------DELETE GROUP---------------------------------------------"); return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSIGN_STAFF_URL,assignStaffAndInheritStaffForClientAccountsAsJSON(staffId),"changes"); } @@ -136,10 +138,9 @@ public static String getTestGroupAsJSON(final boolean active, final String activ } else { map.put("active", "false"); map.put("submittedOnDate", "04 March 2011"); - System.out.println("defaulting to inactive group: 04 March 2011"); + LOG.info("defaulting to inactive group: 04 March 2011"); } - - System.out.println("map : " + map); + LOG.debug("map : {} ", map); return new Gson().toJson(map); } @@ -148,7 +149,7 @@ public static String associateClientAsJSON(final String clientMember) { final List list = new ArrayList<>(); list.add(clientMember); map.put("clientMembers", list); - System.out.println("map : " + map); + LOG.debug("map : {}", map); return new Gson().toJson(map); } @@ -160,36 +161,36 @@ public static String activateGroupAsJSON(final String activationDate) { map.put("activationDate", activationDate); } else { map.put("activationDate", "04 March 2011"); - System.out.println("defaulting to fixed date: 04 March 2011"); + LOG.info("defaulting to fixed date: 04 March 2011"); } - System.out.println("map : " + map); + LOG.debug("map : {}", map); return new Gson().toJson(map); } public static String updateGroupAsJSON(final String name) { final HashMap map = new HashMap<>(); map.put("name", name); - System.out.println("map : " + map); + LOG.debug("map : {}", map); return new Gson().toJson(map); } public static String assignStaffAsJSON(final Long staffId) { final HashMap map = new HashMap<>(); map.put("staffId", staffId); - System.out.println("map : " + map); + LOG.debug("map : {}", map); return new Gson().toJson(map); } public static String assignStaffAndInheritStaffForClientAccountsAsJSON(final String staffId) { final HashMap map = new HashMap<>(); map.put("staffId", staffId); map.put("inheritStaffForClientAccounts","true"); - System.out.println("map : " + map); + LOG.debug("map : {}", map); return new Gson().toJson(map); } public static void verifyGroupCreatedOnServer(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedGroupID) { - System.out.println("------------------------------CHECK GROUP DETAILS------------------------------------\n"); + LOG.info("------------------------------CHECK GROUP DETAILS------------------------------------\n"); final String GROUP_URL = "/fineract-provider/api/v1/groups/" + generatedGroupID + "?" + Utils.TENANT_IDENTIFIER; final Integer responseGroupID = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "id"); assertEquals("ERROR IN CREATING THE GROUP", generatedGroupID, responseGroupID); @@ -197,7 +198,7 @@ public static void verifyGroupCreatedOnServer(final RequestSpecification request public static void verifyGroupDetails(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedGroupID, final String field, final String expectedValue) { - System.out.println("------------------------------CHECK GROUP DETAILS------------------------------------\n"); + LOG.info("------------------------------CHECK GROUP DETAILS------------------------------------\n"); final String GROUP_URL = "/fineract-provider/api/v1/groups/" + generatedGroupID + "?" + Utils.TENANT_IDENTIFIER; final String responseValue = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, field); assertEquals("ERROR IN CREATING THE GROUP", expectedValue, responseValue); @@ -205,7 +206,7 @@ public static void verifyGroupDetails(final RequestSpecification requestSpec, fi public static void verifyGroupActivatedOnServer(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedGroupID, final boolean generatedGroupStatus) { - System.out.println("------------------------------CHECK GROUP STATUS------------------------------------\n"); + LOG.info("------------------------------CHECK GROUP STATUS------------------------------------\n"); final String GROUP_URL = "/fineract-provider/api/v1/groups/" + generatedGroupID + "?" + Utils.TENANT_IDENTIFIER; final Boolean responseGroupStatus = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "active"); assertEquals("ERROR IN ACTIVATING THE GROUP", generatedGroupStatus, responseGroupStatus); @@ -214,33 +215,65 @@ public static void verifyGroupActivatedOnServer(final RequestSpecification reque public static void verifyGroupMembers(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedGroupID, final Integer groupMember) { List list = new ArrayList<>(); - System.out.println("------------------------------CHECK GROUP MEMBERS------------------------------------\n"); + LOG.info("------------------------------CHECK GROUP MEMBERS------------------------------------\n"); final String GROUP_URL = "/fineract-provider/api/v1/groups/" + generatedGroupID + "?associations=clientMembers&" + Utils.TENANT_IDENTIFIER; list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "clientMembers"); + LOG.debug("the list of verifyEmptyGroupMembers : {} ", list); assertTrue("ERROR IN GROUP MEMBER", list.toString().contains("id=" + groupMember.toString())); } public static void verifyEmptyGroupMembers(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedGroupID) { List list = new ArrayList<>(); - System.out.println("------------------------------CHECK EMPTY GROUP MEMBER LIST------------------------------------\n"); + LOG.info("------------------------------CHECK EMPTY GROUP MEMBER LIST------------------------------------\n"); final String GROUP_URL = "/fineract-provider/api/v1/groups/" + generatedGroupID + "?associations=clientMembers&" + Utils.TENANT_IDENTIFIER; list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "clientMembers"); + LOG.debug("the list of verifyEmptyGroupMembers : {} ", list); assertEquals("GROUP MEMBER LIST NOT EMPTY", list, null); } public static void verifyGroupDeleted(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedGroupID) { List list = new ArrayList<>(); - System.out.println("------------------------------CHECK GROUP DELETED------------------------------------\n"); + LOG.info("------------------------------CHECK GROUP DELETED------------------------------------\n"); final String GROUP_URL = "/fineract-provider/api/v1/groups/?" + Utils.TENANT_IDENTIFIER; list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "pageItems"); - assertFalse("GROUP NOT DELETED", list.toString().contains("id=" + generatedGroupID.toString())); } + //Glim_Gsim_testing + public static List verifyRetrieveGlimAccountsByGroupId(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer groupID) { + List list = new ArrayList<>(); + LOG.info("------------------------------CHECK GROUP Retrieve Accounts------------------------------------\n"); + final String GROUP_URL = "/fineract-provider/api/v1/groups/"+groupID+"/glimaccounts?" + Utils.TENANT_IDENTIFIER; + list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "glimId"); + LOG.debug("GlimId of Retrieved Account : {} ", list); + return list; + } + + public static List verifyRetrieveGlimAccountsByGlimId(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer glimId) { + List list = new ArrayList<>(); + LOG.info("------------------------------CHECK GROUP Retrieve Accounts------------------------------------\n"); + final String GROUP_URL = "/fineract-provider/api/v1/loans/glimAccount/"+glimId+"?"+ Utils.TENANT_IDENTIFIER; + list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "glimId"); + LOG.debug("GlimId of Retrieved Account: {} ", list); + return list; + } + + public static List verifyRetrieveGsimAccounts(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Integer groupID) { + List list = new ArrayList<>(); + LOG.info("------------------------------CHECK GROUP Retrieve Accounts------------------------------------\n"); + final String GROUP_URL = "/fineract-provider/api/v1/groups/"+groupID+"/gsimaccounts?" + Utils.TENANT_IDENTIFIER; + list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "gsimId"); + LOG.debug("GsimId Retrieved Accounts: {} ", list); + return list; + } + public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) { return Utils.randomStringGenerator(prefix, lenOfRandomSuffix); } @@ -259,7 +292,7 @@ public static String getTestGroupWithDatatableAsJson(final String registeredTabl map.put("active", "false"); map.put("submittedOnDate", "04 March 2011"); String requestJson = getTestDatatableAsJson(map, registeredTableName); - System.out.println("map : " + requestJson); + LOG.debug("map : {} ", requestJson); return requestJson; } diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java index b00fabced8d..4f9515a1dde 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanApplicationTestBuilder.java @@ -22,9 +22,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class LoanApplicationTestBuilder { + private final static Logger LOG = LoggerFactory.getLogger(LoanApplicationTestBuilder.class); private static final String DAYS = "0"; private static final String WEEKS = "1"; private static final String MONTHS = "2"; @@ -34,9 +38,11 @@ public class LoanApplicationTestBuilder { private static final String EQUAL_PRINCIPAL_PAYMENTS = "0"; private static final String EQUAL_INSTALLMENTS = "1"; private static final String CALCULATION_PERIOD_SAME_AS_REPAYMENT_PERIOD = "1"; + private static final String LOCALE = "en_GB"; public static final String DEFAULT_STRATEGY = "1"; public static final String RBI_INDIA_STRATEGY = "4"; + private String principal = "10,000"; private String loanTermFrequency = ""; private String loanTermFrequencyType = ""; @@ -61,10 +67,14 @@ public class LoanApplicationTestBuilder { @SuppressWarnings("rawtypes") private List charges = new ArrayList<>(); private String repaymentsStartingFromDate = null; + private String isParentAccount = null; + private String totalLoan = "0"; private String calendarId; private boolean syncDisbursementWithMeeting = false; private List> datatables = null; + private List> approvalFormData =null; + public String build(final String clientID, final String groupID, final String loanProductId, final String savingsID) { final HashMap map = new HashMap<>(); @@ -76,6 +86,16 @@ public String build(final String clientID, final String groupID, final String lo } map.put("syncDisbursementWithMeeting", this.syncDisbursementWithMeeting); } + + if (this.loanType == "glim") { + if (isParentAccount!=null){ + map.put("isParentAccount", this.isParentAccount); + } + + if (totalLoan!=null){ + map.put("totalLoan", this.totalLoan); + } + } return build(map, loanProductId, savingsID); } @@ -91,6 +111,19 @@ public String build(final String ID, final String loanProductId, final String sa return build(map, loanProductId, savingsID); } + public String build() + { + final HashMap map = new HashMap<>(); + + if(this.approvalFormData != null) { + map.put("approvalFormData", this.approvalFormData) ; + } + + String approvalFormData=new Gson().toJson(map); + LOG.info("approvalFormData: {} ", approvalFormData); + return approvalFormData; + } + private String build(final HashMap map, final String loanProductId, final String savingsID) { map.put("dateFormat", "dd MMMM yyyy"); map.put("locale", "en_GB"); @@ -137,7 +170,7 @@ private String build(final HashMap map, final String loanProduct if (datatables != null) { map.put("datatables", this.datatables); } - System.out.println("Loan Application request : " + map); + LOG.info("Loan Application request : {} ", map); return new Gson().toJson(map); } @@ -256,6 +289,11 @@ public LoanApplicationTestBuilder withLoanType(final String loanType) { return this; } + public LoanApplicationTestBuilder withtotalLoan(final String totalLoan) { + this.totalLoan = totalLoan; + return this; + } + public LoanApplicationTestBuilder withPrincipalGrace(final String graceOnPrincipalPayment) { this.graceOnPrincipalPayment = graceOnPrincipalPayment; return this; @@ -283,6 +321,17 @@ public LoanApplicationTestBuilder withFirstRepaymentDate(final String firstRepay return this; } + public LoanApplicationTestBuilder withParentAccount(final String parentAccount) { + this.isParentAccount = parentAccount; + return this; + } + + public LoanApplicationTestBuilder withApprovalFormData(final List> approvalFormData) { + this.approvalFormData = new ArrayList<>(); + this.approvalFormData.addAll(approvalFormData); + return this; + } + /** * calendarID parameter is used to sync repayments with group meetings, * especially when using jlg loans diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanStatusChecker.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanStatusChecker.java index afeabd0d458..b59f7dc39b6 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanStatusChecker.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanStatusChecker.java @@ -62,6 +62,10 @@ public static void verifyLoanAccountForeclosed(final HashMap loanSubStatusHashMa assertEquals("Foreclosed", getSubStatus(loanSubStatusHashMap, "value")); } + public static void verifyLoanAccountRejected(final HashMap loanSubStatusHashMap) { + assertEquals("Rejected", getSubStatus(loanSubStatusHashMap, "value")); + } + public static HashMap getStatusOfLoan(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer loanID) { final String url = "/fineract-provider/api/v1/loans/" + loanID + "?" + Utils.TENANT_IDENTIFIER; diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java index 92c618e39e7..d1316627a70 100755 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import org.apache.fineract.integrationtests.common.CommonConstants; @@ -38,12 +39,15 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Workbook; import org.joda.time.LocalDate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @SuppressWarnings({ "rawtypes", "unchecked" }) public class LoanTransactionHelper { private final RequestSpecification requestSpec; private final ResponseSpecification responseSpec; + private final static Logger LOG = LoggerFactory.getLogger(LoanTransactionHelper.class); private static final String CREATE_LOAN_PRODUCT_URL = "/fineract-provider/api/v1/loanproducts?" + Utils.TENANT_IDENTIFIER; private static final String APPLY_LOAN_URL = "/fineract-provider/api/v1/loans?" + Utils.TENANT_IDENTIFIER; @@ -53,6 +57,7 @@ public class LoanTransactionHelper { private static final String DISBURSE_LOAN_COMMAND = "disburse"; private static final String DISBURSE_LOAN_TO_SAVINGS_COMMAND = "disburseToSavings"; private static final String UNDO_DISBURSE_LOAN_COMMAND = "undoDisbursal"; + private static final String REJECT_LOAN_COMMAND = "reject"; private static final String UNDO_LAST_DISBURSE_LOAN_COMMAND = "undolastdisbursal"; private static final String WRITE_OFF_LOAN_COMMAND = "writeoff"; private static final String WAIVE_INTEREST_COMMAND = "waiveinterest"; @@ -77,6 +82,16 @@ public Integer getLoanId(final String loanApplicationJSON) { return Utils.performServerPost(this.requestSpec, this.responseSpec, APPLY_LOAN_URL, loanApplicationJSON, "loanId"); } + public HashMap getGlimId(final String loanApplicationJSON) { + return Utils.performServerPost(this.requestSpec, this.responseSpec, APPLY_LOAN_URL, loanApplicationJSON, ""); + } + + public Object getGlimLoanId(final String glimId) { + final String GET_LOAN_URL = "/fineract-provider/api/v1/loans/glimAccount/" + glimId + "?" + Utils.TENANT_IDENTIFIER; + return Utils.performServerGet(this.requestSpec, this.responseSpec, GET_LOAN_URL, "childLoanId"); + + } + public Object getLoanError(final String loanApplicationJSON, final String responseAttribute) { return Utils.performServerPost(this.requestSpec, this.responseSpec, APPLY_LOAN_URL, loanApplicationJSON, responseAttribute); } @@ -153,8 +168,8 @@ public ArrayList getLoanCharges(final Integer loanId) { public HashMap approveLoan(final String approvalDate, final Integer loanID) { String loanApprovalCommand = createLoanOperationURL(APPROVE_LOAN_COMMAND, loanID); String loanApprovalRequest = getApproveLoanAsJSON(approvalDate); - System.out.println("Loan approval command:" + loanApprovalCommand); - System.out.println("Loan approval request:" + loanApprovalRequest); + LOG.info("Loan approval command: {} ", loanApprovalCommand); + LOG.info("Loan approval request: {} ", loanApprovalRequest); return performLoanTransaction(loanApprovalCommand, loanApprovalRequest); } @@ -206,18 +221,50 @@ public HashMap disburseLoanToSavings(final String date, final Integer loanID) { public HashMap undoDisbursal(final Integer loanID) { final String undoDisburseJson = "{'note' : 'UNDO DISBURSAL'}"; - System.out.println("IN DISBURSE LOAN"); + LOG.info("IN DISBURSE LOAN"); final String url = createLoanOperationURL(UNDO_DISBURSE_LOAN_COMMAND, loanID); - System.out.println("IN DISBURSE LOAN URL " + url); + LOG.info("IN DISBURSE LOAN URL : {} ", url); return performLoanTransaction(createLoanOperationURL(UNDO_DISBURSE_LOAN_COMMAND, loanID), undoDisburseJson); } public Float undoLastDisbursal(final Integer loanID) { final String undoLastDisburseJson = "{'note' : 'UNDO LAST DISBURSAL'}"; final String url = createLoanOperationURL(UNDO_LAST_DISBURSE_LOAN_COMMAND, loanID); - System.out.println("IN UNDO LAST DISBURSE LOAN URL " + url); + LOG.info("IN UNDO LAST DISBURSE LOAN URL : {} ", url); return performUndoLastLoanDisbursementTransaction(createLoanOperationURL(UNDO_LAST_DISBURSE_LOAN_COMMAND, loanID), undoLastDisburseJson); } + //glimtesting + public HashMap approveGlimAccount(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final List> approvalFormData, final Integer glimID) { + String approvalForm = new LoanApplicationTestBuilder() // + .withApprovalFormData(approvalFormData) + .build(); + + final String approvalURL = createGlimAccountURL(APPROVE_LOAN_COMMAND, glimID); + return performLoanTransaction(approvalURL, approvalForm); + } + + public HashMap disburseGlimAccount(final String date, final Integer glimID) { + LOG.info("--------------------------------- GLIM DISBURSEMENT APPLICATION -------------------------------"); + return performLoanTransaction(createGlimAccountURL(DISBURSE_LOAN_COMMAND, glimID), getDisbursementAsJSON(date)); + } + + public HashMap undoDisburseGlimAccount(final Integer glimID) { + LOG.info("--------------------------------- UNDO DISBURSAL GLIM APPLICATION -------------------------------"); + final String undoBodyJson = "{'note':'UNDO DISBURSAL'}"; + return performLoanTransaction(createGlimAccountURL(UNDO_DISBURSE_LOAN_COMMAND, glimID), undoBodyJson); + } + + public HashMap undoApprovalGlimAccount(final Integer glimID) { + LOG.info("--------------------------------- UNDO APPROVAL GLIM APPLICATION -------------------------------"); + final String undoBodyJson = "{'note':'UNDO APPROVAL'}"; + return performLoanTransaction(createGlimAccountURL(UNDO_APPROVAL_LOAN_COMMAND, glimID), undoBodyJson); + } + + public HashMap rejectGlimAccount(final String date, final Integer glimID) { + LOG.info("--------------------------------- REJECT GLIM APPLICATION -------------------------------"); + return performLoanTransaction(createGlimAccountURL(REJECT_LOAN_COMMAND, glimID), getRejectAsJSON(date)); + } public void recoverFromGuarantor(final Integer loanID) { performLoanTransaction(createLoanOperationURL(RECOVER_FROM_GUARANTORS_COMMAND, loanID), "", ""); @@ -253,7 +300,7 @@ public HashMap withdrawLoanApplicationByClient(final String date, final Integer } public Integer addChargesForLoan(final Integer loanId, final String request) { - System.out.println("--------------------------------- ADD CHARGES FOR LOAN --------------------------------"); + LOG.info("--------------------------------- ADD CHARGES FOR LOAN --------------------------------"); final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges?" + Utils.TENANT_IDENTIFIER; final HashMap response = Utils.performServerPost(requestSpec, responseSpec, ADD_CHARGES_URL, request, ""); return (Integer) response.get("resourceId"); @@ -265,7 +312,7 @@ public Object addChargesForAllreadyDisursedLoan(final Integer loanId, final Stri } public Integer updateChargesForLoan(final Integer loanId, final Integer loanchargeId, final String request) { - System.out.println("--------------------------------- ADD CHARGES FOR LOAN --------------------------------"); + LOG.info("--------------------------------- ADD CHARGES FOR LOAN --------------------------------"); final String UPDATE_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges/" + loanchargeId + "?" + Utils.TENANT_IDENTIFIER; final HashMap response = Utils.performServerPut(requestSpec, responseSpec, UPDATE_CHARGES_URL, request, ""); @@ -273,7 +320,7 @@ public Integer updateChargesForLoan(final Integer loanId, final Integer loanchar } public Integer deleteChargesForLoan(final Integer loanId, final Integer loanchargeId) { - System.out.println("--------------------------------- DELETE CHARGES FOR LOAN --------------------------------"); + LOG.info("--------------------------------- DELETE CHARGES FOR LOAN --------------------------------"); final String DELETE_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges/" + loanchargeId + "?" + Utils.TENANT_IDENTIFIER; final HashMap response = Utils.performServerDelete(requestSpec, responseSpec, DELETE_CHARGES_URL, ""); @@ -281,7 +328,7 @@ public Integer deleteChargesForLoan(final Integer loanId, final Integer loanchar } public Integer waiveChargesForLoan(final Integer loanId, final Integer loanchargeId, final String json) { - System.out.println("--------------------------------- WAIVE CHARGES FOR LOAN --------------------------------"); + LOG.info("--------------------------------- WAIVE CHARGES FOR LOAN --------------------------------"); final String CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges/" + loanchargeId + "?command=waive&" + Utils.TENANT_IDENTIFIER; final HashMap response = Utils.performServerPost(requestSpec, responseSpec, CHARGES_URL, json, ""); @@ -289,7 +336,7 @@ public Integer waiveChargesForLoan(final Integer loanId, final Integer loancharg } public Integer payChargesForLoan(final Integer loanId, final Integer loanchargeId, final String json) { - System.out.println("--------------------------------- WAIVE CHARGES FOR LOAN --------------------------------"); + LOG.info("--------------------------------- WAIVE CHARGES FOR LOAN --------------------------------"); final String CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges/" + loanchargeId + "?command=pay&" + Utils.TENANT_IDENTIFIER; final HashMap response = Utils.performServerPost(requestSpec, responseSpec, CHARGES_URL, json, ""); @@ -305,7 +352,7 @@ private String getDisburseLoanAsJSON(final String actualDisbursementDate, final if (transactionAmount != null) { map.put("transactionAmount", transactionAmount); } - System.out.println("Loan Application disburse request : " + map); + LOG.info("Loan Application disburse request : {} ", map); return new Gson().toJson(map); } @@ -319,7 +366,7 @@ private String getDisburseLoanWithRepaymentRescheduleAsJSON(final String actualD if (transactionAmount != null) { map.put("transactionAmount", transactionAmount); } - System.out.println("Loan Application disburse request : " + map); + LOG.info("Loan Application disburse request : {} ", map); return new Gson().toJson(map); } @@ -346,6 +393,22 @@ private String getApproveLoanAsJSON(final String approvalDate, final String expe return new Gson().toJson(map); } + private String getDisbursementAsJSON(final String date) { + final HashMap map = new HashMap<>(); + map.put("actualDisbursementDate", date); + map.put("locale", "en"); + map.put("dateFormat", "dd MMMM yyyy"); + return new Gson().toJson(map); + } + + private String getRejectAsJSON(final String date) { + final HashMap map = new HashMap<>(); + map.put("rejectedOnDate", date); + map.put("locale", "en"); + map.put("dateFormat", "dd MMMM yyyy"); + return new Gson().toJson(map); + } + private String getRepaymentBodyAsJSON(final String transactionDate, final Float transactionAmount) { final HashMap map = new HashMap<>(); map.put("locale", "en"); @@ -363,7 +426,7 @@ private String getForeclosureBodyAsJSON(final String transactionDate, final Inte map.put("transactionDate", transactionDate); map.put("note", "Foreclosure Made!!!"); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info(json); return json; } @@ -408,7 +471,7 @@ public static String getSpecifiedDueDateChargesForLoanAsJSON(final String charge map.put("dueDate", dueDate); map.put("chargeId", chargeId); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -423,7 +486,7 @@ public static String getDisbursementChargesForLoanAsJSON(final String chargeId, map.put("amount", amount); map.put("chargeId", chargeId); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -434,7 +497,7 @@ public static String getInstallmentChargesForLoanAsJSON(final String chargeId, f map.put("amount", amount); map.put("chargeId", chargeId); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -444,7 +507,7 @@ public static String getUpdateChargesForLoanAsJSON(String amount) { map.put("dateFormat", "dd MMMM yyyy"); map.put("amount", amount); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -457,7 +520,7 @@ public static String getPayChargeJSON(final String date, final String installmen map.put("installmentNumber", installmentNumber); } String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -466,7 +529,7 @@ public static String getWaiveChargeJSON(final String installmentNumber) { map.put("locale", "en_GB"); map.put("installmentNumber", installmentNumber); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -499,6 +562,10 @@ private String createLoanTransactionURL(final String command, final Integer loan return "/fineract-provider/api/v1/loans/" + loanID + "/transactions?command=" + command + "&" + Utils.TENANT_IDENTIFIER; } + private String createGlimAccountURL(final String command, final Integer glimID) { + return "/fineract-provider/api/v1/loans/glimAccount/" + glimID + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER; + } + private HashMap performLoanTransaction(final String postURLForLoanTransaction, final String jsonToBeSent) { final HashMap response = Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForLoanTransaction, jsonToBeSent, @@ -540,7 +607,7 @@ private String getAdjustTransactionJSON(final String date, final String transact map.put("transactionDate", date); map.put("transactionAmount", transactionAmount); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info(json); return json; } @@ -556,7 +623,7 @@ private String createLoanRefundTransferURL() { } public void verifyRepaymentScheduleEntryFor(final int repaymentNumber, final float expectedPrincipalOutstanding, final Integer loanID) { - System.out.println("---------------------------GETTING LOAN REPAYMENT SCHEDULE--------------------------------"); + LOG.info("---------------------------GETTING LOAN REPAYMENT SCHEDULE--------------------------------"); final ArrayList repaymentPeriods = getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); assertEquals("Mismatch in Principal Loan Balance Outstanding ", expectedPrincipalOutstanding, repaymentPeriods.get(repaymentNumber) .get("principalLoanBalanceOutstanding")); @@ -675,7 +742,7 @@ public static String getEditDisbursementsAsJSON(final String approvalAmount, fin map.put("updatedExpectedDisbursementDate", updatedExpectedDisbursementDate); map.put("updatedPrincipal", updatedPrincipal); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } @@ -688,7 +755,7 @@ public static String getAddAndDeleteDisbursementsAsJSON(final String approvalAmo map.put("expectedDisbursementDate", expectedDisbursementDate); map.put("disbursementData", disbursementData); String json = new Gson().toJson(map); - System.out.println(json); + LOG.info("{}",json); return json; } diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java index 746b565621c..a41c39795b1 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import org.apache.fineract.integrationtests.common.CommonConstants; @@ -39,12 +40,15 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Workbook; import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @SuppressWarnings({ "rawtypes" }) public class SavingsAccountHelper { private final RequestSpecification requestSpec; private final ResponseSpecification responseSpec; + private final static Logger LOG = LoggerFactory.getLogger(SavingsAccountHelper.class); private static final String SAVINGS_ACCOUNT_URL = "/fineract-provider/api/v1/savingsaccounts"; private static final String APPROVE_SAVINGS_COMMAND = "approve"; @@ -60,6 +64,9 @@ public class SavingsAccountHelper { private static final String DEPOSIT_SAVINGS_COMMAND = "deposit"; private static final String WITHDRAW_SAVINGS_COMMAND = "withdrawal"; + private static final String GSIM_SAVINGS = "/gsim"; + private static final String GSIM_SAVINGS_COMMAND = "/gsimcommands"; + private static final String GSIM_DEPOSIT_SAVINGS_COMMAND = "gsimDeposit"; private static final String MODIFY_TRASACTION_COMMAND = "modify"; private static final String UNDO_TRASACTION_COMMAND = "undo"; @@ -111,7 +118,7 @@ public Integer applyForSavingsApplicationWithExternalId(final Integer ID, final public Integer applyForSavingsApplicationOnDate(final Integer ID, final Integer savingsProductID, final String accountType, String externalId, boolean withdrawalFeeForTransfers, final String submittedOnDate) { - System.out.println("--------------------------------APPLYING FOR SAVINGS APPLICATION--------------------------------"); + LOG.info("--------------------------------APPLYING FOR SAVINGS APPLICATION--------------------------------"); final String savingsApplicationJSON = new SavingsApplicationTestBuilder() // .withExternalId(externalId) // .withWithdrawalFeeForTransfers(withdrawalFeeForTransfers) // @@ -123,7 +130,7 @@ public Integer applyForSavingsApplicationOnDate(final Integer ID, final Integer public Integer applyForSavingsApplicationWithDatatables(final Integer ID, final Integer savingsProductID, final String accountType, final String submittedOnDate, final String datatableName) { - System.out.println("----------------------------APPLYING FOR SAVINGS APPLICATION WITH DATATABLES----------------------------"); + LOG.info("----------------------------APPLYING FOR SAVINGS APPLICATION WITH DATATABLES----------------------------"); final String savingsApplicationJSON = new SavingsApplicationTestBuilder() // .withSubmittedOnDate(submittedOnDate) // .withDatatables(getTestDatatableAsJson(datatableName)) // @@ -134,7 +141,7 @@ public Integer applyForSavingsApplicationWithDatatables(final Integer ID, final public Object applyForSavingsApplicationWithFailure(final Integer ID, final Integer savingsProductID, final String accountType, final String submittedOnDate, final String responseAttribute) { - System.out.println("----------------------------APPLYING FOR SAVINGS APPLICATION WITH ERROR----------------------------"); + LOG.info("----------------------------APPLYING FOR SAVINGS APPLICATION WITH ERROR----------------------------"); final String savingsApplicationJSON = new SavingsApplicationTestBuilder() // .withSubmittedOnDate(submittedOnDate) // .build(ID.toString(), savingsProductID.toString(), accountType); @@ -150,6 +157,21 @@ public HashMap updateSavingsAccount(final Integer ID, final Integer savingsProdu return Utils.performServerPut(this.requestSpec, this.responseSpec, SAVINGS_ACCOUNT_URL + "/" + savingsId + "?" + Utils.TENANT_IDENTIFIER, savingsApplicationJSON, CommonConstants.RESPONSE_CHANGES); } + //GLIM_GSIM_TESTING + public Integer applyForGsimApplication(List> clientArray) { + LOG.info("----------------------------APPLYING FOR GSIM SAVINGS APPLICATION----------------------------"); + LOG.info("clientArray is : {} ", clientArray); + String clientArrays = new SavingsApplicationTestBuilder() // + .withClientArray(clientArray) + .build(); + return SavingsAccountHelper.applyForGsimApplication(clientArrays, requestSpec, responseSpec); + } + + public static Integer applyForGsimApplication(final String clientArrays, final RequestSpecification requestSpec, + final ResponseSpecification responseSpec) { + return Utils.performServerPost(requestSpec,responseSpec, SAVINGS_ACCOUNT_URL + GSIM_SAVINGS +"?" + Utils.TENANT_IDENTIFIER, + clientArrays, "gsimId"); + } public HashMap updateSavingsAccountWithHoldTaxStatus(final Integer savingsId, final boolean value) { final HashMap map = new HashMap<>(); @@ -165,7 +187,7 @@ public HashMap approveSavings(final Integer savingsID) { } public HashMap approveSavingsOnDate(final Integer savingsID, final String approvalDate) { - System.out.println("--------------------------------- APPROVING SAVINGS APPLICATION ------------------------------------"); + LOG.info("--------------------------------- APPROVING SAVINGS APPLICATION ------------------------------------"); final String savingsOperationURL = createSavingsOperationURL(APPROVE_SAVINGS_COMMAND, savingsID); if (approvalDate == null || approvalDate.equals("")) return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJSON(), isBlock); @@ -173,85 +195,85 @@ public HashMap approveSavingsOnDate(final Integer savingsID, final String approv } public HashMap undoApproval(final Integer savingsID) { - System.out.println("--------------------------------- UNDO APPROVING SAVINGS APPLICATION -------------------------------"); + LOG.info("--------------------------------- UNDO APPROVING SAVINGS APPLICATION -------------------------------"); final String undoBodyJson = "{'note':'UNDO APPROVAL'}"; return performSavingApplicationActions(createSavingsOperationURL(UNDO_APPROVAL_SAVINGS_COMMAND, savingsID), undoBodyJson, isBlock); } public HashMap rejectApplication(final Integer savingsID) { - System.out.println("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------"); + LOG.info("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------"); return performSavingApplicationActions(createSavingsOperationURL(REJECT_SAVINGS_COMMAND, savingsID), getRejectedSavingsAsJSON(CREATED_DATE_PLUS_ONE), isBlock); } public List rejectApplicationWithErrorCode(final Integer savingsId, final String date) { - System.out.println("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------"); + LOG.info("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------"); return (List) performSavingActions(createSavingsOperationURL(REJECT_SAVINGS_COMMAND, savingsId), getRejectedSavingsAsJSON(date), CommonConstants.RESPONSE_ERROR); } public HashMap withdrawApplication(final Integer savingsID) { - System.out.println("--------------------------------- Withdraw SAVINGS APPLICATION -------------------------------"); + LOG.info("--------------------------------- Withdraw SAVINGS APPLICATION -------------------------------"); return performSavingApplicationActions(createSavingsOperationURL(WITHDRAWN_BY_CLIENT_SAVINGS_COMMAND, savingsID), getWithdrawnSavingsAsJSON(), isBlock); } public HashMap activateSavings(final Integer savingsID) { - System.out.println("---------------------------------- ACTIVATING SAVINGS APPLICATION ----------------------------------"); + LOG.info("---------------------------------- ACTIVATING SAVINGS APPLICATION ----------------------------------"); return performSavingApplicationActions(createSavingsOperationURL(ACTIVATE_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public HashMap closeSavingsAccount(final Integer savingsID, String withdrawBalance) { - System.out.println("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); + LOG.info("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); return performSavingApplicationActions(createSavingsOperationURL(CLOSE_SAVINGS_COMMAND, savingsID), getCloseAccountJSON(withdrawBalance, LAST_TRANSACTION_DATE), isBlock); } public Object deleteSavingsApplication(final Integer savingsId, final String jsonAttributeToGetBack) { - System.out.println("---------------------------------- DELETE SAVINGS APPLICATION ----------------------------------"); + LOG.info("---------------------------------- DELETE SAVINGS APPLICATION ----------------------------------"); return Utils.performServerDelete(this.requestSpec, this.responseSpec, SAVINGS_ACCOUNT_URL + "/" + savingsId + "?" + Utils.TENANT_IDENTIFIER, jsonAttributeToGetBack); } public Object depositToSavingsAccount(final Integer savingsID, final String amount, String date, String jsonAttributeToGetback) { - System.out.println("--------------------------------- SAVINGS TRANSACTION DEPOSIT --------------------------------"); + LOG.info("--------------------------------- SAVINGS TRANSACTION DEPOSIT --------------------------------"); return performSavingActions(createSavingsTransactionURL(DEPOSIT_SAVINGS_COMMAND, savingsID), getSavingsTransactionJSON(amount, date), jsonAttributeToGetback); } public Object withdrawalFromSavingsAccount(final Integer savingsId, final String amount, String date, String jsonAttributeToGetback) { - System.out.println("\n--------------------------------- SAVINGS TRANSACTION WITHDRAWAL --------------------------------"); + LOG.info("\n--------------------------------- SAVINGS TRANSACTION WITHDRAWAL --------------------------------"); return performSavingActions(createSavingsTransactionURL(WITHDRAW_SAVINGS_COMMAND, savingsId), getSavingsTransactionJSON(amount, date), jsonAttributeToGetback); } public Integer updateSavingsAccountTransaction(final Integer savingsId, final Integer transactionId, final String amount) { - System.out.println("\n--------------------------------- MODIFY SAVINGS TRANSACTION --------------------------------"); + LOG.info("\n--------------------------------- MODIFY SAVINGS TRANSACTION --------------------------------"); return (Integer) performSavingActions(createAdjustTransactionURL(MODIFY_TRASACTION_COMMAND, savingsId, transactionId), getSavingsTransactionJSON(amount, LAST_TRANSACTION_DATE), CommonConstants.RESPONSE_RESOURCE_ID); } public Integer undoSavingsAccountTransaction(final Integer savingsId, final Integer transactionId) { - System.out.println("\n--------------------------------- UNDO SAVINGS TRANSACTION --------------------------------"); + LOG.info("\n--------------------------------- UNDO SAVINGS TRANSACTION --------------------------------"); return (Integer) performSavingActions(createAdjustTransactionURL(UNDO_TRASACTION_COMMAND, savingsId, transactionId), getSavingsTransactionJSON("0", LAST_TRANSACTION_DATE), CommonConstants.RESPONSE_RESOURCE_ID); } public void calculateInterestForSavings(final Integer savingsId) { - System.out.println("--------------------------------- CALCULATING INTEREST FOR SAVINGS --------------------------------"); + LOG.info("--------------------------------- CALCULATING INTEREST FOR SAVINGS --------------------------------"); performSavingActions(createSavingsCalculateInterestURL(CALCULATE_INTEREST_SAVINGS_COMMAND, savingsId), getCalculatedInterestForSavingsApplicationAsJSON(), ""); } public void postInterestForSavings(final Integer savingsId) { - System.out.println("--------------------------------- POST INTEREST FOR SAVINGS --------------------------------"); + LOG.info("--------------------------------- POST INTEREST FOR SAVINGS --------------------------------"); performSavingActions(createSavingsCalculateInterestURL(POST_INTEREST_SAVINGS_COMMAND, savingsId), getCalculatedInterestForSavingsApplicationAsJSON(), ""); } public void postInterestAsOnSavings(final Integer savingsId, final String today) { - System.out.println("--------------------------------- POST INTEREST AS ON FOR SAVINGS --------------------------------"); + LOG.info("--------------------------------- POST INTEREST AS ON FOR SAVINGS --------------------------------"); performSavingActions(createSavingsPostInterestAsOnURL(POST_INTEREST_AS_ON_SAVINGS_COMMAND, savingsId), getCalculatedInterestForSavingsApplicationAsJSON(today), CommonConstants.RESPONSE_RESOURCE_ID); } @@ -261,7 +283,7 @@ public Integer addChargesForSavings(final Integer savingsId, final Integer charg } public Integer addChargesForSavings(final Integer savingsId, final Integer chargeId, boolean addDueDate, BigDecimal amount) { - System.out.println("--------------------------------- ADD CHARGES FOR SAVINGS --------------------------------"); + LOG.info("--------------------------------- ADD CHARGES FOR SAVINGS --------------------------------"); return (Integer) performSavingActions(SAVINGS_ACCOUNT_URL + "/" + savingsId + "/charges?" + Utils.TENANT_IDENTIFIER, getPeriodChargeRequestJSON(chargeId, addDueDate, amount), CommonConstants.RESPONSE_RESOURCE_ID); } @@ -292,55 +314,55 @@ public Integer deleteCharge(final Integer chargeId, final Integer savingsId) { } public HashMap blockSavings(final Integer savingsID) { - System.out.println("---------------------------------- BLOCKING SAVINGS ACCOUNT ----------------------------------"); + LOG.info("---------------------------------- BLOCKING SAVINGS ACCOUNT ----------------------------------"); Boolean isBlock = true; return performSavingApplicationActions(createSavingsOperationURL(BLOCK_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public HashMap unblockSavings(final Integer savingsID) { - System.out.println("---------------------------------- UNBLOCKING SAVINGS ACCOUNT ----------------------------------"); + LOG.info("---------------------------------- UNBLOCKING SAVINGS ACCOUNT ----------------------------------"); Boolean isBlock = true; return performSavingApplicationActions(createSavingsOperationURL(UNBLOCK_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public HashMap blockDebit(final Integer savingsID) { - System.out.println("---------------------------------- BLOCKING DEBIT TRANSACTIONS ----------------------------------"); + LOG.info("---------------------------------- BLOCKING DEBIT TRANSACTIONS ----------------------------------"); Boolean isBlock = true; return performSavingApplicationActions(createSavingsOperationURL(BLOCK_DEBITS_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public HashMap unblockDebit(final Integer savingsID) { - System.out.println("---------------------------------- UNBLOCKING DEBIT TRANSACTIONS ----------------------------------"); + LOG.info("---------------------------------- UNBLOCKING DEBIT TRANSACTIONS ----------------------------------"); Boolean isBlock = true; return performSavingApplicationActions(createSavingsOperationURL(UNBLOCK_DEBITS_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public HashMap blockCredit(final Integer savingsID) { - System.out.println("---------------------------------- BLOCKING CREDIT TRANSACTIONS ----------------------------------"); + LOG.info("---------------------------------- BLOCKING CREDIT TRANSACTIONS ----------------------------------"); Boolean isBlock = true; return performSavingApplicationActions(createSavingsOperationURL(BLOCK_CREDITS_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public HashMap unblockCredit(final Integer savingsID) { - System.out.println("---------------------------------- UNBLOCKING CREDIT TRANSACTIONS ----------------------------------"); + LOG.info("---------------------------------- UNBLOCKING CREDIT TRANSACTIONS ----------------------------------"); Boolean isBlock = true; return performSavingApplicationActions(createSavingsOperationURL(UNBLOCK_CREDITS_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock); } public Object holdAmountInSavingsAccount(final Integer savingsID, final String amount, String date, String jsonAttributeToGetback) { - System.out.println("--------------------------------- SAVINGS TRANSACTION HOLD AMOUNT--------------------------------"); + LOG.info("--------------------------------- SAVINGS TRANSACTION HOLD AMOUNT--------------------------------"); return performSavingActions(createSavingsTransactionURL(HOLD_AMOUNT_SAVINGS_COMMAND, savingsID), getSavingsTransactionJSON(amount, date), jsonAttributeToGetback); } public Integer releaseAmount(final Integer savingsId, final Integer transactionId) { - System.out.println("\n--------------------------------- SAVINGS TRANSACTION RELEASE AMOUNT--------------------------------"); + LOG.info("\n--------------------------------- SAVINGS TRANSACTION RELEASE AMOUNT--------------------------------"); return (Integer) performSavingActions(createAdjustTransactionURL(RELEASE_AMOUNT_SAVINGS_COMMAND, savingsId, transactionId), getSavingsTransactionJSON("1000", LAST_TRANSACTION_DATE), CommonConstants.RESPONSE_RESOURCE_ID); } @@ -356,7 +378,7 @@ private String getApproveSavingsAsJsonOnDate(final String approvalDate) { map.put("approvedOnDate", approvalDate); map.put("note", "Approval NOTE"); String savingsAccountApproveJson = new Gson().toJson(map); - System.out.println(savingsAccountApproveJson); + LOG.info(savingsAccountApproveJson); return savingsAccountApproveJson; } @@ -367,7 +389,7 @@ private String getRejectedSavingsAsJSON(final String rejectedOnDate) { map.put("rejectedOnDate", rejectedOnDate); map.put("note", "Rejected NOTE"); String savingsAccountJson = new Gson().toJson(map); - System.out.println(savingsAccountJson); + LOG.info(savingsAccountJson); return savingsAccountJson; } @@ -378,7 +400,7 @@ private String getWithdrawnSavingsAsJSON() { map.put("withdrawnOnDate", CREATED_DATE_PLUS_ONE); map.put("note", "Rejected NOTE"); String savingsAccountJson = new Gson().toJson(map); - System.out.println(savingsAccountJson); + LOG.info(savingsAccountJson); return savingsAccountJson; } @@ -388,7 +410,7 @@ private String getActivatedSavingsAsJSON() { map.put("dateFormat", CommonConstants.dateFormat); map.put("activatedOnDate", TRANSACTION_DATE); String savingsAccountActivateJson = new Gson().toJson(map); - System.out.println(savingsAccountActivateJson); + LOG.info(savingsAccountActivateJson); return savingsAccountActivateJson; } @@ -399,14 +421,14 @@ private String getSavingsTransactionJSON(final String amount, final String trans map.put("transactionDate", transactionDate); map.put("transactionAmount", amount); String savingsAccountWithdrawalJson = new Gson().toJson(map); - System.out.println(savingsAccountWithdrawalJson); + LOG.info(savingsAccountWithdrawalJson); return savingsAccountWithdrawalJson; } private String getCalculatedInterestForSavingsApplicationAsJSON() { final HashMap map = new HashMap<>(); String savingsAccountCalculatedInterestJson = new Gson().toJson(map); - System.out.println(savingsAccountCalculatedInterestJson); + LOG.info(savingsAccountCalculatedInterestJson); return savingsAccountCalculatedInterestJson; } @@ -472,10 +494,25 @@ private String getCloseAccountPostInterestJSON(String withdrawBalance, String cl return josn; } + private String updateGsimJSON(String clientID, String groupID, String productID) { + final HashMap map = new HashMap<>(); + map.put("clientId", clientID); + map.put("groupId", groupID); + map.put("productId", productID); + String savingsAccountJson = new Gson().toJson(map); + LOG.info(savingsAccountJson); + return savingsAccountJson; + } + + private String createSavingsOperationURL(final String command, final Integer savingsID) { return SAVINGS_ACCOUNT_URL + "/" + savingsID + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER; } + private String createSavingsGsimOperationURL(final String command, final Integer gsimID) { + return SAVINGS_ACCOUNT_URL + GSIM_SAVINGS_COMMAND +"/" + gsimID + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER; + } + private String createSavingsTransactionURL(final String command, final Integer savingsID) { return SAVINGS_ACCOUNT_URL + "/" + savingsID + "/transactions?command=" + command + "&" + Utils.TENANT_IDENTIFIER; } @@ -568,14 +605,14 @@ private Object performSavingActions(final String postURLForSavingsTransaction, f public Object closeSavingsAccountAndGetBackRequiredField(final Integer savingsID, String withdrawBalance, final String jsonAttributeToGetBack, final String closedOnDate) { - System.out.println("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); + LOG.info("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); return performSavingActions(createSavingsOperationURL(CLOSE_SAVINGS_COMMAND, savingsID), getCloseAccountJSON(withdrawBalance, closedOnDate), jsonAttributeToGetBack); } public Object closeSavingsAccountPostInterestAndGetBackRequiredField(final Integer savingsID, String withdrawBalance, final String jsonAttributeToGetBack, final String closedOnDate) { - System.out.println("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); + LOG.info("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); return performSavingActions(createSavingsOperationURL(CLOSE_SAVINGS_COMMAND, savingsID), getCloseAccountPostInterestJSON(withdrawBalance, closedOnDate), jsonAttributeToGetBack); } @@ -656,7 +693,7 @@ public static Integer openSavingsAccount(final RequestSpecification requestSpec, private static Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String minOpenningBalance) { - System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); + LOG.info("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); SavingsProductHelper savingsProductHelper = new SavingsProductHelper(); final String savingsProductJSON = savingsProductHelper // .withInterestCompoundingPeriodTypeAsDaily() // @@ -705,4 +742,80 @@ public String getOutputTemplateLocation(final String importDocumentId){ return Utils.performServerOutputTemplateLocationGet(requestSpec,responseSpec,"/fineract-provider/api/v1/imports/getOutputTemplateLocation"+"?" +Utils.TENANT_IDENTIFIER,importDocumentId); } + //gsim testing + public HashMap approveGsimSavings(final Integer gsimID) { + LOG.info("---------------GSIM APPROVAL---------------"); + return approveGsimSavingsOnDate(gsimID, null); + } + + public HashMap approveGsimSavingsOnDate(final Integer gsimID, final String approvalDate) { + LOG.info("--------------------------------- APPROVING GSIM SAVINGS APPLICATION ------------------------------------"); + final String savingsOperationURL = createSavingsGsimOperationURL(APPROVE_SAVINGS_COMMAND, gsimID); + + if (approvalDate == null || approvalDate.equals("")) + return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJSON(), isBlock); + return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJsonOnDate(approvalDate), isBlock); + } + + public HashMap rejectGsimApplication(final Integer gsimID) { + LOG.info("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------"); + return performSavingApplicationActions(createSavingsGsimOperationURL(REJECT_SAVINGS_COMMAND, gsimID), + getRejectedSavingsAsJSON(CREATED_DATE_PLUS_ONE), isBlock); + } + + + public List rejectGsimApplicationWithErrorCode(final Integer gsimID, final String date) { + LOG.info("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------"); + return (List) performSavingActions(createSavingsGsimOperationURL(REJECT_SAVINGS_COMMAND, gsimID), getRejectedSavingsAsJSON(date), + CommonConstants.RESPONSE_ERROR); + } + + public HashMap undoApprovalGsimSavings(final Integer gsimId) { + LOG.info("--------------------------------- UNDO APPROVING GSIM SAVINGS APPLICATION -------------------------------"); + final String undoBodyJson = "{'note':'UNDO APPROVAL'}"; + return performSavingApplicationActions(createSavingsGsimOperationURL(UNDO_APPROVAL_SAVINGS_COMMAND, gsimId), undoBodyJson, isBlock); + } + + public Integer depositGsimApplication(Integer savingsID, List> savingsArray) { + LOG.info("--------------------------------- DEPOSIT GSIM SAVINGS APPLICATION -------------------------------"); + String savingsArrays = new SavingsApplicationTestBuilder() // + .withSavingsArray(savingsArray) + .build(); + LOG.info("savingsArray : {} ", savingsArrays); + return SavingsAccountHelper.depositGsimApplication(savingsID, savingsArrays, requestSpec, responseSpec); + + } + + public static Integer depositGsimApplication(Integer savingsID, final String savingsArrays, final RequestSpecification requestSpec, + final ResponseSpecification responseSpec) { + + final String depositGsimURL= SAVINGS_ACCOUNT_URL +"/"+savingsID+"/transactions"+"?"+"command="+GSIM_DEPOSIT_SAVINGS_COMMAND +"&"+ Utils.TENANT_IDENTIFIER; + LOG.info("depositGsimURL : {} ", depositGsimURL); + return Utils.performServerPost(requestSpec,responseSpec,depositGsimURL,savingsArrays, CommonConstants.RESPONSE_RESOURCE_ID); + } + + public HashMap activateGsimSavings(final Integer gsimID) { + LOG.info("---------------------------------- ACTIVATING GSIM SAVINGS APPLICATION ----------------------------------"); + return performSavingApplicationActions(createSavingsGsimOperationURL(ACTIVATE_SAVINGS_COMMAND, gsimID), getActivatedSavingsAsJSON(), isBlock); + } + + public HashMap closeGsimSavingsAccount(final Integer gsimID, String withdrawBalance) { + LOG.info("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); + return performSavingApplicationActions(createSavingsGsimOperationURL(CLOSE_SAVINGS_COMMAND, gsimID), + getCloseAccountJSON(withdrawBalance, LAST_TRANSACTION_DATE), isBlock); + } + + public Object closeGsimSavingsAccountAndGetBackRequiredField(final Integer gsimId, String withdrawBalance, + final String jsonAttributeToGetBack, final String closedOnDate) { + LOG.info("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------"); + return performSavingActions(createSavingsGsimOperationURL(CLOSE_SAVINGS_COMMAND, gsimId), + getCloseAccountJSON(withdrawBalance, closedOnDate), jsonAttributeToGetBack); + } + + public HashMap updateGsimApplication(final Integer gsimID, final Integer clientID, final Integer groupID, final Integer productID) { + LOG.info("--------------------------------- UPDATE GSIM SAVINGS APPLICATION -------------------------------"); + final String GSIM_URL = "/fineract-provider/api/v1/savingsaccounts/gsim/" + gsimID + "?" + Utils.TENANT_IDENTIFIER; + return Utils.performServerPut(requestSpec, responseSpec, GSIM_URL, updateGsimJSON(clientID.toString(), groupID.toString(), productID.toString()), ""); + } + } \ No newline at end of file diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsApplicationTestBuilder.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsApplicationTestBuilder.java index 4ec4eb4af72..6fdddaec517 100755 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsApplicationTestBuilder.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsApplicationTestBuilder.java @@ -19,11 +19,17 @@ package org.apache.fineract.integrationtests.common.savings; import com.google.gson.Gson; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class SavingsApplicationTestBuilder { + private final static Logger LOG = LoggerFactory.getLogger(SavingsApplicationTestBuilder.class); private static final String LOCALE = "en_GB"; private String submittedOnDate = ""; @@ -35,6 +41,9 @@ public class SavingsApplicationTestBuilder { private List> datatables = null; + private List> clientArray =null; + private List> savingsArray =null; + public String build(final String ID, final String savingsProductId, final String accountType) { final HashMap map = new HashMap<>(); @@ -55,11 +64,26 @@ public String build(final String ID, final String savingsProductId, final String if (datatables != null) { map.put("datatables", this.datatables); } + String savingsApplicationJSON = new Gson().toJson(map); - System.out.println(savingsApplicationJSON); + LOG.info("{}",savingsApplicationJSON); return savingsApplicationJSON; } + public String build() + { + final HashMap map = new HashMap<>(); + if(this.clientArray != null) { + map.put("clientArray", this.clientArray) ; + } + + if(this.savingsArray != null) { + map.put("savingsArray", this.savingsArray) ; + } + String GsimApplicationJSON = new Gson().toJson(map); + return GsimApplicationJSON; + } + public SavingsApplicationTestBuilder withSubmittedOnDate(final String savingsApplicationSubmittedDate) { this.submittedOnDate = savingsApplicationSubmittedDate; return this; @@ -84,4 +108,17 @@ public SavingsApplicationTestBuilder withDatatables(final List> clientArray) { + this.clientArray = new ArrayList<>(); + this.clientArray.addAll(clientArray); + return this; + } + + public SavingsApplicationTestBuilder withSavingsArray(final List> savingsArray) { + this.savingsArray = new ArrayList<>(); + this.savingsArray.addAll(savingsArray); + return this; + } + } \ No newline at end of file diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java index 19b18d6a376..c424135edfe 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java @@ -28,10 +28,13 @@ import java.util.Map; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @SuppressWarnings("unused") public class SavingsProductHelper { + private final static Logger LOG = LoggerFactory.getLogger(SavingsProductHelper.class); private static final String SAVINGS_PRODUCT_URL = "/fineract-provider/api/v1/savingsproducts"; private static final String CREATE_SAVINGS_PRODUCT_URL = SAVINGS_PRODUCT_URL + "?" + Utils.TENANT_IDENTIFIER; @@ -89,6 +92,9 @@ public class SavingsProductHelper { private String daysToInactive = null; private String daysToDormancy = null; private String daysToEscheat = null; + private Boolean withgsimID = null; + private Integer gsimID = null; + public String build() { final HashMap map = new HashMap<>(); @@ -125,6 +131,7 @@ public String build() { map.put("minRequiredBalance", this.minRequiredBalance); map.put("enforceMinRequiredBalance", this.enforceMinRequiredBalance); map.put("withHoldTax", this.withHoldTax.toString()); + if (withHoldTax) { map.put("taxGroupId", taxGroupId); } @@ -138,8 +145,9 @@ public String build() { map.put("daysToEscheat", this.daysToEscheat); } + String savingsProductCreateJson = new Gson().toJson(map); - System.out.println(savingsProductCreateJson); + LOG.info("{}",savingsProductCreateJson); return savingsProductCreateJson; } @@ -228,6 +236,13 @@ public SavingsProductHelper withWithHoldTax(final String taxGroupId) { return this; } + public SavingsProductHelper withgsimID(final Integer gsimID) { + if(withgsimID !=null) { + this.gsimID = gsimID; + } + return this; + } + public SavingsProductHelper withCurrencyCode(String currency) { this.currencyCode = currency; return this; @@ -275,7 +290,7 @@ public static Integer createSavingsProduct(final String savingsProductJSON, fina public static void verifySavingsProductCreatedOnServer(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final Integer generatedProductID) { - System.out.println("------------------------------CHECK CLIENT DETAILS------------------------------------\n"); + LOG.info("------------------------------CHECK CLIENT DETAILS------------------------------------\n"); final String GET_SAVINGS_PRODUCT_URL = SAVINGS_PRODUCT_URL + "/" + generatedProductID + "?" + Utils.TENANT_IDENTIFIER; final Integer responseSavingsProductID = Utils.performServerGet(requestSpec, responseSpec, GET_SAVINGS_PRODUCT_URL, "id"); assertEquals("ERROR IN CREATING THE Savings Product", generatedProductID, responseSavingsProductID); @@ -286,7 +301,6 @@ public SavingsProductHelper withDormancy() { this.daysToInactive = "30"; this.daysToDormancy = "60"; this.daysToEscheat = "90"; - return this; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index f713c1beb20..12cb81a1db2 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -883,6 +883,15 @@ public CommandWrapperBuilder rejectLoanApplication(final Long loanId) { return this; } + public CommandWrapperBuilder rejectGLIMApplication(final Long glimId) { + this.actionName = "REJECT"; + this.entityName = "GLIMLOAN"; + this.entityId = glimId; + this.loanId = glimId; + this.href = "/loans/" + glimId; + return this; + } + public CommandWrapperBuilder withdrawLoanApplication(final Long loanId) { this.actionName = "WITHDRAW"; this.entityName = "LOAN"; @@ -901,6 +910,50 @@ public CommandWrapperBuilder approveLoanApplication(final Long loanId) { return this; } + public CommandWrapperBuilder approveGLIMLoanApplication(final Long glimId) { + this.actionName = "APPROVE"; + this.entityName = "GLIMLOAN"; + this.entityId = glimId; + this.loanId = glimId; + this.href = "/loans/" + glimId; + return this; + } + + public CommandWrapperBuilder disburseGlimLoanApplication(final Long glimId) { + this.actionName = "DISBURSE"; + this.entityName = "GLIMLOAN"; + this.entityId = glimId; + this.loanId = glimId; + this.href = "/loans/" + glimId; + return this; + } + + public CommandWrapperBuilder repaymentGlimLoanApplication(final Long glimId) { + this.actionName = "REPAYMENT"; + this.entityName = "GLIMLOAN"; + this.entityId = glimId; + this.loanId = glimId; + this.href = "/loans/" + glimId; + return this; + } + public CommandWrapperBuilder undoGLIMLoanDisbursal(final Long glimId) { + this.actionName = "UNDODISBURSAL"; + this.entityName = "GLIMLOAN"; + this.entityId = glimId; + this.loanId = glimId; + this.href = "/loans/" + glimId; + return this; + } + + public CommandWrapperBuilder undoGLIMLoanApproval(final Long glimId) { + this.actionName = "UNDOAPPROVAL"; + this.entityName = "GLIMLOAN"; + this.entityId = glimId; + this.loanId = glimId; + this.href = "/loans/" + glimId; + return this; + } + public CommandWrapperBuilder disburseLoanApplication(final Long loanId) { this.actionName = "DISBURSE"; this.entityName = "LOAN"; @@ -1126,6 +1179,14 @@ public CommandWrapperBuilder createSavingsAccount() { return this; } + public CommandWrapperBuilder createGSIMAccount() { + this.actionName = "CREATE"; + this.entityName = "GSIMACCOUNT"; + this.entityId = null; + this.href = "/gsimaccounts/template"; + return this; + } + public CommandWrapperBuilder updateSavingsAccount(final Long accountId) { this.actionName = "UPDATE"; this.entityName = "SAVINGSACCOUNT"; @@ -1134,6 +1195,14 @@ public CommandWrapperBuilder updateSavingsAccount(final Long accountId) { return this; } + public CommandWrapperBuilder updateGSIMAccount(final Long accountId) { + this.actionName = "UPDATE"; + this.entityName = "GSIMACCOUNT"; + this.entityId = accountId; + this.href = "/gsimaccounts/" + accountId; + return this; + } + public CommandWrapperBuilder deleteSavingsAccount(final Long accountId) { this.actionName = "DELETE"; this.entityName = "SAVINGSACCOUNT"; @@ -1151,6 +1220,15 @@ public CommandWrapperBuilder rejectSavingsAccountApplication(final Long accountI return this; } + public CommandWrapperBuilder rejectGSIMAccountApplication(final Long accountId) { + this.actionName = "REJECT"; + this.entityName = "GSIMACCOUNT"; + this.entityId = accountId; + this.savingsId = accountId; + this.href = "/savingsaccounts/" + accountId + "?command=reject"; + return this; + } + public CommandWrapperBuilder withdrawSavingsAccountApplication(final Long accountId) { this.actionName = "WITHDRAW"; this.entityName = "SAVINGSACCOUNT"; @@ -1169,6 +1247,15 @@ public CommandWrapperBuilder approveSavingsAccountApplication(final Long account return this; } + public CommandWrapperBuilder approveGSIMAccountApplication(final Long accountId) { + this.actionName = "APPROVE"; + this.entityName = "GSIMACCOUNT"; + this.entityId = accountId; + this.savingsId = accountId; + this.href = "/gsimsaccounts/" + accountId + "?command=approve"; + return this; + } + public CommandWrapperBuilder undoSavingsAccountApplication(final Long accountId) { this.actionName = "APPROVALUNDO"; this.entityName = "SAVINGSACCOUNT"; @@ -1178,6 +1265,15 @@ public CommandWrapperBuilder undoSavingsAccountApplication(final Long accountId) return this; } + public CommandWrapperBuilder undoGSIMApplicationApproval(final Long accountId) { + this.actionName = "APPROVALUNDO"; + this.entityName = "GSIMACCOUNT"; + this.entityId = accountId; + this.savingsId = accountId; + this.href = "/savingsaccounts/" + accountId + "?command=undoapproval"; + return this; + } + public CommandWrapperBuilder savingsAccountActivation(final Long accountId) { this.actionName = "ACTIVATE"; this.entityName = "SAVINGSACCOUNT"; @@ -1187,6 +1283,15 @@ public CommandWrapperBuilder savingsAccountActivation(final Long accountId) { return this; } + public CommandWrapperBuilder gsimAccountActivation(final Long accountId) { + this.actionName = "ACTIVATE"; + this.entityName = "GSIMACCOUNT"; + this.savingsId = accountId; + this.entityId = null; + this.href = "/savingsaccounts/" + accountId + "?command=activate"; + return this; + } + public CommandWrapperBuilder closeSavingsAccountApplication(final Long accountId) { this.actionName = "CLOSE"; this.entityName = "SAVINGSACCOUNT"; @@ -1196,6 +1301,15 @@ public CommandWrapperBuilder closeSavingsAccountApplication(final Long accountId return this; } + public CommandWrapperBuilder closeGSIMApplication(final Long accountId) { + this.actionName = "CLOSE"; + this.entityName = "GSIMACCOUNT"; + this.entityId = accountId; + this.savingsId = accountId; + this.href = "/savingsaccounts/" + accountId + "?command=close"; + return this; + } + public CommandWrapperBuilder createAccountTransfer() { this.actionName = "CREATE"; this.entityName = "ACCOUNTTRANSFER"; @@ -1237,6 +1351,15 @@ public CommandWrapperBuilder savingsAccountDeposit(final Long accountId) { return this; } + public CommandWrapperBuilder gsimSavingsAccountDeposit(final Long accountId) { + this.actionName = "DEPOSIT"; + this.entityName = "GSIMACCOUNT"; + this.savingsId = accountId; + this.entityId = null; + this.href = "/savingsaccounts/" + accountId + "/transactions"; + return this; + } + public CommandWrapperBuilder savingsAccountWithdrawal(final Long accountId) { this.actionName = "WITHDRAWAL"; this.entityName = "SAVINGSACCOUNT"; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java index d68d5fd6cdc..1dfd0bace7c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java @@ -97,6 +97,13 @@ public static JsonCommand fromExistingCommand(JsonCommand command, final JsonEle command.transactionId, command.url, command.productId,command.creditBureauId,command.organisationCreditBureauId); } + public static JsonCommand fromExistingCommand(JsonCommand command, final JsonElement parsedCommand,final Long clientId) { + final String jsonCommand = command.fromApiJsonHelper.toJson(parsedCommand); + return new JsonCommand(command.commandId, jsonCommand, parsedCommand, command.fromApiJsonHelper, command.entityName, + command.resourceId, command.subresourceId, command.groupId, clientId, command.loanId, command.savingsId, + command.transactionId, command.url, command.productId,command.creditBureauId,command.organisationCreditBureauId); + } + public JsonCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long subresourceId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String transactionId, final String url, diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java index 7fd07a54ce0..d9ce6fb19b5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResult.java @@ -41,13 +41,15 @@ public class CommandProcessingResult implements Serializable { @SuppressWarnings("unused") private final String resourceIdentifier; private final Long productId; + private final Long gsimId; + private final Long glimId; private Boolean rollbackTransaction; public static CommandProcessingResult fromDetails(final Long commandId, final Long officeId, final Long groupId, final Long clientId, - final Long loanId, final Long savingsId, final String resourceIdentifier, final Long entityId, final String transactionId, + final Long loanId, final Long savingsId, final String resourceIdentifier, final Long entityId, final Long gsimId, final Long glimId, final String transactionId, final Map changes, final Long productId, final Boolean rollbackTransaction, final Long subResourceId) { return new CommandProcessingResult(commandId, officeId, groupId, clientId, loanId, savingsId, resourceIdentifier, entityId, - transactionId, changes, productId, rollbackTransaction, subResourceId); + transactionId, changes, productId, gsimId, glimId, rollbackTransaction, subResourceId); } public static CommandProcessingResult commandOnlyResult(final Long commandId) { @@ -97,12 +99,14 @@ public CommandProcessingResult(final Long entityId) { this.transactionId = null; this.changes = new HashMap<>(); this.productId = null; + this.gsimId=null; + this.glimId=null; this.subResourceId = null; } private CommandProcessingResult(final Long commandId, final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String resourceIdentifier, final Long resourceId, final String transactionId, - final Map changesOnly, final Long productId, Boolean rollbackTransaction, final Long subResourceId) { + final Map changesOnly, final Long productId, final Long gsimId, final Long glimId, Boolean rollbackTransaction, final Long subResourceId) { this.commandId = commandId; this.officeId = officeId; this.groupId = groupId; @@ -114,6 +118,8 @@ private CommandProcessingResult(final Long commandId, final Long officeId, final this.changes = changesOnly; this.transactionId = transactionId; this.productId = productId; + this.gsimId=gsimId; + this.glimId=glimId; this.rollbackTransaction = rollbackTransaction; this.subResourceId = subResourceId; } @@ -134,6 +140,8 @@ protected CommandProcessingResult(final Long resourceId, final Long officeId, fi this.commandId = commandId; this.changes = changesOnly; this.productId = null; + this.gsimId=null; + this.glimId=null; this.subResourceId = null; } @@ -190,6 +198,14 @@ public Long getProductId() { return this.productId; } + public Long getGsimId() { + return this.gsimId; + } + + public Long getGlimId() { + return this.glimId; + } + public boolean isRollbackTransaction() { return this.rollbackTransaction != null && this.rollbackTransaction; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java index bfc3575141f..335c31a3f6b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/data/CommandProcessingResultBuilder.java @@ -35,6 +35,8 @@ public class CommandProcessingResultBuilder { private String resourceIdentifier; private Long entityId; private Long subEntityId; + private Long gsimId; + private Long glimId; private String transactionId; private Map changes; private Long productId; @@ -42,7 +44,7 @@ public class CommandProcessingResultBuilder { public CommandProcessingResult build() { return CommandProcessingResult.fromDetails(this.commandId, this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, - this.resourceIdentifier, this.entityId, this.transactionId, this.changes, this.productId, this.rollbackTransaction, + this.resourceIdentifier, this.entityId, this.gsimId, this.glimId, this.transactionId, this.changes, this.productId, this.rollbackTransaction, this.subEntityId); } @@ -106,6 +108,16 @@ public CommandProcessingResultBuilder withProductId(final Long productId) { return this; } + public CommandProcessingResultBuilder withGsimId(final Long gsimId) { + this.gsimId = gsimId; + return this; + } + + public CommandProcessingResultBuilder withGlimId(final Long glimId) { + this.glimId = glimId; + return this; + } + public CommandProcessingResultBuilder setRollbackTransaction(final boolean rollbackTransaction) { this.rollbackTransaction = this.rollbackTransaction || rollbackTransaction; return this; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java index 0a156d07efc..b161a189a35 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java @@ -52,6 +52,8 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService; import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail; import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues; +import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy; +import org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler; import org.apache.fineract.portfolio.savings.domain.SavingsAccountDomainService; @@ -77,6 +79,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer private final SavingsAccountWritePlatformService savingsAccountWritePlatformService; private final AccountTransferDetailRepository accountTransferDetailRepository; private final LoanReadPlatformService loanReadPlatformService; + private final GSIMRepositoy gsimRepository; @Autowired public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValidator accountTransfersDataValidator, @@ -85,7 +88,8 @@ public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValida final LoanAssembler loanAssembler, final LoanAccountDomainService loanAccountDomainService, final SavingsAccountWritePlatformService savingsAccountWritePlatformService, final AccountTransferDetailRepository accountTransferDetailRepository, - final LoanReadPlatformService loanReadPlatformService) { + final LoanReadPlatformService loanReadPlatformService, + final GSIMRepositoy gsimRepository) { this.accountTransfersDataValidator = accountTransfersDataValidator; this.accountTransferAssembler = accountTransferAssembler; this.accountTransferRepository = accountTransferRepository; @@ -96,6 +100,7 @@ public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValida this.savingsAccountWritePlatformService = savingsAccountWritePlatformService; this.accountTransferDetailRepository = accountTransferDetailRepository; this.loanReadPlatformService = loanReadPlatformService; + this.gsimRepository=gsimRepository; } @Transactional @@ -410,6 +415,16 @@ public Long transferFunds(final AccountTransferDTO accountTransferDTO) { toSavingsAccount, deposit, loanTransaction); this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails); transferTransactionId = accountTransferDetails.getId(); + + // if the savings account is GSIM, update its parent as well + if(toSavingsAccount.getGsim()!=null) + { + GroupSavingsIndividualMonitoring gsim=gsimRepository.findById(toSavingsAccount.getGsim().getId()).get(); + BigDecimal currentBalance=gsim.getParentDeposit(); + BigDecimal newBalance=currentBalance.add(accountTransferDTO.getTransactionAmount()); + gsim.setParentDeposit(newBalance); + gsimRepository.save(gsim); + } } else { throw new GeneralPlatformDomainRuleException("error.msg.accounttransfer.loan.to.loan.not.supported", "Account transfer from loan to another loan is not supported"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/AccountSummaryCollectionData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/AccountSummaryCollectionData.java index 2b207bf9ad0..b6c0fc46c8e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/AccountSummaryCollectionData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/AccountSummaryCollectionData.java @@ -27,6 +27,7 @@ public class AccountSummaryCollectionData { private final Collection loanAccounts; + private final Collection groupLoanIndividualMonitoringAccounts; private final Collection savingsAccounts; private final Collection shareAccounts ; private final Collection guarantorAccounts; @@ -35,10 +36,15 @@ public class AccountSummaryCollectionData { private final Collection memberSavingsAccounts; private final Collection memberGuarantorAccounts; - public AccountSummaryCollectionData(final Collection loanAccounts, - final Collection savingsAccounts, final Collection shareAccounts, - final Collection guarantorAccounts) { + + /* METHOD SIGNATURE CHANGE NOTICE: Method's signature + was changed for GLIM & GSIM implementation*/ + public AccountSummaryCollectionData(final Collection loanAccounts,final Collection groupLoanIndividualMonitoringAccounts, + final Collection savingsAccounts, final Collection shareAccounts,final Collection guarantorAccounts) + { + this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts); + this.groupLoanIndividualMonitoringAccounts=groupLoanIndividualMonitoringAccounts; this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts); this.shareAccounts = defaultShareAccountsIfEmpty(shareAccounts) ; this.guarantorAccounts = guarantorAccounts; @@ -47,10 +53,13 @@ public AccountSummaryCollectionData(final Collection loa this.memberGuarantorAccounts = null; } - public AccountSummaryCollectionData(final Collection loanAccounts, + public AccountSummaryCollectionData(final Collection loanAccounts,final Collection groupLoanIndividualMonitoringAccounts, final Collection savingsAccounts, final Collection guarantorAccounts, final Collection memberLoanAccounts, final Collection memberSavingsAccounts, final Collection memberGuarantorAccounts) { + /* Note to Self: GSIM not passed in*/ + this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts); + this.groupLoanIndividualMonitoringAccounts=groupLoanIndividualMonitoringAccounts; this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts); this.guarantorAccounts = guarantorAccounts; this.shareAccounts = null ; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/LoanAccountSummaryData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/LoanAccountSummaryData.java index 88e9f678751..29edf5aa188 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/LoanAccountSummaryData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/LoanAccountSummaryData.java @@ -31,6 +31,7 @@ public class LoanAccountSummaryData { private final Long id; private final String accountNo; + private final String parentAccountNumber; private final String externalId; private final Long productId; private final String productName; @@ -49,6 +50,28 @@ public LoanAccountSummaryData(final Long id, final String accountNo, final Strin final LoanApplicationTimelineData timeline, final Boolean inArrears,final BigDecimal originalLoan,final BigDecimal loanBalance,final BigDecimal amountPaid) { this.id = id; this.accountNo = accountNo; + this.parentAccountNumber=null; + this.externalId = externalId; + this.productId = productId; + this.productName = loanProductName; + this.shortProductName = shortLoanProductName; + this.status = loanStatus; + this.loanType = loanType; + this.loanCycle = loanCycle; + this.timeline = timeline; + this.inArrears = inArrears; + this.loanBalance = loanBalance; + this.originalLoan = originalLoan; + this.amountPaid = amountPaid; + } + + + public LoanAccountSummaryData(final Long id, final String accountNo,final String parentAccountNumber, final String externalId, final Long productId, + final String loanProductName, final String shortLoanProductName, final LoanStatusEnumData loanStatus, final EnumOptionData loanType, final Integer loanCycle, + final LoanApplicationTimelineData timeline, final Boolean inArrears,final BigDecimal originalLoan,final BigDecimal loanBalance,final BigDecimal amountPaid) { + this.id = id; + this.accountNo = accountNo; + this.parentAccountNumber=parentAccountNumber; this.externalId = externalId; this.productId = productId; this.productName = loanProductName; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsAccountSummaryData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsAccountSummaryData.java index ae721b499ec..73e3793b454 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsAccountSummaryData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsAccountSummaryData.java @@ -69,4 +69,12 @@ public SavingsAccountSummaryData(final Long id, final String accountNo, final St this.subStatus = subStatus; this.lastActiveTransactionDate = lastActiveTransactionDate; } + + public String getAccountNo() { + return accountNo; + } + + public Long getId() { + return id; + } } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsSummaryCustom.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsSummaryCustom.java new file mode 100644 index 00000000000..5805508b962 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/data/SavingsSummaryCustom.java @@ -0,0 +1,83 @@ +/** + * 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.accountdetails.data; + +import java.math.BigDecimal; +import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.organisation.monetary.data.CurrencyData; +import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData; +import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData; +import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData; +import org.joda.time.LocalDate; + + +@SuppressWarnings("unused") +public class SavingsSummaryCustom + { + private final Long id; + private final String displayName; + private final String accountNo; + private final String externalId; + private final Long productId; + private final String productName; + private final String shortProductName; + private final SavingsAccountStatusEnumData status; + private final CurrencyData currency; + private final BigDecimal accountBalance; + //differentiate Individual, JLG or Group account + private final EnumOptionData accountType; + private final SavingsAccountApplicationTimelineData timeline; + private final SavingsAccountSubStatusEnumData subStatus; + private final LocalDate lastActiveTransactionDate; + + //differentiate deposit accounts Savings, FD and RD accounts + private final EnumOptionData depositType; + + public SavingsSummaryCustom(final Long id,final String displayName, final String accountNo, final String externalId, final Long productId, + final String productName, final String shortProductName, final SavingsAccountStatusEnumData status, final CurrencyData currency, + final BigDecimal accountBalance, final EnumOptionData accountType, final SavingsAccountApplicationTimelineData timeline, final EnumOptionData depositType, + final SavingsAccountSubStatusEnumData subStatus, final LocalDate lastActiveTransactionDate) { + this.id = id; + this.displayName=displayName; + this.accountNo = accountNo; + this.externalId = externalId; + this.productId = productId; + this.productName = productName; + this.shortProductName = shortProductName; + this.status = status; + this.currency = currency; + this.accountBalance = accountBalance; + this.accountType = accountType; + this.timeline = timeline; + this.depositType = depositType; + this.subStatus = subStatus; + this.lastActiveTransactionDate = lastActiveTransactionDate; + } + + public String getAccountNo() { + return accountNo; + } + + public Long getId() { + return id; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/domain/AccountType.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/domain/AccountType.java index 386d67c49e2..450282fe507 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/domain/AccountType.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/domain/AccountType.java @@ -26,7 +26,9 @@ public enum AccountType { INVALID(0, "accountType.invalid"), // INDIVIDUAL(1, "accountType.individual"), // GROUP(2, "accountType.group"), // - JLG(3, "accountType.jlg");// JLG account given in group context + JLG(3, "accountType.jlg"),// JLG account given in group context + GLIM(4, "accountType.glim"), + GSIM(5, "accountType.gsim"); private final Integer value; private final String code; @@ -49,6 +51,12 @@ public static AccountType fromInt(final Integer accountTypeValue) { case 3: enumeration = AccountType.JLG; break; + case 4: + enumeration = AccountType.GLIM; + break; + case 5: + enumeration = AccountType.GSIM; + break; } return enumeration; } @@ -91,4 +99,12 @@ public boolean isGroupAccount() { public boolean isJLGAccount() { return this.value.equals(AccountType.JLG.getValue()); } + + public boolean isGLIMAccount() { + return this.value.equals(AccountType.GLIM.getValue()); + } + + public boolean isGSIMAccount() { + return this.value.equals(AccountType.GSIM.getValue()); + } } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java index 1b5f7f76f10..51a6c9b7cf4 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformService.java @@ -19,6 +19,7 @@ package org.apache.fineract.portfolio.accountdetails.service; import java.util.Collection; +import java.util.List; import org.apache.fineract.portfolio.accountdetails.data.AccountSummaryCollectionData; import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData; @@ -33,4 +34,8 @@ public interface AccountDetailsReadPlatformService { public Collection retrieveGroupLoanAccountsByLoanOfficerId(final Long groupId, final Long loanOfficerId); public Collection retrieveClientActiveLoanAccountSummary(final Long clientId); + + public List retrieveLoanAccountDetailsByGroupIdAndGlimAccountNumber(Long groupId,final String glimAccount); + + AccountSummaryCollectionData retrieveGroupAccountDetails(Long groupId, Long gsimId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java index b9cd852ef67..185d96c711f 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountDetailsReadPlatformServiceJpaRepositoryImpl.java @@ -74,15 +74,20 @@ public AccountSummaryCollectionData retrieveClientAccountDetails(final Long clie // Check if client exists this.clientReadPlatformService.retrieveOne(clientId); final String loanwhereClause = " where l.client_id = ?"; + final String glimLoanClause=" where l.client_id = ? and l.loan_type_enum=4"; + + //note to self: investigate the effect of have loans stored as another type especially given that we want to maintain how the system currently handles loans of exisiting types. final String savingswhereClause = " where sa.client_id = ? order by sa.status_enum ASC, sa.account_no ASC"; + final String guarantorWhereClause = " where g.entity_id = ? and g.is_active = 1 order by l.account_no ASC"; + final List glimAccounts = retrieveLoanAccountDetails(glimLoanClause, new Object[] { clientId }); final List loanAccounts = retrieveLoanAccountDetails(loanwhereClause, new Object[] { clientId }); final List savingsAccounts = retrieveAccountDetails(savingswhereClause, new Object[] { clientId }); final List shareAccounts = retrieveShareAccountDetails(clientId) ; final List guarantorloanAccounts = retrieveGuarantorLoanAccountDetails( - guarantorWhereClause, new Object[] { clientId }); - return new AccountSummaryCollectionData(loanAccounts, savingsAccounts, shareAccounts, guarantorloanAccounts); + guarantorWhereClause, new Object[] { clientId }); + return new AccountSummaryCollectionData(loanAccounts,glimAccounts, savingsAccounts, shareAccounts,guarantorloanAccounts); } @Override @@ -90,11 +95,14 @@ public AccountSummaryCollectionData retrieveGroupAccountDetails(final Long group // Check if group exists this.groupReadPlatformService.retrieveOne(groupId); final String loanWhereClauseForGroup = " where l.group_id = ? and l.client_id is null"; + final String loanWhereClauseForGroupAndLoanType = " where l.group_id = ? and l.loan_type_enum=4"; final String loanWhereClauseForMembers = " where l.group_id = ? and l.client_id is not null"; final String savingswhereClauseForGroup = " where sa.group_id = ? and sa.client_id is null order by sa.status_enum ASC, sa.account_no ASC"; final String savingswhereClauseForMembers = " where sa.group_id = ? and sa.client_id is not null order by sa.status_enum ASC, sa.account_no ASC"; + final String guarantorWhereClauseForGroup = " where l.group_id = ? and l.client_id is null and g.is_active = 1 order by l.account_no ASC"; final String guarantorWhereClauseForMembers = " where l.group_id = ? and l.client_id is not null and g.is_active = 1 order by l.account_no ASC"; + final List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); final List groupLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroup, new Object[] { groupId }); final List groupSavingsAccounts = retrieveAccountDetails(savingswhereClauseForGroup, @@ -105,9 +113,32 @@ public AccountSummaryCollectionData retrieveGroupAccountDetails(final Long group new Object[] { groupId }); final List memberSavingsAccounts = retrieveAccountDetails(savingswhereClauseForMembers, new Object[] { groupId }); + final List memberGuarantorloanAccounts = retrieveGuarantorLoanAccountDetails( - guarantorWhereClauseForMembers, new Object[] { groupId }); - return new AccountSummaryCollectionData(groupLoanAccounts, groupSavingsAccounts, groupGuarantorloanAccounts, memberLoanAccounts, memberSavingsAccounts, memberGuarantorloanAccounts); + guarantorWhereClauseForMembers, new Object[] { groupId }); + return new AccountSummaryCollectionData(groupLoanAccounts,glimAccounts, groupSavingsAccounts, groupGuarantorloanAccounts, memberLoanAccounts, memberSavingsAccounts, memberGuarantorloanAccounts); + + } + + @Override + public AccountSummaryCollectionData retrieveGroupAccountDetails(final Long groupId,final Long gsimId) { + // Check if group exists + this.groupReadPlatformService.retrieveOne(groupId); + final String loanWhereClauseForGroup = " where l.group_id = ? and l.client_id is null"; + final String loanWhereClauseForGroupAndLoanType = " where l.group_id = ? and l.loan_type_enum=4"; + final String loanWhereClauseForMembers = " where l.group_id = ? and l.client_id is not null"; + final String savingswhereClauseForGroup = " where sa.group_id = ? and sa.gsim_id = ? sa.client_id is null order by sa.status_enum ASC, sa.account_no ASC"; + final String savingswhereClauseForMembers = " where sa.group_id = ? and sa.client_id is not null order by sa.status_enum ASC, sa.account_no ASC"; + + final List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); + final List groupLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroup, new Object[] { groupId }); + final List gsimSavingsAccounts = retrieveAccountDetails(savingswhereClauseForGroup, + new Object[] { groupId,gsimId }); + final List memberLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForMembers, + new Object[] { groupId }); + final List memberSavingsAccounts = retrieveAccountDetails(savingswhereClauseForMembers, + new Object[] { groupId }); + return new AccountSummaryCollectionData(groupLoanAccounts, glimAccounts,gsimSavingsAccounts, null,memberLoanAccounts, memberSavingsAccounts,null); } @Override @@ -131,6 +162,16 @@ public Collection retrieveGroupLoanAccountsByLoanOfficer return retrieveLoanAccountDetails(loanWhereClause, new Object[] { clientId }); } + @Override + public List retrieveLoanAccountDetailsByGroupIdAndGlimAccountNumber(final Long groupId,final String glimAccount) { + final LoanAccountSummaryDataMapper rm = new LoanAccountSummaryDataMapper(); + final String loanWhereClauseForGroupAndLoanType = " where l.group_id =? and glim.account_number=? and l.loan_type_enum=4"; + final String sql = "select " + rm.loanAccountSummarySchema() + loanWhereClauseForGroupAndLoanType; + // this.columnValidator.validateSqlInjection(rm.loanAccountSummarySchema(), loanWhereClauseForGroupAndLoanType); + return this.jdbcTemplate.query(sql, rm, new Object[]{groupId , glimAccount}); + } + + private List retrieveLoanAccountDetails(final String loanwhereClause, final Object[] inputs) { final LoanAccountSummaryDataMapper rm = new LoanAccountSummaryDataMapper(); final String sql = "select " + rm.loanAccountSummarySchema() + loanwhereClause; @@ -404,6 +445,8 @@ public String loanAccountSummarySchema() { .append(" l.product_id as productId, lp.name as productName, lp.short_name as shortProductName,") .append(" l.loan_status_id as statusId, l.loan_type_enum as loanType,") + .append(" glim.account_number as parentAccountNumber,") + .append("l.principal_disbursed_derived as originalLoan,") .append("l.total_outstanding_derived as loanBalance,") .append("l.total_repayment_derived as amountPaid,") @@ -437,7 +480,8 @@ public String loanAccountSummarySchema() { .append(" left join m_appuser abu on abu.id = l.approvedon_userid") .append(" left join m_appuser dbu on dbu.id = l.disbursedon_userid") .append(" left join m_appuser cbu on cbu.id = l.closedon_userid") - .append(" left join m_loan_arrears_aging la on la.loan_id = l.id"); + .append(" left join m_loan_arrears_aging la on la.loan_id = l.id") + .append(" left join glim_accounts glim on glim.id=l.glim_id"); return accountsSummary.toString(); } @@ -447,6 +491,7 @@ public LoanAccountSummaryData mapRow(final ResultSet rs, @SuppressWarnings("unus final Long id = JdbcSupport.getLong(rs, "id"); final String accountNo = rs.getString("accountNo"); + final String parentAccountNumber=rs.getString("parentAccountNumber"); final String externalId = rs.getString("externalId"); final Long productId = JdbcSupport.getLong(rs, "productId"); final String loanProductName = rs.getString("productName"); @@ -509,7 +554,7 @@ public LoanAccountSummaryData mapRow(final ResultSet rs, @SuppressWarnings("unus disbursedByFirstname, disbursedByLastname, closedOnDate, closedByUsername, closedByFirstname, closedByLastname, expectedMaturityDate, writtenOffOnDate, closedByUsername, closedByFirstname, closedByLastname); - return new LoanAccountSummaryData(id, accountNo, externalId, productId, loanProductName, shortLoanProductName, loanStatus, loanType, loanCycle, + return new LoanAccountSummaryData(id, accountNo,parentAccountNumber, externalId, productId, loanProductName, shortLoanProductName, loanStatus, loanType, loanCycle, timeline, inArrears,originalLoan,loanBalance,amountPaid); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountEnumerations.java index 0f3c1e19fac..5df984623ea 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/accountdetails/service/AccountEnumerations.java @@ -47,6 +47,9 @@ public static EnumOptionData loanType(final AccountType type) { case JLG: optionData = new EnumOptionData(AccountType.JLG.getValue().longValue(), AccountType.JLG.getCode(), "JLG"); break; + case GLIM: + optionData = new EnumOptionData(AccountType.GLIM.getValue().longValue(), AccountType.GLIM.getCode(), "GLIM"); + break; } return optionData; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformService.java index d84e4a897a7..3b77146cc50 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarReadPlatformService.java @@ -51,4 +51,6 @@ Collection retrieveParentCalendarsByEntity(final Long entityId, fi Boolean isCalendarAssociatedWithEntity(final Long entityId, final Long calendarId, Long entityTypeId); + + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java index d4b83f9a062..b0a820dc9df 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/api/GroupsApiResource.java @@ -33,6 +33,7 @@ import java.io.InputStream; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -88,15 +89,18 @@ import org.apache.fineract.portfolio.group.service.CenterReadPlatformService; import org.apache.fineract.portfolio.group.service.GroupReadPlatformService; import org.apache.fineract.portfolio.group.service.GroupRolesReadPlatformService; +import org.apache.fineract.portfolio.loanaccount.data.GLIMContainer; +import org.apache.fineract.portfolio.loanaccount.service.GLIMAccountInfoReadPlatformService; import org.apache.fineract.portfolio.meeting.data.MeetingData; import org.apache.fineract.portfolio.meeting.service.MeetingReadPlatformService; +import org.apache.fineract.portfolio.savings.data.GSIMContainer; +import org.apache.fineract.portfolio.savings.service.GSIMReadPlatformService; import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; - @Path("/groups") @Component @Scope("singleton") @@ -113,6 +117,8 @@ public class GroupsApiResource { private final ToApiJsonSerializer toApiJsonSerializer; private final ToApiJsonSerializer groupGeneralApiJsonSerializer; private final ToApiJsonSerializer groupSummaryToApiJsonSerializer; + private final ToApiJsonSerializer glimContainerToApiJsonSerializer; + private final ToApiJsonSerializer gsimContainerToApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; private final CollectionSheetReadPlatformService collectionSheetReadPlatformService; @@ -124,6 +130,8 @@ public class GroupsApiResource { private final EntityDatatableChecksReadService entityDatatableChecksReadService; private final BulkImportWorkbookService bulkImportWorkbookService; private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService; + private final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService; + private final GSIMReadPlatformService gsimReadPlatformService; @Autowired @@ -132,6 +140,8 @@ public GroupsApiResource(final PlatformSecurityContext context, final GroupReadP final ToApiJsonSerializer toApiJsonSerializer, final ToApiJsonSerializer groupTopOfHierarchyApiJsonSerializer, final ToApiJsonSerializer groupSummaryToApiJsonSerializer, + final ToApiJsonSerializer glimContainerToApiJsonSerializer, + final ToApiJsonSerializer gsimContainerToApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final CollectionSheetReadPlatformService collectionSheetReadPlatformService, final FromJsonHelper fromJsonHelper, @@ -140,15 +150,18 @@ public GroupsApiResource(final PlatformSecurityContext context, final GroupReadP final CalendarReadPlatformService calendarReadPlatformService, final MeetingReadPlatformService meetingReadPlatformService, final EntityDatatableChecksReadService entityDatatableChecksReadService, final BulkImportWorkbookService bulkImportWorkbookService, - final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService) { - - this.context = context; + final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService, + final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService, + final GSIMReadPlatformService gsimReadPlatformService) { + this.context = context; this.groupReadPlatformService = groupReadPlatformService; this.centerReadPlatformService = centerReadPlatformService; this.clientReadPlatformService = clientReadPlatformService; this.toApiJsonSerializer = toApiJsonSerializer; this.groupGeneralApiJsonSerializer = groupTopOfHierarchyApiJsonSerializer; this.groupSummaryToApiJsonSerializer = groupSummaryToApiJsonSerializer; + this.glimContainerToApiJsonSerializer=glimContainerToApiJsonSerializer; + this.gsimContainerToApiJsonSerializer=gsimContainerToApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; this.collectionSheetReadPlatformService = collectionSheetReadPlatformService; @@ -160,6 +173,9 @@ public GroupsApiResource(final PlatformSecurityContext context, final GroupReadP this.entityDatatableChecksReadService = entityDatatableChecksReadService; this.bulkImportWorkbookPopulatorService=bulkImportWorkbookPopulatorService; this.bulkImportWorkbookService=bulkImportWorkbookService; + this.glimAccountInfoReadPlatformService=glimAccountInfoReadPlatformService; + this.gsimReadPlatformService=gsimReadPlatformService; + } @GET @@ -482,13 +498,14 @@ public String retrieveAccounts(@PathParam("groupId") @ApiParam(value = "groupId" final AccountSummaryCollectionData groupAccount = this.accountDetailsReadPlatformService.retrieveGroupAccountDetails(groupId); - final Set GROUP_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("loanAccounts", "savingsAccounts", + final Set GROUP_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("loanAccounts", "groupLoanIndividualMonitoringAccounts","savingsAccounts", "memberLoanAccounts", "memberSavingsAccounts")); final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.groupSummaryToApiJsonSerializer.serialize(settings, groupAccount, GROUP_ACCOUNTS_DATA_PARAMETERS); } + @GET @Path("downloadtemplate") @Produces("application/vnd.ms-excel") @@ -508,4 +525,64 @@ public String postGroupTemplate(@FormDataParam("file") InputStream uploadedInput uploadedInputStream,fileDetail,locale,dateFormat); return this.toApiJsonSerializer.serialize(importDocumentId); } + + @GET + @Path("{groupId}/glimaccounts") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveglimAccounts(@PathParam("groupId") final Long groupId, @QueryParam("parentLoanAccountNo")final String parentLoanAccountNo, @Context final UriInfo uriInfo) + { + this.context.authenticatedUser().validateHasReadPermission("GROUP"); + List glimContainer = Collections.emptyList(); + if(parentLoanAccountNo==null) + { + glimContainer=(List)glimAccountInfoReadPlatformService.findGlimAccount(groupId); + } + else + { + glimContainer=(List)glimAccountInfoReadPlatformService.findGlimAccountbyGroupAndAccount(groupId,parentLoanAccountNo); + } + + + + final Set GLIM_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("groupId", "accountNumber","childGLIMAccounts","memberLoanAccounts", "parentPrincipalAmount")); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.glimContainerToApiJsonSerializer.serialize(settings, glimContainer, GLIM_ACCOUNTS_DATA_PARAMETERS); + + } + + @GET + @Path("{groupId}/gsimaccounts") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveGsimAccounts(@PathParam("groupId") final Long groupId, @QueryParam("parentGSIMAccountNo")final String parentGSIMAccountNo, + @QueryParam("parentGSIMId")final Long parentGSIMId,@Context final UriInfo uriInfo) + { + List gsimContainer; + this.context.authenticatedUser().validateHasReadPermission("GROUP"); + + if(parentGSIMAccountNo==null && parentGSIMId!=null) + { + gsimContainer= (List)this.gsimReadPlatformService.findGsimAccountContainerbyGsimAccountId(parentGSIMId); + } + else if(parentGSIMAccountNo !=null && parentGSIMId==null ) + { + gsimContainer= (List)this.gsimReadPlatformService.findGsimAccountContainerbyGsimAccountNumber(parentGSIMAccountNo); + } + else + { + gsimContainer= (List)this.gsimReadPlatformService.findGSIMAccountContainerByGroupId(groupId); + + } + + + final Set GSIM_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("gsimId","groupId", "accountNumber","childGSIMAccounts", + "parentBalance", "savingsStatus")); + + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.gsimContainerToApiJsonSerializer.serialize(settings, gsimContainer, GSIM_ACCOUNTS_DATA_PARAMETERS); + + } + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java index 9a141456672..91e29144bce 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/domain/Group.java @@ -58,6 +58,7 @@ import org.apache.fineract.portfolio.group.exception.GroupExistsInCenterException; import org.apache.fineract.portfolio.group.exception.GroupNotExistsInCenterException; import org.apache.fineract.portfolio.group.exception.InvalidGroupStateTransitionException; +import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; import org.apache.fineract.useradministration.domain.AppUser; import org.joda.time.LocalDate; @@ -144,6 +145,9 @@ public final class Group extends AbstractPersistableCustom { @OneToMany(mappedBy="group",cascade = CascadeType.REMOVE) private Set groupRole; + @OneToMany(mappedBy = "group") + private List glimLoan; + // JPA default constructor for entity protected Group() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMemberNotFoundInGSIMException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMemberNotFoundInGSIMException.java new file mode 100644 index 00000000000..5da7aae1a0d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/exception/GroupMemberNotFoundInGSIMException.java @@ -0,0 +1,30 @@ +/** + * 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.group.exception; + +import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException; + + public class GroupMemberNotFoundInGSIMException extends AbstractPlatformDomainRuleException + { + public GroupMemberNotFoundInGSIMException(final Long clientId) + { + super("error.msg.Group.member.not.found.in.linked.gsim", "The client with id `" + clientId + "` is not present in GSIM", clientId); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java index 2919fac487e..6edee48951f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java @@ -31,6 +31,7 @@ public interface LoanApiConstants { public static final String loanChargeIdParameterName = "loanChargeId"; public static final String principalDisbursedParameterName = "transactionAmount"; public static final String chargesParameterName = "charges"; + public static final String loanIdTobeApproved="loanId"; public static final String approvedLoanAmountParameterName = "approvedLoanAmount"; public static final String approvedOnDateParameterName = "approvedOnDate"; @@ -109,6 +110,8 @@ public interface LoanApiConstants { public static final String dueDateParamName = "dueDate"; public static final String modifiedDueDateParamName = "modifiedDueDate"; public static final String principalParamName = "principal"; + public static final String parentAccountParamName="isParentAccount"; + public static final String totalLoanParamName="totalLoan"; public static final String installmentAmountParamName = "installmentAmount"; //loan write off public static final String WRITEOFFREASONS = "WriteOffReasons"; @@ -126,4 +129,7 @@ public interface LoanApiConstants { public static final String datatables = "datatables"; public static final String isEqualAmortizationParam = "isEqualAmortization"; + public static final String applicationId = "applicationId"; + public static final String lastApplication = "lastApplication"; + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java index 112d830cf64..49a76805d8c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java @@ -105,6 +105,7 @@ import org.apache.fineract.portfolio.group.data.GroupGeneralData; import org.apache.fineract.portfolio.group.service.GroupReadPlatformService; 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; @@ -121,6 +122,7 @@ 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; @@ -265,6 +267,8 @@ public class LoansApiResource { LoanApiConstants.datatables, LoanProductConstants.ratesParamName)); private final Set LOAN_APPROVAL_DATA_PARAMETERS = new HashSet<>(Arrays.asList("approvalDate", "approvalAmount")); + final Set GLIM_ACCOUNTS_DATA_PARAMETERS = new HashSet<>(Arrays.asList("glimId","groupId", "clientId","parentLoanAccountNo","parentPrincipalAmount", + "childLoanAccountNo", "childPrincipalAmount","clientName")); private final String resourceNameForPermissions = "LOAN"; private final PlatformSecurityContext context; @@ -296,6 +300,8 @@ public class LoansApiResource { private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService; private final RateReadService rateReadService; private final ConfigurationDomainService configurationDomainService; + private final DefaultToApiJsonSerializer glimTemplateToApiJsonSerializer; + private final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService; @Autowired public LoansApiResource(final PlatformSecurityContext context, final LoanReadPlatformService loanReadPlatformService, @@ -319,7 +325,8 @@ public LoansApiResource(final PlatformSecurityContext context, final LoanReadPla final EntityDatatableChecksReadService entityDatatableChecksReadService, final BulkImportWorkbookService bulkImportWorkbookService, final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService, final RateReadService rateReadService, - final ConfigurationDomainService configurationDomainService) { + final ConfigurationDomainService configurationDomainService, final DefaultToApiJsonSerializer glimTemplateToApiJsonSerializer, + final GLIMAccountInfoReadPlatformService glimAccountInfoReadPlatformService) { this.context = context; this.loanReadPlatformService = loanReadPlatformService; this.loanProductReadPlatformService = loanProductReadPlatformService; @@ -349,6 +356,8 @@ public LoansApiResource(final PlatformSecurityContext context, final LoanReadPla this.bulkImportWorkbookService=bulkImportWorkbookService; this.bulkImportWorkbookPopulatorService=bulkImportWorkbookPopulatorService; this.configurationDomainService = configurationDomainService; + this.glimTemplateToApiJsonSerializer=glimTemplateToApiJsonSerializer; + this.glimAccountInfoReadPlatformService=glimAccountInfoReadPlatformService; } /* @@ -918,6 +927,57 @@ public Response getLoansTemplate(@QueryParam("officeId") final Long officeId, 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=this.glimAccountInfoReadPlatformService.findglimRepaymentTemplate(glimId); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.glimTemplateToApiJsonSerializer.serialize(settings, glimRepaymentTemplate, this.GLIM_ACCOUNTS_DATA_PARAMETERS); + } + + @POST + @Path("glimAccount/{glimId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @ApiOperation(value = "Approve GLIM Application | Undo GLIM Application Approval | Reject GLIM Application | Disburse Loan Disburse Loan To Savings Account | Undo Loan Disbursal", httpMethod = "POST", notes = "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") + @ApiImplicitParams({@ApiImplicitParam(value = "body", required = true, paramType = "body", dataType = "body", format = "body", dataTypeClass = LoansApiResourceSwagger.PostLoansLoanIdRequest.class)}) + @ApiResponses({@ApiResponse(code = 200, message = "OK", response = 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") diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GLIMContainer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GLIMContainer.java new file mode 100644 index 00000000000..82aea12aa19 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GLIMContainer.java @@ -0,0 +1,73 @@ +/** + * 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.data; + +import java.math.BigDecimal; +import java.util.List; +import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData; + +public class GLIMContainer { + + private final BigDecimal glimId; + + private final BigDecimal groupId; + + private final String accountNumber; + + private final List childGLIMAccounts; + + private final BigDecimal parentPrincipalAmount; + + private final String loanStatus; + + public GLIMContainer(final BigDecimal glimId,final BigDecimal groupId,final String accountNumber,final List childGLIMAccounts, + final BigDecimal parentPrincipalAmount,final String loanStatus) { + this.glimId=glimId; + this.groupId=groupId; + this.accountNumber = accountNumber; + this.childGLIMAccounts=childGLIMAccounts; + this.parentPrincipalAmount = parentPrincipalAmount; + this.loanStatus=loanStatus; + + } + + public BigDecimal getGlimId() { + return glimId; + } + + public BigDecimal getGroupId() { + return groupId; + } + + public String getAccountNumber() { + return accountNumber; + } + + public List getChildGLIMAccounts() { + return childGLIMAccounts; + } + + public BigDecimal getParentPrincipalAmount() { + return parentPrincipalAmount; + } + + public String getLoanStatus() { + return loanStatus; + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GlimRepaymentTemplate.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GlimRepaymentTemplate.java new file mode 100644 index 00000000000..7176a13c729 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GlimRepaymentTemplate.java @@ -0,0 +1,105 @@ +/** + * 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.data; + +import java.math.BigDecimal; + +public class GlimRepaymentTemplate +{ + + private final BigDecimal glimId; + + private final BigDecimal groupId; + + private final BigDecimal clientId; + + private final String clientName; + + private final BigDecimal childLoanId; + + private final String parentAccountNo; + + private final BigDecimal parentPrincipalAmount; + + private final String childLoanAccountNo; + + private final BigDecimal childPrincipalAmount ; + + private GlimRepaymentTemplate(final BigDecimal glimId,final BigDecimal groupId,final BigDecimal clientId, + final String clientName,final BigDecimal childLoanId,final String parentAccountNo,final BigDecimal parentPrincipalAmount, + final String childLoanAccountNo,final BigDecimal childPrincipalAmount) + { + this.glimId=glimId; + this.groupId=groupId; + this.clientId=clientId; + this.clientName=clientName; + this.childLoanId=childLoanId; + this.parentAccountNo=parentAccountNo; + this.parentPrincipalAmount=parentPrincipalAmount; + this.childLoanAccountNo=childLoanAccountNo; + this.childPrincipalAmount=childPrincipalAmount; + } + + public static GlimRepaymentTemplate getInstance(final BigDecimal glimId,final BigDecimal groupId,final BigDecimal clientId, + final String clientName,final BigDecimal childLoanId,final String parentAccountNo,final BigDecimal parentPrincipalAmount, + final String childLoanAccountNo,final BigDecimal childPrincipalAmount) + { + return new GlimRepaymentTemplate(glimId,groupId,clientId,clientName,childLoanId,parentAccountNo, + parentPrincipalAmount,childLoanAccountNo,childPrincipalAmount); + } + + public BigDecimal getGlimId() { + return glimId; + } + + public BigDecimal getGroupId() { + return groupId; + } + + public BigDecimal getClientId() { + return clientId; + } + + public String getClientName() { + return clientName; + } + + public BigDecimal getChildLoanId() { + return childLoanId; + } + + public String getParentAccountNo() { + return parentAccountNo; + } + + public BigDecimal getParentPrincipalAmount() { + return parentPrincipalAmount; + } + + public String getChildLoanAccountNo() { + return childLoanAccountNo; + } + + public BigDecimal getChildPrincipalAmount() { + return childPrincipalAmount; + } + +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GroupLoanIndividualMonitoringAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GroupLoanIndividualMonitoringAccountData.java new file mode 100644 index 00000000000..319cbbb211b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/GroupLoanIndividualMonitoringAccountData.java @@ -0,0 +1,103 @@ +/** + * 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.data; + +import java.math.BigDecimal; + +public class GroupLoanIndividualMonitoringAccountData +{ + private final BigDecimal glimId; + + private final BigDecimal groupId; + + private final String accountNumber; + + private final String childAccountNumber; + + private final BigDecimal childPrincipalAmount; + + private final BigDecimal parentPrincipalAmount; + + private final Long childAccountsCount; + + private final String loanStatus; + + private GroupLoanIndividualMonitoringAccountData(final BigDecimal glimId,final BigDecimal groupId,final String accountNumber, final String childAccountNumber, + final BigDecimal childPrincipalAmount, final BigDecimal parentPrincipalAmount, + final Long childAccountsCount,final String loanStatus) { + this.glimId=glimId; + this.groupId=groupId; + this.accountNumber = accountNumber; + this.childAccountNumber = childAccountNumber; + this.childPrincipalAmount = childPrincipalAmount; + this.parentPrincipalAmount = parentPrincipalAmount; + this.childAccountsCount = childAccountsCount; + this.loanStatus=loanStatus; + } + + public static GroupLoanIndividualMonitoringAccountData getInstance(final BigDecimal glimId, final BigDecimal groupId,final String accountNumber, final String childAccountNumber, + final BigDecimal childPrincipalAmount, final BigDecimal parentPrincipalAmount, + final Long childAccountsCount,final String loanStatus) + { + return new GroupLoanIndividualMonitoringAccountData(glimId,groupId,accountNumber,childAccountNumber, + childPrincipalAmount,parentPrincipalAmount,childAccountsCount,loanStatus); + } + + public static GroupLoanIndividualMonitoringAccountData getInstance1(final BigDecimal glimId,final BigDecimal groupId,final String accountNumber, + final BigDecimal parentPrincipalAmount,final String loanStatus) + { + return new GroupLoanIndividualMonitoringAccountData(glimId,groupId,accountNumber,null,null,parentPrincipalAmount,null,loanStatus); + } + + + + public BigDecimal getGlimId() { + return glimId; + } + + public BigDecimal getGroupId() { + return groupId; + } + + + public String getAccountNumber() { + return accountNumber; + } + + public String getChildAccountNumber() { + return childAccountNumber; + } + + public BigDecimal getChildPrincipalAmount() { + return childPrincipalAmount; + } + + public BigDecimal getParentPrincipalAmount() { + return parentPrincipalAmount; + } + + public Long getChildAccountsCount() { + return childAccountsCount; + } + + public String getLoanStatus() { + return loanStatus; + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GLIMAccountInfoRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GLIMAccountInfoRepository.java new file mode 100644 index 00000000000..ab6ba39b5f9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GLIMAccountInfoRepository.java @@ -0,0 +1,34 @@ +/** + * 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.domain; + +import java.math.BigDecimal; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface GLIMAccountInfoRepository extends JpaRepository, + JpaSpecificationExecutor { + + GroupLoanIndividualMonitoringAccount findOneByIsAcceptingChild(boolean acceptingChild); + + GroupLoanIndividualMonitoringAccount findOneByIsAcceptingChildAndApplicationId(boolean acceptingChild, + BigDecimal applicationId); + + GroupLoanIndividualMonitoringAccount findOneByAccountNumber(String accountNumber); +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GroupLoanIndividualMonitoringAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GroupLoanIndividualMonitoringAccount.java new file mode 100644 index 00000000000..22ec95a913a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/GroupLoanIndividualMonitoringAccount.java @@ -0,0 +1,146 @@ +/** + * 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.domain; + +import java.math.BigDecimal; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.group.domain.Group; + +@Entity +@Table(name = "glim_accounts", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_number" }, name = "FK_glim_id")}) +public class GroupLoanIndividualMonitoringAccount extends AbstractPersistableCustom { + + @ManyToOne + @JoinColumn(name = "group_id", nullable = false) + private Group group; + + @Column(name = "account_number", nullable = false) + private String accountNumber; + + @Column(name = "principal_amount") + private BigDecimal principalAmount; + + + @Column(name = "child_accounts_count") + private Long childAccountsCount; + + @Column(name = "accepting_child") + private Boolean isAcceptingChild; + + @OneToMany + private Set childLoan; + + @Column(name = "loan_status_id", nullable = false) + private Integer loanStatus; + + @Column(name = "application_id", nullable = true) + private BigDecimal applicationId; + + private GroupLoanIndividualMonitoringAccount(String accountNumber,Group group,BigDecimal principalAmount,Long childAccountsCount, + Boolean isAcceptingChild,Integer loanStatus,BigDecimal applicationId) + { + this.accountNumber=accountNumber; + this.group=group; + this.principalAmount=principalAmount; + this.childAccountsCount=childAccountsCount; + this.isAcceptingChild=isAcceptingChild; + this.loanStatus=loanStatus; + this.applicationId=applicationId; + } + + public static GroupLoanIndividualMonitoringAccount getInstance(String accountNumber,Group group,BigDecimal principalAmount,Long childAccountsCount, + Boolean isAcceptingChild,Integer loanStatus,BigDecimal applicationId) + { + return new GroupLoanIndividualMonitoringAccount(accountNumber,group,principalAmount,childAccountsCount, + isAcceptingChild,loanStatus,applicationId); + } + + public String getAccountNumber() { + return accountNumber; + } + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public Set getChildLoan() { + return childLoan; + } + + public void setChildLoan(Set childLoan) { + this.childLoan = childLoan; + } + + public BigDecimal getPrincipalAmount() { + return principalAmount; + } + + public void setPrincipalAmount(BigDecimal principalAmount) { + this.principalAmount = principalAmount; + } + + public Long getChildAccountsCount() { + return childAccountsCount; + } + + public void setChildAccountsCount(Long childAccountsCount) { + this.childAccountsCount = childAccountsCount; + } + + public Boolean getIsAcceptingChild() { + return isAcceptingChild; + } + + public void setIsAcceptingChild(Boolean isAcceptingChild) { + this.isAcceptingChild = isAcceptingChild; + } + + public Integer getLoanStatus() { + return loanStatus; + } + + public void setLoanStatus(Integer loanStatus) { + this.loanStatus = loanStatus; + } + + public BigDecimal getApplicationId() { + return applicationId; + } + + public void setApplicationId(BigDecimal applicationId) { + this.applicationId = applicationId; + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index eff1c247851..3f45b80eaff 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -167,6 +167,10 @@ public class Loan extends AbstractPersistableCustom { @JoinColumn(name = "group_id", nullable = true) private Group group; + @ManyToOne + @JoinColumn(name = "glim_id", nullable = true) + private GroupLoanIndividualMonitoringAccount glim; + @Column(name = "loan_type_enum", nullable = false) private Integer loanType; @@ -627,6 +631,7 @@ public ChangedTransactionDetail reprocessTransactions() { changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), charges()); for (final Map.Entry mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { + mapEntry.getValue().updateLoan(this); } this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values()); @@ -675,6 +680,7 @@ public LoanTransaction handleChargeAppliedTransaction(final LoanCharge loanCharg final LoanTransaction applyLoanChargeTransaction = LoanTransaction.accrueLoanCharge(this, getOffice(), chargeAmount, transactionDate, feeCharges, penaltyCharges, DateUtils.getLocalDateTimeOfTenant(), currentUser); + Integer installmentNumber = null; final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(applyLoanChargeTransaction, loanCharge, loanCharge.getAmount( getCurrency()).getAmount(), installmentNumber); @@ -701,6 +707,7 @@ private void handleChargePaidTransaction(final LoanCharge charge, final LoanTran List installments = getRepaymentScheduleInstallments() ; for (final LoanRepaymentScheduleInstallment installment : installments) { if (installmentNumber == null && charge.isDueForCollectionFromAndUpToAndIncluding(startDate, installment.getDueDate())) { + chargePaymentInstallments.add(installment); break; } else if (installmentNumber != null && installment.getInstallmentNumber().equals(installmentNumber)) { @@ -712,6 +719,7 @@ private void handleChargePaidTransaction(final LoanCharge charge, final LoanTran final Set loanCharges = new HashSet<>(1); loanCharges.add(charge); loanRepaymentScheduleTransactionProcessor.handleTransaction(chargesPayment, getCurrency(), chargePaymentInstallments, loanCharges); + updateLoanSummaryDerivedFields(); doPostLoanTransactionChecks(chargesPayment.getTransactionDate(), loanLifecycleStateMachine); } @@ -720,6 +728,7 @@ private void validateLoanIsNotClosed(final LoanCharge loanCharge) { if (isClosed()) { final String defaultUserMessage = "This charge cannot be added as the loan is already closed."; throw new LoanChargeCannotBeAddedException("loanCharge", "loan.is.closed", defaultUserMessage, getId(), loanCharge.name()); + } } @@ -727,6 +736,7 @@ private void validateLoanChargeIsNotWaived(final LoanCharge loanCharge) { if (loanCharge.isWaived()) { final String defaultUserMessage = "This loan charge cannot be removed as the charge as already been waived."; throw new LoanChargeCannotBeAddedException("loanCharge", "loanCharge.is.waived", defaultUserMessage, getId(), loanCharge.name()); + } } @@ -805,6 +815,7 @@ private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursemen final Money penaltychargesPortion = Money.zero(currency); transaction.updateComponentsAndTotal(principalPortion, interestPortion, chargeAmount, penaltychargesPortion); + } else { transactionToRemove = transaction; } @@ -1072,6 +1083,14 @@ public Client client() { return this.client; } + public GroupLoanIndividualMonitoringAccount getGlim() { + return glim; + } + + public void setGlim(GroupLoanIndividualMonitoringAccount glim) { + this.glim = glim; + } + public LoanProduct loanProduct() { return this.loanProduct; } @@ -4203,6 +4222,14 @@ public Long getGroupId() { return groupId; } + public Long getGlimId() { + Long glimId = null; + if (this.glim != null) { + glimId = this.glim.getId(); + } + return glimId; + } + public Long getOfficeId() { Long officeId = null; if (this.client != null) { @@ -6558,4 +6585,13 @@ public void setRates(List rates) { public List getRates() { return rates; } + + public Integer getLoanType() { + return loanType; + } + + public void setLoanType(Integer loanType) { + this.loanType = loanType; + } + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java index 43c8d67eb1b..681d5eaf459 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java @@ -120,6 +120,9 @@ List findByClientIdAndGroupIdAndLoanStatus(@Param("clientId") Long clientI @Query("select loan from Loan loan where loan.group.id = :groupId and loan.client.id is null") List findByGroupId(@Param("groupId") Long groupId); + @Query("select loan from Loan loan where loan.glim.id = :glimId") + List findByGlimId(@Param("glimId") Long glimId); + @Query("select loan from Loan loan where loan.id IN :ids and loan.loanStatus IN :loanStatuses and loan.loanType IN :loanTypes") List findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection ids, @Param("loanStatuses") Collection loanStatuses, @Param("loanTypes") Collection loanTypes); @@ -153,4 +156,5 @@ List findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection findActiveLoansByLoanIdAndGroupId(Long clientId, Long groupId) { final Collection loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(), diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java index 3f449239031..35f6c2d6f83 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformService.java @@ -45,4 +45,5 @@ public interface GuarantorReadPlatformService { List retrieveObligeeDetails(Long clientId); + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java index 8ca63aec42d..00762b00719 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/guarantor/service/GuarantorReadPlatformServiceImpl.java @@ -88,6 +88,7 @@ public List retrieveGuarantorsForLoan(final Long loanId) { return mergedGuarantorDatas; } + @Override public GuarantorData retrieveGuarantor(final Long loanId, final Long guarantorId) { final GuarantorMapper rm = new GuarantorMapper(); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMApplicationRejectionCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMApplicationRejectionCommandHandler.java new file mode 100644 index 00000000000..cf3e6bf58d8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMApplicationRejectionCommandHandler.java @@ -0,0 +1,49 @@ +/** + * 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.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.loanaccount.service.LoanApplicationWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GLIMLOAN", action = "REJECT") +public class GLIMApplicationRejectionCommandHandler implements NewCommandSourceHandler +{ + + private final LoanApplicationWritePlatformService writePlatformService; + + @Autowired + public GLIMApplicationRejectionCommandHandler(final LoanApplicationWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.rejectGLIMApplicationApproval(command.entityId(), command); + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMBulkRepaymentCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMBulkRepaymentCommandHandler.java new file mode 100644 index 00000000000..c03e7b0d828 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMBulkRepaymentCommandHandler.java @@ -0,0 +1,49 @@ +/** + * 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.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GLIMLOAN", action = "REPAYMENT") +public class GLIMBulkRepaymentCommandHandler implements NewCommandSourceHandler { + + private final LoanWritePlatformService writePlatformService; + + @Autowired + public GLIMBulkRepaymentCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.makeGLIMLoanRepayment(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMLoanApplicationApprovalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMLoanApplicationApprovalCommandHandler.java new file mode 100644 index 00000000000..6f876eb1ebe --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GLIMLoanApplicationApprovalCommandHandler.java @@ -0,0 +1,49 @@ +/** + * 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.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.loanaccount.service.LoanApplicationWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GLIMLOAN", action = "APPROVE") +public class GLIMLoanApplicationApprovalCommandHandler implements NewCommandSourceHandler { + + private final LoanApplicationWritePlatformService writePlatformService; + + @Autowired + public GLIMLoanApplicationApprovalCommandHandler(final LoanApplicationWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.approveGLIMLoanAppication(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GlimLoanApplicationDisburseCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GlimLoanApplicationDisburseCommandHandler.java new file mode 100644 index 00000000000..a77f10fd175 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/GlimLoanApplicationDisburseCommandHandler.java @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.apache.fineract.portfolio.loanaccount.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +@CommandType(entity = "GLIMLOAN", action = "DISBURSE") +public class GlimLoanApplicationDisburseCommandHandler implements NewCommandSourceHandler +{ + + private final LoanWritePlatformService writePlatformService; + + @Autowired + public GlimLoanApplicationDisburseCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.disburseGLIMLoan(command.entityId(), command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanApplicationApproval.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanApplicationApproval.java new file mode 100644 index 00000000000..672ad727e55 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanApplicationApproval.java @@ -0,0 +1,49 @@ +/** + * 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.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.loanaccount.service.LoanApplicationWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GLIMLOAN", action = "UNDOAPPROVAL") +public class UndoGLIMLoanApplicationApproval implements NewCommandSourceHandler +{ + + private final LoanApplicationWritePlatformService writePlatformService; + + @Autowired + public UndoGLIMLoanApplicationApproval(final LoanApplicationWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.undoGLIMLoanApplicationApproval(command.entityId(), command); + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanDisbursalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanDisbursalCommandHandler.java new file mode 100644 index 00000000000..050bb88bf35 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/handler/UndoGLIMLoanDisbursalCommandHandler.java @@ -0,0 +1,49 @@ +/** + * 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.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GLIMLOAN", action = "UNDODISBURSAL") +public class UndoGLIMLoanDisbursalCommandHandler implements NewCommandSourceHandler +{ + +private final LoanWritePlatformService writePlatformService; + + @Autowired + public UndoGLIMLoanDisbursalCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.undoGLIMLoanDisbursal(command.entityId(), command); + } + +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformService.java index 91a5a8470a0..331962f44d7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformService.java @@ -29,4 +29,5 @@ public interface LoanScheduleCalculationPlatformService { void updateFutureSchedule(LoanScheduleData loanScheduleData, Long loanId); LoanScheduleData generateLoanScheduleForVariableInstallmentRequest(Long loanId, String json); + } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java index 4feea413e73..47cc9832052 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java @@ -137,6 +137,7 @@ public LoanScheduleModel calculateLoanSchedule(final JsonQuery query, Boolean va return this.loanScheduleAssembler.assembleLoanScheduleFrom(query.parsedJson()); } + @Override public void updateFutureSchedule(LoanScheduleData loanScheduleData, final Long loanId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java index 24992bc1cc9..c2d1922c389 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java @@ -62,7 +62,7 @@ public final class LoanApplicationCommandFromApiJsonHelper { final Set supportedParameters = new HashSet<>(Arrays.asList(LoanApiConstants.dateFormatParameterName, LoanApiConstants.localeParameterName, LoanApiConstants.idParameterName, LoanApiConstants.clientIdParameterName, LoanApiConstants.groupIdParameterName, LoanApiConstants.loanTypeParameterName, LoanApiConstants.productIdParameterName, - LoanApiConstants.principalParamName, LoanApiConstants.loanTermFrequencyParameterName, + LoanApiConstants.principalParamName,LoanApiConstants.totalLoanParamName,LoanApiConstants.parentAccountParamName, LoanApiConstants.loanTermFrequencyParameterName, LoanApiConstants.loanTermFrequencyTypeParameterName, LoanApiConstants.numberOfRepaymentsParameterName, LoanApiConstants.repaymentEveryParameterName, LoanApiConstants.repaymentFrequencyTypeParameterName, LoanApiConstants.repaymentFrequencyNthDayTypeParameterName, LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName, @@ -91,7 +91,9 @@ public final class LoanApplicationCommandFromApiJsonHelper { LoanApiConstants.linkAccountIdParameterName, LoanApiConstants.disbursementDataParameterName, LoanApiConstants.emiAmountParameterName, LoanApiConstants.maxOutstandingBalanceParameterName, LoanProductConstants.graceOnArrearsAgeingParameterName, LoanApiConstants.createStandingInstructionAtDisbursementParameterName, - LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, LoanApiConstants.datatables, LoanApiConstants.isEqualAmortizationParam, LoanProductConstants.ratesParamName)); + LoanApiConstants.isTopup, LoanApiConstants.loanIdToClose, LoanApiConstants.datatables, LoanApiConstants.isEqualAmortizationParam,LoanProductConstants.ratesParamName, + LoanApiConstants.applicationId, // glim specific + LoanApiConstants.lastApplication)); // glim specific private final FromJsonHelper fromApiJsonHelper; private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper; @@ -120,7 +122,7 @@ public void validateForCreate(final String json, final boolean isMeetingMandator if (!StringUtils.isBlank(loanTypeStr)) { final AccountType loanType = AccountType.fromName(loanTypeStr); - baseDataValidator.reset().parameter(loanTypeParameterName).value(loanType.getValue()).inMinMaxRange(1, 3); + baseDataValidator.reset().parameter(loanTypeParameterName).value(loanType.getValue()).inMinMaxRange(1, 4); final Long clientId = this.fromApiJsonHelper.extractLongNamed("clientId", element); final Long groupId = this.fromApiJsonHelper.extractLongNamed("groupId", element); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionApiJsonValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionApiJsonValidator.java index 505a6a3c92c..9a829f462a1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionApiJsonValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionApiJsonValidator.java @@ -58,7 +58,7 @@ public void validateApproval(final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } - final Set disbursementParameters = new HashSet<>(Arrays.asList(LoanApiConstants.approvedLoanAmountParameterName, + final Set disbursementParameters = new HashSet<>(Arrays.asList(LoanApiConstants.loanIdTobeApproved,LoanApiConstants.approvedLoanAmountParameterName, LoanApiConstants.approvedOnDateParameterName, LoanApiConstants.noteParameterName, LoanApiConstants.localeParameterName, LoanApiConstants.dateFormatParameterName,LoanApiConstants.disbursementDataParameterName,LoanApiConstants.disbursementDateParameterName)); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java index e1790ad081a..5f123677501 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanEventApiJsonValidator.java @@ -155,7 +155,7 @@ public void validateNewRepaymentTransaction(final String json) { final Set transactionParameters = new HashSet<>(Arrays.asList("transactionDate", "transactionAmount", "externalId", "note", "locale", "dateFormat", "paymentTypeId", "accountNumber", "checkNumber", "routingCode", "receiptNumber", - "bankNumber")); + "bankNumber","loanId")); final Type typeOfMap = new TypeToken>() {}.getType(); this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, transactionParameters); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformService.java new file mode 100644 index 00000000000..7974ceff56a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformService.java @@ -0,0 +1,44 @@ +/** + * 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.service; + +import java.util.Collection; +import org.apache.fineract.portfolio.loanaccount.data.GLIMContainer; +import org.apache.fineract.portfolio.loanaccount.data.GlimRepaymentTemplate; +import org.apache.fineract.portfolio.loanaccount.data.GroupLoanIndividualMonitoringAccountData; + +public interface GLIMAccountInfoReadPlatformService +{ + Collection findGlimAccountsByGroupId(String groupId); + + Collection findGlimAccountByGroupId(String groupId); + + Collection findGlimAccount(Long groupId); + + Collection findGlimAccountByGroupIdandAccountNo(String groupId, String accountNo); + + Collection findGlimAccountbyGroupAndAccount(Long groupId, String accountNo); + + Collection findGlimAccountByParentAccountId(String parentAccountIds); + + Collection findGlimAccountsByGLIMId(Long glimId); + + Collection findglimRepaymentTemplate(Long glimId); +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformServiceImpl.java new file mode 100644 index 00000000000..3f1c64667b8 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoReadPlatformServiceImpl.java @@ -0,0 +1,262 @@ +/** + * 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.service; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData; +import org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPlatformService; +import org.apache.fineract.portfolio.loanaccount.data.GLIMContainer; +import org.apache.fineract.portfolio.loanaccount.data.GlimRepaymentTemplate; +import org.apache.fineract.portfolio.loanaccount.data.GroupLoanIndividualMonitoringAccountData; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class GLIMAccountInfoReadPlatformServiceImpl implements GLIMAccountInfoReadPlatformService +{ + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + private final AccountDetailsReadPlatformService accountDetailsReadPlatforService; + + + @Autowired + public GLIMAccountInfoReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource, + final AccountDetailsReadPlatformService accountDetailsReadPlatforService) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.accountDetailsReadPlatforService=accountDetailsReadPlatforService; + + } + + private static final class GLIMFieldsMapper implements RowMapper { + public String schema() { + return "glim.id as glimId,ln.group_id as groupId,glim.account_number as accountNumber, ln.account_no as childAccountNumber,ln.principal_amount as childPrincipalAmount,glim.principal_amount as parentPrincipalAmount,glim.child_accounts_count as childAccountsCount," + +"glim.loan_status_id as loanStatus from glim_accounts glim,m_loan ln where glim.id=ln.glim_id"; + } + + @Override + public GroupLoanIndividualMonitoringAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final BigDecimal glimId=rs.getBigDecimal("glimId"); + + final BigDecimal groupId=rs.getBigDecimal("groupId"); + + final String accountNumber=rs.getString("accountNumber"); + + final String childAccountNumber=rs.getString("childAccountNumber"); + + final Long childAccountsCount=rs.getLong("childAccountsCount"); + + final BigDecimal parentPrincipalAmount=rs.getBigDecimal("parentPrincipalAmount"); + + final BigDecimal childPrincipalAmount=rs.getBigDecimal("childPrincipalAmount"); + + final String loanStatus=LoanStatus.fromInt((int)rs.getLong("loanStatus")).toString(); + + + return GroupLoanIndividualMonitoringAccountData.getInstance(glimId,groupId,accountNumber,childAccountNumber,childPrincipalAmount,parentPrincipalAmount, + childAccountsCount,loanStatus); + + } + } + + + @Override + public Collection findGlimAccountsByGLIMId(final Long glimId) { + this.context.authenticatedUser(); + + final GLIMFieldsMapper rm = new GLIMFieldsMapper(); + final String sql = "select " + rm.schema() + " and glim.id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { glimId }); + } + + @Override + public Collection findGlimAccountsByGroupId(String groupId) { + this.context.authenticatedUser(); + + final GLIMFieldsMapper rm = new GLIMFieldsMapper(); + final String sql = "select " + rm.schema() + " and ln.group_id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); + } + + + @Override + public Collection findGlimAccountByGroupId(String groupId) { + this.context.authenticatedUser(); + + GLIMMapper rm=new GLIMMapper(); + + final String sql="select "+rm.schema()+" where glim.group_id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); + } + + + @Override + public Collection findGlimAccountByParentAccountId(String parentAccountIds) { + this.context.authenticatedUser(); + + final GLIMFieldsMapper rm = new GLIMFieldsMapper(); + final String sql = "select " + rm.schema() + " and glim.accountNumber=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { parentAccountIds }); + } + + @Override + public Collection findGlimAccountByGroupIdandAccountNo(String groupId,String accountNo) { + this.context.authenticatedUser(); + + GLIMMapper rm=new GLIMMapper(); + + final String sql="select "+rm.schema()+" where glim.group_id=? and glim.account_number=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { groupId,accountNo }); + } + + @Override + public Collection findGlimAccount(Long groupId) { + this.context.authenticatedUser(); + Collection glimInfo=findGlimAccountByGroupId(groupId+""); + + //List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); + + List glimAccounts=new ArrayList(); + for(GroupLoanIndividualMonitoringAccountData glimAccount:glimInfo) + { + + List childLoans=accountDetailsReadPlatforService.retrieveLoanAccountDetailsByGroupIdAndGlimAccountNumber(groupId,glimAccount.getAccountNumber()); + glimAccounts.add(new GLIMContainer(glimAccount.getGlimId(),glimAccount.getGroupId(), glimAccount.getAccountNumber(), + childLoans, glimAccount.getParentPrincipalAmount(),glimAccount.getLoanStatus())); + } + + return glimAccounts; + } + + @Override + public Collection findGlimAccountbyGroupAndAccount(Long groupId,String accountNo) { + this.context.authenticatedUser(); + Collection glimInfo=findGlimAccountByGroupIdandAccountNo(groupId+"", accountNo+""); + + //List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); + + List glimAccounts=new ArrayList(); + for(GroupLoanIndividualMonitoringAccountData glimAccount:glimInfo) + { + + List childLoans=accountDetailsReadPlatforService.retrieveLoanAccountDetailsByGroupIdAndGlimAccountNumber(groupId,glimAccount.getAccountNumber()); + glimAccounts.add(new GLIMContainer(glimAccount.getGlimId(),glimAccount.getGroupId(), glimAccount.getAccountNumber(), + childLoans, glimAccount.getParentPrincipalAmount(),glimAccount.getLoanStatus())); + } + + return glimAccounts; + } + + @Override + public Collection findglimRepaymentTemplate(final Long glimId) + { + this.context.authenticatedUser(); + + GLIMRepaymentMapper rm=new GLIMRepaymentMapper(); + + final String sql="select "+rm.schema()+" where glim.id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] {glimId}); + + } + + + private static final class GLIMMapper implements RowMapper { + public String schema() { + return "glim.id as glimId,glim.group_id as groupId,glim.account_number as accountNumber,glim.principal_amount as principalAmount,glim.child_accounts_count as childAccountsCount,"+ + "glim.loan_status_id as loanStatus from glim_accounts glim"; + } + + @Override + public GroupLoanIndividualMonitoringAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final BigDecimal glimId=rs.getBigDecimal("glimId"); + + final BigDecimal groupId=rs.getBigDecimal("groupId"); + + final String accountNumber=rs.getString("accountNumber"); + + final BigDecimal principalAmount=rs.getBigDecimal("principalAmount"); + + final String loanStatus=LoanStatus.fromInt((int)rs.getLong("loanStatus")).toString(); + + return GroupLoanIndividualMonitoringAccountData.getInstance1(glimId,groupId, accountNumber, principalAmount,loanStatus); + + } + } + + + private static final class GLIMRepaymentMapper implements RowMapper { + public String schema() { + return "glim.id as glimId,loan.group_id as groupId,client.id as clientId,glim.account_number as parentLoanAccountNo,"+ + "glim.principal_amount as parentPrincipalAmount,loan.id as childLoanId,loan.account_no as childLoanAccountNo,loan.approved_principal as childPrincipalAmount,"+ + "client.display_name as clientName from glim_accounts glim left join m_loan loan on loan.glim_id=glim.id "+ + "left join m_client client on client.id=loan.client_id"; + } + + @Override + public GlimRepaymentTemplate mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final BigDecimal glimId=rs.getBigDecimal("glimId"); + + final BigDecimal groupId=rs.getBigDecimal("groupId"); + + final BigDecimal clientId=rs.getBigDecimal("clientId"); + + final String clientName=rs.getString("clientName"); + + final BigDecimal childLoanId=rs.getBigDecimal("childLoanId"); + + final String parentLoanAccountNo=rs.getString("parentLoanAccountNo"); + + final BigDecimal parentPrincipalAmount=rs.getBigDecimal("parentPrincipalAmount"); + + final String childLoanAccountNo=rs.getString("childLoanAccountNo"); + + final BigDecimal childPrincipalAmount=rs.getBigDecimal("childPrincipalAmount"); + + return GlimRepaymentTemplate.getInstance(glimId,groupId,clientId,clientName,childLoanId,parentLoanAccountNo, + parentPrincipalAmount,childLoanAccountNo,childPrincipalAmount); + + } + } + +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformService.java new file mode 100644 index 00000000000..4c3d1b4f05d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformService.java @@ -0,0 +1,36 @@ +/** + * 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.service; + +import java.math.BigDecimal; +import org.apache.fineract.portfolio.group.domain.Group; +import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; + +public interface GLIMAccountInfoWritePlatformService { + + void setIsAcceptingChild(GroupLoanIndividualMonitoringAccount glimAccount); + + void resetIsAcceptingChild(GroupLoanIndividualMonitoringAccount glimAccount); + + void incrementChildAccountCount(GroupLoanIndividualMonitoringAccount glimAccount); + + void addGLIMAccountInfo(String accountNumber, Group group, BigDecimal principalAmount, Long childAccountsCount, + Boolean isAcceptingChild, Integer loanStatus, BigDecimal applicationId); +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformServiceImpl.java new file mode 100644 index 00000000000..dbe32144fc2 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/GLIMAccountInfoWritePlatformServiceImpl.java @@ -0,0 +1,94 @@ +/** + * 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.service; + +import java.math.BigDecimal; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.group.domain.Group; +import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository; +import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GLIMAccountInfoWritePlatformServiceImpl implements GLIMAccountInfoWritePlatformService +{ + + private final PlatformSecurityContext context; + + private final GLIMAccountInfoRepository glimAccountRepository; + + private final LoanRepository loanRepository; + + @Autowired + public GLIMAccountInfoWritePlatformServiceImpl(final PlatformSecurityContext context,final GLIMAccountInfoRepository glimAccountRepository, + final LoanRepository loanRepository) + { + this.context=context; + this.glimAccountRepository=glimAccountRepository; + this.loanRepository=loanRepository; + } + + @Override + public void addGLIMAccountInfo(String accountNumber,Group group,BigDecimal principalAmount,Long childAccountsCount, + Boolean isAcceptingChild,Integer loanStatus,BigDecimal applicationId) + { + childAccountsCount=2L; + GroupLoanIndividualMonitoringAccount glimAccountInfo=GroupLoanIndividualMonitoringAccount.getInstance(accountNumber,group,principalAmount,childAccountsCount, + isAcceptingChild,loanStatus,applicationId); + + this.glimAccountRepository.save(glimAccountInfo ); + + + } + + + @Override + public void setIsAcceptingChild(GroupLoanIndividualMonitoringAccount glimAccount) + { + glimAccount.setIsAcceptingChild(true); + glimAccountRepository.save(glimAccount); + + } + + + @Override + public void resetIsAcceptingChild(GroupLoanIndividualMonitoringAccount glimAccount) + { + glimAccount.setIsAcceptingChild(false); + glimAccountRepository.save(glimAccount); + + } + + + @Override + public void incrementChildAccountCount(GroupLoanIndividualMonitoringAccount glimAccount) + { + long count=glimAccount.getChildAccountsCount(); + glimAccount.setChildAccountsCount(count+1); + glimAccountRepository.save(glimAccount); + + } + + + + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformService.java index 96ae8316ce6..dac5507f1e7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformService.java @@ -36,4 +36,10 @@ public interface LoanApplicationWritePlatformService { CommandProcessingResult rejectApplication(Long loanId, JsonCommand command); CommandProcessingResult applicantWithdrawsFromApplication(Long loanId, JsonCommand command); + + CommandProcessingResult approveGLIMLoanAppication(Long loanId, JsonCommand command); + + CommandProcessingResult undoGLIMLoanApplicationApproval(Long loanId, JsonCommand command); + + CommandProcessingResult rejectGLIMApplicationApproval(Long loanId, JsonCommand command); } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index 9995a39c7d4..a380eed5dc0 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -20,6 +20,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; @@ -87,11 +88,14 @@ import org.apache.fineract.portfolio.fund.domain.Fund; import org.apache.fineract.portfolio.group.domain.Group; import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper; +import org.apache.fineract.portfolio.group.exception.GroupMemberNotFoundInGSIMException; import org.apache.fineract.portfolio.group.exception.GroupNotActiveException; import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData; import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; +import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository; +import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails; @@ -99,6 +103,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper; @@ -115,6 +120,7 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationTransitionApiJsonValidator; import org.apache.fineract.portfolio.loanproduct.LoanProductConstants; import org.apache.fineract.portfolio.loanproduct.data.LoanProductData; +//import org.apache.fineract.portfolio.loanproduct.domain.*; import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail; import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository; @@ -127,8 +133,10 @@ import org.apache.fineract.portfolio.note.domain.Note; import org.apache.fineract.portfolio.note.domain.NoteRepository; import org.apache.fineract.portfolio.rate.service.RateAssembler; +import org.apache.fineract.portfolio.savings.data.GroupSavingsIndividualMonitoringAccountData; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler; +import org.apache.fineract.portfolio.savings.service.GSIMReadPlatformService; import org.apache.fineract.useradministration.domain.AppUser; import org.joda.time.LocalDate; import org.slf4j.Logger; @@ -139,6 +147,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; + @Service public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements LoanApplicationWritePlatformService { @@ -179,7 +188,12 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final FineractEntityToEntityMappingRepository repository; private final FineractEntityRelationRepository fineractEntityRelationRepository; private final LoanProductReadPlatformService loanProductReadPlatformService; + private final RateAssembler rateAssembler; + private final GLIMAccountInfoWritePlatformService glimAccountInfoWritePlatformService; + private final GLIMAccountInfoRepository glimRepository; + private final LoanRepository loanRepository; + private final GSIMReadPlatformService gsimReadPlatformService; @Autowired public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper, @@ -202,8 +216,12 @@ public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecuri final LoanScheduleAssembler loanScheduleAssembler, final LoanUtilService loanUtilService, final CalendarReadPlatformService calendarReadPlatformService, final GlobalConfigurationRepositoryWrapper globalConfigurationRepository, final FineractEntityToEntityMappingRepository repository, final FineractEntityRelationRepository fineractEntityRelationRepository, - final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, final LoanProductReadPlatformService loanProductReadPlatformService, - final RateAssembler rateAssembler) { + final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, + final GLIMAccountInfoWritePlatformService glimAccountInfoWritePlatformService, + final GLIMAccountInfoRepository glimRepository,final LoanRepository loanRepository, + final GSIMReadPlatformService gsimReadPlatformService, final RateAssembler rateAssembler, + final LoanProductReadPlatformService loanProductReadPlatformService + ) { this.context = context; this.fromJsonHelper = fromJsonHelper; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; @@ -240,6 +258,10 @@ public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecuri this.fineractEntityRelationRepository = fineractEntityRelationRepository; this.loanProductReadPlatformService = loanProductReadPlatformService; this.rateAssembler = rateAssembler; + this.glimAccountInfoWritePlatformService=glimAccountInfoWritePlatformService; + this.glimRepository=glimRepository; + this.loanRepository=loanRepository; + this.gsimReadPlatformService=gsimReadPlatformService; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -365,11 +387,106 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { createAndPersistCalendarInstanceForInterestRecalculation(newLoanApplication); } + + // loan account number generation + String accountNumber=""; + GroupLoanIndividualMonitoringAccount glimAccount; + BigDecimal applicationId=BigDecimal.ZERO; + Boolean isLastChildApplication=false; + + if (newLoanApplication.isAccountNumberRequiresAutoGeneration()) { - final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository - .findByAccountType(EntityAccountType.LOAN); - newLoanApplication.updateAccountNo(this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat)); - this.loanRepositoryWrapper.save(newLoanApplication); + + final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository.findByAccountType(EntityAccountType.LOAN); + // if application is of GLIM type + if(newLoanApplication.getLoanType()==4) + { + Group group= this.groupRepository.findOneWithNotFoundDetection(groupId); + + //GLIM specific parameters + if(command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("applicationId")!=null) + { + applicationId=command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("applicationId"); + } + + if(command.booleanObjectValueOfParameterNamed("lastApplication")!=null) + { + isLastChildApplication=command.booleanPrimitiveValueOfParameterNamed("lastApplication"); + } + + if(command.booleanObjectValueOfParameterNamed("isParentAccount")!=null) + { + + //empty table check + if(glimRepository.count()!=0) + { + //**************Parent-Not an empty table******************** + accountNumber=this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat); + newLoanApplication.updateAccountNo(accountNumber+"1"); + glimAccountInfoWritePlatformService.addGLIMAccountInfo(accountNumber,group, command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("totalLoan"),Long.valueOf(1),true, + LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),applicationId); + newLoanApplication.setGlim(glimRepository.findOneByAccountNumber(accountNumber)); + this.loanRepositoryWrapper.save(newLoanApplication); + + } + else + { + //************** Parent-empty table******************** + + accountNumber=this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat); + newLoanApplication.updateAccountNo(accountNumber+"1"); + glimAccountInfoWritePlatformService.addGLIMAccountInfo(accountNumber,group, command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("totalLoan"),Long.valueOf(1),true, + LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),applicationId); + newLoanApplication.setGlim(glimRepository.findOneByAccountNumber(accountNumber)); + this.loanRepositoryWrapper.save(newLoanApplication); + + } + + } + else + { + + + if(glimRepository.count()!=0) + { + // Child-Not an empty table + + glimAccount=glimRepository.findOneByIsAcceptingChildAndApplicationId(true,applicationId); + accountNumber=glimAccount.getAccountNumber()+(glimAccount.getChildAccountsCount()+1); + newLoanApplication.updateAccountNo(accountNumber); + this.glimAccountInfoWritePlatformService.incrementChildAccountCount(glimAccount); + newLoanApplication.setGlim(glimAccount); + this.loanRepositoryWrapper.save(newLoanApplication); + + } + else + { + //**************Child-empty table******************** + // if the glim info is empty set the current account as parent + accountNumber=this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat); + newLoanApplication.updateAccountNo(accountNumber+"1"); + glimAccountInfoWritePlatformService.addGLIMAccountInfo(accountNumber,group, command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("totalLoan"),Long.valueOf(1),true, + LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),applicationId); + newLoanApplication.setGlim(glimRepository.findOneByAccountNumber(accountNumber)); + this.loanRepositoryWrapper.save(newLoanApplication); + + } + + // reset in cases of last child application of glim + + if(isLastChildApplication) + { + this.glimAccountInfoWritePlatformService.resetIsAcceptingChild(glimRepository.findOneByIsAcceptingChildAndApplicationId(true,applicationId)); + } + + + } + } + else // for applications other than GLIM + { + newLoanApplication.updateAccountNo(this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat)); + this.loanRepositoryWrapper.save(newLoanApplication); + } } final String submittedOnNote = command.stringValueOfParameterNamed("submittedOnNote"); @@ -411,17 +528,53 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { } } - // Save linked account information + // Save linked account information + SavingsAccount savingsAccount; + AccountAssociations accountAssociations; final Long savingsAccountId = command.longValueOfParameterNamed("linkAccountId"); if (savingsAccountId != null) { - final SavingsAccount savingsAccount = this.savingsAccountAssembler.assembleFrom(savingsAccountId); - this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, newLoanApplication); - boolean isActive = true; - final AccountAssociations accountAssociations = AccountAssociations.associateSavingsAccount(newLoanApplication, - savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive); - this.accountAssociationsRepository.save(accountAssociations); + if(newLoanApplication.getLoanType()==4) + { + + List childSavings= (List)gsimReadPlatformService.findGSIMAccountsByGSIMId(savingsAccountId); + //List childSavings=gsimAccount.getChildGSIMAccounts(); + List gsimClientMembers=new ArrayList(); + Map clientAccountMappings=new HashMap<>(); + for(GroupSavingsIndividualMonitoringAccountData childSaving:childSavings) + { + gsimClientMembers.add(childSaving.getClientId()); + clientAccountMappings.put(childSaving.getClientId(), childSaving.getChildAccountId()); + + + } + + if(gsimClientMembers.contains(BigDecimal.valueOf(newLoanApplication.getClientId()))) + { + savingsAccount = this.savingsAccountAssembler.assembleFrom((clientAccountMappings.get(BigDecimal.valueOf(newLoanApplication.getClientId()))).longValue()); + + this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, newLoanApplication); + boolean isActive = true; + accountAssociations = AccountAssociations.associateSavingsAccount(newLoanApplication, + savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive); + this.accountAssociationsRepository.save(accountAssociations); + + }else + { + throw new GroupMemberNotFoundInGSIMException(newLoanApplication.getClientId()); + } } + else + { + + savingsAccount = this.savingsAccountAssembler.assembleFrom(savingsAccountId); + this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, newLoanApplication); + boolean isActive = true; + accountAssociations = AccountAssociations.associateSavingsAccount(newLoanApplication, + savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive); + this.accountAssociationsRepository.save(accountAssociations); + } + } if(command.parameterExists(LoanApiConstants.datatables)){ this.entityDatatableChecksWritePlatformService.saveDatatables(StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getName(), newLoanApplication.getId(), newLoanApplication.productId(), @@ -441,7 +594,8 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { .withOfficeId(newLoanApplication.getOfficeId()) // .withClientId(newLoanApplication.getClientId()) // .withGroupId(newLoanApplication.getGroupId()) // - .withLoanId(newLoanApplication.getId()) // + .withLoanId(newLoanApplication.getId()) + .withGlimId(newLoanApplication.getGlimId()) .build(); } catch (final DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); @@ -1131,6 +1285,60 @@ public void validateMultiDisbursementData(final JsonCommand command, LocalDate e if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } + + @Transactional + @Override + public CommandProcessingResult approveGLIMLoanAppication(final Long loanId, final JsonCommand command) + { + + final Long parentLoanId=loanId; + GroupLoanIndividualMonitoringAccount parentLoan=glimRepository.findById(parentLoanId).get(); + JsonArray approvalFormData=command.arrayOfParameterNamed("approvalFormData"); + + JsonObject jsonObject=null; + JsonCommand childCommand=null; + Long[] childLoanId=new Long[approvalFormData.size()]; + BigDecimal parentPrincipalAmount=command.bigDecimalValueOfParameterNamed("glimPrincipal"); + + for (int i = 0; i < approvalFormData.size(); i++) { + + jsonObject=approvalFormData.get(i).getAsJsonObject(); + + childLoanId[i]=jsonObject.get("loanId").getAsLong(); + } + + + CommandProcessingResult result=null; + int count=0,j=0; + for(JsonElement approvals:approvalFormData) + { + + childCommand=JsonCommand.fromExistingCommand(command,approvals); + + + result=approveApplication(childLoanId[j++],childCommand); + + if(result.getLoanId()!=null) + { + count++; + // if all the child loans are approved, mark the parent loan as approved + if(count==parentLoan.getChildAccountsCount()) + { + parentLoan.setPrincipalAmount(parentPrincipalAmount); + parentLoan.setLoanStatus(LoanStatus.APPROVED.getValue()); + glimRepository.save(parentLoan); + } + + + } + + + } + + return result; + } + + @Transactional @Override public CommandProcessingResult approveApplication(final Long loanId, final JsonCommand command) { @@ -1177,6 +1385,8 @@ public CommandProcessingResult approveApplication(final Long loanId, final JsonC final Map changes = loan.loanApplicationApproval(currentUser, command, disbursementDataArray, defaultLoanLifecycleStateMachine()); + + entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, EntityTables.LOAN.getName(), StatusEnum.APPROVE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId()); @@ -1239,6 +1449,42 @@ public CommandProcessingResult approveApplication(final Long loanId, final JsonC .build(); } + + @Transactional + @Override + public CommandProcessingResult undoGLIMLoanApplicationApproval(final Long loanId, final JsonCommand command) + { + + //GroupLoanIndividualMonitoringAccount glimAccount=glimRepository.findOne(loanId); + final Long parentLoanId=loanId; + GroupLoanIndividualMonitoringAccount parentLoan=glimRepository.findById(parentLoanId).get(); + List childLoans=this.loanRepository.findByGlimId(loanId); + + CommandProcessingResult result=null; + int count=0; + for(Loan loan:childLoans) + { + result=undoApplicationApproval(loan.getId(),command); + + if(result.getLoanId()!=null) + { + count++; + // if all the child loans are approved, mark the parent loan as approved + if(count==parentLoan.getChildAccountsCount()) + { + parentLoan.setLoanStatus(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue()); + glimRepository.save(parentLoan); + } + + + } + + + } + + return result; + } + @Transactional @Override public CommandProcessingResult undoApplicationApproval(final Long loanId, final JsonCommand command) { @@ -1285,6 +1531,41 @@ public CommandProcessingResult undoApplicationApproval(final Long loanId, final .build(); } + @Transactional + @Override + public CommandProcessingResult rejectGLIMApplicationApproval(final Long glimId, final JsonCommand command) + { + + //GroupLoanIndividualMonitoringAccount glimAccount=glimRepository.findOne(loanId); + final Long parentLoanId=glimId; + GroupLoanIndividualMonitoringAccount parentLoan=glimRepository.findById(parentLoanId).get(); + List childLoans=this.loanRepository.findByGlimId(glimId); + + CommandProcessingResult result=null; + int count=0; + for(Loan loan:childLoans) + { + result=rejectApplication(loan.getId(),command); + + if(result.getLoanId()!=null) + { + count++; + // if all the child loans are Rejected, mark the parent loan as rejected + if(count==parentLoan.getChildAccountsCount()) + { + parentLoan.setLoanStatus(LoanStatus.REJECTED.getValue()); + glimRepository.save(parentLoan); + } + + + } + + + } + + return result; + } + @Transactional @Override public CommandProcessingResult rejectApplication(final Long loanId, final JsonCommand command) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java index 6414975693f..38f3ba47e46 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java @@ -148,6 +148,7 @@ public Loan assembleFrom(final Long accountId) { return loanAccount; } + public void setHelpers(final Loan loanAccount) { loanAccount.setHelpers(defaultLoanLifecycleStateMachine(), this.loanSummaryWrapper, this.loanRepaymentScheduleTransactionProcessorFactory); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java index 058589a5a0e..99b2a554cd2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -133,7 +133,6 @@ LoanScheduleData retrieveRepaymentSchedule(Long loanId, RepaymentScheduleRelated LoanTransactionData retrieveLoanForeclosureTemplate(final Long loanId, final LocalDate transactionDate); - LoanAccountData retrieveLoanByLoanAccount(String loanAccountNumber); Long retrieveLoanIdByAccountNumber(String loanAccountNumber); @@ -142,4 +141,6 @@ LoanScheduleData retrieveRepaymentSchedule(Long loanId, RepaymentScheduleRelated Integer retrieveNumberOfActiveLoans(); + List retrieveGLIMChildLoansByGLIMParentAccount(String parentloanAccountNumber); + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index c1eadc7e87f..e516eee643c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -233,6 +233,23 @@ public LoanAccountData retrieveLoanByLoanAccount(String loanAccountNumber) } + @Override + public List retrieveGLIMChildLoansByGLIMParentAccount(String parentloanAccountNumber) + { + + + //final AppUser currentUser = this.context.authenticatedUser(); + this.context.authenticatedUser(); + final LoanMapper rm = new LoanMapper(); + + String sql="select "+rm.loanSchema()+" left join glim_parent_child_mapping as glim on glim.glim_child_account_id=l.account_no "+ + "where glim.glim_parent_account_id=?"; + + + return this.jdbcTemplate.query(sql, rm, new Object[] { parentloanAccountNumber }); + + } + @Override public LoanScheduleData retrieveRepaymentSchedule(final Long loanId, final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection disbursementData, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java index 0af995cfab6..b2001a0b267 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java @@ -108,4 +108,10 @@ void applyMeetingDateChanges(Calendar calendar, Collection loa CommandProcessingResult forecloseLoan(final Long loanId, JsonCommand command); + CommandProcessingResult disburseGLIMLoan(Long loanId, JsonCommand command); + + CommandProcessingResult undoGLIMLoanDisbursal(Long loanId, JsonCommand command); + + CommandProcessingResult makeGLIMLoanRepayment(Long loanId, JsonCommand command); + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 94cb93b2b55..f69fd6c5756 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -20,6 +20,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; @@ -127,6 +128,8 @@ import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO; import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail; import org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; +import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository; +import org.apache.fineract.portfolio.loanaccount.domain.GroupLoanIndividualMonitoringAccount; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; @@ -140,6 +143,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus; @@ -191,6 +195,7 @@ import org.springframework.transaction.annotation.Transactional; + @Service public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatformService { @@ -234,6 +239,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessingStrategy; private final CodeValueRepositoryWrapper codeValueRepository; private final CashierTransactionDataValidator cashierTransactionDataValidator; + private final GLIMAccountInfoRepository glimRepository; + private final LoanRepository loanRepository; @Autowired public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -264,7 +271,10 @@ public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext c final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessingStrategy, final CodeValueRepositoryWrapper codeValueRepository, final LoanRepositoryWrapper loanRepositoryWrapper, - final CashierTransactionDataValidator cashierTransactionDataValidator) { + final CashierTransactionDataValidator cashierTransactionDataValidator, + final GLIMAccountInfoRepository glimRepository, + final LoanRepository loanRepository + ) { this.context = context; this.loanEventApiJsonValidator = loanEventApiJsonValidator; this.loanAssembler = loanAssembler; @@ -303,6 +313,8 @@ public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext c this.entityDatatableChecksWritePlatformService = entityDatatableChecksWritePlatformService; this.codeValueRepository = codeValueRepository; this.cashierTransactionDataValidator = cashierTransactionDataValidator; + this.loanRepository=loanRepository; + this.glimRepository=glimRepository; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -310,6 +322,32 @@ private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses); } + @Transactional + @Override + public CommandProcessingResult disburseGLIMLoan(final Long loanId, final JsonCommand command) + { + final Long parentLoanId=loanId; + GroupLoanIndividualMonitoringAccount parentLoan=glimRepository.findById(parentLoanId).get(); + List childLoans=this.loanRepository.findByGlimId(loanId); + CommandProcessingResult result=null; + int count=0; + for(Loan loan:childLoans) + { + result=disburseLoan(loan.getId(),command,false); + if(result.getLoanId()!=null) + { + count++; + // if all the child loans are approved, mark the parent loan as approved + if(count==parentLoan.getChildAccountsCount()) + { + parentLoan.setLoanStatus(LoanStatus.ACTIVE.getValue()); + glimRepository.save(parentLoan); + } + } + } + return result; + } + @Transactional @Override public CommandProcessingResult disburseLoan(final Long loanId, final JsonCommand command, Boolean isAccountTransfer) { @@ -729,18 +767,44 @@ public Map bulkLoanDisbursal(final JsonCommand command, final Co return changes; } + + @Transactional + @Override + public CommandProcessingResult undoGLIMLoanDisbursal(final Long loanId, final JsonCommand command) + { + //GroupLoanIndividualMonitoringAccount glimAccount=glimRepository.findOne(loanId); + final Long parentLoanId=loanId; + GroupLoanIndividualMonitoringAccount parentLoan=glimRepository.findById(parentLoanId).get(); + List childLoans=this.loanRepository.findByGlimId(loanId); + CommandProcessingResult result=null; + int count=0; + for(Loan loan:childLoans) + { + result=undoLoanDisbursal(loan.getId(),command); + if(result.getLoanId()!=null) + { + count++; + // if all the child loans are approved, mark the parent loan as approved + if(count==parentLoan.getChildAccountsCount()) + { + parentLoan.setLoanStatus(LoanStatus.APPROVED.getValue()); + glimRepository.save(parentLoan); + } + } + } + return result; + } + @Transactional @Override public CommandProcessingResult undoLoanDisbursal(final Long loanId, final JsonCommand command) { final AppUser currentUser = getAppUserIfPresent(); - final Loan loan = this.loanAssembler.assembleFrom(loanId); checkClientOrGroupActive(loan); this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_UNDO_DISBURSAL, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); removeLoanCycle(loan); - final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); // @@ -784,6 +848,36 @@ public CommandProcessingResult undoLoanDisbursal(final Long loanId, final JsonCo .build(); } + + @Transactional + @Override + public CommandProcessingResult makeGLIMLoanRepayment(final Long loanId, final JsonCommand command) + { + + final Long parentLoanId=loanId; + + GroupLoanIndividualMonitoringAccount parentLoan=glimRepository.findById(parentLoanId).get(); + + JsonArray repayments= command.arrayOfParameterNamed("formDataArray"); + JsonCommand childCommand=null; + CommandProcessingResult result=null; + JsonObject jsonObject=null; + + Long[] childLoanId=new Long[repayments.size()]; + for (int i = 0; i < repayments.size(); i++) { + jsonObject=repayments.get(i).getAsJsonObject(); + LOG.info("{}",jsonObject.toString()); + childLoanId[i]=jsonObject.get("loanId").getAsLong(); + } + int j=0; + for(JsonElement element:repayments ) + { + childCommand=JsonCommand.fromExistingCommand(command,element); + result=makeLoanRepayment(childLoanId[j++],childCommand,false); + } + return result; + } + @Transactional @Override public CommandProcessingResult makeLoanRepayment(final Long loanId, final JsonCommand command, final boolean isRecoveryRepayment) { @@ -3020,4 +3114,4 @@ private void validateTransactionsForTransfer(final Loan loan, final LocalDate tr } } -} +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java index 69342487e0c..36afd94a756 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java @@ -18,7 +18,7 @@ */ package org.apache.fineract.portfolio.savings; -public class SavingsApiConstants { +public class SavingsApiConstants { public static final String SAVINGS_PRODUCT_RESOURCE_NAME = "savingsproduct"; public static final String SAVINGS_ACCOUNT_RESOURCE_NAME = "savingsaccount"; @@ -72,11 +72,20 @@ public class SavingsApiConstants { // savings product and account parameters public static final String idParamName = "id"; + public static final String isGSIM="isGSIM"; + public static final String isParentAccount="isParentAccount"; public static final String accountNoParamName = "accountNo"; public static final String externalIdParamName = "externalId"; public static final String statusParamName = "status"; public static final String subStatusParamName = "subStatus"; public static final String clientIdParamName = "clientId"; + public static final String isRetailAccountParamName = "isRetailAccount"; + public static final String autogenerateTransactionIdParamName="autogenerateTransactionId"; + public static final String transactionUpperLimitParamName="transactionUpperLimit"; + public static final String transactionLowerLimitParamName="transactionLowerLimit"; + public static final String retailEntriesParamName="retailEntries"; + public static final String childAccountIdParamName="childAccountId"; + public static final String groupIdParamName = "groupId"; public static final String productIdParamName = "productId"; public static final String fieldOfficerIdParamName = "fieldOfficerId"; @@ -178,5 +187,7 @@ public class SavingsApiConstants { public static final String datatables = "datatables"; + public static final String gsimApplicationId = "applicationId"; + public static final String gsimLastApplication = "lastApplication"; public static final String ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE = "not.in.active.state"; } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountTransactionsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountTransactionsApiResource.java index 2d1add36483..83cec1b8847 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountTransactionsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountTransactionsApiResource.java @@ -137,6 +137,11 @@ public String transaction(@PathParam("savingsId") final Long savingsId, @QueryPa if (is(commandParam, "deposit")) { final CommandWrapper commandRequest = builder.savingsAccountDeposit(savingsId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } + else if(is(commandParam, "gsimDeposit")) + { + final CommandWrapper commandRequest = builder.gsimSavingsAccountDeposit(savingsId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); } else if (is(commandParam, "withdrawal")) { final CommandWrapper commandRequest = builder.savingsAccountWithdrawal(savingsId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java index 28ccc7f91e1..8682c1d9475 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java @@ -170,6 +170,19 @@ public String submitApplication(@ApiParam(hidden = true) final String apiRequest return this.toApiJsonSerializer.serialize(result); } + @POST + @Path("/gsim") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String submitGSIMApplication(final String apiRequestBodyAsJson) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().createGSIMAccount().withJson(apiRequestBodyAsJson).build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } + @GET @Path("{accountId}") @Consumes({ MediaType.APPLICATION_JSON }) @@ -265,6 +278,83 @@ public String update(@PathParam("accountId") @ApiParam(value = "accountId") fina return this.toApiJsonSerializer.serialize(result); } + @PUT + @Path("/gsim/{parentAccountId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + /* public String updateGsim(@PathParam("parentAccountId") final Long parentAccountId, final String apiRequestBodyAsJson, + @QueryParam("command") final String commandParam) {*/ + public String updateGsim(@PathParam("parentAccountId") final Long parentAccountId, final String apiRequestBodyAsJson) + { + + /* if (is(commandParam, "updateWithHoldTax")) { + final CommandWrapper commandRequest = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson).updateWithHoldTax(accountId) + .build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); + }*/ + + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateGSIMAccount(parentAccountId).withJson(apiRequestBodyAsJson) + .build(); + + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + + return this.toApiJsonSerializer.serialize(result); + } + @POST + @Path("/gsimcommands/{parentAccountId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String handleGSIMCommands(@PathParam("parentAccountId") final Long parentAccountId, @QueryParam("command") final String commandParam, + final String apiRequestBodyAsJson) { + + String jsonApiRequest = apiRequestBodyAsJson; + if (StringUtils.isBlank(jsonApiRequest)) { + jsonApiRequest = "{}"; + } + + final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(jsonApiRequest); + + CommandProcessingResult result = null; + if (is(commandParam, "reject")) { + final CommandWrapper commandRequest = builder.rejectGSIMAccountApplication(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "withdrawnByApplicant")) { + final CommandWrapper commandRequest = builder.withdrawSavingsAccountApplication(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "approve")) { + final CommandWrapper commandRequest = builder.approveGSIMAccountApplication(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "undoapproval")) { + final CommandWrapper commandRequest = builder.undoGSIMApplicationApproval(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "activate")) { + final CommandWrapper commandRequest = builder.gsimAccountActivation(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "calculateInterest")) { + final CommandWrapper commandRequest = builder.withNoJsonBody().savingsAccountInterestCalculation(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "postInterest")) { + final CommandWrapper commandRequest = builder.savingsAccountInterestPosting(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "applyAnnualFees")) { + final CommandWrapper commandRequest = builder.savingsAccountApplyAnnualFees(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "close")) { + final CommandWrapper commandRequest = builder.closeGSIMApplication(parentAccountId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } + if (result == null) { + throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "reject", "withdrawnByApplicant", "approve", + "undoapproval", "activate", "calculateInterest", "postInterest", "close", "assignSavingsOfficer", + "unassignSavingsOfficer", SavingsApiConstants.COMMAND_BLOCK_DEBIT, SavingsApiConstants.COMMAND_UNBLOCK_DEBIT, + SavingsApiConstants.COMMAND_BLOCK_CREDIT, SavingsApiConstants.COMMAND_UNBLOCK_CREDIT, + SavingsApiConstants.COMMAND_BLOCK_ACCOUNT, SavingsApiConstants.COMMAND_UNBLOCK_ACCOUNT }); + } + + return this.toApiJsonSerializer.serialize(result); + } + @POST @Path("{accountId}") @Consumes({ MediaType.APPLICATION_JSON }) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GSIMContainer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GSIMContainer.java new file mode 100644 index 00000000000..95ef74595a1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GSIMContainer.java @@ -0,0 +1,75 @@ + +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.data; + +import java.math.BigDecimal; +import java.util.List; +import org.apache.fineract.portfolio.accountdetails.data.SavingsSummaryCustom; + +public class GSIMContainer { + + private final BigDecimal gsimId; + + private final BigDecimal groupId; + + private final String accountNumber; + + private final List childGSIMAccounts; + + private final BigDecimal parentBalance; + + private final String savingsStatus; + + public GSIMContainer(final BigDecimal gsimId, final BigDecimal groupId, final String accountNumber, + final List childGSIMAccounts, final BigDecimal parentBalance, + final String savingsStatus) { + this.gsimId = gsimId; + this.groupId = groupId; + this.accountNumber = accountNumber; + this.childGSIMAccounts = childGSIMAccounts; + this.parentBalance = parentBalance; + this.savingsStatus = savingsStatus; + + } + + public BigDecimal getGsimId() { + return gsimId; + } + + public BigDecimal getGroupId() { + return groupId; + } + + public String getAccountNumber() { + return accountNumber; + } + + public List getChildGSIMAccounts() { + return childGSIMAccounts; + } + + public BigDecimal getparentBalance() { + return parentBalance; + } + + public String getSavingsStatus() { + return savingsStatus; + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GroupSavingsIndividualMonitoringAccountData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GroupSavingsIndividualMonitoringAccountData.java new file mode 100644 index 00000000000..a6f54731e2d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/GroupSavingsIndividualMonitoringAccountData.java @@ -0,0 +1,125 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.data; + +import java.math.BigDecimal; + +public class GroupSavingsIndividualMonitoringAccountData +{ + + private final BigDecimal gsimId; + + private final BigDecimal groupId; + + private final BigDecimal clientId; + + private final String accountNumber; + + private final BigDecimal childAccountId; + + private final String childAccountNumber; + + private final BigDecimal childDeposit; + + private final BigDecimal parentDeposit; + + private final Long childAccountsCount; + + private final String savingsStatus; + + private GroupSavingsIndividualMonitoringAccountData(final BigDecimal glimId,final BigDecimal groupId,final BigDecimal clientId,final String accountNumber,final BigDecimal childAccountId, final String childAccountNumber, + final BigDecimal childDeposit, final BigDecimal parentDeposit, + final Long childAccountsCount,final String savingsStatus) { + this.gsimId=glimId; + this.groupId=groupId; + this.clientId=clientId; + this.accountNumber = accountNumber; + this.childAccountId=childAccountId; + this.childAccountNumber = childAccountNumber; + this.childDeposit = childDeposit; + this.parentDeposit = parentDeposit; + this.childAccountsCount = childAccountsCount; + this.savingsStatus=savingsStatus; + } + + public static GroupSavingsIndividualMonitoringAccountData getInstance(final BigDecimal glimId, final BigDecimal groupId,final String accountNumber, final String childAccountNumber, + final BigDecimal childDeposit, final BigDecimal parentDeposit, + final Long childAccountsCount,final String savingsStatus) + { + return new GroupSavingsIndividualMonitoringAccountData(glimId,groupId,null,accountNumber,null,childAccountNumber, + childDeposit,parentDeposit,childAccountsCount,savingsStatus); + } + + public static GroupSavingsIndividualMonitoringAccountData getInstance1(final BigDecimal glimId,final BigDecimal groupId,final String accountNumber, + final BigDecimal parentDeposit,final String savingsStatus) + { + return new GroupSavingsIndividualMonitoringAccountData(glimId,groupId,null,accountNumber,null,null,null,parentDeposit,null,savingsStatus); + } + + public static GroupSavingsIndividualMonitoringAccountData getInstance2(final BigDecimal glimId, final BigDecimal groupId,final BigDecimal clientId,final String accountNumber, final BigDecimal childAccountId,final String childAccountNumber, + final BigDecimal childDeposit, final BigDecimal parentDeposit, + final Long childAccountsCount,final String savingsStatus) + { + return new GroupSavingsIndividualMonitoringAccountData(glimId,groupId,clientId,accountNumber,childAccountId,childAccountNumber, + childDeposit,parentDeposit,childAccountsCount,savingsStatus); + } + + public BigDecimal getGsimId() { + return gsimId; + } + + public BigDecimal getGroupId() { + return groupId; + } + + public BigDecimal getClientId() { + return clientId; + } + + public String getAccountNumber() { + return accountNumber; + } + + + public BigDecimal getChildAccountId() { + return childAccountId; + } + + public String getChildAccountNumber() { + return childAccountNumber; + } + + public BigDecimal getChildDeposit() { + return childDeposit; + } + + public BigDecimal getParentDeposit() { + return parentDeposit; + } + + public Long getChildAccountsCount() { + return childAccountsCount; + } + + public String getSavingsStatus() { + return savingsStatus; + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java index a86950db0e2..c503c50d923 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountConstant.java @@ -31,7 +31,7 @@ public class SavingsAccountConstant extends SavingsApiConstants { * parameters to match those of request parameters. */ protected static final Set SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList( - localeParamName, dateFormatParamName, monthDayFormatParamName, staffIdParamName, accountNoParamName, + localeParamName, dateFormatParamName, monthDayFormatParamName, staffIdParamName, isGSIM, isParentAccount,accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName, fieldOfficerIdParamName, submittedOnDateParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName, @@ -41,7 +41,8 @@ public class SavingsAccountConstant extends SavingsApiConstants { withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName, overdraftLimitParamName, minRequiredBalanceParamName, enforceMinRequiredBalanceParamName, nominalAnnualInterestRateOverdraftParamName, - minOverdraftForInterestCalculationParamName, withHoldTaxParamName, datatables)); + minOverdraftForInterestCalculationParamName, withHoldTaxParamName, datatables, gsimApplicationId, + gsimLastApplication)); /** * These parameters will match the class level parameters of @@ -52,7 +53,8 @@ public class SavingsAccountConstant extends SavingsApiConstants { protected static final Set SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>( Arrays.asList(localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName, transactionAccountNumberParamName, checkNumberParamName, - routingCodeParamName, receiptNumberParamName, bankNumberParamName, noteParamName)); + routingCodeParamName, receiptNumberParamName, bankNumberParamName, retailEntriesParamName, + childAccountIdParamName, noteParamName)); protected static final Set SAVINGS_ACCOUNT_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>( Arrays.asList(idParamName, accountNoParamName)); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GSIMRepositoy.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GSIMRepositoy.java new file mode 100644 index 00000000000..35d7b049e0e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GSIMRepositoy.java @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.domain; + +import java.math.BigDecimal; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface GSIMRepositoy extends JpaRepository, JpaSpecificationExecutor +{ + + GroupSavingsIndividualMonitoring findOneByIsAcceptingChild(boolean acceptingChild); + GroupSavingsIndividualMonitoring findOneByIsAcceptingChildAndApplicationId(boolean acceptingChild,BigDecimal applicationId); + GroupSavingsIndividualMonitoring findOneByAccountNumber(String accountNumber); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GroupSavingsIndividualMonitoring.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GroupSavingsIndividualMonitoring.java new file mode 100644 index 00000000000..8a020940600 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/GroupSavingsIndividualMonitoring.java @@ -0,0 +1,140 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.domain; + +import java.math.BigDecimal; +import java.util.Set; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; +import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; +import org.apache.fineract.portfolio.group.domain.Group; + +@Entity +@Table(name = "gsim_accounts", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_number" }, name = "gsim_id")}) +public class GroupSavingsIndividualMonitoring extends AbstractPersistableCustom +{ + + @ManyToOne + @JoinColumn(name = "group_id", nullable = false) + private Group group; + + @Column(name = "account_number", nullable = false) + private String accountNumber; + + @Column(name = "parent_deposit") + private BigDecimal parentDeposit; + + + @Column(name = "child_accounts_count") + private Long childAccountsCount; + + @Column(name = "accepting_child") + private Boolean isAcceptingChild; + + @OneToMany + private Set childSaving; + + @Column(name = "savings_status_id", nullable = false) + private Integer savingsStatus; + + @Column(name = "application_id", nullable = true) + private BigDecimal applicationId; + + private GroupSavingsIndividualMonitoring(String accountNumber,Group group,BigDecimal parentDeposit,Long childAccountsCount, + Boolean isAcceptingChild,Integer savingsStatus,BigDecimal applicationId) + { + this.accountNumber=accountNumber; + this.group=group; + this.parentDeposit=parentDeposit; + this.childAccountsCount=childAccountsCount; + this.isAcceptingChild=isAcceptingChild; + this.savingsStatus=savingsStatus; + this.applicationId=applicationId; + + } + + public static GroupSavingsIndividualMonitoring getInstance(String accountNumber,Group group,BigDecimal parentDeposit,Long childAccountsCount, + Boolean isAcceptingChild,Integer savingsStatus,BigDecimal applicationId) + { + return new GroupSavingsIndividualMonitoring(accountNumber,group,parentDeposit,childAccountsCount, + isAcceptingChild,savingsStatus,applicationId); + } + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public BigDecimal getParentDeposit() { + return parentDeposit; + } + + public void setParentDeposit(BigDecimal parentDeposit) { + this.parentDeposit = parentDeposit; + } + + public Long getChildAccountsCount() { + return childAccountsCount; + } + + public void setChildAccountsCount(Long childAccountsCount) { + this.childAccountsCount = childAccountsCount; + } + + public Boolean getIsAcceptingChild() { + return isAcceptingChild; + } + + public void setIsAcceptingChild(Boolean isAcceptingChild) { + this.isAcceptingChild = isAcceptingChild; + } + + public Set getChildSaving() { + return childSaving; + } + + public void setChildSaving(Set childSaving) { + this.childSaving = childSaving; + } + + public Integer getSavingsStatus() { + return savingsStatus; + } + + public void setSavingsStatus(Integer savingsStatus) { + this.savingsStatus = savingsStatus; + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java index a0e69204f09..f489f61a027 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java @@ -140,10 +140,14 @@ public class SavingsAccount extends AbstractPersistableCustom { @JoinColumn(name = "client_id", nullable = true) protected Client client; - @ManyToOne(optional = true) + @ManyToOne(optional = true, fetch=FetchType.LAZY) @JoinColumn(name = "group_id", nullable = true) protected Group group; + @ManyToOne(fetch=FetchType.LAZY) + @JoinColumn(name = "gsim_id", nullable = true) + private GroupSavingsIndividualMonitoring gsim; + @ManyToOne @JoinColumn(name = "product_id", nullable = false) protected SavingsProduct product; @@ -1612,7 +1616,15 @@ public Long groupId() { return id; } - public Long hasSavingsOfficerId() { + public GroupSavingsIndividualMonitoring getGsim() { + return gsim; + } + + public void setGsim(GroupSavingsIndividualMonitoring gsim) { + this.gsim = gsim; + } + + public Long hasSavingsOfficerId() { Long id = null; if (this.savingsOfficer != null) { id = this.savingsOfficer.getId(); @@ -2691,10 +2703,6 @@ public LocalDate accountSubmittedOrActivationDate() { return getActivationLocalDate() == null ? getSubmittedOnLocalDate() : getActivationLocalDate(); } - public AccountType getAccountType() { - return AccountType.fromInt(accountType); - } - public DepositAccountType depositAccountType() { return DepositAccountType.fromInt(depositType); } @@ -3137,8 +3145,19 @@ public void releaseAmount(BigDecimal amount) { this.savingsOnHoldAmount = getSavingsHoldAmount().subtract(amount); } + public AccountType getAccountType() { + return AccountType.fromInt(accountType); + } + + public Integer getAccountTypes() { + return accountType; + } + + public void setAccountType(Integer accountType) { + this.accountType = accountType; + } + private boolean isOverdraft() { return allowOverdraft; } - } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java index f9f923dccf5..f1fe45bce26 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountAssembler.java @@ -71,12 +71,15 @@ import org.apache.fineract.portfolio.savings.exception.SavingsProductNotFoundException; import org.apache.fineract.useradministration.domain.AppUser; import org.joda.time.LocalDate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class SavingsAccountAssembler { + private final static Logger LOG = LoggerFactory.getLogger(SavingsAccountAssembler.class); private final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper; private final SavingsHelper savingsHelper; private final ClientRepositoryWrapper clientRepository; @@ -125,6 +128,8 @@ public SavingsAccount assembleFrom(final JsonCommand command, final AppUser subm Group group = null; Staff fieldOfficer = null; AccountType accountType = AccountType.INVALID; + + final Long clientId = this.fromApiJsonHelper.extractLongNamed(clientIdParamName, element); if (clientId != null) { client = this.clientRepository.findOneWithNotFoundDetection(clientId); @@ -147,6 +152,15 @@ public SavingsAccount assembleFrom(final JsonCommand command, final AppUser subm accountType = AccountType.JLG; } + if((Boolean)command.booleanPrimitiveValueOfParameterNamed("isGSIM")!=null) + { + LOG.info("setting system to gsim"); + if(command.booleanPrimitiveValueOfParameterNamed("isGSIM")) + { + accountType = AccountType.GSIM; + } + } + final Long fieldOfficerId = this.fromApiJsonHelper.extractLongNamed(fieldOfficerIdParamName, element); if (fieldOfficerId != null) { fieldOfficer = this.staffRepository.findOneWithNotFoundDetection(fieldOfficerId); @@ -298,6 +312,7 @@ public SavingsAccount assembleFrom(final Long savingsId) { return account; } + public void setHelpers(final SavingsAccount account) { account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java index a56c15a43ea..003f6c394f4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainService.java @@ -36,4 +36,5 @@ SavingsAccountTransaction handleDeposit(SavingsAccount account, DateTimeFormatte void postJournalEntries(SavingsAccount savingsAccount, Set existingTransactionIds, Set existingReversedTransactionIds); SavingsAccountTransaction handleDividendPayout(SavingsAccount account, LocalDate transactionDate, BigDecimal transactionAmount); + } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java index 05467448142..bcaa63d5aac 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java @@ -134,6 +134,7 @@ private AppUser getAppUserIfPresent() { return user; } + @Transactional @Override public SavingsAccountTransaction handleDeposit(final SavingsAccount account, final DateTimeFormatter fmt, @@ -176,7 +177,6 @@ private SavingsAccountTransaction handleDeposit(final SavingsAccount account, fi account.calculateInterestUsing(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate); } - saveTransactionToGenerateTransactionId(deposit); this.savingsAccountRepository.saveAndFlush(account); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java index 963da6abfdb..c8bbff03172 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java @@ -32,6 +32,9 @@ public interface SavingsAccountRepository extends JpaRepository findSavingAccountByClientId(@Param("clientId") Long clientId); + @Query("select s_acc from SavingsAccount s_acc where s_acc.gsim.id = :gsimId") + List findSavingAccountByGsimId(@Param("gsimId") Long gsimId); + @Query("select s_acc from SavingsAccount s_acc where s_acc.status = :status") List findSavingAccountByStatus(@Param("status") Integer status); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java index b1de206a2aa..f6f0e0622ff 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepositoryWrapper.java @@ -102,6 +102,10 @@ public List findByGroupId(@Param("groupId") Long groupId) { return this.repository.findByGroupId(groupId) ; } + public List findByGsimId(@Param("gsimId") Long gsimId) { + return this.repository.findSavingAccountByGsimId(gsimId); + } + //Root Entity is enough public SavingsAccount findNonClosedAccountByAccountNumber(@Param("accountNumber") String accountNumber) { return this.repository.findNonClosedAccountByAccountNumber(accountNumber) ; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java index c1532b6e131..0d4d4646ffa 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java @@ -117,6 +117,10 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom { @Column(name = "is_manual", length = 1, nullable = true) private boolean isManualTransaction; + @Column(name = "is_loan_disbursement", length = 1, nullable = true) + private boolean isLoanDisbursement; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch=FetchType.EAGER) @JoinColumn(name = "savings_transaction_id", referencedColumnName = "id", nullable = false) private List taxDetails = new ArrayList<>(); @@ -407,6 +411,10 @@ public boolean occursOn(final LocalDate occursOnDate) { return getTransactionLocalDate().isEqual(occursOnDate); } + public void setLoanDisbursement(boolean isLoanDisbursement) { + this.isLoanDisbursement = isLoanDisbursement; + } + public void zeroBalanceFields() { this.runningBalance = null; this.cumulativeBalance = null; diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CloseGSIMCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CloseGSIMCommandHandler.java new file mode 100644 index 00000000000..9b88cee4705 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CloseGSIMCommandHandler.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "CLOSE") +public class CloseGSIMCommandHandler implements NewCommandSourceHandler +{ + + + private final SavingsAccountWritePlatformService writePlatformService; + + @Autowired + public CloseGSIMCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) { + this.writePlatformService = savingAccountWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.bulkGSIMClose(command.getSavingsId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMAccountActivationCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMAccountActivationCommandHandler.java new file mode 100644 index 00000000000..8198019373c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMAccountActivationCommandHandler.java @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "ACTIVATE") +public class GSIMAccountActivationCommandHandler implements NewCommandSourceHandler { + private final SavingsAccountWritePlatformService savingAccountWritePlatformService; + + @Autowired + public GSIMAccountActivationCommandHandler( + final SavingsAccountWritePlatformService savingAccountWritePlatformService) { + this.savingAccountWritePlatformService = savingAccountWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.savingAccountWritePlatformService.gsimActivate(command.getSavingsId(),command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationApprovalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationApprovalCommandHandler.java new file mode 100644 index 00000000000..c4a9d60d26a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationApprovalCommandHandler.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "APPROVE") +public class GSIMApplicationApprovalCommandHandler implements NewCommandSourceHandler +{ + + private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService; + + @Autowired + public GSIMApplicationApprovalCommandHandler( + final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) { + this.savingAccountWritePlatformService = savingAccountWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.savingAccountWritePlatformService.approveGSIMApplication(command.getSavingsId(),command); + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationModificationCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationModificationCommandHandler.java new file mode 100644 index 00000000000..cac5ee820d1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationModificationCommandHandler.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "UPDATE") +public class GSIMApplicationModificationCommandHandler implements NewCommandSourceHandler +{ + + private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService; + + @Autowired + public GSIMApplicationModificationCommandHandler( + final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) { + this.savingAccountWritePlatformService = savingAccountWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.savingAccountWritePlatformService.modifyGSIMApplication(command.entityId(), command); + } + +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationRejectionHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationRejectionHandler.java new file mode 100644 index 00000000000..2f0c88fe92e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationRejectionHandler.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "REJECT") +public class GSIMApplicationRejectionHandler implements NewCommandSourceHandler +{ + + private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService; + + @Autowired + public GSIMApplicationRejectionHandler( + final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) { + this.savingAccountWritePlatformService = savingAccountWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.savingAccountWritePlatformService.rejectGSIMApplication(command.entityId(),command); + } + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationSubmittalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationSubmittalCommandHandler.java new file mode 100644 index 00000000000..476f196e80a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMApplicationSubmittalCommandHandler.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "CREATE") +public class GSIMApplicationSubmittalCommandHandler implements NewCommandSourceHandler +{ + + + private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService; + + @Autowired + public GSIMApplicationSubmittalCommandHandler( + final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) { + this.savingAccountWritePlatformService = savingAccountWritePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.savingAccountWritePlatformService.submitGSIMApplication(command); + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMDepositCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMDepositCommandHandler.java new file mode 100644 index 00000000000..3428715816a --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMDepositCommandHandler.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "DEPOSIT") +public class GSIMDepositCommandHandler implements NewCommandSourceHandler { + + private final SavingsAccountWritePlatformService writePlatformService; + + @Autowired + public GSIMDepositCommandHandler(final SavingsAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.gsimDeposit(command.getSavingsId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMUndoApprovalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMUndoApprovalCommandHandler.java new file mode 100644 index 00000000000..09e8e4c8a97 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/GSIMUndoApprovalCommandHandler.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + + +@Service +@CommandType(entity = "GSIMACCOUNT", action = "APPROVALUNDO") +public class GSIMUndoApprovalCommandHandler implements NewCommandSourceHandler +{ + + private final SavingsApplicationProcessWritePlatformService writePlatformService; + + @Autowired + public GSIMUndoApprovalCommandHandler(final SavingsApplicationProcessWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + + return this.writePlatformService.undoGSIMApplicationApproval(command.entityId(), command); + } + +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformService.java new file mode 100644 index 00000000000..201fdfcc352 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformService.java @@ -0,0 +1,48 @@ + +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.service; + +import java.util.Collection; +import java.util.List; +import org.apache.fineract.portfolio.savings.data.GSIMContainer; +import org.apache.fineract.portfolio.savings.data.GroupSavingsIndividualMonitoringAccountData; + +public interface GSIMReadPlatformService { + + Collection findGsimAccountByParentAccountNumber(String parentAccountIds); + + Collection findGSIMAccountsByGSIMId(Long glimId); + + Collection findGSIMAccountsByGroupId(String groupId); + + Collection findGSIMAccountContainerByGroupId(Long groupId); + + Collection findGsimAccountContainerbyGsimAccountNumber(String accountNumber); + + + Collection findGsimAccountByGroupIdandAccountNo(String groupId, + String accountNo); + + List findGsimAccountContainerbyGsimAccountId(Long parentAccountId); + + GroupSavingsIndividualMonitoringAccountData findGSIMAccountByGSIMId(Long gsimId); + +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformServiceImpl.java new file mode 100644 index 00000000000..7e7da33cacb --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GSIMReadPlatformServiceImpl.java @@ -0,0 +1,389 @@ + +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.service; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.fineract.infrastructure.core.data.EnumOptionData; +import org.apache.fineract.infrastructure.core.domain.JdbcSupport; +import org.apache.fineract.infrastructure.core.service.RoutingDataSource; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.infrastructure.security.utils.ColumnValidator; +import org.apache.fineract.organisation.monetary.data.CurrencyData; +import org.apache.fineract.portfolio.accountdetails.data.SavingsSummaryCustom; +import org.apache.fineract.portfolio.accountdetails.service.AccountEnumerations; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; +import org.apache.fineract.portfolio.savings.data.GSIMContainer; +import org.apache.fineract.portfolio.savings.data.GroupSavingsIndividualMonitoringAccountData; +import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData; +import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData; +import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData; +import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType; +import org.joda.time.LocalDate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class GSIMReadPlatformServiceImpl implements GSIMReadPlatformService +{ + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + private final ColumnValidator columnValidator; + + + + @Autowired + public GSIMReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource + ,final ColumnValidator columnValidator) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.columnValidator = columnValidator; + + } + + private static final class GSIMFieldsMapper implements RowMapper { + public String schema() { + return "gsim.id as gsimId,sv.group_id as groupId,sv.client_id as clientId,gsim.account_number as accountNumber, sv.id as childAccountId,sv.account_no as childAccountNumber,sv.account_balance_derived as childBalance,gsim.parent_deposit as parentBalance,gsim.child_accounts_count as childAccountsCount," + +"gsim.savings_status_id as savingsStatus from gsim_accounts gsim,m_savings_account sv where gsim.id=sv.gsim_id"; + } + + @Override + public GroupSavingsIndividualMonitoringAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final BigDecimal gsimId=rs.getBigDecimal("gsimId"); + final BigDecimal groupId=rs.getBigDecimal("groupId"); + final BigDecimal clientId=rs.getBigDecimal("clientId"); + final String accountNumber=rs.getString("accountNumber"); + final BigDecimal childAccountId=rs.getBigDecimal("childAccountId"); + final String childAccountNumber=rs.getString("childAccountNumber"); + final Long childAccountsCount=rs.getLong("childAccountsCount"); + final BigDecimal parentBalance=rs.getBigDecimal("parentBalance"); + final BigDecimal childBalance=rs.getBigDecimal("childBalance"); + final String savingsStatus=SavingsAccountStatusType.fromInt((int)rs.getLong("savingsStatus")).toString(); + return GroupSavingsIndividualMonitoringAccountData.getInstance2(gsimId,groupId,clientId,accountNumber,childAccountId,childAccountNumber,parentBalance,childBalance, + childAccountsCount,savingsStatus); + } + } + + private static final class GSIMMapper implements RowMapper { + public String schema() { + return "gsim.id as gsimId,gsim.group_id as groupId,gsim.account_number as accountNumber,gsim.parent_deposit as parentDeposit,gsim.child_accounts_count as childAccountsCount," + +"gsim.savings_status_id as savingsStatus from gsim_accounts gsim"; + } + + @Override + public GroupSavingsIndividualMonitoringAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + throws SQLException { + + final BigDecimal glimId=rs.getBigDecimal("gsimId"); + + final BigDecimal groupId=rs.getBigDecimal("groupId"); + + final String accountNumber=rs.getString("accountNumber"); + + final BigDecimal parentDeposit=rs.getBigDecimal("parentDeposit"); + + final String loanStatus=LoanStatus.fromInt((int)rs.getLong("savingsStatus")).toString(); + + return GroupSavingsIndividualMonitoringAccountData.getInstance1(glimId,groupId, accountNumber, parentDeposit,loanStatus); + + } + } + + @Override + public Collection findGSIMAccountContainerByGroupId(Long groupId) { + this.context.authenticatedUser(); + Collection gsimInfo=findGSIMAccountsByGroupId(groupId+""); + + //List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); + String savingswhereClauseForGroup; + + List gsimAccounts=new ArrayList(); + List childSavings; + for(GroupSavingsIndividualMonitoringAccountData gsimAccount:gsimInfo) + { + BigDecimal gsimId = gsimAccount.getGsimId(); + savingswhereClauseForGroup = " where sa.group_id = ? and sa.gsim_id = ? order by sa.status_enum ASC, sa.account_no ASC"; + + childSavings=retrieveAccountDetails(savingswhereClauseForGroup,new Object[] { groupId , gsimId}); + + gsimAccounts.add(new GSIMContainer(gsimAccount.getGsimId(),gsimAccount.getGroupId(), gsimAccount.getAccountNumber(), + childSavings, gsimAccount.getParentDeposit(),gsimAccount.getSavingsStatus())); + } + + return gsimAccounts; + } + + + @Override + public Collection findGsimAccountContainerbyGsimAccountNumber(String accountNumber) { + this.context.authenticatedUser(); + Collection gsimInfo=findGsimAccountByParentAccountNumber(accountNumber); + + //List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); + final String savingswhereClauseForGroup = " where gsim.account_number = ? order by sa.status_enum ASC, sa.account_no ASC"; + + List gsimAccounts=new ArrayList(); + for(GroupSavingsIndividualMonitoringAccountData gsimAccount:gsimInfo) + { + + List childSavings=retrieveAccountDetails(savingswhereClauseForGroup,new Object[] { accountNumber }); + + gsimAccounts.add(new GSIMContainer(gsimAccount.getGsimId(),gsimAccount.getGroupId(), gsimAccount.getAccountNumber(), + childSavings, gsimAccount.getParentDeposit(),gsimAccount.getSavingsStatus())); + } + + return gsimAccounts; + } + + + @Override + public List findGsimAccountContainerbyGsimAccountId(Long parentAccountId) { + this.context.authenticatedUser(); + GroupSavingsIndividualMonitoringAccountData gsimAccount=findGSIMAccountByGSIMId(parentAccountId); + + //List glimAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroupAndLoanType, new Object[] { groupId }); + final String savingswhereClauseForGroup = " where sa.gsim_id = ? order by sa.status_enum ASC, sa.account_no ASC"; + + List childSavings=retrieveAccountDetails(savingswhereClauseForGroup,new Object[] { parentAccountId }); + + List parentGsim=new ArrayList(); + + parentGsim.add(new GSIMContainer(gsimAccount.getGsimId(),gsimAccount.getGroupId(), gsimAccount.getAccountNumber(), + childSavings, gsimAccount.getParentDeposit(),gsimAccount.getSavingsStatus())); + + return parentGsim ; + + } + + + @Override + public Collection findGSIMAccountsByGSIMId(final Long gsimId) { + this.context.authenticatedUser(); + + final GSIMFieldsMapper rm = new GSIMFieldsMapper(); + final String sql = "select " + rm.schema() + " and gsim.id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { gsimId }); + } + + @Override + public GroupSavingsIndividualMonitoringAccountData findGSIMAccountByGSIMId(final Long gsimId) { + this.context.authenticatedUser(); + + final GSIMMapper rm = new GSIMMapper(); + final String sql = "select " + rm.schema() + " where gsim.id=?"; + + return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { gsimId }); + } + + + @Override + public Collection findGSIMAccountsByGroupId(String groupId) { + this.context.authenticatedUser(); + + final GSIMMapper rm = new GSIMMapper(); + final String sql = "select " + rm.schema() + " where gsim.group_id=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { groupId }); + } + + + @Override + public Collection findGsimAccountByParentAccountNumber(String parentAccountIds) { + this.context.authenticatedUser(); + + final GSIMMapper rm = new GSIMMapper(); + final String sql = "select " + rm.schema() + " where gsim.account_number=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { parentAccountIds }); + } + + + @Override + public Collection findGsimAccountByGroupIdandAccountNo(String groupId,String accountNo) { + this.context.authenticatedUser(); + + GSIMMapper rm=new GSIMMapper(); + + final String sql="select "+rm.schema()+" where gsim.group_id=? and gsim.account_number=?"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { accountNo }); + } + + + + private List retrieveAccountDetails(final String savingswhereClause, final Object[] inputs) { + final SavingsAccountSummaryDataMapper savingsAccountSummaryDataMapper = new SavingsAccountSummaryDataMapper(); + final String savingsSql = "select " + savingsAccountSummaryDataMapper.schema() + savingswhereClause; + this.columnValidator.validateSqlInjection(savingsAccountSummaryDataMapper.schema() , savingswhereClause); + return this.jdbcTemplate.query(savingsSql, savingsAccountSummaryDataMapper, inputs); + } + + + private static final class SavingsAccountSummaryDataMapper implements RowMapper { + + final String schemaSql; + + public SavingsAccountSummaryDataMapper() { + final StringBuilder accountsSummary = new StringBuilder(); + accountsSummary.append("sa.id as id, CONCAT('(',clnt.id,') ',clnt.display_name) as displayName,sa.account_no as accountNo, sa.external_id as externalId, sa.gsim_id as gsimId,gsim.account_number as parentAccountNo,sa.status_enum as statusEnum, "); + accountsSummary.append("sa.account_type_enum as accountType, "); + accountsSummary.append("sa.account_balance_derived as accountBalance, "); + + accountsSummary.append("sa.submittedon_date as submittedOnDate,"); + accountsSummary.append("sbu.username as submittedByUsername,"); + accountsSummary.append("sbu.firstname as submittedByFirstname, sbu.lastname as submittedByLastname,"); + + accountsSummary.append("sa.rejectedon_date as rejectedOnDate,"); + accountsSummary.append("rbu.username as rejectedByUsername,"); + accountsSummary.append("rbu.firstname as rejectedByFirstname, rbu.lastname as rejectedByLastname,"); + + accountsSummary.append("sa.withdrawnon_date as withdrawnOnDate,"); + accountsSummary.append("wbu.username as withdrawnByUsername,"); + accountsSummary.append("wbu.firstname as withdrawnByFirstname, wbu.lastname as withdrawnByLastname,"); + + accountsSummary.append("sa.approvedon_date as approvedOnDate,"); + accountsSummary.append("abu.username as approvedByUsername,"); + accountsSummary.append("abu.firstname as approvedByFirstname, abu.lastname as approvedByLastname,"); + + accountsSummary.append("sa.activatedon_date as activatedOnDate,"); + accountsSummary.append("avbu.username as activatedByUsername,"); + accountsSummary.append("avbu.firstname as activatedByFirstname, avbu.lastname as activatedByLastname,"); + + accountsSummary.append("sa.sub_status_enum as subStatusEnum, "); + accountsSummary.append("(select IFNULL(max(sat.transaction_date),sa.activatedon_date) "); + accountsSummary.append("from m_savings_account_transaction as sat "); + accountsSummary.append("where sat.is_reversed = 0 "); + accountsSummary.append("and sat.transaction_type_enum in (1,2) "); + accountsSummary.append("and sat.savings_account_id = sa.id) as lastActiveTransactionDate, "); + + accountsSummary.append("sa.closedon_date as closedOnDate,"); + accountsSummary.append("cbu.username as closedByUsername,"); + accountsSummary.append("cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname,"); + + accountsSummary + .append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, sa.currency_multiplesof as inMultiplesOf, "); + accountsSummary.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, "); + accountsSummary.append("curr.display_symbol as currencyDisplaySymbol, "); + accountsSummary.append("sa.product_id as productId, p.name as productName, p.short_name as shortProductName, "); + accountsSummary.append("sa.deposit_type_enum as depositType "); + accountsSummary.append("from m_savings_account sa "); + accountsSummary.append("join m_savings_product as p on p.id = sa.product_id "); + accountsSummary.append("join m_currency curr on curr.code = sa.currency_code "); + accountsSummary.append("left join m_appuser sbu on sbu.id = sa.submittedon_userid "); + accountsSummary.append("left join m_appuser rbu on rbu.id = sa.rejectedon_userid "); + accountsSummary.append("left join m_appuser wbu on wbu.id = sa.withdrawnon_userid "); + accountsSummary.append("left join m_appuser abu on abu.id = sa.approvedon_userid "); + accountsSummary.append("left join m_appuser avbu on rbu.id = sa.activatedon_userid "); + accountsSummary.append("left join m_appuser cbu on cbu.id = sa.closedon_userid "); + accountsSummary.append("left join gsim_accounts gsim on gsim.id=sa.gsim_id "); + accountsSummary.append("left join m_client clnt on clnt.id=sa.client_id "); + + + this.schemaSql = accountsSummary.toString(); + } + + public String schema() { + return this.schemaSql; + } + + @Override + public SavingsSummaryCustom mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { + + final Long id = JdbcSupport.getLong(rs, "id"); + final String accountNo = rs.getString("accountNo"); + final String displayName=rs.getString("displayName"); + final String externalId = rs.getString("externalId"); + final Long productId = JdbcSupport.getLong(rs, "productId"); + final String productName = rs.getString("productName"); + final String shortProductName = rs.getString("shortProductName"); + final Integer statusId = JdbcSupport.getInteger(rs, "statusEnum"); + final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "accountBalance"); + final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusId); + final Integer accountType = JdbcSupport.getInteger(rs, "accountType"); + final EnumOptionData accountTypeData = AccountEnumerations.loanType(accountType); + final Integer depositTypeId = JdbcSupport.getInteger(rs, "depositType"); + final EnumOptionData depositTypeData = SavingsEnumerations.depositType(depositTypeId); + + final String currencyCode = rs.getString("currencyCode"); + final String currencyName = rs.getString("currencyName"); + final String currencyNameCode = rs.getString("currencyNameCode"); + final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); + final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits"); + final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf"); + final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf, + currencyDisplaySymbol, currencyNameCode); + + final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate"); + final String submittedByUsername = rs.getString("submittedByUsername"); + final String submittedByFirstname = rs.getString("submittedByFirstname"); + final String submittedByLastname = rs.getString("submittedByLastname"); + + final LocalDate rejectedOnDate = JdbcSupport.getLocalDate(rs, "rejectedOnDate"); + final String rejectedByUsername = rs.getString("rejectedByUsername"); + final String rejectedByFirstname = rs.getString("rejectedByFirstname"); + final String rejectedByLastname = rs.getString("rejectedByLastname"); + + final LocalDate withdrawnOnDate = JdbcSupport.getLocalDate(rs, "withdrawnOnDate"); + final String withdrawnByUsername = rs.getString("withdrawnByUsername"); + final String withdrawnByFirstname = rs.getString("withdrawnByFirstname"); + final String withdrawnByLastname = rs.getString("withdrawnByLastname"); + + final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedOnDate"); + final String approvedByUsername = rs.getString("approvedByUsername"); + final String approvedByFirstname = rs.getString("approvedByFirstname"); + final String approvedByLastname = rs.getString("approvedByLastname"); + + final LocalDate activatedOnDate = JdbcSupport.getLocalDate(rs, "activatedOnDate"); + final String activatedByUsername = rs.getString("activatedByUsername"); + final String activatedByFirstname = rs.getString("activatedByFirstname"); + final String activatedByLastname = rs.getString("activatedByLastname"); + + final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate"); + final String closedByUsername = rs.getString("closedByUsername"); + final String closedByFirstname = rs.getString("closedByFirstname"); + final String closedByLastname = rs.getString("closedByLastname"); + final Integer subStatusEnum = JdbcSupport.getInteger(rs, "subStatusEnum"); + final SavingsAccountSubStatusEnumData subStatus = SavingsEnumerations.subStatus(subStatusEnum); + + final LocalDate lastActiveTransactionDate = JdbcSupport.getLocalDate(rs, "lastActiveTransactionDate"); + + final SavingsAccountApplicationTimelineData timeline = new SavingsAccountApplicationTimelineData(submittedOnDate, + submittedByUsername, submittedByFirstname, submittedByLastname, rejectedOnDate, rejectedByUsername, + rejectedByFirstname, rejectedByLastname, withdrawnOnDate, withdrawnByUsername, withdrawnByFirstname, + withdrawnByLastname, approvedOnDate, approvedByUsername, approvedByFirstname, approvedByLastname, activatedOnDate, + activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, closedByUsername, closedByFirstname, + closedByLastname); + + return new SavingsSummaryCustom(id,displayName, accountNo, externalId, productId, productName, shortProductName, status, currency, accountBalance, + accountTypeData, timeline, depositTypeData, subStatus, lastActiveTransactionDate); + } + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformService.java new file mode 100644 index 00000000000..2fbe48466a2 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformService.java @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.portfolio.savings.service; + +import java.math.BigDecimal; +import org.apache.fineract.portfolio.group.domain.Group; +import org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring; + +public interface GroupSavingsIndividualMonitoringWritePlatformService +{ + + void setIsAcceptingChild(GroupSavingsIndividualMonitoring gsimAccount); + + void resetIsAcceptingChild(GroupSavingsIndividualMonitoring gsimAccount); + + void incrementChildAccountCount(GroupSavingsIndividualMonitoring gsimAccount); + + GroupSavingsIndividualMonitoring addGSIMAccountInfo(String accountNumber, Group group, BigDecimal parentDeposit, Long childAccountsCount, + Boolean isAcceptingChild, Integer loanStatus, BigDecimal applicationId); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java new file mode 100644 index 00000000000..2b787abb490 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/GroupSavingsIndividualMonitoringWritePlatformServiceImpl.java @@ -0,0 +1,88 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.service; + +import java.math.BigDecimal; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.portfolio.group.domain.Group; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; +import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy; +import org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GroupSavingsIndividualMonitoringWritePlatformServiceImpl implements GroupSavingsIndividualMonitoringWritePlatformService +{ + + + private final PlatformSecurityContext context; + + private final GSIMRepositoy gsimAccountRepository; + + private final LoanRepository loanRepository; + + @Autowired + public GroupSavingsIndividualMonitoringWritePlatformServiceImpl(final PlatformSecurityContext context,final GSIMRepositoy gsimAccountRepository, + final LoanRepository loanRepository) + { + this.context=context; + this.gsimAccountRepository=gsimAccountRepository; + this.loanRepository=loanRepository; + } + + @Override + public GroupSavingsIndividualMonitoring addGSIMAccountInfo(String accountNumber,Group group,BigDecimal parentDeposit,Long childAccountsCount, + Boolean isAcceptingChild,Integer loanStatus,BigDecimal applicationId) + { + + GroupSavingsIndividualMonitoring glimAccountInfo=GroupSavingsIndividualMonitoring.getInstance(accountNumber,group,parentDeposit,childAccountsCount, + isAcceptingChild,loanStatus,applicationId); + + return this.gsimAccountRepository.save(glimAccountInfo ); + + } + + + @Override + public void setIsAcceptingChild(GroupSavingsIndividualMonitoring glimAccount) + { + glimAccount.setIsAcceptingChild(true); + gsimAccountRepository.save(glimAccount); + + } + + + @Override + public void resetIsAcceptingChild(GroupSavingsIndividualMonitoring glimAccount) + { + glimAccount.setIsAcceptingChild(false); + gsimAccountRepository.save(glimAccount); + + } + + + @Override + public void incrementChildAccountCount(GroupSavingsIndividualMonitoring glimAccount) + { + long count=glimAccount.getChildAccountsCount(); + glimAccount.setChildAccountsCount(count+1); + gsimAccountRepository.save(glimAccount); + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java index d09049531b4..74ac3153f91 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java @@ -103,4 +103,10 @@ void processPostActiveActions(SavingsAccount account, DateTimeFormatter fmt, Set CommandProcessingResult unblockDebits(Long savingsId); CommandProcessingResult releaseAmount(Long savingsId, Long transactionId); + + CommandProcessingResult gsimActivate(Long gsimId, JsonCommand command); + + CommandProcessingResult gsimDeposit(Long gsimId, JsonCommand command); + + CommandProcessingResult bulkGSIMClose(Long gsimId, JsonCommand command); } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index 0d7f923b982..9fe6475baba 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -26,6 +26,8 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName; import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawBalanceParamName; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import java.math.BigDecimal; import java.math.MathContext; import java.util.ArrayList; @@ -92,6 +94,8 @@ import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDataValidator; import org.apache.fineract.portfolio.savings.domain.DepositAccountOnHoldTransaction; import org.apache.fineract.portfolio.savings.domain.DepositAccountOnHoldTransactionRepository; +import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy; +import org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler; import org.apache.fineract.portfolio.savings.domain.SavingsAccountCharge; @@ -115,6 +119,8 @@ import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -148,6 +154,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi private final AppUserRepositoryWrapper appuserRepository; private final StandingInstructionRepository standingInstructionRepository; private final BusinessEventNotifierService businessEventNotifierService; + private final GSIMRepositoy gsimRepository; @Autowired public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -169,7 +176,7 @@ public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurit final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository, final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, final AppUserRepositoryWrapper appuserRepository, final StandingInstructionRepository standingInstructionRepository, - final BusinessEventNotifierService businessEventNotifierService) { + final BusinessEventNotifierService businessEventNotifierService, final GSIMRepositoy gsimRepository) { this.context = context; this.savingAccountRepositoryWrapper = savingAccountRepositoryWrapper; this.savingsAccountTransactionRepository = savingsAccountTransactionRepository; @@ -195,8 +202,33 @@ public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurit this.appuserRepository = appuserRepository; this.standingInstructionRepository = standingInstructionRepository; this.businessEventNotifierService = businessEventNotifierService; + this.gsimRepository=gsimRepository; } + private final static Logger logger = LoggerFactory.getLogger(SavingsAccountWritePlatformServiceJpaRepositoryImpl.class); + @Transactional + @Override + public CommandProcessingResult gsimActivate(final Long gsimId, final JsonCommand command) { + + Long parentSavingId = gsimId; + GroupSavingsIndividualMonitoring parentSavings = gsimRepository.findById(parentSavingId).get(); + List childSavings = this.savingAccountRepositoryWrapper.findByGsimId(gsimId); + + CommandProcessingResult result = null; + int count = 0; + for (SavingsAccount account : childSavings) { + result = activate(account.getId(), command); + if (result != null) { + count++; + if (count == parentSavings.getChildAccountsCount()) { + parentSavings.setSavingsStatus(SavingsAccountStatusType.ACTIVE.getValue()); + gsimRepository.save(parentSavings); + } + } + } + return result; + } + @Transactional @Override public CommandProcessingResult activate(final Long savingsId, final JsonCommand command) { @@ -265,6 +297,28 @@ public void processPostActiveActions(final SavingsAccount account, final DateTim depositAccountOnHoldTransactions); } + @Transactional + @Override + public CommandProcessingResult gsimDeposit(final Long gsimId, final JsonCommand command) { + + Long parentSavingId = gsimId; + // GroupSavingsIndividualMonitoringparentSavings=gsimRepository.findById(parentSavingId).get(); + List childSavings = this.savingAccountRepositoryWrapper.findByGsimId(gsimId); + + JsonArray savingsArray = command.arrayOfParameterNamed("savingsArray"); + + JsonArray childAccounts = command.arrayOfParameterNamed("childAccounts"); + int count = 0; + + CommandProcessingResult result = null; + for (JsonElement element : savingsArray) { + + result = deposit(element.getAsJsonObject().get("childAccountId").getAsLong(), + JsonCommand.fromExistingCommand(command, element)); + } + return result; + } + @Transactional @Override public CommandProcessingResult deposit(final Long savingsId, final JsonCommand command) { @@ -272,6 +326,12 @@ public CommandProcessingResult deposit(final Long savingsId, final JsonCommand c this.context.authenticatedUser(); this.savingsAccountTransactionDataValidator.validate(command); + boolean isGsim = false; + + if (this.savingAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsId).getGsim() != null) { + isGsim = true; + logger.info("is gsim"); + } final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId); checkClientOrGroupActive(account); @@ -288,6 +348,21 @@ public CommandProcessingResult deposit(final Long savingsId, final JsonCommand c final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(account, fmt, transactionDate, transactionAmount, paymentDetail, isAccountTransfer, isRegularTransaction); + if (isGsim && (deposit.getId() != null)) { + + logger.debug("Deposit account has been created: {} ", deposit); + + GroupSavingsIndividualMonitoring gsim = gsimRepository.findById(account.getGsim().getId()).get(); + logger.info("parent deposit : {} ", gsim.getParentDeposit()); + logger.info("child account : {} ", savingsId); + BigDecimal currentBalance = gsim.getParentDeposit(); + BigDecimal newBalance = currentBalance.add(transactionAmount); + gsim.setParentDeposit(newBalance); + gsimRepository.save(gsim); + logger.info("balance after making deposit : {} ", gsimRepository.findById(account.getGsim().getId()).get().getParentDeposit()); + + } + final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { final Note note = Note.savingsTransactionNote(account, deposit, noteText); @@ -316,6 +391,11 @@ public CommandProcessingResult withdrawal(final Long savingsId, final JsonComman this.savingsAccountTransactionDataValidator.validate(command); + boolean isGsim = false; + if (this.savingAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsId).getGsim() != null) { + isGsim = true; + } + final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate"); final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount"); @@ -337,6 +417,14 @@ public CommandProcessingResult withdrawal(final Long savingsId, final JsonComman final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(account, fmt, transactionDate, transactionAmount, paymentDetail, transactionBooleanValues); + if (isGsim && (withdrawal.getId() != null)) { + GroupSavingsIndividualMonitoring gsim = gsimRepository.findById(account.getGsim().getId()).get(); + BigDecimal currentBalance = gsim.getParentDeposit().subtract(transactionAmount); + gsim.setParentDeposit(currentBalance); + gsimRepository.save(gsim); + + } + final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { final Note note = Note.savingsTransactionNote(account, withdrawal, noteText); @@ -669,6 +757,29 @@ private void checkClientOrGroupActive(final SavingsAccount account) { } } + @Override + public CommandProcessingResult bulkGSIMClose(final Long gsimId, final JsonCommand command) { + + final Long parentSavingId = gsimId; + GroupSavingsIndividualMonitoring parentSavings = gsimRepository.findById(parentSavingId).get(); + List childSavings = this.savingAccountRepositoryWrapper.findByGsimId(gsimId); + + CommandProcessingResult result = null; + int count = 0; + for (SavingsAccount account : childSavings) { + result = close(account.getId(), command); + + if (result != null) { + count++; + if (count == parentSavings.getChildAccountsCount()) { + parentSavings.setSavingsStatus(SavingsAccountStatusType.CLOSED.getValue()); + gsimRepository.save(parentSavings); + } + } + } + return result; + } + @Override public CommandProcessingResult close(final Long savingsId, final JsonCommand command) { final AppUser user = this.context.authenticatedUser(); @@ -1556,4 +1667,4 @@ TransferApiConstants.transferClientSavingsException, new LocalDate(transaction.c } } -} +} \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformService.java index fa2dbfac531..959a2fe0cba 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformService.java @@ -39,4 +39,14 @@ public interface SavingsApplicationProcessWritePlatformService { CommandProcessingResult applicantWithdrawsFromApplication(Long savingsId, JsonCommand command); CommandProcessingResult createActiveApplication(SavingsAccountDataDTO savingsAccountDataDTO); + + CommandProcessingResult submitGSIMApplication(JsonCommand command); + + CommandProcessingResult approveGSIMApplication(Long gsimId, JsonCommand command); + + CommandProcessingResult rejectGSIMApplication(Long gsimId, JsonCommand command); + + CommandProcessingResult undoGSIMApplicationApproval(Long gsimId, JsonCommand command); + + CommandProcessingResult modifyGSIMApplication(Long gsimId, JsonCommand command); } \ No newline at end of file diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java index b3efece9662..59427c7f84a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java @@ -20,6 +20,9 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -60,6 +63,7 @@ import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService; import org.apache.fineract.portfolio.group.domain.Group; import org.apache.fineract.portfolio.group.domain.GroupRepository; +import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper; import org.apache.fineract.portfolio.group.exception.CenterNotActiveException; import org.apache.fineract.portfolio.group.exception.GroupNotActiveException; import org.apache.fineract.portfolio.group.exception.GroupNotFoundException; @@ -68,12 +72,15 @@ import org.apache.fineract.portfolio.savings.SavingsApiConstants; import org.apache.fineract.portfolio.savings.data.SavingsAccountDataDTO; import org.apache.fineract.portfolio.savings.data.SavingsAccountDataValidator; +import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy; +import org.apache.fineract.portfolio.savings.domain.GroupSavingsIndividualMonitoring; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler; import org.apache.fineract.portfolio.savings.domain.SavingsAccountCharge; import org.apache.fineract.portfolio.savings.domain.SavingsAccountChargeAssembler; import org.apache.fineract.portfolio.savings.domain.SavingsAccountDomainService; import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper; +import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType; import org.apache.fineract.portfolio.savings.domain.SavingsProduct; import org.apache.fineract.portfolio.savings.domain.SavingsProductRepository; import org.apache.fineract.portfolio.savings.exception.SavingsProductNotFoundException; @@ -108,6 +115,9 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository; private final BusinessEventNotifierService businessEventNotifierService; private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService; + private final GSIMRepositoy gsimRepository; + private final GroupRepositoryWrapper groupRepositoryWrapper; + private final GroupSavingsIndividualMonitoringWritePlatformService gsimWritePlatformService; @Autowired public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -122,7 +132,9 @@ public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final Plat final SavingsAccountWritePlatformService savingsAccountWritePlatformService, final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final BusinessEventNotifierService businessEventNotifierService, - final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService) { + final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, + final GSIMRepositoy gsimRepository, final GroupRepositoryWrapper groupRepositoryWrapper, + final GroupSavingsIndividualMonitoringWritePlatformService gsimWritePlatformService) { this.context = context; this.savingAccountRepository = savingAccountRepository; this.savingAccountAssembler = savingAccountAssembler; @@ -141,6 +153,9 @@ public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final Plat this.savingsAccountWritePlatformService = savingsAccountWritePlatformService; this.businessEventNotifierService = businessEventNotifierService ; this.entityDatatableChecksWritePlatformService = entityDatatableChecksWritePlatformService; + this.gsimRepository = gsimRepository; + this.groupRepositoryWrapper = groupRepositoryWrapper; + this.gsimWritePlatformService = gsimWritePlatformService; } /* @@ -170,6 +185,27 @@ private void handleDataIntegrityIssues(final JsonCommand command, final Throwabl throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Unknown data integrity issue with savings account."); } + @Transactional + @Override + public CommandProcessingResult submitGSIMApplication(final JsonCommand command) { + + CommandProcessingResult result = null; + + JsonArray gsimApplications = command.arrayOfParameterNamed("clientArray"); + + final Object lock = new Object(); + synchronized (lock){ + for (JsonElement gsimApplication : gsimApplications) { + // result=submitApplication(JsonCommand.fromExistingCommand(command, + // gsimApplication)); + result = submitApplication(JsonCommand.fromExistingCommand(command, gsimApplication, + gsimApplication.getAsJsonObject().get("clientId").getAsLong())); + } + } + + return result; + } + @Transactional @Override public CommandProcessingResult submitApplication(final JsonCommand command) { @@ -179,9 +215,88 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { final SavingsAccount account = this.savingAccountAssembler.assembleFrom(command, submittedBy); this.savingAccountRepository.save(account); - - generateAccountNumber(account); - + String accountNumber = ""; + GroupSavingsIndividualMonitoring gsimAccount = null; + BigDecimal applicationId = BigDecimal.ZERO; + Boolean isLastChildApplication = false; + + //gsim + if (account.isAccountNumberRequiresAutoGeneration()) { + + final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository + .findByAccountType(EntityAccountType.SAVINGS); + // if application is of GSIM type + if (account.getAccountTypes() == 5) { + final Long groupId = command.longValueOfParameterNamed("groupId"); + // GSIM specific parameters + if (command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("applicationId") != null) { + applicationId = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero("applicationId"); + } + + if (command.booleanObjectValueOfParameterNamed("lastApplication") != null) { + isLastChildApplication = command.booleanPrimitiveValueOfParameterNamed("lastApplication"); + } + + Group group = this.groupRepositoryWrapper.findOneWithNotFoundDetection(groupId); + + if (command.booleanObjectValueOfParameterNamed("isParentAccount") != null) + { + // empty table check + if (gsimRepository.count() != 0) { + // Parent-Not an empty table + + accountNumber = this.accountNumberGenerator.generate(account, accountNumberFormat); + account.updateAccountNo(accountNumber + "1"); + gsimAccount = gsimWritePlatformService.addGSIMAccountInfo(accountNumber, group, BigDecimal.ZERO, + Long.valueOf(1), true, + SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue(),applicationId); + account.setGsim(gsimAccount); + this.savingAccountRepository.save(account); + + } else { + // Parent-empty table + accountNumber = this.accountNumberGenerator.generate(account, accountNumberFormat); + account.updateAccountNo(accountNumber + "1"); + gsimWritePlatformService.addGSIMAccountInfo(accountNumber, group, BigDecimal.ZERO, + Long.valueOf(1), true, + SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue(),applicationId); + account.setGsim(gsimRepository.findOneByAccountNumber(accountNumber)); + this.savingAccountRepository.save(account); + } + } else { + if (gsimRepository.count() != 0) { + // Child-Not an empty table check + gsimAccount = gsimRepository.findOneByIsAcceptingChildAndApplicationId(true,applicationId); + accountNumber = gsimAccount.getAccountNumber() + + (gsimAccount.getChildAccountsCount() + 1); + account.updateAccountNo(accountNumber); + this.gsimWritePlatformService.incrementChildAccountCount(gsimAccount); + account.setGsim(gsimAccount); + this.savingAccountRepository.save(account); + + } else { + // Child-empty table + // if the gsim info is empty set the current account as parent + accountNumber = this.accountNumberGenerator.generate(account, accountNumberFormat); + account.updateAccountNo(accountNumber + "1"); + gsimWritePlatformService.addGSIMAccountInfo(accountNumber, group, BigDecimal.ZERO, + Long.valueOf(1), true, + SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue(),applicationId); + account.setGsim(gsimAccount); + this.savingAccountRepository.save(account); + } + //reset isAcceptingChild when processing last application of GSIM + if (isLastChildApplication) { + this.gsimWritePlatformService.resetIsAcceptingChild( + gsimRepository.findOneByIsAcceptingChildAndApplicationId(true, applicationId)); + } + } + } else // for applications other than GSIM + { + generateAccountNumber(account); + } + } + // end of gsim final Long savingsId = account.getId(); if(command.parameterExists(SavingsApiConstants.datatables)){ this.entityDatatableChecksWritePlatformService.saveDatatables(StatusEnum.CREATE.getCode().longValue(), @@ -202,6 +317,7 @@ public CommandProcessingResult submitApplication(final JsonCommand command) { .withClientId(account.clientId()) // .withGroupId(account.groupId()) // .withSavingsId(savingsId) // + .withGsimId(gsimAccount==null ? 0 : gsimAccount.getId()) .build(); } catch (final DataAccessException dve) { handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); @@ -222,6 +338,22 @@ private void generateAccountNumber(final SavingsAccount account) { } } + @Transactional + @Override + public CommandProcessingResult modifyGSIMApplication(final Long gsimId, final JsonCommand command) { + + final Long parentSavingId = gsimId; + List childSavings = this.savingAccountRepository.findByGsimId(parentSavingId); + + CommandProcessingResult result = null; + + for (SavingsAccount account : childSavings) { + result = modifyApplication(account.getId(), command); + } + + return result; + } + @Transactional @Override public CommandProcessingResult modifyApplication(final Long savingsId, final JsonCommand command) { @@ -347,6 +479,32 @@ public CommandProcessingResult deleteApplication(final Long savingsId) { .build(); } + @Transactional + @Override + public CommandProcessingResult approveGSIMApplication(final Long gsimId, final JsonCommand command) { + + // GroupLoanIndividualMonitoringAccount + // glimAccount=glimRepository.findOne(loanId); + Long parentSavingId = gsimId; + GroupSavingsIndividualMonitoring parentSavings = gsimRepository.findById(parentSavingId).get(); + List childSavings = this.savingAccountRepository.findByGsimId(gsimId); + CommandProcessingResult result = null; + int count = 0; + for (SavingsAccount account : childSavings) { + + result = approveApplication(account.getId(), command); + + if (result != null) { + count++; + if (count == parentSavings.getChildAccountsCount()) { + parentSavings.setSavingsStatus(SavingsAccountStatusType.APPROVED.getValue()); + gsimRepository.save(parentSavings); + } + } + } + return result; + } + @Transactional @Override public CommandProcessingResult approveApplication(final Long savingsId, final JsonCommand command) { @@ -389,6 +547,31 @@ public CommandProcessingResult approveApplication(final Long savingsId, final Js .build(); } + @Transactional + @Override + public CommandProcessingResult undoGSIMApplicationApproval(final Long gsimId, final JsonCommand command) { + final Long parentSavingId = gsimId; + GroupSavingsIndividualMonitoring parentSavings = gsimRepository.findById(parentSavingId).get(); + List childSavings = this.savingAccountRepository.findByGsimId(gsimId); + + CommandProcessingResult result = null; + int count = 0; + for (SavingsAccount account : childSavings) { + result = undoApplicationApproval(account.getId(), command); + + if (result != null) { + count++; + if (count == parentSavings.getChildAccountsCount()) { + parentSavings.setSavingsStatus(SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue()); + gsimRepository.save(parentSavings); + } + } + + } + + return result; + } + @Transactional @Override public CommandProcessingResult undoApplicationApproval(final Long savingsId, final JsonCommand command) { @@ -423,6 +606,30 @@ public CommandProcessingResult undoApplicationApproval(final Long savingsId, fin .build(); } + @Transactional + @Override + public CommandProcessingResult rejectGSIMApplication(final Long gsimId, final JsonCommand command) { + + final Long parentSavingId = gsimId; + GroupSavingsIndividualMonitoring parentSavings = gsimRepository.findById(parentSavingId).get(); + List childSavings = this.savingAccountRepository.findByGsimId(gsimId); + + CommandProcessingResult result = null; + int count = 0; + for (SavingsAccount account : childSavings) { + result = rejectApplication(account.getId(), command); + + if (result != null) { + count++; + if (count == parentSavings.getChildAccountsCount()) { + parentSavings.setSavingsStatus(SavingsAccountStatusType.REJECTED.getValue()); + gsimRepository.save(parentSavings); + } + } + } + return result; + } + @Transactional @Override public CommandProcessingResult rejectApplication(final Long savingsId, final JsonCommand command) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/data/SelfSavingsDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/data/SelfSavingsDataValidator.java index 0a300e23a35..f294ee01991 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/data/SelfSavingsDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/data/SelfSavingsDataValidator.java @@ -41,87 +41,82 @@ @Component public class SelfSavingsDataValidator { - private final FromJsonHelper fromApiJsonHelper; + private final FromJsonHelper fromApiJsonHelper; - @Autowired - public SelfSavingsDataValidator(final FromJsonHelper fromApiJsonHelper) { - this.fromApiJsonHelper = fromApiJsonHelper; - } + @Autowired + public SelfSavingsDataValidator(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } - private static final Set allowedAssociationParameters = new HashSet<>( - Arrays.asList(SavingsApiConstants.transactions, - SavingsApiConstants.charges)); + private static final Set allowedAssociationParameters = new HashSet<>( + Arrays.asList(SavingsApiConstants.transactions, SavingsApiConstants.charges)); - public void validateRetrieveSavings(final UriInfo uriInfo) { - List unsupportedParams = new ArrayList<>(); + public void validateRetrieveSavings(final UriInfo uriInfo) { + List unsupportedParams = new ArrayList<>(); - validateTemplate(uriInfo, unsupportedParams); + validateTemplate(uriInfo, unsupportedParams); - Set associationParameters = ApiParameterHelper - .extractAssociationsForResponseIfProvided(uriInfo - .getQueryParameters()); - if (!associationParameters.isEmpty()) { - associationParameters.removeAll(allowedAssociationParameters); - if (!associationParameters.isEmpty()) { - unsupportedParams.addAll(associationParameters); - } - } + Set associationParameters = ApiParameterHelper + .extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); + if (!associationParameters.isEmpty()) { + associationParameters.removeAll(allowedAssociationParameters); + if (!associationParameters.isEmpty()) { + unsupportedParams.addAll(associationParameters); + } + } - if (uriInfo.getQueryParameters().getFirst("exclude") != null) { - unsupportedParams.add("exclude"); - } + if (uriInfo.getQueryParameters().getFirst("exclude") != null) { + unsupportedParams.add("exclude"); + } - throwExceptionIfReqd(unsupportedParams); - } + throwExceptionIfReqd(unsupportedParams); + } - public void validateRetrieveSavingsTransaction(final UriInfo uriInfo) { - List unsupportedParams = new ArrayList<>(); + public void validateRetrieveSavingsTransaction(final UriInfo uriInfo) { + List unsupportedParams = new ArrayList<>(); - validateTemplate(uriInfo, unsupportedParams); + validateTemplate(uriInfo, unsupportedParams); - throwExceptionIfReqd(unsupportedParams); - } + throwExceptionIfReqd(unsupportedParams); + } - private void throwExceptionIfReqd(final List unsupportedParams) { - if (unsupportedParams.size() > 0) { - throw new UnsupportedParameterException(unsupportedParams); - } - } + private void throwExceptionIfReqd(final List unsupportedParams) { + if (unsupportedParams.size() > 0) { + throw new UnsupportedParameterException(unsupportedParams); + } + } - private void validateTemplate(final UriInfo uriInfo, - List unsupportedParams) { - final boolean templateRequest = ApiParameterHelper.template(uriInfo - .getQueryParameters()); - if (templateRequest) { - unsupportedParams.add("template"); - } - } + private void validateTemplate(final UriInfo uriInfo, List unsupportedParams) { + final boolean templateRequest = ApiParameterHelper.template(uriInfo.getQueryParameters()); + if (templateRequest) { + unsupportedParams.add("template"); + } + } - public HashMap validateSavingsApplication(final String json) { - if (StringUtils.isBlank(json)) { - throw new InvalidJsonException(); - } + public HashMap validateSavingsApplication(final String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } - final List dataValidationErrors = new ArrayList<>(); - final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) - .resource(SelfSavingsAccountConstants.savingsAccountResource); + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(SelfSavingsAccountConstants.savingsAccountResource); - final JsonElement element = this.fromApiJsonHelper.parse(json); + final JsonElement element = this.fromApiJsonHelper.parse(json); - final Long clientId = this.fromApiJsonHelper.extractLongNamed(SelfSavingsAccountConstants.clientIdParameterName, - element); - baseDataValidator.reset().parameter(SelfSavingsAccountConstants.clientIdParameterName).value(clientId).notNull() - .longGreaterThanZero(); + final Long clientId = this.fromApiJsonHelper.extractLongNamed(SelfSavingsAccountConstants.clientIdParameterName, + element); + baseDataValidator.reset().parameter(SelfSavingsAccountConstants.clientIdParameterName).value(clientId).notNull() + .longGreaterThanZero(); - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException(dataValidationErrors); - } + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException(dataValidationErrors); + } - HashMap parameterMap = new HashMap<>(); - parameterMap.put(SelfSavingsAccountConstants.clientIdParameterName, clientId); + HashMap parameterMap = new HashMap<>(); + parameterMap.put(SelfSavingsAccountConstants.clientIdParameterName, clientId); - return parameterMap; + return parameterMap; - } - -} + } +} \ No newline at end of file diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V356__GSIM_migration_script.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V356__GSIM_migration_script.sql new file mode 100644 index 00000000000..4dcbd8c394a --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V356__GSIM_migration_script.sql @@ -0,0 +1,63 @@ +-- +-- 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. +-- + + +-- permissions added + + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_GSIMACCOUNT', 'GSIMACCOUNT', 'CREATE', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'APPROVE_GSIMACCOUNT', 'GSIMACCOUNT', 'APPROVE', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'ACTIVATE_GSIMACCOUNT', 'GSIMACCOUNT', 'ACTIVATE', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'APPROVALUNDO_GSIMACCOUNT', 'GSIMACCOUNT', 'APPROVALUNDO', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_GSIMACCOUNT', 'GSIMACCOUNT', 'UPDATE', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'REJECT_GSIMACCOUNT', 'GSIMACCOUNT', 'REJECT', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DEPOSIT_GSIMACCOUNT', 'GSIMACCOUNT', 'DEPOSIT', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CLOSE_GSIMACCOUNT', 'GSIMACCOUNT', 'CLOSE', 0); + + +-- new gsim table +CREATE TABLE `gsim_accounts` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `group_id` BIGINT(20) NOT NULL DEFAULT '0', + `account_number` VARCHAR(50) NOT NULL, + `parent_deposit` DECIMAL(19,6) NOT NULL DEFAULT '0.000000', + `child_accounts_count` INT(11) NOT NULL, + `accepting_child` TINYINT(4) NOT NULL DEFAULT '0', + `savings_status_id` SMALLINT(5) NOT NULL DEFAULT '0', + `application_id` DECIMAL(10,0) NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE INDEX `gsim_account_no_UNIQUE` (`account_number`), + INDEX `FK_gsim_group_id` (`group_id`), + CONSTRAINT `FK_gsim_group_id` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`) +); + + -- changes to savings + ALTER TABLE `m_savings_account` ADD COLUMN `gsim_id` bigint(20) DEFAULT NULL AFTER `group_id`; + + ALTER TABLE `m_savings_account` ADD CONSTRAINT `FK_gsim_id` FOREIGN KEY (`gsim_id`) REFERENCES `gsim_accounts` (`id`); + + -- changes to savings_Transaction + ALTER TABLE `m_savings_account_transaction` ADD COLUMN `is_loan_disbursement` bigint(20); \ No newline at end of file diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V357__GLIM_migration_script.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V357__GLIM_migration_script.sql new file mode 100644 index 00000000000..aa1ffaa06cf --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V357__GLIM_migration_script.sql @@ -0,0 +1,58 @@ +-- +-- 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. +-- + + + +-- permissions added + + INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'APPROVE_GLIMLOAN', 'GLIMLOAN', 'APPROVE', 0); + INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DISBURSE_GLIMLOAN', 'GLIMLOAN', 'DISBURSE', 0); + INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'REPAYMENT_GLIMLOAN', 'GLIMLOAN', 'REPAYMENT', 0); + INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNDODISBURSAL_GLIMLOAN', 'GLIMLOAN', 'UNDODISBURSAL', 0); + INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UNDOAPPROVAL_GLIMLOAN', 'GLIMLOAN', 'UNDOAPPROVAL', 0); + INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'REJECT_GLIMLOAN', 'GLIMLOAN', 'REJECT', 0); + + -- new table glim_accounts added + + CREATE TABLE `glim_accounts` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `group_id` BIGINT(20) NOT NULL DEFAULT '0', + `account_number` VARCHAR(50) NOT NULL, + `principal_amount` DECIMAL(19,6) NOT NULL DEFAULT '0.000000', + `child_accounts_count` INT(11) NOT NULL, + `accepting_child` TINYINT(4) NOT NULL DEFAULT '0', + `loan_status_id` SMALLINT(5) NOT NULL DEFAULT '0', + `application_id` DECIMAL(10,0) NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE INDEX `glim_account_no_UNIQUE` (`account_number`), + INDEX `FK_group_id` (`group_id`), + CONSTRAINT `FK_group_id` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`) +); + + -- change m_loan table + + alter table `m_loan` add COLUMN `glim_id` bigint(20) DEFAULT NULL AFTER `group_id`; + + alter table `m_loan` add CONSTRAINT `FK_glim_id` FOREIGN KEY (`glim_id`) REFERENCES `glim_accounts` (`id`); + + + + + + \ No newline at end of file