diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 9a9faf578..88ed51e5e 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -261,6 +261,21 @@ function getBaseURL(docURL) Update a Staff Member + + CHARGEScharges + Create a Charge + List Charges + + + + + + charges/{chargeId} + + Retrieve a Charge + Update a Charge + Delete a Charge + @@ -2703,6 +2718,207 @@ Request Body: + +   +
+
+

Charges

+

Its typical for MFIs to add extra costs to their financial products. There are typically Fees or Penalites.

+

Charges is what we use to model both fees and penalities. For now charges can only be associated with loan products / loans.

+
+
+ +   +
+
+

Create/Define a Charge

+

Define a new charge that can later be associated with loan products or loans.

+
+
+ POST https://Domain Name/api/v1/charges + POST charges +Content-Type: application/json +Request Body: +{ + "name": "Loan service fee", + "chargeAppliesTo": 1, + "currencyCode": "USD", + "locale": "en", + "amount": "230.56", + "chargeTimeType": "1", + "chargeCalculationType": "1" +} + + { + "resourceId": 2 +} + +
+
+ +   +
+
+

Retrieve Charges

+

Returns the list of defined charges.

+

Example Requests:

+
charges
+
+
+ GET https://Domain Name/api/v1/charges + [ + { + "id": 2, + "name": "Loan service fee", + "active": false, + "penalty": false, + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "amount": 230.56, + "chargeTimeType": { + "id": 1, + "code": "chargeTimeType.disbursement", + "value": "Disbursement" + }, + "chargeAppliesTo": { + "id": 1, + "code": "chargeAppliesTo.loan", + "value": "Loan" + }, + "chargeCalculationType": { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + } + }, + { + "id": 1, + "name": "newcharge", + "active": true, + "penalty": false, + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "amount": 456, + "chargeTimeType": { + "id": 1, + "code": "chargeTimeType.disbursement", + "value": "Disbursement" + }, + "chargeAppliesTo": { + "id": 1, + "code": "chargeAppliesTo.loan", + "value": "Loan" + }, + "chargeCalculationType": { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + } + } +] + +
+
+ +   +
+
+

Retrieve a Charge

+

Returns the details of a defined Charge.

+

Example Requests:

+
charges/2
+
+
+ GET https://Domain Name/api/v1/charges/2 + { + "id": 2, + "name": "Loan service fee", + "active": false, + "penalty": false, + "currency": { + "code": "USD", + "name": "US Dollar", + "decimalPlaces": 2, + "displaySymbol": "$", + "nameCode": "currency.USD", + "displayLabel": "US Dollar ($)" + }, + "amount": 230.56, + "chargeTimeType": { + "id": 1, + "code": "chargeTimeType.disbursement", + "value": "Disbursement" + }, + "chargeAppliesTo": { + "id": 1, + "code": "chargeAppliesTo.loan", + "value": "Loan" + }, + "chargeCalculationType": { + "id": 1, + "code": "chargeCalculationType.flat", + "value": "Flat" + } +} + +
+
+ +   +
+
+

Update a Charge

+

Updates the details of a Charge.

+
+
+ PUT https://Domain Name/api/v1/charges/1 + PUT charges/1 +Content-Type: application/json +Request Body: +{ + "name": "Loan service fee(changed)" +} + + { + "resourceId": 2, + "changes": { + "name": "Loan service fee(changed)" + } +} + +
+
+ +   +
+
+

Delete a Charge

+

Deletes a Charge.

+
+
+ DELETE https://Domain Name/api/v1/charges/2 + DELETE charges/2 +Content-Type: application/json + + { + "resourceId": 2 +} + +
+
+  
@@ -3839,6 +4055,21 @@ Request body: Update a Staff Member + + CHARGEScharges + Create a Charge + List Charges + + + + + + charges/{chargeId} + + Retrieve a Charge + Update a Charge + Delete a Charge + DATA TABLEdatatablesList Data Tables datatables/register/{datatable}/{apptable}Register Data Table datatables/deregister/{datatable}Deregister Data Table diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/command/ChargeDefinitionCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/command/ChargeDefinitionCommand.java deleted file mode 100644 index a61cda3a2..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/command/ChargeDefinitionCommand.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.mifosplatform.portfolio.charge.command; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -import org.mifosplatform.infrastructure.core.data.ApiParameterError; -import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; -import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; - -/** - * Immutable data object for creating and modifying defined charges. - */ -public class ChargeDefinitionCommand { - - private final String name; - private final BigDecimal amount; - private final String currencyCode; - private final Integer chargeTimeType; - private final Integer chargeAppliesTo; - private final Integer chargeCalculationType; - private final Boolean penalty; - private final Boolean active; - - public ChargeDefinitionCommand(final String name, final BigDecimal amount, final String currencyCode, final Integer chargeTimeType, - final Integer chargeAppliesTo, final Integer chargeCalculationType, final Boolean penalty, final Boolean active) { - this.name = name; - this.amount = amount; - this.currencyCode = currencyCode; - this.chargeTimeType = chargeTimeType; - this.chargeAppliesTo = chargeAppliesTo; - this.chargeCalculationType = chargeCalculationType; - this.penalty = penalty; - this.active = active; - } - - public String getName() { - return name; - } - - public BigDecimal getAmount() { - return amount; - } - - public String getCurrencyCode() { - return currencyCode; - } - - public Integer getChargeCalculationType() { - return chargeCalculationType; - } - - public Integer getChargeAppliesTo() { - return chargeAppliesTo; - } - - public Integer getChargeTimeType() { - return chargeTimeType; - } - - public boolean isPenalty() { - return penalty; - } - - public boolean isFee() { - return !penalty; - } - - public boolean isActive() { - return active; - } - - public void validateForCreate() { - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); - - baseDataValidator.reset().parameter("name").value(this.name).notBlank().notExceedingLengthOf(100); - baseDataValidator.reset().parameter("amount").value(this.amount).notNull().positiveAmount(); - baseDataValidator.reset().parameter("currencyCode").value(this.currencyCode).notBlank(); - baseDataValidator.reset().parameter("chargeAppliesTo").value(this.chargeAppliesTo).notNull().inMinMaxRange(1, 1); - baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType).notNull().inMinMaxRange(1, 2); - baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculationType).notNull().inMinMaxRange(1, 4); - - if (this.penalty && this.chargeTimeType.equals(Integer.valueOf(1))) { - // FIXME - KW - cannot have penalty charge at time of disbursement - } - - if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); } - } - - public void validateForUpdate() { - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); - - baseDataValidator.reset().parameter("name").value(this.name).ignoreIfNull().notBlank().notExceedingLengthOf(100); - baseDataValidator.reset().parameter("amount").value(this.amount).ignoreIfNull().positiveAmount(); - baseDataValidator.reset().parameter("currencyCode").value(this.currencyCode).ignoreIfNull().notBlank(); - - // FIXME - kw - need to check if parameter exists in update and if so that its not null - baseDataValidator.reset().parameter("chargeAppliesTo").value(this.chargeAppliesTo).ignoreIfNull().notNull().inMinMaxRange(1, 1); - baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType).ignoreIfNull().notNull().inMinMaxRange(1, 2); - baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculationType).ignoreIfNull().notNull() - .inMinMaxRange(1, 4); - - if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); } - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java index eacba74ba..347284e76 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/Charge.java @@ -10,6 +10,7 @@ import javax.persistence.Table; import javax.persistence.UniqueConstraint; import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.portfolio.charge.exception.ChargeDueAtDisbursementCannotBePenaltyException; import org.springframework.data.jpa.domain.AbstractPersistable; @Entity @@ -74,6 +75,7 @@ public class Charge extends AbstractPersistable { this.chargeCalculation = chargeCalculationType.getValue(); this.penalty = penalty; this.active = active; + if (penalty && chargeTime.isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); } } public String getName() { @@ -173,6 +175,8 @@ public class Charge extends AbstractPersistable { actualChanges.put(activeParamName, newValue); this.active = newValue; } + + if (this.penalty && ChargeTimeType.fromInt(this.chargeTime).isTimeOfDisbursement()) { throw new ChargeDueAtDisbursementCannotBePenaltyException(name); } return actualChanges; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java index d44b209fc..6e1442cb8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/domain/ChargeTimeType.java @@ -1,9 +1,9 @@ package org.mifosplatform.portfolio.charge.domain; public enum ChargeTimeType { - - INVALID(0, "chargeTimeType.invalid"), - DISBURSEMENT(1, "chargeTimeType.disbursement"), + + INVALID(0, "chargeTimeType.invalid"), // + DISBURSEMENT(1, "chargeTimeType.disbursement"), // SPECIFIED_DUE_DATE(2, "chargeTimeType.specifiedDueDate"); private final Integer value; @@ -24,17 +24,21 @@ public enum ChargeTimeType { public static ChargeTimeType fromInt(final Integer chargeTime) { ChargeTimeType chargeTimeType = ChargeTimeType.INVALID; - switch(chargeTime){ + switch (chargeTime) { case 1: chargeTimeType = DISBURSEMENT; - break; + break; case 2: chargeTimeType = SPECIFIED_DUE_DATE; - break; + break; default: chargeTimeType = INVALID; - break; + break; } return chargeTimeType; } + + public boolean isTimeOfDisbursement() { + return ChargeTimeType.DISBURSEMENT.getValue().equals(this.value); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeDueAtDisbursementCannotBePenaltyException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeDueAtDisbursementCannotBePenaltyException.java new file mode 100644 index 000000000..2984bbfd6 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeDueAtDisbursementCannotBePenaltyException.java @@ -0,0 +1,14 @@ +package org.mifosplatform.portfolio.charge.exception; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException; + +/** + * {@link AbstractPlatformDomainRuleException} thrown when attempting to crate + * charge of type penalty due at disbursement . + */ +public class ChargeDueAtDisbursementCannotBePenaltyException extends AbstractPlatformDomainRuleException { + + public ChargeDueAtDisbursementCannotBePenaltyException(final String name) { + super("error.msg.charge.due.at.disbursement.cannot.be.penalty", "Charge '" + name + "' is invalid.", name, name); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeIsNotActiveException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeIsNotActiveException.java index 7b3bce9eb..48690dd15 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeIsNotActiveException.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/exception/ChargeIsNotActiveException.java @@ -7,7 +7,7 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRul */ public class ChargeIsNotActiveException extends AbstractPlatformDomainRuleException { - public ChargeIsNotActiveException(final Long id, final String name) { - super("error.msg.charge.is.not.active", "Charge '" + name + "' with identifier " + id + " is not active", name, id); - } + public ChargeIsNotActiveException(final Long id, final String name) { + super("error.msg.charge.is.not.active", "Charge '" + name + "' with identifier " + id + " is not active", name, id); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java index 37efb3a85..8f1daf813 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/serialization/ChargeDefinitionCommandFromApiJsonDeserializer.java @@ -2,16 +2,20 @@ package org.mifosplatform.portfolio.charge.serialization; import java.lang.reflect.Type; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; -import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; -import org.mifosplatform.portfolio.charge.command.ChargeDefinitionCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -19,7 +23,7 @@ import com.google.gson.JsonElement; import com.google.gson.reflect.TypeToken; @Component -public final class ChargeDefinitionCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { +public final class ChargeDefinitionCommandFromApiJsonDeserializer { /** * The parameters supported for this command. @@ -35,27 +39,104 @@ public final class ChargeDefinitionCommandFromApiJsonDeserializer extends Abstra this.fromApiJsonHelper = fromApiJsonHelper; } - @Override - public ChargeDefinitionCommand commandFromApiJson(final String json) { + public void validateForCreate(final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } final Type typeOfMap = new TypeToken>() {}.getType(); fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); + final List dataValidationErrors = new ArrayList(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); + final JsonElement element = fromApiJsonHelper.parse(json); final String name = fromApiJsonHelper.extractStringNamed("name", element); + baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100); + final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element); + baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3); + final BigDecimal amount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element.getAsJsonObject()); + baseDataValidator.reset().parameter("amount").value(amount).notNull().positiveAmount(); - final Integer chargeTimeType = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeTimeType", element); - final Integer chargeAppliesTo = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeAppliesTo", element); - final Integer chargeCalculationType = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeCalculationType", element); + final Integer chargeAppliesTo = fromApiJsonHelper.extractIntegerNamed("chargeAppliesTo", element, Locale.getDefault()); + baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull().inMinMaxRange(1, 1); - final Boolean penalty = fromApiJsonHelper.extractBooleanNamed("penalty", element); - final Boolean active = fromApiJsonHelper.extractBooleanNamed("active", element); + final Integer chargeTimeType = fromApiJsonHelper.extractIntegerNamed("chargeTimeType", element, Locale.getDefault()); + baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull().inMinMaxRange(1, 2); - return new ChargeDefinitionCommand(name, amount, currencyCode, chargeTimeType, chargeAppliesTo, chargeCalculationType, penalty, - active); + final Integer chargeCalculationType = fromApiJsonHelper.extractIntegerNamed("chargeCalculationType", element, Locale.getDefault()); + baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull().inMinMaxRange(1, 4); + + if (fromApiJsonHelper.parameterExists("penalty", element)) { + final Boolean penalty = fromApiJsonHelper.extractBooleanNamed("penalty", element); + baseDataValidator.reset().parameter("penalty").value(penalty).notNull(); + } + + if (fromApiJsonHelper.parameterExists("active", element)) { + final Boolean active = fromApiJsonHelper.extractBooleanNamed("active", element); + baseDataValidator.reset().parameter("active").value(active).notNull(); + } + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + public void validateForUpdate(final String json) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); + + final List dataValidationErrors = new ArrayList(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); + + final JsonElement element = fromApiJsonHelper.parse(json); + if (fromApiJsonHelper.parameterExists("name", element)) { + final String name = fromApiJsonHelper.extractStringNamed("name", element); + baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100); + } + + if (fromApiJsonHelper.parameterExists("currencyCode", element)) { + final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element); + baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3); + } + + if (fromApiJsonHelper.parameterExists("amount", element)) { + final BigDecimal amount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element.getAsJsonObject()); + baseDataValidator.reset().parameter("amount").value(amount).notNull().positiveAmount(); + } + + if (fromApiJsonHelper.parameterExists("chargeAppliesTo", element)) { + final Integer chargeAppliesTo = fromApiJsonHelper.extractIntegerNamed("chargeAppliesTo", element, Locale.getDefault()); + baseDataValidator.reset().parameter("chargeAppliesTo").value(chargeAppliesTo).notNull().inMinMaxRange(1, 1); + } + + if (fromApiJsonHelper.parameterExists("chargeTimeType", element)) { + final Integer chargeTimeType = fromApiJsonHelper.extractIntegerNamed("chargeTimeType", element, Locale.getDefault()); + baseDataValidator.reset().parameter("chargeTimeType").value(chargeTimeType).notNull().inMinMaxRange(1, 2); + } + + if (fromApiJsonHelper.parameterExists("chargeCalculationType", element)) { + final Integer chargeCalculationType = fromApiJsonHelper.extractIntegerNamed("chargeCalculationType", element, + Locale.getDefault()); + baseDataValidator.reset().parameter("chargeCalculationType").value(chargeCalculationType).notNull().inMinMaxRange(1, 4); + } + + if (fromApiJsonHelper.parameterExists("penalty", element)) { + final Boolean penalty = fromApiJsonHelper.extractBooleanNamed("penalty", element); + baseDataValidator.reset().parameter("penalty").value(penalty).notNull(); + } + + if (fromApiJsonHelper.parameterExists("active", element)) { + final Boolean active = fromApiJsonHelper.extractBooleanNamed("active", element); + baseDataValidator.reset().parameter("active").value(active).notNull(); + } + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + + private void throwExceptionIfValidationWarningsExist(final List dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java index ef519b9bb..cd7e4bc8c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformService.java @@ -3,9 +3,7 @@ package org.mifosplatform.portfolio.charge.service; import java.util.Collection; import org.mifosplatform.portfolio.charge.data.ChargeData; -import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; -// FIXME - KW - break out methods that belong to product charges and loan charges public interface ChargeReadPlatformService { Collection retrieveAllCharges(); @@ -17,10 +15,4 @@ public interface ChargeReadPlatformService { Collection retrieveLoanApplicableCharges(boolean feeChargesOnly); Collection retrieveLoanProductCharges(Long loanProductId); - - Collection retrieveLoanCharges(Long loanId); - - LoanChargeData retrieveLoanChargeDetails(Long loanChargeId, Long loanId); - - ChargeData retrieveLoanChargeTemplate(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java index 290b1028c..64f54913d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeReadPlatformServiceImpl.java @@ -6,7 +6,6 @@ import java.sql.SQLException; import java.util.Collection; import java.util.List; -import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; @@ -16,7 +15,6 @@ import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformServi import org.mifosplatform.portfolio.charge.data.ChargeData; import org.mifosplatform.portfolio.charge.domain.ChargeAppliesTo; import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException; -import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -93,31 +91,6 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService return this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId }); } - @Override - public Collection retrieveLoanCharges(final Long loanId) { - this.context.authenticatedUser(); - - final LoanChargeMapper rm = new LoanChargeMapper(); - - // TODO - KW - check to see if its important that 'c.is_deleted=0' is - // required here? - final String sql = "select " + rm.loanChargeSchema() + " where c.is_deleted=0 and lc.loan_id=? " - + " order by lc.charge_time_enum ASC, lc.due_for_collection_as_of_date ASC, lc.is_penalty ASC"; - - return this.jdbcTemplate.query(sql, rm, new Object[] { loanId }); - } - - @Override - public LoanChargeData retrieveLoanChargeDetails(final Long id, final Long loanId) { - this.context.authenticatedUser(); - - final LoanChargeMapper rm = new LoanChargeMapper(); - - final String sql = "select " + rm.loanChargeSchema() + " where lc.id=? and lc.loan_id=?"; - - return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { id, loanId }); - } - @Override public Collection retrieveLoanApplicableCharges(final boolean feeChargesOnly) { this.context.authenticatedUser(); @@ -134,16 +107,6 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService return this.jdbcTemplate.query(sql, rm, new Object[] { ChargeAppliesTo.LOAN.getValue() }); } - @Override - public ChargeData retrieveLoanChargeTemplate() { - this.context.authenticatedUser(); - - final List allowedChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService.retrieveCalculationTypes(); - final List allowedChargeTimeOptions = this.chargeDropdownReadPlatformService.retrieveCollectionTimeTypes(); - - return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions); - } - private static final class ChargeMapper implements RowMapper { public String chargeSchema() { @@ -185,60 +148,8 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService final boolean penalty = rs.getBoolean("penalty"); final boolean active = rs.getBoolean("active"); - return ChargeData.instance(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType, penalty, 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 amountDue, " - + "lc.amount_paid_derived as amountPaid, " + "lc.amount_waived_derived as amountWaived, " - + "lc.amount_writtenoff_derived as amountWrittenOff, " + "lc.amount_outstanding_derived as amountOutstanding, " - + "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, " - + "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, " - + "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_calculation_enum as chargeCalculation, " - + "c.currency_code as currencyCode, 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(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { - - final Long id = rs.getLong("id"); - final Long chargeId = rs.getLong("chargeId"); - final String name = rs.getString("name"); - final BigDecimal amount = rs.getBigDecimal("amountDue"); - final BigDecimal amountPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPaid"); - final BigDecimal amountWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountWaived"); - final BigDecimal amountWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountWrittenOff"); - final BigDecimal amountOutstanding = rs.getBigDecimal("amountOutstanding"); - - final BigDecimal percentageOf = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "percentageOf"); - final BigDecimal amountPercentageAppliedTo = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPercentageAppliedTo"); - - 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 currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces"); - - final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces, currencyDisplaySymbol, - currencyNameCode); - - final int chargeTime = rs.getInt("chargeTime"); - final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime); - - final LocalDate dueAsOfDate = JdbcSupport.getLocalDate(rs, "dueAsOfDate"); - - final int chargeCalculation = rs.getInt("chargeCalculation"); - final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation); - final boolean penalty = rs.getBoolean("penalty"); - - return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, - chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty); + return ChargeData.instance(id, name, amount, currency, chargeTimeType, chargeAppliesToType, chargeCalculationType, penalty, + active); } } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java index 6c3138a9b..b797e6471 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/charge/service/ChargeWritePlatformServiceJpaRepositoryImpl.java @@ -7,7 +7,6 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; -import org.mifosplatform.portfolio.charge.command.ChargeDefinitionCommand; import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.ChargeRepository; import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException; @@ -42,8 +41,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP try { this.context.authenticatedUser(); - final ChargeDefinitionCommand chargeDefinitionCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); - chargeDefinitionCommand.validateForCreate(); + this.fromApiJsonDeserializer.validateForCreate(command.json()); final Charge charge = Charge.fromJson(command); this.chargeRepository.save(charge); @@ -62,8 +60,7 @@ public class ChargeWritePlatformServiceJpaRepositoryImpl implements ChargeWriteP try { this.context.authenticatedUser(); - final ChargeDefinitionCommand chargeDefinitionCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); - chargeDefinitionCommand.validateForUpdate(); + this.fromApiJsonDeserializer.validateForUpdate(command.json()); final Charge chargeForUpdate = this.chargeRepository.findOne(chargeId); if (chargeForUpdate == null) { throw new ChargeNotFoundException(chargeId); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java index b3fe38cbe..de717eb98 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java @@ -31,6 +31,7 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext import org.mifosplatform.portfolio.charge.data.ChargeData; import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService; import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; +import org.mifosplatform.portfolio.loanaccount.service.LoanChargeReadPlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -48,17 +49,20 @@ public class LoanChargesApiResource { private final PlatformSecurityContext context; private final ChargeReadPlatformService chargeReadPlatformService; + private final LoanChargeReadPlatformService loanChargeReadPlatformService; private final DefaultToApiJsonSerializer toApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @Autowired public LoanChargesApiResource(final PlatformSecurityContext context, final ChargeReadPlatformService chargeReadPlatformService, + final LoanChargeReadPlatformService loanChargeReadPlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; this.chargeReadPlatformService = chargeReadPlatformService; + this.loanChargeReadPlatformService = loanChargeReadPlatformService; this.toApiJsonSerializer = toApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; @@ -93,7 +97,7 @@ public class LoanChargesApiResource { context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); - final LoanChargeData loanCharge = this.chargeReadPlatformService.retrieveLoanChargeDetails(loanChargeId, loanId); + final LoanChargeData loanCharge = this.loanChargeReadPlatformService.retrieveLoanChargeDetails(loanChargeId, loanId); final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); return this.toApiJsonSerializer.serialize(settings, loanCharge, RESPONSE_DATA_PARAMETERS); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java index 1bba0507f..204604063 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java @@ -52,6 +52,7 @@ import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData; import org.mifosplatform.portfolio.loanaccount.gaurantor.service.GuarantorReadPlatformService; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService; +import org.mifosplatform.portfolio.loanaccount.service.LoanChargeReadPlatformService; import org.mifosplatform.portfolio.loanaccount.service.LoanReadPlatformService; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.TransactionProcessingStrategyData; @@ -88,6 +89,7 @@ public class LoansApiResource { private final LoanDropdownReadPlatformService dropdownReadPlatformService; private final FundReadPlatformService fundReadPlatformService; private final ChargeReadPlatformService chargeReadPlatformService; + private final LoanChargeReadPlatformService loanChargeReadPlatformService; private final LoanScheduleCalculationPlatformService calculationPlatformService; private final StaffReadPlatformService staffReadPlatformService; private final GuarantorReadPlatformService guarantorReadPlatformService; @@ -102,7 +104,7 @@ public class LoansApiResource { public LoansApiResource(final PlatformSecurityContext context, final LoanReadPlatformService loanReadPlatformService, final LoanProductReadPlatformService loanProductReadPlatformService, final LoanDropdownReadPlatformService dropdownReadPlatformService, final FundReadPlatformService fundReadPlatformService, - final ChargeReadPlatformService chargeReadPlatformService, + final ChargeReadPlatformService chargeReadPlatformService, final LoanChargeReadPlatformService loanChargeReadPlatformService, final LoanScheduleCalculationPlatformService calculationPlatformService, final StaffReadPlatformService staffReadPlatformService, final GuarantorReadPlatformService guarantorReadPlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer, @@ -116,6 +118,7 @@ public class LoansApiResource { this.dropdownReadPlatformService = dropdownReadPlatformService; this.fundReadPlatformService = fundReadPlatformService; this.chargeReadPlatformService = chargeReadPlatformService; + this.loanChargeReadPlatformService = loanChargeReadPlatformService; this.calculationPlatformService = calculationPlatformService; this.staffReadPlatformService = staffReadPlatformService; this.guarantorReadPlatformService = guarantorReadPlatformService; @@ -154,7 +157,7 @@ public class LoansApiResource { final boolean feeChargesOnly = false; Collection chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly); - ChargeData chargeTemplate = this.chargeReadPlatformService.retrieveLoanChargeTemplate(); + ChargeData chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate(); LoanBasicDetailsData loanBasicDetails; Long officeId; @@ -258,7 +261,7 @@ public class LoansApiResource { } if (associationParameters.contains("charges")) { - charges = this.chargeReadPlatformService.retrieveLoanCharges(loanId); + charges = this.loanChargeReadPlatformService.retrieveLoanCharges(loanId); if (CollectionUtils.isEmpty(charges)) { charges = null; // set back to null so doesnt appear in JSON // is no charges exist. @@ -293,7 +296,7 @@ public class LoansApiResource { repaymentStrategyOptions = this.dropdownReadPlatformService.retreiveTransactionProcessingStrategies(); final boolean feeChargesOnly = false; chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly); - chargeTemplate = this.chargeReadPlatformService.retrieveLoanChargeTemplate(); + chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate(); } final LoanAccountData loanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, repaymentSchedule, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformService.java new file mode 100644 index 000000000..0476fb357 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformService.java @@ -0,0 +1,15 @@ +package org.mifosplatform.portfolio.loanaccount.service; + +import java.util.Collection; + +import org.mifosplatform.portfolio.charge.data.ChargeData; +import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; + +public interface LoanChargeReadPlatformService { + + ChargeData retrieveLoanChargeTemplate(); + + Collection retrieveLoanCharges(Long loanId); + + LoanChargeData retrieveLoanChargeDetails(Long loanChargeId, Long loanId); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java new file mode 100644 index 000000000..856c6673b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanChargeReadPlatformServiceImpl.java @@ -0,0 +1,126 @@ +package org.mifosplatform.portfolio.loanaccount.service; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.List; + +import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.core.data.EnumOptionData; +import org.mifosplatform.infrastructure.core.domain.JdbcSupport; +import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.organisation.monetary.data.CurrencyData; +import org.mifosplatform.portfolio.charge.data.ChargeData; +import org.mifosplatform.portfolio.charge.service.ChargeDropdownReadPlatformService; +import org.mifosplatform.portfolio.charge.service.ChargeEnumerations; +import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; +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 LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + private final PlatformSecurityContext context; + private final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService; + + @Autowired + public LoanChargeReadPlatformServiceImpl(final PlatformSecurityContext context, + final ChargeDropdownReadPlatformService chargeDropdownReadPlatformService, final TenantAwareRoutingDataSource dataSource) { + this.context = context; + this.chargeDropdownReadPlatformService = chargeDropdownReadPlatformService; + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class LoanChargeMapper implements RowMapper { + + public String schema() { + return "lc.id as id, c.id as chargeId, c.name as name, " + "lc.amount as amountDue, " + + "lc.amount_paid_derived as amountPaid, " + "lc.amount_waived_derived as amountWaived, " + + "lc.amount_writtenoff_derived as amountWrittenOff, " + "lc.amount_outstanding_derived as amountOutstanding, " + + "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, " + + "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, " + + "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_calculation_enum as chargeCalculation, " + + "c.currency_code as currencyCode, 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(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { + + final Long id = rs.getLong("id"); + final Long chargeId = rs.getLong("chargeId"); + final String name = rs.getString("name"); + final BigDecimal amount = rs.getBigDecimal("amountDue"); + final BigDecimal amountPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPaid"); + final BigDecimal amountWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountWaived"); + final BigDecimal amountWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountWrittenOff"); + final BigDecimal amountOutstanding = rs.getBigDecimal("amountOutstanding"); + + final BigDecimal percentageOf = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "percentageOf"); + final BigDecimal amountPercentageAppliedTo = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPercentageAppliedTo"); + + 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 currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces"); + + final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces, currencyDisplaySymbol, + currencyNameCode); + + final int chargeTime = rs.getInt("chargeTime"); + final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime); + + final LocalDate dueAsOfDate = JdbcSupport.getLocalDate(rs, "dueAsOfDate"); + + final int chargeCalculation = rs.getInt("chargeCalculation"); + final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation); + final boolean penalty = rs.getBoolean("penalty"); + + return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding, + chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty); + } + } + + @Override + public ChargeData retrieveLoanChargeTemplate() { + this.context.authenticatedUser(); + + final List allowedChargeCalculationTypeOptions = this.chargeDropdownReadPlatformService.retrieveCalculationTypes(); + final List allowedChargeTimeOptions = this.chargeDropdownReadPlatformService.retrieveCollectionTimeTypes(); + + return ChargeData.template(null, allowedChargeCalculationTypeOptions, null, allowedChargeTimeOptions); + } + + @Override + public LoanChargeData retrieveLoanChargeDetails(final Long id, final Long loanId) { + this.context.authenticatedUser(); + + final LoanChargeMapper rm = new LoanChargeMapper(); + + final String sql = "select " + rm.schema() + " where lc.id=? and lc.loan_id=?"; + + return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { id, loanId }); + } + + @Override + public Collection retrieveLoanCharges(final Long loanId) { + this.context.authenticatedUser(); + + final LoanChargeMapper rm = new LoanChargeMapper(); + + // TODO - KW - check to see if its important that 'c.is_deleted=0' is + // required here? + final String sql = "select " + rm.schema() + " where c.is_deleted=0 and lc.loan_id=? " + + " order by lc.charge_time_enum ASC, lc.due_for_collection_as_of_date ASC, lc.is_penalty ASC"; + + return this.jdbcTemplate.query(sql, rm, new Object[] { loanId }); + } +}