diff --git a/mifosng-db/patches/patch-0004-add-auto-primary_key_to_m_loan_charge.sql b/mifosng-db/patches/patch-0004-add-auto-primary_key_to_m_loan_charge.sql new file mode 100644 index 000000000..8d5a485f0 --- /dev/null +++ b/mifosng-db/patches/patch-0004-add-auto-primary_key_to_m_loan_charge.sql @@ -0,0 +1,13 @@ +DROP TABLE `m_loan_charge`; +CREATE TABLE `m_loan_charge` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `loan_id` bigint(20) NOT NULL, + `charge_id` bigint(20) NOT NULL, + `charge_time_enum` smallint(5) NOT NULL, + `charge_calculation_enum` smallint(5) NOT NULL, + `amount` decimal(19,6) NOT NULL, + PRIMARY KEY (`id`), + KEY `charge_id` (`charge_id`), + CONSTRAINT `m_loan_charge_ibfk_1` FOREIGN KEY (`charge_id`) REFERENCES `m_charge` (`id`), + CONSTRAINT `m_loan_charge_ibfk_2` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/DataValidatorBuilder.java b/mifosng-provider/src/main/java/org/mifosng/platform/DataValidatorBuilder.java index ea4f09113..e2b66886d 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/DataValidatorBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/DataValidatorBuilder.java @@ -201,6 +201,23 @@ public class DataValidatorBuilder { } return this; } + + public DataValidatorBuilder longGreaterThanZero() { + if (value == null && ignoreNullValue) { + return this; + } + + if (value != null) { + Long number = Long.valueOf(value.toString()); + if (number < 1) { + StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter).append(".not.greater.than.zero"); + StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must be greater than 0."); + ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(), parameter, number, 0); + dataValidationErrors.add(error); + } + } + return this; + } public DataValidatorBuilder arrayNotEmpty() { if (value == null && ignoreNullValue) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java index e1b77ace0..ece790d28 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java @@ -33,6 +33,7 @@ import org.mifosng.platform.api.data.EnumOptionData; import org.mifosng.platform.api.data.FundData; import org.mifosng.platform.api.data.LoanAccountData; import org.mifosng.platform.api.data.LoanBasicDetailsData; +import org.mifosng.platform.api.data.LoanChargeData; import org.mifosng.platform.api.data.LoanPermissionData; import org.mifosng.platform.api.data.LoanProductLookup; import org.mifosng.platform.api.data.LoanRepaymentTransactionData; @@ -148,12 +149,9 @@ public class LoansApiResource { ChargeData chargeTemplate = this.chargeReadPlatformService.retrieveLoanChargeTemplate(); LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService.retrieveClientAndProductDetails(clientId, productId); - if (loanBasicDetails.getCharges() != null) { - chargeOptions.removeAll(loanBasicDetails.getCharges()); - } final boolean convenienceDataRequired = false; - Collection charges = loanBasicDetails.getCharges(); + Collection charges = loanBasicDetails.getCharges(); Collection allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.getClientOfficeId()); @@ -185,7 +183,7 @@ public class LoansApiResource { Collection loanRepayments = null; LoanScheduleData repaymentSchedule = null; LoanPermissionData permissions = null; - Collection charges = null; + Collection charges = null; boolean convenienceDataRequired = false; final Set associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); @@ -250,9 +248,6 @@ public class LoansApiResource { fundOptions = this.fundReadPlatformService.retrieveAllFunds(); repaymentStrategyOptions = this.dropdownReadPlatformService.retreiveTransactionProcessingStrategies(); chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(); - if (charges != null) { - chargeOptions.removeAll(charges); - } allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.getClientOfficeId()); chargeTemplate = this.chargeReadPlatformService.retrieveLoanChargeTemplate(); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanChargeCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanChargeCommand.java index e62ce3bf6..0c4d22e9f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanChargeCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanChargeCommand.java @@ -6,6 +6,7 @@ import java.util.Set; public class LoanChargeCommand { private final Long id; + private final Long chargeId; private final BigDecimal amount; private final Integer chargeTimeType; @@ -13,10 +14,11 @@ public class LoanChargeCommand { private final Set modifiedParameters; - public LoanChargeCommand(final Set modifiedParameters, final Long id, final BigDecimal amount, - final Integer chargeTimeType, final Integer chargeCalculationType) { + public LoanChargeCommand(final Set modifiedParameters, final Long id, final Long chargeId, + final BigDecimal amount, final Integer chargeTimeType, final Integer chargeCalculationType) { this.modifiedParameters = modifiedParameters; this.id = id; + this.chargeId = chargeId; this.amount = amount; this.chargeTimeType = chargeTimeType; this.chargeCalculationType = chargeCalculationType; @@ -26,6 +28,10 @@ public class LoanChargeCommand { return id; } + public Long getChargeId() { + return chargeId; + } + public BigDecimal getAmount() { return amount; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java index 108a3d8d7..38b9a45fd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java @@ -54,7 +54,7 @@ public class LoanAccountData { // associations private final LoanScheduleData repaymentSchedule; private final Collection loanRepayments; - private final Collection charges; + private final Collection charges; private final LoanPermissionData permissions; private final LoanConvenienceData convenienceData; @@ -78,7 +78,7 @@ public class LoanAccountData { final LoanScheduleData repaymentSchedule, final Collection loanRepayments, final LoanPermissionData permissions, - final Collection charges, + final Collection charges, final Collection productOptions, final Collection termFrequencyTypeOptions, final Collection repaymentFrequencyTypeOptions, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java index 2dbf25412..e832d00b3 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanBasicDetailsData.java @@ -1,6 +1,7 @@ package org.mifosng.platform.api.data; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Collection; import org.joda.time.DateTime; @@ -53,7 +54,7 @@ public class LoanBasicDetailsData { private final LocalDate expectedMaturityDate; private final LocalDate lifeCycleStatusDate; - private final Collection charges; + private final Collection charges; public static LoanBasicDetailsData populateForNewLoanCreation(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate, final Long clientOfficeId) { @@ -64,6 +65,12 @@ public class LoanBasicDetailsData { final Integer termFrequency = product.getNumberOfRepayments() * product.getRepaymentEvery(); final EnumOptionData termPeriodFrequencyType = product.getRepaymentFrequencyType(); + final Collection charges = new ArrayList(); + for (ChargeData charge : product.getCharges()){ + charges.add(new LoanChargeData(null, charge.getId(), charge.getName(), charge.getCurrency(), + charge.getAmount(), charge.getChargeTimeType(), charge.getChargeCalculationType())); + } + return new LoanBasicDetailsData( loanAccount.clientId, loanAccount.clientName, loanAccount.clientOfficeId, product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), @@ -71,7 +78,7 @@ public class LoanBasicDetailsData { termFrequency, termPeriodFrequencyType, product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), product.getTransactionProcessingStrategyId(), product.getAmortizationType(), product.getInterestRatePerPeriod(), product.getInterestRateFrequencyType(), product.getInterestType(), product.getInterestCalculationPeriodType(), - loanAccount.expectedDisbursementDate, product.getCharges()); + loanAccount.expectedDisbursementDate, charges); } private LoanBasicDetailsData( @@ -89,7 +96,7 @@ public class LoanBasicDetailsData { final EnumOptionData interestRateFrequencyType, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType, - final LocalDate expectedDisbursementDate, final Collection charges) { + final LocalDate expectedDisbursementDate, final Collection charges) { this.id = null; this.externalId = null; this.clientId = clientId; @@ -219,7 +226,7 @@ public class LoanBasicDetailsData { final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, final Integer transactionStrategyId, - final Collection charges, + final Collection charges, final Long loanOfficerId, String loanOfficerName) { this.id = id; this.externalId = externalId; @@ -490,7 +497,7 @@ public class LoanBasicDetailsData { return transactionStrategyId; } - public Collection getCharges() { + public Collection getCharges() { return charges; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanChargeData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanChargeData.java new file mode 100644 index 000000000..01ab3eaa6 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanChargeData.java @@ -0,0 +1,58 @@ +package org.mifosng.platform.api.data; + +import java.math.BigDecimal; + +/** + * Immutable data object for loan charge data. + */ +public class LoanChargeData { + + private final Long id; + private final Long chargeId; + + private final String name; + private final CurrencyData currency; + + private final BigDecimal amount; + private final EnumOptionData chargeTimeType; + private final EnumOptionData chargeCalculationType; + + public LoanChargeData(Long id, Long chargeId, String name, CurrencyData currency, BigDecimal amount, + EnumOptionData chargeTimeType, EnumOptionData chargeCalculationType) { + this.id = id; + this.chargeId = chargeId; + this.name = name; + this.currency = currency; + this.amount = amount; + this.chargeTimeType = chargeTimeType; + this.chargeCalculationType = chargeCalculationType; + } + + public Long getId() { + return id; + } + + public Long getChargeId() { + return chargeId; + } + + public String getName() { + return name; + } + + public CurrencyData getCurrency() { + return currency; + } + + public BigDecimal getAmount() { + return amount; + } + + public EnumOptionData getChargeTimeType() { + return chargeTimeType; + } + + public EnumOptionData getChargeCalculationType() { + return chargeCalculationType; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index bbc489b23..9591d5d8f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -497,25 +497,19 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { charges = new LoanChargeCommand[array.size()]; for (int i=0; i chargeRequestMap = gsonConverter.fromJson(loanCharge, typeOfMap); + if (requestMap.containsKey("locale")){ + chargeRequestMap.put("locale", requestMap.get("locale")); + } Set chargeModifiedParameters = new HashSet(); - Long id = loanCharge.get("id").getAsLong(); - BigDecimal amount = null; - Integer chargeTimeType = null; - Integer chargeCalculationType = null; - if (loanCharge.has("amount")){ - chargeModifiedParameters.add("amount"); - amount = convertFrom(loanCharge.get("amount").getAsString(), "amount", extractLocaleValue(requestMap)); - } - if (loanCharge.has("chargeTimeType")){ - chargeModifiedParameters.add("chargeTimeType"); - chargeTimeType = loanCharge.get("chargeTimeType").getAsInt(); - } - if (loanCharge.has("chargeCalculationType")){ - chargeModifiedParameters.add("chargeCalculationType"); - chargeCalculationType = loanCharge.get("chargeCalculationType").getAsInt(); - } - charges[i] = new LoanChargeCommand(chargeModifiedParameters, id, amount, chargeTimeType, chargeCalculationType); + Long chargeId = extractLongParameter("chargeId", chargeRequestMap, chargeModifiedParameters); + BigDecimal amount = extractBigDecimalParameter("amount", chargeRequestMap, chargeModifiedParameters); + Integer chargeTimeType = extractIntegerParameter("chargeTimeType", chargeRequestMap, chargeModifiedParameters); + Integer chargeCalculationType = extractIntegerParameter("chargeCalculationType", chargeRequestMap, chargeModifiedParameters); + + charges[i] = new LoanChargeCommand(chargeModifiedParameters, null, chargeId, amount, + chargeTimeType, chargeCalculationType); } } } @@ -709,7 +703,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } return paramValue; } - + private boolean extractBooleanParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { boolean paramValue = false; String paramValueAsString = null; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformService.java index aaf650c6e..0cdc86628 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformService.java @@ -1,6 +1,7 @@ package org.mifosng.platform.charge.service; import org.mifosng.platform.api.data.ChargeData; +import org.mifosng.platform.api.data.LoanChargeData; import java.util.Collection; @@ -16,7 +17,7 @@ public interface ChargeReadPlatformService { Collection retrieveLoanProductCharges(Long loanProductId); - Collection retrieveLoanCharges(Long loanId); + Collection retrieveLoanCharges(Long loanId); ChargeData retrieveLoanChargeTemplate(); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformServiceImpl.java index e2dce512c..c9d95d19a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/charge/service/ChargeReadPlatformServiceImpl.java @@ -3,6 +3,7 @@ package org.mifosng.platform.charge.service; import org.mifosng.platform.api.data.ChargeData; import org.mifosng.platform.api.data.CurrencyData; import org.mifosng.platform.api.data.EnumOptionData; +import org.mifosng.platform.api.data.LoanChargeData; import org.mifosng.platform.charge.domain.ChargeAppliesTo; import org.mifosng.platform.charge.domain.ChargeCalculationType; import org.mifosng.platform.charge.domain.ChargeTimeType; @@ -106,10 +107,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService } @Override - public Collection retrieveLoanCharges(Long loanId) { + public Collection retrieveLoanCharges(Long loanId) { this.context.authenticatedUser(); - ChargeMapper rm = new ChargeMapper(); + LoanChargeMapper rm = new LoanChargeMapper(); String sql = "select " + rm.loanChargeSchema() + " where c.is_deleted=0 and lc.loan_id=?"; @@ -159,15 +160,7 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService return chargeSchema() + " join m_product_loan_charge plc on plc.charge_id = c.id"; } - public String loanChargeSchema(){ - return "c.id as id, c.name as name, lc.amount as amount, c.currency_code as currencyCode, " + - "c.charge_applies_to_enum as chargeAppliesTo, lc.charge_time_enum as chargeTime, " + - "lc.charge_calculation_enum as chargeCalculation, is_active as active, oc.name as currencyName, " + - "oc.decimal_places as currencyDecimalPlaces, oc.display_symbol as currencyDisplaySymbol, " + - "oc.internationalized_name_code as currencyNameCode from m_charge c " + - "join m_organisation_currency oc on c.currency_code = oc.code " + - "join m_loan_charge lc on lc.charge_id = c.id "; - } + @Override public ChargeData mapRow(ResultSet rs, int rowNum) throws SQLException { @@ -198,4 +191,42 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService return new ChargeData(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType, active); } } + + private static final class LoanChargeMapper implements RowMapper { + + public String loanChargeSchema(){ + return "lc.id as id, c.id as chargeId, c.name as name, lc.amount as amount, c.currency_code as currencyCode, " + + "lc.charge_time_enum as chargeTime, " + + "lc.charge_calculation_enum as chargeCalculation, oc.name as currencyName, " + + "oc.decimal_places as currencyDecimalPlaces, oc.display_symbol as currencyDisplaySymbol, " + + "oc.internationalized_name_code as currencyNameCode from m_charge c " + + "join m_organisation_currency oc on c.currency_code = oc.code " + + "join m_loan_charge lc on lc.charge_id = c.id "; + } + + @Override + public LoanChargeData mapRow(ResultSet rs, int rowNum) throws SQLException { + Long id = rs.getLong("id"); + Long chargeId = rs.getLong("chargeId"); + String name = rs.getString("name"); + BigDecimal amount = rs.getBigDecimal("amount"); + + String currencyCode = rs.getString("currencyCode"); + String currencyName = rs.getString("currencyName"); + String currencyNameCode = rs.getString("currencyNameCode"); + String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); + Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces"); + + CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces, + currencyDisplaySymbol, currencyNameCode); + + int chargeTime = rs.getInt("chargeTime"); + EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime); + + int chargeCalculation = rs.getInt("chargeCalculation"); + EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation); + + return new LoanChargeData(id, chargeId, name, currency, amount, chargeTimeType, chargeCalculationType); + } + } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java index 27ad043a5..6dc59030b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java @@ -1,13 +1,10 @@ package org.mifosng.platform.loan.domain; -import java.io.Serializable; import java.math.BigDecimal; import java.math.RoundingMode; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @@ -16,17 +13,20 @@ import org.mifosng.platform.api.commands.LoanChargeCommand; import org.mifosng.platform.charge.domain.Charge; import org.mifosng.platform.charge.domain.ChargeCalculationType; import org.mifosng.platform.charge.domain.ChargeTimeType; +import org.springframework.data.jpa.domain.AbstractPersistable; @Entity -@IdClass(LoanCharge.LoanChargePK.class) @Table(name = "m_loan_charge") -public class LoanCharge { +public class LoanCharge extends AbstractPersistable { - @Id + @SuppressWarnings("unused") + @ManyToOne(optional = false) + @JoinColumn(name = "loan_id", referencedColumnName = "id", nullable=false) private Loan loan; @SuppressWarnings("unused") - @Id + @ManyToOne(optional = false) + @JoinColumn(name = "charge_id", referencedColumnName = "id", nullable=false) private Charge charge; @Column(name = "amount", scale = 6, precision = 19, nullable = false) @@ -85,20 +85,6 @@ public class LoanCharge { this.chargeCalculation = chargeCalculation; } - public static class LoanChargePK implements Serializable { - @SuppressWarnings("unused") - @Id - @ManyToOne(optional = false) - @JoinColumn(name = "loan_id", referencedColumnName = "id", nullable=false) - private Loan loan; - - @SuppressWarnings("unused") - @Id - @ManyToOne(optional = false) - @JoinColumn(name = "charge_id", referencedColumnName = "id", nullable=false) - private Charge charge; - } - public void update(final Loan loan) { this.loan = loan; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java index 87c0b4758..ca4467580 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanAssembler.java @@ -20,6 +20,7 @@ import org.mifosng.platform.exceptions.ChargeIsNotActiveException; import org.mifosng.platform.exceptions.ChargeNotFoundException; import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.FundNotFoundException; +import org.mifosng.platform.exceptions.InvalidCurrencyException; import org.mifosng.platform.exceptions.LoanProductNotFoundException; import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException; import org.mifosng.platform.exceptions.StaffNotFoundException; @@ -101,7 +102,7 @@ public class LoanAssembler { Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId()); // optionally, see if charges are associated with loan on creation (through loan product or by being directly added) - final Set loanCharges = assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges()); + final Set loanCharges = assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges(), loanProduct.getCurrency().getCode()); Loan loan = Loan.createNew(fund,loanOfficer, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail, loanCharges); loan.setExternalId(command.getExternalId()); @@ -130,13 +131,14 @@ public class LoanAssembler { return loan; } - public Set assembleSetOfLoanCharges(LoanChargeCommand[] chargesPassedAtCreation, Set chargesInheritedFromProduct) { + public Set assembleSetOfLoanCharges(LoanChargeCommand[] chargesPassedAtCreation, + Set chargesInheritedFromProduct, String loanCurrencyCode) { Set loanCharges = new HashSet(); if (!ObjectUtils.isEmpty(chargesPassedAtCreation)) { for (LoanChargeCommand loanChargeCommand : chargesPassedAtCreation) { - Long chargeDefinitionId = loanChargeCommand.getId(); + Long chargeDefinitionId = loanChargeCommand.getChargeId(); Charge chargeDefinition = this.chargeRepository.findOne(chargeDefinitionId); if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(chargeDefinitionId); @@ -145,7 +147,12 @@ public class LoanAssembler { if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(chargeDefinitionId); } - + + if (!loanCurrencyCode.equals(chargeDefinition.getCurrencyCode())){ + String errorMessage = "Charge and Loan must have the same currency."; + throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage); + } + loanCharges.add(LoanCharge.createNew(chargeDefinition, loanChargeCommand)); } } else if (chargesPassedAtCreation == null) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanChargeCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanChargeCommandValidator.java index b88d9e471..9d209674b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanChargeCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanChargeCommandValidator.java @@ -22,6 +22,7 @@ public class LoanChargeCommandValidator { DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); + baseDataValidator.reset().parameter("chargeId").value(command.getChargeId()).notNull().longGreaterThanZero(); baseDataValidator.reset().parameter("amount").value(command.getAmount()).ignoreIfNull().positiveAmount(); baseDataValidator.reset().parameter("chargeTimeType").value(command.getChargeTimeType()).ignoreIfNull().inMinMaxRange(1, 1); baseDataValidator.reset().parameter("chargeCalculationType").value(command.getChargeCalculationType()).ignoreIfNull().inMinMaxRange(1, 4); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java index a65831c24..93b43f595 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -6,11 +6,11 @@ import java.sql.SQLException; import java.util.Collection; import org.joda.time.LocalDate; -import org.mifosng.platform.api.data.ChargeData; import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.CurrencyData; import org.mifosng.platform.api.data.EnumOptionData; import org.mifosng.platform.api.data.LoanBasicDetailsData; +import org.mifosng.platform.api.data.LoanChargeData; import org.mifosng.platform.api.data.LoanPermissionData; import org.mifosng.platform.api.data.LoanProductData; import org.mifosng.platform.api.data.LoanRepaymentPeriodData; @@ -403,7 +403,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { lifeCycleStatusDate = closedOnDate; } - Collection charges = null; + Collection charges = null; return new LoanBasicDetailsData(id, externalId, clientId, clientName, clientOfficeId, loanProductId, loanProductName, loanProductDescription, fundId, fundName, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 46896cbdf..0ac291f82 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -145,7 +145,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf Fund fund = this.loanAssembler.findFundByIdIfProvided(command.getFundId()); Staff loanOfficer = this.loanAssembler.findLoanOfficerByIdIfProvided(command.getLoanOfficerId()); LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId()); - Set charges = this.loanAssembler.assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges()) ; + Set charges = this.loanAssembler.assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges(), loan.getCurrency().getCode()); LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(command.toCalculateLoanScheduleCommand()); loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer);