From df8a2eb4a2c03dc849fe3760ed0ae4b204211bd4 Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Mon, 20 May 2013 13:14:40 +0100 Subject: [PATCH 1/7] update release numbers. --- api-docs/apiLive.htm | 2 +- mifosng-provider/gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 88e73924c..95527acb9 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -90,7 +90,7 @@
- +

Overview

diff --git a/mifosng-provider/gradle.properties b/mifosng-provider/gradle.properties index aed354c42..d5e929497 100644 --- a/mifosng-provider/gradle.properties +++ b/mifosng-provider/gradle.properties @@ -1 +1 @@ -releaseVersion=1.1.2.RELEASE +releaseVersion=1.1.3.RELEASE From 6a6f576a614c10598852430f815a818e13865bff Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Mon, 20 May 2013 14:32:53 +0100 Subject: [PATCH 2/7] MIFOSX-367: fix retrieve all filtered by loan account no. --- .../loanaccount/service/LoanReadPlatformServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 573c37e3b..8bb8a7259 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -206,7 +206,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { String sqlQueryCriteria = searchParameters.getSqlSearch(); if (StringUtils.isNotBlank(sqlQueryCriteria)) { sqlQueryCriteria = sqlQueryCriteria.replaceAll("accountNo", "l.account_no"); - sqlBuilder.append(" where (").append(sqlQueryCriteria).append(")"); + sqlBuilder.append(" and (").append(sqlQueryCriteria).append(")"); } if (StringUtils.isNotBlank(searchParameters.getExternalId())) { From 5b53c7f8ed08785296bedcec0115dd0fdd602f8e Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Mon, 20 May 2013 15:29:30 +0100 Subject: [PATCH 3/7] MIFOSX-369: validate client activation date on activate api also. --- .../portfolio/client/domain/Client.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java index dde06235b..5c76de2e4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java @@ -168,7 +168,14 @@ public final class Client extends AbstractPersistable { } deriveDisplayName(); - validateNameParts(); + validate(); + } + + private void validate() { + final List dataValidationErrors = new ArrayList(); + validateNameParts(dataValidationErrors); + validateActivationDate(dataValidationErrors); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } public boolean isAccountNumberRequiresAutoGeneration() { @@ -218,6 +225,8 @@ public final class Client extends AbstractPersistable { this.activationDate = activationLocalDate.toDate(); this.status = ClientStatus.ACTIVE.getValue(); + + validate(); } public boolean isNotActive() { @@ -286,8 +295,6 @@ public final class Client extends AbstractPersistable { this.fullname = newValue; } - validateNameParts(); - final String dateFormatAsInput = command.dateFormat(); final String localeAsInput = command.locale(); @@ -301,14 +308,14 @@ public final class Client extends AbstractPersistable { this.activationDate = newValue.toDate(); } + validate(); + deriveDisplayName(); return actualChanges; } - private void validateNameParts() { - final List dataValidationErrors = new ArrayList(); - + private void validateNameParts(final List dataValidationErrors) { final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("client"); if (StringUtils.isNotBlank(this.fullname)) { @@ -331,7 +338,9 @@ public final class Client extends AbstractPersistable { baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(this.lastname).notBlank() .notExceedingLengthOf(50); } + } + private void validateActivationDate(final List dataValidationErrors) { if (this.activationDate != null) { if (office.isOpeningDateAfter(getActivationLocalDate())) { final String defaultUserMessage = "Client activation date cannot be a date before the office opening date."; @@ -341,8 +350,6 @@ public final class Client extends AbstractPersistable { dataValidationErrors.add(error); } } - - if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } private void deriveDisplayName() { From af8a0b4209b5e9a0bc361879b4898cf42266e74e Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Tue, 21 May 2013 13:42:56 +0100 Subject: [PATCH 4/7] MIFOSX-379: check for invalid currencies when submitting new loan application. --- .../loanaccount/domain/LoanCharge.java | 37 ++----------------- .../loanaccount/service/LoanAssembler.java | 7 ++++ .../loanproduct/domain/LoanProduct.java | 4 ++ .../domain/LoanProductRelatedDetail.java | 4 ++ 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java index 454c8e937..1ebc1d960 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java @@ -88,21 +88,10 @@ public class LoanCharge extends AbstractPersistable { public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeDefinition, final JsonCommand command) { final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount"); - // final Integer chargeTimeType = - // command.integerValueOfParameterNamed("chargeTimeType"); - // final Integer chargeCalculationType = - // command.integerValueOfParameterNamed("chargeCalculationType"); final LocalDate dueDate = command.localDateValueOfParameterNamed("dueDate"); ChargeTimeType chargeTime = null; - // if (chargeTimeType != null) { - // chargeTime = ChargeTimeType.fromInt(chargeTimeType); - // } ChargeCalculationType chargeCalculation = null; - // if (chargeCalculationType != null) { - // chargeCalculation = - // ChargeCalculationType.fromInt(chargeCalculationType); - // } return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation, dueDate); } @@ -286,28 +275,6 @@ public class LoanCharge extends AbstractPersistable { final String dateFormatAsInput = command.dateFormat(); final String localeAsInput = command.locale(); - // final String chargeTimeParamName = "chargeTime"; - // if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, - // this.chargeTime)) { - // final Integer newValue = - // command.integerValueOfParameterNamed(chargeTimeParamName); - // actualChanges.put(chargeTimeParamName, newValue); - // actualChanges.put("locale", localeAsInput); - // this.chargeTime = ChargeTimeType.fromInt(newValue).getValue(); - // } - // - // final String chargeCalculationParamName = "chargeCalculation"; - // if - // (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, - // this.chargeCalculation)) { - // final Integer newValue = - // command.integerValueOfParameterNamed(chargeCalculationParamName); - // actualChanges.put(chargeCalculationParamName, newValue); - // actualChanges.put("locale", localeAsInput); - // this.chargeCalculation = - // ChargeCalculationType.fromInt(newValue).getValue(); - // } - final String dueDateParamName = "dueDate"; if (command.isChangeInLocalDateParameterNamed(dueDateParamName, getDueLocalDate())) { final String valueAsInput = command.stringValueOfParameterNamed(dueDateParamName); @@ -511,6 +478,10 @@ public class LoanCharge extends AbstractPersistable { return this.charge.getName(); } + public String currencyCode() { + return this.charge.getCurrencyCode(); + } + @Override public boolean equals(final Object obj) { if (obj == null) { return false; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java index a403fb8c0..21d649072 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java @@ -45,6 +45,7 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanSchedule import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct; import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository; import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy; +import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException; import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException; import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations; import org.mifosplatform.useradministration.domain.AppUser; @@ -123,6 +124,12 @@ public class LoanAssembler { } final Set collateral = this.loanCollateralAssembler.fromParsedJson(element); final Set loanCharges = this.loanChargeAssembler.fromParsedJson(element); + for (LoanCharge loanCharge : loanCharges) { + if (!loanProduct.hasCurrencyCodeOf(loanCharge.currencyCode())) { + final String errorMessage = "Charge and Loan must have the same currency."; + throw new InvalidCurrencyException("loanCharge", "attach.to.loan", errorMessage); + } + } final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element); final LoanSchedule loanSchedule = this.loanScheduleAssembler.fromJson(element, inArrearsTolerance); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java index c6be7c80a..821d7554b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProduct.java @@ -165,6 +165,10 @@ public class LoanProduct extends AbstractPersistable { this.transactionProcessingStrategy = strategy; } + public boolean hasCurrencyCodeOf(final String currencyCode) { + return this.loanProductRelatedDetail.hasCurrencyCodeOf(currencyCode); + } + public boolean update(final List newProductCharges) { if (newProductCharges == null) return false; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProductRelatedDetail.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProductRelatedDetail.java index 8993b2408..94d4a237e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProductRelatedDetail.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/LoanProductRelatedDetail.java @@ -297,4 +297,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche private void updateInterestRateDerivedFields(final AprCalculator aprCalculator) { this.annualNominalInterestRate = aprCalculator.calculateFrom(this.interestPeriodFrequencyType, this.nominalInterestRatePerPeriod); } + + public boolean hasCurrencyCodeOf(final String currencyCode) { + return this.currency.getCode().equalsIgnoreCase(currencyCode); + } } \ No newline at end of file From fb8fd9c91f5126e20c434dcdd53ca87cb57a70fc Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Tue, 21 May 2013 16:50:13 +0100 Subject: [PATCH 5/7] cherry pick of MIFOSX-368: fix error message being returned based on parameters being passed to api. --- .../client/data/ClientDataValidator.java | 175 ++++++++++++++++-- .../portfolio/client/domain/Client.java | 3 +- 2 files changed, 161 insertions(+), 17 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java index 23d2e90aa..af350e5a5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/data/ClientDataValidator.java @@ -50,17 +50,6 @@ public final class ClientDataValidator { final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); - if (fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) { - final String accountNo = fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element); - baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20); - } - - if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) { - final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element); - baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).ignoreIfNull() - .notExceedingLengthOf(100); - } - final Long officeId = fromApiJsonHelper.extractLongNamed(ClientApiConstants.officeIdParamName, element); baseDataValidator.reset().parameter(ClientApiConstants.officeIdParamName).value(officeId).notNull().integerGreaterThanZero(); @@ -69,6 +58,57 @@ public final class ClientDataValidator { baseDataValidator.reset().parameter(ClientApiConstants.groupIdParamName).value(groupId).notNull().integerGreaterThanZero(); } + if (fromApiJsonHelper.parameterExists(ClientApiConstants.accountNoParamName, element)) { + final String accountNo = fromApiJsonHelper.extractStringNamed(ClientApiConstants.accountNoParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20); + } + + if (isFullnameProvided(element) || isIndividualNameProvided(element)) { + + // 1. No individual name part provided and fullname provided + if (isFullnameProvided(element) && !isIndividualNameProvided(element)) { + fullnameCannotBeBlank(element, baseDataValidator); + } + + // 2. no fullname provided and individual name part provided + if (isIndividualNameProvided(element) && !isFullnameProvided(element)) { + validateRequiredIndividualNamePartsExist(element, baseDataValidator); + } + + // 3. both provided + if (isFullnameProvided(element) && isIndividualNameProvided(element)) { + validateIndividualNamePartsCannotBeUsedWithFullname(element, baseDataValidator); + } + } else { + + if (isFullnameParameterPassed(element) || isIndividualNamePartParameterPassed(element)) { + + // 1. No individual name parameter passed and fullname passed + if (isFullnameParameterPassed(element) && !isIndividualNamePartParameterPassed(element)) { + fullnameCannotBeBlank(element, baseDataValidator); + } + + // 2. no fullname passed and individual name part passed + if (isIndividualNamePartParameterPassed(element) && !isFullnameParameterPassed(element)) { + validateRequiredIndividualNamePartsExist(element, baseDataValidator); + } + + // 3. both parameter types passed + if (isFullnameParameterPassed(element) && isIndividualNamePartParameterPassed(element)) { + baseDataValidator.reset().parameter(ClientApiConstants.idParamName).failWithCode(".no.name.details.passed"); + } + + } else { + baseDataValidator.reset().parameter(ClientApiConstants.idParamName).failWithCode(".no.name.details.passed"); + } + } + + if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) { + final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).ignoreIfNull() + .notExceedingLengthOf(100); + } + final Boolean active = fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element); if (active != null) { if (active.booleanValue()) { @@ -82,6 +122,71 @@ public final class ClientDataValidator { throwExceptionIfValidationWarningsExist(dataValidationErrors); } + private void validateIndividualNamePartsCannotBeUsedWithFullname(final JsonElement element, final DataValidatorBuilder baseDataValidator) { + final String firstnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element); + if (StringUtils.isNotBlank(firstnameParam)) { + final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam) + .mustBeBlankWhenParameterProvided(ClientApiConstants.firstnameParamName, firstnameParam); + } + + final String middlenameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element); + if (StringUtils.isNotBlank(middlenameParam)) { + final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam) + .mustBeBlankWhenParameterProvided(ClientApiConstants.middlenameParamName, middlenameParam); + } + + final String lastnameParamName = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element); + if (StringUtils.isNotBlank(lastnameParamName)) { + final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam) + .mustBeBlankWhenParameterProvided(ClientApiConstants.lastnameParamName, lastnameParamName); + } + } + + private void validateRequiredIndividualNamePartsExist(final JsonElement element, final DataValidatorBuilder baseDataValidator) { + final String firstnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.firstnameParamName).value(firstnameParam).notBlank() + .notExceedingLengthOf(50); + + final String middlenameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.middlenameParamName).value(middlenameParam).ignoreIfNull() + .notExceedingLengthOf(50); + + final String lastnameParamName = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(lastnameParamName).notBlank() + .notExceedingLengthOf(50); + } + + private void fullnameCannotBeBlank(final JsonElement element, final DataValidatorBuilder baseDataValidator) { + final String fullnameParam = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.fullnameParamName).value(fullnameParam).notBlank().notExceedingLengthOf(100); + } + + private boolean isIndividualNamePartParameterPassed(final JsonElement element) { + return fromApiJsonHelper.parameterExists(ClientApiConstants.firstnameParamName, element) + || fromApiJsonHelper.parameterExists(ClientApiConstants.middlenameParamName, element) + || fromApiJsonHelper.parameterExists(ClientApiConstants.lastnameParamName, element); + } + + private boolean isFullnameParameterPassed(final JsonElement element) { + return fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element); + } + + private boolean isIndividualNameProvided(final JsonElement element) { + final String firstname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.firstnameParamName, element); + final String middlename = fromApiJsonHelper.extractStringNamed(ClientApiConstants.middlenameParamName, element); + final String lastname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.lastnameParamName, element); + + return StringUtils.isNotBlank(firstname) || StringUtils.isNotBlank(middlename) || StringUtils.isNotBlank(lastname); + } + + private boolean isFullnameProvided(final JsonElement element) { + final String fullname = fromApiJsonHelper.extractStringNamed(ClientApiConstants.fullnameParamName, element); + return StringUtils.isNotBlank(fullname); + } + public void validateForUpdate(final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } @@ -102,10 +207,44 @@ public final class ClientDataValidator { baseDataValidator.reset().parameter(ClientApiConstants.accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20); } - if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) { - atLeastOneParameterPassedForUpdate = true; - final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element); - baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).notExceedingLengthOf(100); + if (isFullnameProvided(element) || isIndividualNameProvided(element)) { + + // 1. No individual name part provided and fullname provided + if (isFullnameProvided(element) && !isIndividualNameProvided(element)) { + fullnameCannotBeBlank(element, baseDataValidator); + } + + // 2. no fullname provided and individual name part provided + if (isIndividualNameProvided(element) && !isFullnameProvided(element)) { + validateRequiredIndividualNamePartsExist(element, baseDataValidator); + } + + // 3. both provided + if (isFullnameProvided(element) && isIndividualNameProvided(element)) { + validateIndividualNamePartsCannotBeUsedWithFullname(element, baseDataValidator); + } + } else { + + if (isFullnameParameterPassed(element) || isIndividualNamePartParameterPassed(element)) { + + // 1. No individual name parameter passed and fullname passed + if (isFullnameParameterPassed(element) && !isIndividualNamePartParameterPassed(element)) { + fullnameCannotBeBlank(element, baseDataValidator); + } + + // 2. no fullname passed and individual name part passed + if (isIndividualNamePartParameterPassed(element) && !isFullnameParameterPassed(element)) { + validateRequiredIndividualNamePartsExist(element, baseDataValidator); + } + + // 3. both parameter types passed + if (isFullnameParameterPassed(element) && isIndividualNamePartParameterPassed(element)) { + baseDataValidator.reset().parameter(ClientApiConstants.idParamName).failWithCode(".no.name.details.passed"); + } + + } else { + baseDataValidator.reset().parameter(ClientApiConstants.idParamName).failWithCode(".no.name.details.passed"); + } } if (fromApiJsonHelper.parameterExists(ClientApiConstants.fullnameParamName, element)) { @@ -124,6 +263,12 @@ public final class ClientDataValidator { atLeastOneParameterPassedForUpdate = true; } + if (fromApiJsonHelper.parameterExists(ClientApiConstants.externalIdParamName, element)) { + atLeastOneParameterPassedForUpdate = true; + final String externalId = fromApiJsonHelper.extractStringNamed(ClientApiConstants.externalIdParamName, element); + baseDataValidator.reset().parameter(ClientApiConstants.externalIdParamName).value(externalId).notExceedingLengthOf(100); + } + final Boolean active = fromApiJsonHelper.extractBooleanNamed(ClientApiConstants.activeParamName, element); if (active != null) { if (active.booleanValue()) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java index 5c76de2e4..81f7bbc4e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/domain/Client.java @@ -328,9 +328,8 @@ public final class Client extends AbstractPersistable { baseDataValidator.reset().parameter(ClientApiConstants.lastnameParamName).value(this.lastname) .mustBeBlankWhenParameterProvided(ClientApiConstants.fullnameParamName, this.fullname); - } + } else { - if (StringUtils.isBlank(this.fullname)) { baseDataValidator.reset().parameter(ClientApiConstants.firstnameParamName).value(this.firstname).notBlank() .notExceedingLengthOf(50); baseDataValidator.reset().parameter(ClientApiConstants.middlenameParamName).value(this.middlename).ignoreIfNull() From 81e02c497d13acdfebd5fa19f419e5e2569c2dba Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Wed, 22 May 2013 11:20:02 +0200 Subject: [PATCH 6/7] update readme for 1.1.3 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 395829e13..cab5f0486 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The mifos-platform (project named 'Mifos X') has reached public release versi That means there is a published and stable API. This API is documented in the api-docs under Full API Matrix. -Latest stable release: mifosplatform-1.1.2 +Latest stable release: mifosplatform-1.1.3 License ============= From 90427e7c0b5224e1d041763fe7387c13a15ec0c0 Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Wed, 22 May 2013 11:22:52 +0200 Subject: [PATCH 7/7] udpate changelog 1.1.3 release --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6b15bf5f..f2b0f8c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ See VERSIONING (https://github.com/openMF/mifosx/blob/master/VERSIONING.md) for Releases =============== +1. 22 May 2013 - 1.1.3.RELEASE 1. 19 May 2013 - 1.1.2.RELEASE 1. 12 May 2013 - 1.1.1.RELEASE 1. 09 May 2013 - 1.1.0.RELEASE @@ -19,6 +20,23 @@ Releases 1. 05 April 2013 - 0.11.1.beta 1. 05 April 2013 - 0.11.0.beta +1.1.3.RELEASE +============= +Bug Release + +Bug + - [MIFOSX-367] - Not able to figure out the loan details, if proper Account no. is entered in Search text field + - [MIFOSX-368] - To add a new client of client type "corporate" error message is showing "First name is mandatory" and Last name is mandatory" than Full name or Business name. + - [MIFOSX-369] - Client is getting activated before the date of opening of the related office. + - [MIFOSX-379] - For applying "New Loan Application", if loan product currency is in US Dollars the charges applied is in Indian Rupees also, it is accepting. + - [MIFOSX-380] - Smart search on Gaurantors is broken after change of clients api to paginated response + +Improvement + + - [MIFOSX-359] - Edit functionality for "Code Values" not intuitive (and inconsistent with rest of the User Interface) + - [MIFOSX-360] - Inconsistent verbiage for "Cancel" button in "Add/Edit Code Value: " page + - [MIFOSX-363] - Background is broken in the middle of the table in "Client Loans Listing" page + 1.1.2.RELEASE ============= Bug Release