Dear Adi, Sander, Pramod, Did you have a chance to look into the matter below?
Regards, Andris Kaneps > On 2016. gada 12. jūl., at 14:10, Andris Kaneps <akan...@mtgcapital.ch> wrote: > > Dear Adi and the team, > > As you may know Vishwas from Conflux Technologies has finished the > development of Mifos fix that solves the rescheduling issue. We will do > in-house testing for the coming days. > > Can you please let us know when this could be implemented into Mifos update? > > Regards, > Andris > > >> On Tue, Apr 19, 2016 at 10:59 AM, Adi Raju >> <adi.r...@confluxtechnologies.com> wrote: >> Hi Ed, >> >> >> >> Subramanya will be working on this task tomorrow. >> >> >> >> Regards, >> >> Adi >> >> >> >> From: Ed Cable [mailto:edca...@mifos.org] >> Sent: 18 April 2016 21:49 >> To: Andris Kaneps <akan...@mtgcapital.ch> >> Cc: Agris Varpins <agris.varp...@mtgcapital.ch>; Adi Raju >> <adi.r...@confluxtechnologies.com>; Sander van der Heyden >> <sandervanderhey...@musoni.eu>; dev@fineract.incubator.apache.org; robert >> wizglobal <rob...@wizglobal.co.ke>; Zack Wizglobal <z...@wizglobal.co.ke>; >> pra...@confluxtechnologies.com Nuthakki <pra...@confluxtechnologies.com>; >> Philippe Storm <pst...@watucredit.com>; Markus Geiß <mge...@mifos.org> >> Subject: Re: Clarification on Validator Classes for Multiple Rescheduling of >> a Loan >> >> >> >> Adi, >> >> >> >> Now that the team has gotten through the QA for the most recent release, >> could you have the QA team spend some time on testing the scenarios and APIs >> you referenced above. Could you also provide a bit more clarity regarding >> what Zack needs to done for allowing for the undoing of the reschedulings. >> >> >> >> Thanks, >> >> >> >> Ed >> >> >> >> >> >> On Tue, Apr 12, 2016 at 2:46 AM, Andris Kaneps <akan...@mtgcapital.ch> wrote: >> >> Gentlemen, >> >> >> >> If we would comission to Zack the "undo" function- would it be the solution? >> >> >> >> R, >> >> Andris >> >> Sent from my iPhone >> >> >> On 2016. gada 12. apr., at 11:44, Agris Varpins >> <agris.varp...@mtgcapital.ch> wrote: >> >> Who can test it and tell if they are working? I am not an IT person myself, >> As I said I tested the fix in test environment and ext worked fine, however, >> if there is something else to be tested purely from technical point of view, >> then, gentlemen, I trust you are the right people to deliver that verdict!! >> >> Cheers, >> Agris >> >> >> >> On Tue, Apr 12, 2016 at 11:49 AM, Adi Raju >> <adi.r...@confluxtechnologies.com> wrote: >> >> If you look at api doc >> https://demo.openmf.org/api-docs/apiLive.htm#loan_rescheduling >> >> I see APIs to read/reject/approve any reschedule loan request instance. >> >> As long as these APIs are tested to be working fine, it should be good >> enough. >> >> >> >> Regards, >> >> Adi >> >> >> >> From: Agris Varpins [mailto:agris.varp...@mtgcapital.ch] >> Sent: 12 April 2016 13:38 >> To: Adi Raju <adi.r...@confluxtechnologies.com> >> Cc: Sander van der Heyden <sandervanderhey...@musoni.eu>; Ed Cable >> <edca...@mifos.org>; dev@fineract.incubator.apache.org; robert wizglobal >> <rob...@wizglobal.co.ke>; Zack Wizglobal <z...@wizglobal.co.ke>; >> pra...@confluxtechnologies.com Nuthakki <pra...@confluxtechnologies.com>; >> Andris Kaneps <akan...@mtgcapital.ch>; Philippe Storm >> <pst...@watucredit.com>; Markus Geiß <mge...@mifos.org> >> Subject: Re: Clarification on Validator Classes for Multiple Rescheduling of >> a Loan >> >> >> >> Could you clarify what you mean by "undo reschedule if the user makes a >> mistake"? In current version extenion cannot be undone if I am not mistaken >> or are we talking about some othetr functionality? >> >> >> >> On Tue, Apr 12, 2016 at 11:02 AM, Adi Raju >> <adi.r...@confluxtechnologies.com> wrote: >> >> As mentioned by Sander: >> >> “The main reason we put in the restrictions around allowing only one >> reschedule, was to also enable users to undo them easily if they were made >> by mistake. I think that is something that can be solved, but would require >> a bit of extra work ensuring that the correct old schedules are grabbed and >> reapplied to the loan.” >> >> >> >> Until this additional work is done, I wouldn’t recommend current solution to >> be merged. >> >> >> >> Regards, >> >> Adi >> >> >> >> From: Agris Varpins [mailto:agris.varp...@mtgcapital.ch] >> Sent: 12 April 2016 13:14 >> To: Sander van der Heyden <sandervanderhey...@musoni.eu> >> Cc: Ed Cable <edca...@mifos.org>; dev@fineract.incubator.apache.org; robert >> wizglobal <rob...@wizglobal.co.ke>; Zack Wizglobal <z...@wizglobal.co.ke>; >> pra...@confluxtechnologies.com Nuthakki <pra...@confluxtechnologies.com>; >> Andris Kaneps <akan...@mtgcapital.ch>; Philippe Storm >> <pst...@watucredit.com>; Markus Geiß <mge...@mifos.org>; Adi Raju >> <adi.r...@confluxtechnologies.com> >> Subject: Re: Clarification on Validator Classes for Multiple Rescheduling of >> a Loan >> >> >> >> Good morning, gentlemen! >> >> So where do we stand with this update? Ed, has your team done some testing >> of the update to see if it works properly with the test clients? When we >> tested for our purposes, it seemed to work as we expected - loans could be >> rescheduled multiple times and reschedule could be done without undoing >> previously entered payments. Granted, we did not test how this fix affects, >> for example, accounting function, Overall, even if some additional fix is >> necessary to the Zack's product, that still would be doable.I believe it is >> in all interests to achieve that Mifos offers this fuction to its user >> community including ourselves. >> >> Please let us now where do we stand at the moment and what are the prospects >> for this fix so that we can plan accordingly. >> >> Best regards, >> >> Agris >> >> >> >> On Mon, Apr 11, 2016 at 12:29 PM, Sander van der Heyden >> <sandervanderhey...@musoni.eu> wrote: >> >> Hi all, >> >> >> >> Ignore my response, I was responding to the wrong thread, and not paying >> attention, still early here I guess... >> >> >> >> In terms of rescheduling, I think the current solution would need to be >> tested very carefully before it can be considered stable (or not), and >> therefore I'd recommend doing that before we merge the commit. Might also be >> good to add one or 2 test cases for the multiple reschedules to ensure that >> we have it covered there as well. >> >> >> >> S >> >> >> >> >> Sander van der Heyden >> >> CTO Musoni Services >> >> >> >> Mobile (NL): +31 (0)6 14239505 >> Skype: s.vdheyden >> Website: musonisystem.com >> Follow us on Twitter! >> Postal address: Hillegomstraat 12-14, office 0.09, 1058 LS, Amsterdam, The >> Netherlands >> >> >> >> On Mon, Apr 11, 2016 at 11:17 AM, Sander van der Heyden >> <sandervanderhey...@musoni.eu> wrote: >> >> Hi Agris, >> >> >> >> You can already do all of this by using the current datatables, where you >> can add all fields necessary to the clients data that you want to capture. >> So the update is not really a requirement to get this done, a large number >> of MFI's are already using the system with all of these fields added in. >> >> >> >> Thanks, >> >> Sander >> >> >> >> >> Sander van der Heyden >> >> CTO Musoni Services >> >> >> >> Mobile (NL): +31 (0)6 14239505 >> Skype: s.vdheyden >> Website: musonisystem.com >> Follow us on Twitter! >> Postal address: Hillegomstraat 12-14, office 0.09, 1058 LS, Amsterdam, The >> Netherlands >> >> >> >> On Mon, Apr 11, 2016 at 10:58 AM, Agris Varpins >> <agris.varp...@mtgcapital.ch> wrote: >> >> Good morning, all! >> >> Thank you all for you inputs! So what is the verdict regarding this update? >> Will it work? Or if not, can it be easily adjusted and perfected so that it >> does? I cannot overstate hot important this fix is for us and we are really >> looking to solve this issue as soon as possible, >> >> Looking forward to you feedback. >> >> Best regards, >> >> Agris >> >> >> >> On Mon, Apr 11, 2016 at 9:09 AM, Sander van der Heyden >> <sandervanderhey...@musoni.eu> wrote: >> >> Hi all >> >> >> >> The main reason we put in the restrictions around allowing only one >> reschedule, was to also enable users to undo them easily if they were made >> by mistake. I think that is something that can be solved, but would require >> a bit of extra work ensuring that the correct old schedules are grabbed and >> reapplied to the loan. >> >> >> >> S >> >> >> >> >> Sander van der Heyden >> >> CTO Musoni Services >> >> >> >> Mobile (NL): +31 (0)6 14239505 >> Skype: s.vdheyden >> Website: musonisystem.com >> Follow us on Twitter! >> Postal address: Hillegomstraat 12-14, office 0.09, 1058 LS, Amsterdam, The >> Netherlands >> >> >> >> On Fri, Apr 8, 2016 at 5:46 PM, Ed Cable <edca...@mifos.org> wrote: >> >> Sander, have you had a chance to review this thread? >> >> >> >> Andris' team is in need of this feature and wanted to get feedback on the >> approach they've taken to see if they can continue with that or they need to >> follow the path that was proposed by Pramod. >> >> >> >> Ed >> >> >> >> >> >> On Wed, Apr 6, 2016 at 9:38 AM, Ed Cable <edca...@mifos.org> wrote: >> >> Zack and Robert have been working on contributing a fix to add the ability >> to reschedule a loan multiple times. >> >> >> >> They have taken a different approach than what Pramod had previously >> outlined so we wanted to discuss their proposed fix with Sander and his team >> who have provided the initial fix to reschedule a loan a single time. >> >> >> >> Ed >> >> >> >> On Mon, Apr 4, 2016 at 9:32 PM, Adi Raju <adi.r...@confluxtechnologies.com> >> wrote: >> >> Hi Robert, >> >> >> >> Validator classes generally only perform API parameter validations, in other >> words they are the first check point before proceeding to more costlier DB >> or calculation tasks. >> >> All that is done in this change is that the validation at the first check >> point is removed. >> >> These checkpoints were added by earlier developers because they haven’t >> addressed those scenarios in further calculations. >> >> If the core code works for multi-reschedule, they wouldn’t have put this >> check in the first place. >> >> >> >> I really doubt this solution is working as it is supposed to be. Have you >> been able to test it against expected schedule and its values post >> reschedule action? Does other like retrieve/approve/reject reschedule APIs >> work with this solution? >> >> >> >> +Sander, who can help us with more clarifications on why such validations >> were added. >> >> >> >> Regards, >> >> Adi >> >> >> >> >> >> From: robert wizglobal [mailto:rob...@wizglobal.co.ke] >> Sent: 04 April 2016 22:13 >> To: Adi Raju <adi.r...@confluxtechnologies.com> >> Cc: Zack Wizglobal <z...@wizglobal.co.ke>; Ed Cable <edca...@mifos.org>; >> pra...@confluxtechnologies.com; Agris Varpins <agris.varp...@mtgcapital.ch>; >> Andris Kaneps <akan...@mtgcapital.ch>; Philippe Storm <pst...@watucredit.com> >> Subject: Re: Mifos fix >> >> >> >> Hello Adi >> >> >> >> It Was Not a Major Fix Below is the Change i did on the >> LoanRescheduleRequestDataValidator Class >> >> >> >> /** >> >> * 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.rescheduleloan.data; >> >> >> >> import java.lang.reflect.Type; >> >> import java.util.ArrayList; >> >> import java.util.List; >> >> import java.util.Map; >> >> >> >> import org.apache.commons.lang.StringUtils; >> >> import org.apache.fineract.infrastructure.core.api.JsonCommand; >> >> import org.apache.fineract.infrastructure.core.data.ApiParameterError; >> >> import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder; >> >> import >> org.apache.fineract.infrastructure.core.exception.InvalidJsonException; >> >> import >> org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException; >> >> import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; >> >> import org.apache.fineract.portfolio.loanaccount.domain.Loan; >> >> import >> org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; >> >> import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; >> >> import >> org.apache.fineract.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants; >> >> import >> org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest; >> >> import >> org.apache.fineract.portfolio.loanaccount.rescheduleloan.service.LoanRescheduleRequestReadPlatformService; >> >> import org.joda.time.LocalDate; >> >> import org.springframework.beans.factory.annotation.Autowired; >> >> import org.springframework.stereotype.Component; >> >> >> >> import com.google.gson.JsonElement; >> >> import com.google.gson.reflect.TypeToken; >> >> >> >> @Component >> >> public class LoanRescheduleRequestDataValidator { >> >> >> >> private final FromJsonHelper fromJsonHelper; >> >> private final LoanRescheduleRequestReadPlatformService >> loanRescheduleRequestReadPlatformService; >> >> >> >> @Autowired >> >> public LoanRescheduleRequestDataValidator(FromJsonHelper fromJsonHelper, >> >> LoanRescheduleRequestReadPlatformService >> loanRescheduleRequestReadPlatformService) { >> >> this.fromJsonHelper = fromJsonHelper; >> >> this.loanRescheduleRequestReadPlatformService = >> loanRescheduleRequestReadPlatformService; >> >> } >> >> >> >> /** >> >> * Validates the request to create a new loan reschedule entry >> >> * >> >> * @param jsonCommand >> >> * the JSON command object (instance of the JsonCommand class) >> >> * @return void >> >> **/ >> >> public void validateForCreateAction(final JsonCommand jsonCommand, final >> Loan loan) { >> >> >> >> final String jsonString = jsonCommand.json(); >> >> >> >> if (StringUtils.isBlank(jsonString)) { throw new >> InvalidJsonException(); } >> >> >> >> final Type typeToken = new TypeToken<Map<String, Object>>() >> {}.getType(); >> >> this.fromJsonHelper >> >> .checkForUnsupportedParameters(typeToken, jsonString, >> RescheduleLoansApiConstants.CREATE_REQUEST_DATA_PARAMETERS); >> >> >> >> final List<ApiParameterError> dataValidationErrors = new >> ArrayList<>(); >> >> final DataValidatorBuilder dataValidatorBuilder = new >> DataValidatorBuilder(dataValidationErrors).resource(StringUtils >> >> .lowerCase(RescheduleLoansApiConstants.ENTITY_NAME)); >> >> >> >> final JsonElement jsonElement = jsonCommand.parsedJson(); >> >> >> >> if (!loan.status().isActive()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode("loan.is.not.active", >> "Loan is not active"); >> >> } >> >> >> >> final Long loanId = >> this.fromJsonHelper.extractLongNamed(RescheduleLoansApiConstants.loanIdParamName, >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.loanIdParamName).value(loanId).notNull() >> >> .integerGreaterThanZero(); >> >> >> >> final LocalDate submittedOnDate = >> this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.submittedOnDateParamName, >> >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.submittedOnDateParamName).value(submittedOnDate).notNull(); >> >> >> >> if (submittedOnDate != null && >> loan.getDisbursementDate().isAfter(submittedOnDate)) { >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.submittedOnDateParamName) >> >> .failWithCode("before.loan.disbursement.date", >> "Submission date cannot be before the loan disbursement date"); >> >> } >> >> >> >> final LocalDate rescheduleFromDate = >> this.fromJsonHelper.extractLocalDateNamed( >> >> RescheduleLoansApiConstants.rescheduleFromDateParamName, >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName).value(rescheduleFromDate).notNull(); >> >> >> >> final Integer graceOnPrincipal = >> this.fromJsonHelper.extractIntegerWithLocaleNamed( >> >> RescheduleLoansApiConstants.graceOnPrincipalParamName, >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.graceOnPrincipalParamName).value(graceOnPrincipal) >> >> .ignoreIfNull().integerGreaterThanZero(); >> >> >> >> final Integer graceOnInterest = >> this.fromJsonHelper.extractIntegerWithLocaleNamed( >> >> RescheduleLoansApiConstants.graceOnInterestParamName, >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.graceOnInterestParamName).value(graceOnInterest).ignoreIfNull() >> >> .integerGreaterThanZero(); >> >> >> >> final Integer extraTerms = >> this.fromJsonHelper.extractIntegerWithLocaleNamed(RescheduleLoansApiConstants.extraTermsParamName, >> >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.extraTermsParamName).value(extraTerms).ignoreIfNull() >> >> .integerGreaterThanZero(); >> >> >> >> final Long rescheduleReasonId = >> this.fromJsonHelper.extractLongNamed(RescheduleLoansApiConstants.rescheduleReasonIdParamName, >> >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleReasonIdParamName).value(rescheduleReasonId).notNull() >> >> .integerGreaterThanZero(); >> >> >> >> final String rescheduleReasonComment = >> this.fromJsonHelper.extractStringNamed( >> >> >> RescheduleLoansApiConstants.rescheduleReasonCommentParamName, jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleReasonCommentParamName).value(rescheduleReasonComment) >> >> .ignoreIfNull().notExceedingLengthOf(500); >> >> >> >> final LocalDate adjustedDueDate = >> this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.adjustedDueDateParamName, >> >> jsonElement); >> >> >> >> if (adjustedDueDate != null && rescheduleFromDate != null && >> adjustedDueDate.isBefore(rescheduleFromDate)) { >> >> dataValidatorBuilder >> >> .reset() >> >> >> .parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName) >> >> >> .failWithCode("adjustedDueDate.before.rescheduleFromDate", >> >> "Adjusted due date cannot be before the >> reschedule from date"); >> >> } >> >> >> >> // at least one of the following must be provided => >> graceOnPrincipal, >> >> // graceOnInterest, extraTerms, newInterestRate >> >> if >> (!this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.graceOnPrincipalParamName, >> jsonElement) >> >> && >> !this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.graceOnInterestParamName, >> jsonElement) >> >> && >> !this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.extraTermsParamName, >> jsonElement) >> >> && >> !this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.newInterestRateParamName, >> jsonElement) >> >> && >> !this.fromJsonHelper.parameterExists(RescheduleLoansApiConstants.adjustedDueDateParamName, >> jsonElement)) { >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.graceOnPrincipalParamName).notNull(); >> >> } >> >> >> >> if (rescheduleFromDate != null) { >> >> LoanRepaymentScheduleInstallment installment = >> loan.getRepaymentScheduleInstallment(rescheduleFromDate); >> >> >> >> if (installment == null) { >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName) >> >> >> .failWithCode("repayment.schedule.installment.does.not.exist", "Repayment >> schedule installment does not exist"); >> >> } >> >> /* >> >> if (installment != null && installment.isObligationsMet()) { >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName) >> >> >> .failWithCode("repayment.schedule.installment.obligation.met", "Repayment >> schedule installment obligation met"); >> >> } */ >> >> /* >> >> if (installment != null && installment.isPartlyPaid()) { >> >> >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rescheduleFromDateParamName) >> >> >> .failWithCode("repayment.schedule.installment.partly.paid", "Repayment >> schedule installment is partly paid"); >> >> } */ >> >> } >> >> >> >> if (loanId != null) { >> >> List<LoanRescheduleRequestData> loanRescheduleRequestData = >> this.loanRescheduleRequestReadPlatformService >> >> .readLoanRescheduleRequests(loanId, >> LoanStatus.APPROVED.getValue()); >> >> /* //commented this for loan reshedule >> >> if (loanRescheduleRequestData.size() > 0) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode("loan.already.rescheduled", >> >> "The loan can only be rescheduled once."); >> >> } */ >> >> } >> >> if(loan.isMultiDisburmentLoan()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode(RescheduleLoansApiConstants.resheduleForMultiDisbursementNotSupportedErrorCode, >> >> "Loan rescheduling is not supported for >> multidisbursement loans"); >> >> } >> >> >> >> if(loan.isInterestRecalculationEnabledForProduct()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode(RescheduleLoansApiConstants.resheduleWithInterestRecalculationNotSupportedErrorCode, >> >> "Loan rescheduling is not supported for the loan product >> with interest recalculation enabled"); >> >> } >> >> >> >> if (!dataValidationErrors.isEmpty()) { throw new >> PlatformApiDataValidationException(dataValidationErrors); } >> >> } >> >> >> >> /** >> >> * Validates a user request to approve a loan reschedule request >> >> * >> >> * @param jsonCommand >> >> * the JSON command object (instance of the JsonCommand class) >> >> * @return void >> >> **/ >> >> public void validateForApproveAction(final JsonCommand jsonCommand, >> LoanRescheduleRequest loanRescheduleRequest) { >> >> final String jsonString = jsonCommand.json(); >> >> >> >> if (StringUtils.isBlank(jsonString)) { throw new >> InvalidJsonException(); } >> >> >> >> final Type typeToken = new TypeToken<Map<String, Object>>() >> {}.getType(); >> >> this.fromJsonHelper.checkForUnsupportedParameters(typeToken, >> jsonString, >> >> RescheduleLoansApiConstants.APPROVE_REQUEST_DATA_PARAMETERS); >> >> >> >> final List<ApiParameterError> dataValidationErrors = new >> ArrayList<>(); >> >> final DataValidatorBuilder dataValidatorBuilder = new >> DataValidatorBuilder(dataValidationErrors).resource(StringUtils >> >> .lowerCase(RescheduleLoansApiConstants.ENTITY_NAME)); >> >> >> >> final JsonElement jsonElement = jsonCommand.parsedJson(); >> >> >> >> final LocalDate approvedOnDate = >> this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.approvedOnDateParam, >> >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.approvedOnDateParam).value(approvedOnDate).notNull(); >> >> >> >> if (approvedOnDate != null && >> loanRescheduleRequest.getSubmittedOnDate().isAfter(approvedOnDate)) { >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.approvedOnDateParam) >> >> .failWithCode("before.submission.date", "Approval date >> cannot be before the request submission date."); >> >> } >> >> >> >> LoanRescheduleRequestStatusEnumData >> loanRescheduleRequestStatusEnumData = LoanRescheduleRequestEnumerations >> >> .status(loanRescheduleRequest.getStatusEnum()); >> >> >> >> if (!loanRescheduleRequestStatusEnumData.isPendingApproval()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode( >> >> "request.is.not.in.submitted.and.pending.state", >> >> "Loan reschedule request approval is not allowed. " >> >> + "Loan reschedule request is not in submitted >> and pending approval state."); >> >> } >> >> >> >> LocalDate rescheduleFromDate = >> loanRescheduleRequest.getRescheduleFromDate(); >> >> final Loan loan = loanRescheduleRequest.getLoan(); >> >> >> >> if (loan != null) { >> >> Long loanId = loan.getId(); >> >> >> >> if (!loan.status().isActive()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode("loan.is.not.active", >> "Loan is not active"); >> >> } >> >> >> >> if (rescheduleFromDate != null) { >> >> LoanRepaymentScheduleInstallment installment = >> loan.getRepaymentScheduleInstallment(rescheduleFromDate); >> >> >> >> if (installment == null) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode( >> >> >> "loan.repayment.schedule.installment.does.not.exist", "Repayment schedule >> installment does not exist"); >> >> } >> >> /* >> >> if (installment != null && installment.isObligationsMet()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode( >> >> "loan.repayment.schedule.installment." + >> "obligation.met", "Repayment schedule installment obligation met"); >> >> } */ >> >> } >> >> >> >> if (loanId != null) { >> >> List<LoanRescheduleRequestData> loanRescheduleRequestData = >> this.loanRescheduleRequestReadPlatformService >> >> .readLoanRescheduleRequests(loanId, >> LoanStatus.APPROVED.getValue()); >> >> /* >> >> if (loanRescheduleRequestData.size() > 0) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode("loan.already.rescheduled", >> >> "The loan can only be rescheduled once."); >> >> } */ >> >> } >> >> } >> >> >> >> if (!dataValidationErrors.isEmpty()) { throw new >> PlatformApiDataValidationException(dataValidationErrors); } >> >> } >> >> >> >> /** >> >> * Validates a user request to reject a loan reschedule request >> >> * >> >> * @param jsonCommand >> >> * the JSON command object (instance of the JsonCommand class) >> >> * @return void >> >> **/ >> >> public void validateForRejectAction(final JsonCommand jsonCommand, >> LoanRescheduleRequest loanRescheduleRequest) { >> >> final String jsonString = jsonCommand.json(); >> >> >> >> if (StringUtils.isBlank(jsonString)) { throw new >> InvalidJsonException(); } >> >> >> >> final Type typeToken = new TypeToken<Map<String, Object>>() >> {}.getType(); >> >> this.fromJsonHelper >> >> .checkForUnsupportedParameters(typeToken, jsonString, >> RescheduleLoansApiConstants.REJECT_REQUEST_DATA_PARAMETERS); >> >> >> >> final List<ApiParameterError> dataValidationErrors = new >> ArrayList<>(); >> >> final DataValidatorBuilder dataValidatorBuilder = new >> DataValidatorBuilder(dataValidationErrors).resource(StringUtils >> >> .lowerCase(RescheduleLoansApiConstants.ENTITY_NAME)); >> >> >> >> final JsonElement jsonElement = jsonCommand.parsedJson(); >> >> >> >> final LocalDate rejectedOnDate = >> this.fromJsonHelper.extractLocalDateNamed(RescheduleLoansApiConstants.rejectedOnDateParam, >> >> jsonElement); >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rejectedOnDateParam).value(rejectedOnDate).notNull(); >> >> >> >> if (rejectedOnDate != null && >> loanRescheduleRequest.getSubmittedOnDate().isAfter(rejectedOnDate)) { >> >> >> dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.rejectedOnDateParam) >> >> .failWithCode("before.submission.date", "Rejection date >> cannot be before the request submission date."); >> >> } >> >> >> >> LoanRescheduleRequestStatusEnumData >> loanRescheduleRequestStatusEnumData = LoanRescheduleRequestEnumerations >> >> .status(loanRescheduleRequest.getStatusEnum()); >> >> >> >> if (!loanRescheduleRequestStatusEnumData.isPendingApproval()) { >> >> >> dataValidatorBuilder.reset().failWithCodeNoParameterAddedToErrorCode( >> >> "request.is.not.in.submitted.and.pending.state", >> >> "Loan reschedule request rejection is not allowed. " >> >> + "Loan reschedule request is not in submitted >> and pending approval state."); >> >> } >> >> >> >> if (!dataValidationErrors.isEmpty()) { throw new >> PlatformApiDataValidationException(dataValidationErrors); } >> >> } >> >> } >> >> >> >> >> >> On Sat, Apr 2, 2016 at 5:14 AM, Adi Raju <adi.r...@confluxtechnologies.com> >> wrote: >> >> Hi Robert, >> >> Please send either a pull request or share your fork and branch details for >> us to have a look at code changes. Also if possible send us a short >> description of your technical solution. >> >> Regards, >> Adi >> >> On 01-Apr-2016 7:00 pm, "Zack Wizglobal" <z...@wizglobal.co.ke> wrote: >> >> Hi Ed, >> >> >> >> Thanks for the call. Robert copied here is our key developer for the Mifos >> System and he will be able to answer all your questions. >> >> Robert here we have a team from Mifos who would want to know how we >> implemented the loan reschedule. >> >> >> >> -- >> Kind Regards, >> >> Zack Githinji >> Systems Developer >> Wizglobal Kenya >> P.O. BOX 21373-00100 >> Nairobi. >> Mobile: +254 (0) 722 649199 >> >> z...@wizglobal.co.ke >> www.wizglobal.co.ke >> >> >> >> On 24 Mar 2016, at 21:06, Andris Kaneps <akan...@mtgcapital.ch> wrote: >> >> >> >> Dear Zack, Ed, Adi and Pramod, >> >> As you may know Mifos currently has a problem with rescheduling function - >> we can't reschedule a loan more than once and its impossible to reschedule a >> loan if any repayment has been entered. >> >> This function is crucial for Watu Credit loan product so we have >> commissioned a Nairobi based software developer Wizglobal (represented by >> Zack Githinji) to fix the problem. The fix currently is complete and we have >> done preliminary testing. >> >> As discussed with Ed, we would like to contribute the fix to Mifos community >> so that the problem is solved in next Mifos update. >> >> So Adi and Pramod, could you please get in touch directly with Zack to >> discuss all the technical details? >> >> Kind regards, >> >> Andris Kaneps >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> -- >> >> Ed Cable >> >> Director of Community Programs, Mifos Initiative >> >> edca...@mifos.org | Skype: edcable | Mobile: +1.484.477.8649 >> >> >> >> Collectively Creating a World of 3 Billion Maries | http://mifos.org >> >> >> >> >> >> >> >> >> >> >> -- >> >> Ed Cable >> >> Director of Community Programs, Mifos Initiative >> >> edca...@mifos.org | Skype: edcable | Mobile: +1.484.477.8649 >> >> >> >> Collectively Creating a World of 3 Billion Maries | http://mifos.org >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> -- >> >> Ed Cable >> >> Director of Community Programs, Mifos Initiative >> >> edca...@mifos.org | Skype: edcable | Mobile: +1.484.477.8649 >> >> >> >> Collectively Creating a World of 3 Billion Maries | http://mifos.org >> > > > > -- > This e-mail was sent to you by MTG Capital Management,any attached documents > may contain privileged and confidential information and should only be read > by those persons to whom this e-mail is addressed. Use by other than intended > recipients is prohibited. If you are not the addressee, you must not copy, > distribute, disclose or use any of the information in it. If you have > received it in error, please delete it and immediately notify the sender. MTG > Capital Management reserves the right to monitor all e-mail messages passing > through its network. As we cannot guarantee the genuineness,accuracy or > completeness of the information contained in this message, the statements set > forth are not legally binding.