diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java index 972586c85..48ec259d8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/api/DataTableApiResource.java @@ -1,8 +1,6 @@ package org.mifosplatform.infrastructure.dataqueries.api; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -13,16 +11,10 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; -import org.codehaus.jettison.json.JSONArray; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; @@ -31,11 +23,7 @@ import org.mifosplatform.infrastructure.dataqueries.data.DatatableData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.service.GenericDataService; import org.mifosplatform.infrastructure.dataqueries.service.ReadWriteNonCoreDataService; -import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; -import org.mifosplatform.useradministration.domain.AppUser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -45,242 +33,143 @@ import org.springframework.stereotype.Component; @Scope("singleton") public class DataTableApiResource { - private final static Logger logger = LoggerFactory - .getLogger(DataTableApiResource.class); + private final PlatformSecurityContext context; + private final GenericDataService genericDataService; + private final ReadWriteNonCoreDataService readWriteNonCoreDataService; + private final ToApiJsonSerializer toApiJsonSerializer; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; - private final PlatformSecurityContext context; - private final GenericDataService genericDataService; - private final ReadWriteNonCoreDataService readWriteNonCoreDataService; - private final ToApiJsonSerializer toApiJsonSerializer; - private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + @Autowired + public DataTableApiResource(final PlatformSecurityContext context, final GenericDataService genericDataService, + final ReadWriteNonCoreDataService readWriteNonCoreDataService, + final ToApiJsonSerializer toApiJsonSerializer, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { + this.context = context; + this.genericDataService = genericDataService; + this.readWriteNonCoreDataService = readWriteNonCoreDataService; + this.toApiJsonSerializer = toApiJsonSerializer; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + } - @Autowired - public DataTableApiResource( - final PlatformSecurityContext context, - final GenericDataService genericDataService, - final ReadWriteNonCoreDataService readWriteNonCoreDataService, - ToApiJsonSerializer toApiJsonSerializer, - final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { - this.context = context; - this.genericDataService = genericDataService; - this.readWriteNonCoreDataService = readWriteNonCoreDataService; - this.toApiJsonSerializer = toApiJsonSerializer; - this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; - } + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getDatatables(@QueryParam("apptable") final String apptable, @Context final UriInfo uriInfo) { - @GET - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String getDatatables(@QueryParam("apptable") final String apptable, - @Context final UriInfo uriInfo) { + final List result = this.readWriteNonCoreDataService.retrieveDatatableNames(apptable); - final List result = this.readWriteNonCoreDataService - .retrieveDatatableNames(apptable); + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serializePretty(prettyPrint, result); + } - final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo - .getQueryParameters()); - return this.toApiJsonSerializer.serializePretty(prettyPrint, result); - } + @POST + @Path("register/{datatable}/{apptable}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String registerDatatable(@PathParam("datatable") final String datatable, @PathParam("apptable") final String apptable) { - @POST - @Path("register/{datatable}/{apptable}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String registerDatatable( - @PathParam("datatable") final String datatable, - @PathParam("apptable") final String apptable) { + this.readWriteNonCoreDataService.registerDatatable(datatable, apptable); - this.readWriteNonCoreDataService.registerDatatable(datatable, apptable); + return this.toApiJsonSerializer.serialize(EntityIdentifier.empty()); + } - return this.toApiJsonSerializer.serialize(EntityIdentifier.empty()); - } + @POST + @Path("deregister/{datatable}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String deregisterDatatable(@PathParam("datatable") final String datatable) { - @POST - @Path("deregister/{datatable}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String deregisterDatatable( - @PathParam("datatable") final String datatable) { + this.readWriteNonCoreDataService.deregisterDatatable(datatable); - this.readWriteNonCoreDataService.deregisterDatatable(datatable); + return this.toApiJsonSerializer.serialize(EntityIdentifier.empty()); + } - return this.toApiJsonSerializer.serialize(EntityIdentifier.empty()); - } + @GET + @Path("{datatable}/{apptableId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String getDatatable(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId, + @QueryParam("order") final String order, @Context final UriInfo uriInfo) { - @GET - @Path("{datatable}/{apptableId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String getDatatable(@PathParam("datatable") final String datatable, - @PathParam("apptableId") final Long apptableId, - @QueryParam("order") final String order, - @Context final UriInfo uriInfo) { + context.authenticatedUser().validateHasDatatableReadPermission(datatable); - checkUserPermissionForDatatable(datatable, "READ"); + GenericResultsetData results = this.readWriteNonCoreDataService.retrieveDataTableGenericResultSet(datatable, apptableId, order, + null); - GenericResultsetData results = this.readWriteNonCoreDataService - .retrieveDataTableGenericResultSet(datatable, apptableId, - order, null); + String json = ""; + final boolean genericResultSet = ApiParameterHelper.genericResultSet(uriInfo.getQueryParameters()); + if (genericResultSet) { + final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + json = this.toApiJsonSerializer.serializePretty(prettyPrint, results); + } else { + json = this.genericDataService.generateJsonFromGenericResultsetData(results); + } - String json = ""; - final boolean genericResultSet = ApiParameterHelper - .genericResultSet(uriInfo.getQueryParameters()); - if (genericResultSet) { - final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo - .getQueryParameters()); - json = this.toApiJsonSerializer.serializePretty(prettyPrint, - results); - } else { - json = this.genericDataService - .generateJsonFromGenericResultsetData(results); - } + return json; + } - return json; - } + @POST + @Path("{datatable}/{apptableId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String newDatatableEntry(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId, + final String apiRequestBodyAsJson) { - @POST - @Path("{datatable}/{apptableId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String newDatatableEntry( - @PathParam("datatable") final String datatable, - @PathParam("apptableId") final Long apptableId, - final String apiRequestBodyAsJson) { + final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("CREATE", datatable, "CREATE", + "datatables/" + datatable, apptableId, apiRequestBodyAsJson); - final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService - .logCommandSource("CREATE", datatable, "CREATE", "datatables/"+datatable, - apptableId, apiRequestBodyAsJson); + return this.toApiJsonSerializer.serialize(entityIdentifier); + } - return this.toApiJsonSerializer.serialize(entityIdentifier); - } + @PUT + @Path("{datatable}/{apptableId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateDatatableEntryOnetoOne(@PathParam("datatable") final String datatable, + @PathParam("apptableId") final Long apptableId, final String apiRequestBodyAsJson) { - @PUT - @Path("{datatable}/{apptableId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String updateDatatableEntryOnetoOne( - @PathParam("datatable") final String datatable, - @PathParam("apptableId") final Long apptableId, - final String apiRequestBodyAsJson) { - /* - * for updating one to one relationships (where foreign key is the - * primary key) - */ -// checkUserPermissionForDatatable(datatable, "UPDATE"); -// Map queryParams = getQueryParamsFromJsonRequestBody(jsonRequestBody); - - final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService - .logCommandSource("UPDATE", datatable, "UPDATE", "datatables/"+datatable, - apptableId, apiRequestBodyAsJson); + final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", datatable, "UPDATE", + "datatables/" + datatable, apptableId, apiRequestBodyAsJson); -// this.readWriteNonCoreDataService.updateDatatableEntryOnetoOne( -// datatable, apptableId, queryParams); -// -// EntityIdentifier entityIdentifier = EntityIdentifier.resourceResult( -// Long.valueOf(apptableId), null); + return this.toApiJsonSerializer.serialize(entityIdentifier); + } - return this.toApiJsonSerializer.serialize(entityIdentifier); - } + @PUT + @Path("{datatable}/{apptableId}/{datatableId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateDatatableEntryOneToMany(@PathParam("datatable") final String datatable, + @PathParam("apptableId") final Long apptableId, @PathParam("datatableId") final Long datatableId, + final String apiRequestBodyAsJson) { - @PUT - @Path("{datatable}/{apptableId}/{datatableId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String updateDatatableEntryOnetoOne( - @PathParam("datatable") final String datatable, - @PathParam("apptableId") final Long apptableId, - @PathParam("datatableId") final Long datatableId, - final String apiRequestBodyAsJson) { - /* - * for updating one to many relationships (where foreign key isn't the - * primary key) - */ - - final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService - .logCommandSource("UPDATE", datatable, "UPDATE_MULTIPLE", "datatables/"+datatable, apptableId, "datatables/"+datatable, datatableId, apiRequestBodyAsJson); + final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", datatable, + "UPDATE_MULTIPLE", "datatables/" + datatable, apptableId, "datatables/" + datatable, datatableId, apiRequestBodyAsJson); - return this.toApiJsonSerializer.serialize(entityIdentifier); - -// checkUserPermissionForDatatable(datatable, "UPDATE"); -// Map queryParams = getQueryParamsFromJsonRequestBody(jsonRequestBody); -// -// this.readWriteNonCoreDataService.updateDatatableEntryOnetoMany( -// datatable, apptableId, datatableId, queryParams); -// -// EntityIdentifier entityIdentifier = EntityIdentifier.resourceResult( -// Long.valueOf(apptableId), null); -// -// return this.toApiJsonSerializer.serialize(entityIdentifier); - } + return this.toApiJsonSerializer.serialize(entityIdentifier); + } - @DELETE - @Path("{datatable}/{apptableId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String deleteDatatableEntries( - @PathParam("datatable") final String datatable, - @PathParam("apptableId") final Long apptableId) { + @DELETE + @Path("{datatable}/{apptableId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId) { - final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService - .logCommandSource("DELETE", datatable, "DELETE", "datatables/"+datatable, - apptableId, "{}"); - - return this.toApiJsonSerializer.serialize(entityIdentifier); - } + final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("DELETE", datatable, "DELETE", + "datatables/" + datatable, apptableId, "{}"); - @DELETE - @Path("{datatable}/{apptableId}/{datatableId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String deleteDatatableEntries( - @PathParam("datatable") final String datatable, - @PathParam("apptableId") final Long apptableId, - @PathParam("datatableId") final Long datatableId) { + return this.toApiJsonSerializer.serialize(entityIdentifier); + } - final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService - .logCommandSource("DELETE", datatable, "DELETE_MULTIPLE", "datatables/"+datatable, apptableId, "datatables/"+datatable, datatableId, "{}"); + @DELETE + @Path("{datatable}/{apptableId}/{datatableId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId, + @PathParam("datatableId") final Long datatableId) { - return this.toApiJsonSerializer.serialize(entityIdentifier); - } + final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("DELETE", datatable, + "DELETE_MULTIPLE", "datatables/" + datatable, apptableId, "datatables/" + datatable, datatableId, "{}"); - private Map getQueryParamsFromJsonRequestBody( - final String jsonRequestBody) { - - Map queryParams = new HashMap(); - - String pValue = ""; - String pName; - try { - JSONObject jsonObj = new JSONObject(jsonRequestBody); - JSONArray jsonArr = jsonObj.names(); - if (jsonArr != null) { - for (int i = 0; i < jsonArr.length(); i++) { - pName = (String) jsonArr.get(i); - pValue = jsonObj.getString(pName); - logger.info("getQueryParamsFromJsonRequestBody: " + pName - + " - " + pValue); - queryParams.put(pName, pValue); - } - return queryParams; - } - throw new WebApplicationException(Response - .status(Status.BAD_REQUEST).entity("JSON body empty") - .build()); - - } catch (JSONException e) { - throw new WebApplicationException(Response - .status(Status.BAD_REQUEST).entity("JSON body is wrong") - .build()); - } - - } - - private void checkUserPermissionForDatatable(final String datatable, - final String accessType) { - AppUser currentUser = context.authenticatedUser(); - if (currentUser.hasNotPermissionForDatatable(datatable, accessType)) { - throw new NoAuthorizationException("Not Authorised to " - + accessType + " Data Table: " + datatable); - } - } + return this.toApiJsonSerializer.serialize(entityIdentifier); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java index 4fd091ea9..22d594fd7 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java @@ -16,144 +16,138 @@ import org.mifosplatform.organisation.monetary.domain.Money; * installment, the over paid amount is pay off on the principal component of * subsequent installments. * - * If the entire principal of an installment is paid in advance then the interest component is waived. + * If the entire principal of an installment is paid in advance then the + * interest component is waived. */ @SuppressWarnings("unused") public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor { - - /** - * For late repayments, pay off in the same way as on-time payments, - * interest first then principal. - */ - @Override - protected Money handleTransactionThatIsALateRepaymentOfInstallment( - final LoanRepaymentScheduleInstallment currentInstallment, - final List installments, - final LoanTransaction loanTransaction, - final Money transactionAmountUnprocessed) { - return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed); - } + /** + * For late repayments, pay off in the same way as on-time payments, + * interest first then principal. + */ + @Override + protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment, + final List installments, final LoanTransaction loanTransaction, + final Money transactionAmountUnprocessed) { - @Override - protected boolean isTransactionInAdvanceOfInstallment( - final int currentInstallmentIndex, - final List installments, - final LocalDate transactionDate, - final Money transactionAmount) { - - boolean isInAdvance = false; - - LocalDate lastInstallmentDueDate = null; - if (currentInstallmentIndex > 0) { - int previousInstallmentIndex = currentInstallmentIndex - 1; - LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex); - lastInstallmentDueDate = previousInstallment.getDueDate(); - - return !transactionDate.isAfter(lastInstallmentDueDate); - } - - return isInAdvance; - } + return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed); + } - /** - * For early/'in advance' repayments, pays off principal component only. - */ - @Override - protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment( - final LoanRepaymentScheduleInstallment currentInstallment, - final List installments, - final LoanTransaction loanTransaction, - final LocalDate transactionDate, final Money paymentInAdvance) { - - final MonetaryCurrency currency = paymentInAdvance.getCurrency(); - Money transactionAmountRemaining = paymentInAdvance; - Money principalPortion = Money.zero(currency); - Money interestPortion = Money.zero(currency); - Money feeChargesPortion = Money.zero(currency); - Money penaltyChargesPortion = Money.zero(currency); - - if (loanTransaction.isInterestWaiver()) { - interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); - } else { + @Override + protected boolean isTransactionInAdvanceOfInstallment(final int currentInstallmentIndex, + final List installments, final LocalDate transactionDate, final Money transactionAmount) { - if (currentInstallment.isPrincipalNotCompleted(currency)) { - principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); - if (currentInstallment.isPrincipalCompleted(currency)) { - // FIXME - KW - if auto waiving interest need to create another transaction to handle this. - currentInstallment.waiveInterestComponent(currentInstallment.getInterest(currency)); - } + boolean isInAdvance = false; - loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); + LocalDate lastInstallmentDueDate = null; + int previousInstallmentIndex = 0; + if (currentInstallmentIndex > 0) { + previousInstallmentIndex = currentInstallmentIndex - 1; + } - transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); - } - - penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); - - feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); - - interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); - - principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); - } - - loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); - return transactionAmountRemaining; - } - - /** - * For normal on-time repayments, pays off interest first, then principal. - */ - @Override - protected Money handleTransactionThatIsOnTimePaymentOfInstallment( - final LoanRepaymentScheduleInstallment currentInstallment, - final LoanTransaction loanTransaction, - final Money transactionAmountUnprocessed) { - - final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency(); - Money transactionAmountRemaining = transactionAmountUnprocessed; - Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); - Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); - Money feeChargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); - Money penaltyChargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); - - if (loanTransaction.isChargesWaiver()) { - penaltyChargesPortion = currentInstallment.waivePenaltyChargesComponent(loanTransaction.getPenaltyChargesPortion(currency)); - transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); - - feeChargesPortion = currentInstallment.waiveFeeChargesComponent(loanTransaction.getFeeChargesPortion(currency)); - transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); - - } else if (loanTransaction.isInterestWaiver()) { - interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); - } else { - penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); - - feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); - - interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); - - principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); - transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); - } - - loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); - return transactionAmountRemaining; - } + LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex); + lastInstallmentDueDate = previousInstallment.getDueDate(); - @Override - protected void onLoanOverpayment( - final LoanTransaction loanTransaction, - final Money loanOverPaymentAmount) { - } + isInAdvance = !transactionDate.isAfter(lastInstallmentDueDate); + + return isInAdvance; + } + + /** + * For early/'in advance' repayments, pays off principal component only. + */ + @Override + protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment, + final List installments, final LoanTransaction loanTransaction, + final LocalDate transactionDate, final Money paymentInAdvance) { + + final MonetaryCurrency currency = paymentInAdvance.getCurrency(); + Money transactionAmountRemaining = paymentInAdvance; + Money principalPortion = Money.zero(currency); + Money interestPortion = Money.zero(currency); + Money feeChargesPortion = Money.zero(currency); + Money penaltyChargesPortion = Money.zero(currency); + + if (loanTransaction.isInterestWaiver()) { + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); + } else { + + if (currentInstallment.isPrincipalNotCompleted(currency)) { + principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); + if (currentInstallment.isPrincipalCompleted(currency)) { + // FIXME - KW - if auto waiving interest need to create + // another transaction to handle this. + currentInstallment.waiveInterestComponent(currentInstallment.getInterest(currency)); + } + + loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); + + transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); + } + + // 1. pay of principal with over payment. + principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); + + penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); + + feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); + + interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); + } + + loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); + return transactionAmountRemaining; + } + + /** + * For normal on-time repayments, pays off interest first, then principal. + */ + @Override + protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment, + final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) { + + final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency(); + Money transactionAmountRemaining = transactionAmountUnprocessed; + Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); + Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); + Money feeChargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); + Money penaltyChargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); + + if (loanTransaction.isChargesWaiver()) { + penaltyChargesPortion = currentInstallment.waivePenaltyChargesComponent(loanTransaction.getPenaltyChargesPortion(currency)); + transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); + + feeChargesPortion = currentInstallment.waiveFeeChargesComponent(loanTransaction.getFeeChargesPortion(currency)); + transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); + + } else if (loanTransaction.isInterestWaiver()) { + interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); + } else { + penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); + + feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); + + // 1. pay of principal before interest. + principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); + + interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); + } + + loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); + return transactionAmountRemaining; + } + + @Override + protected void onLoanOverpayment(final LoanTransaction loanTransaction, final Money loanOverPaymentAmount) {} } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java index dfdbdd048..e579a01ec 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java @@ -324,7 +324,7 @@ public class AppUser extends AbstractAuditableCustom implements P return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "REPAYMENTINPAST_LOAN", "PORTFOLIO_MANAGEMENT_SUPER_USER"); } - public boolean hasNotPermissionForReport(String reportName) { + public boolean hasNotPermissionForReport(final String reportName) { if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "REPORTING_SUPER_USER", "READ_" + reportName)) return true; @@ -490,4 +490,10 @@ public class AppUser extends AbstractAuditableCustom implements P throw new NoAuthorizationException(authorizationMessage); } } + + public void validateHasDatatableReadPermission(final String datatable) { + if (hasNotPermissionForDatatable(datatable, "READ")) { + throw new NoAuthorizationException("Not authorised to read datatable: " + datatable); + } + } } \ No newline at end of file diff --git a/mifosng-provider/src/test/java/org/mifosplatform/portfolio/loanaccount/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java b/mifosng-provider/src/test/java/org/mifosplatform/portfolio/loanaccount/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java index 36470acd1..cbe705c2d 100644 --- a/mifosng-provider/src/test/java/org/mifosplatform/portfolio/loanaccount/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java +++ b/mifosng-provider/src/test/java/org/mifosplatform/portfolio/loanaccount/HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest.java @@ -18,404 +18,593 @@ import org.mockito.runners.MockitoJUnitRunner; @SuppressWarnings("unused") @RunWith(MockitoJUnitRunner.class) public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest { - - // class under test - private HeavensFamilyLoanRepaymentScheduleTransactionProcessor processor; - - // - private LocalDate july2nd = new LocalDate(2012, 7, 2); - private MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build(); - private List installments; - - @Before - public void setUpForEachTestCase() { - - installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars); - - processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); - } - /** - * Scenario 1: Single transaction which is less than the interest component of the first installment. - * - * Expectation: - * - First installment shows interest completed equal to that of transactions, zero principal completed. (payment order interest, principal) - * - transaction has interest portion equal to transaction amount, and zero principal portion - */ - @Test - public void givenSingleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() { - -// // setup -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// -// Money oneHundredDollars = new MoneyBuilder().with(usDollars).with("100.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", singleInstallment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", onTimePartialPayment); - } - -// /** -// * Scenario 2: Two transactions which is less than the interest component of the first installment. -// * -// * Expectation: -// * - First installment shows interest completed equal to that of transactions, zero principal completed. (payment order interest, principal) -// * - transactions has interest portion equal to transaction amount, and zero principal portion -// */ -// @Test -// public void givenMultipleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() { -// -// // setup -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// -// Money oneHundredDollars = new MoneyBuilder().with(usDollars).with("100.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build(); -// -// Money fiftyDollars = new MoneyBuilder().with(usDollars).with("50.00").build(); -// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(fiftyDollars).build(); -// -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", "150.00", singleInstallment); -// -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", onTimePartialPayment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "50.00", secondOnTimePartialPayment); -// } -// -// /** -// * Scenario 3: Single transaction which is greater than the interest component of the first installment but less than the total due for installment. -// * -// * Expectation: -// * - First installment shows interest completed equal to that interest due, remainder is against principal completed. (payment order interest, principal) -// * - transaction has interest portion equal to interest expected and principal portion of remainder. -// */ -// @Test -// public void givenSingleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() { -// -// // setup -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// -// Money amount = new MoneyBuilder().with(usDollars).with("300.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", singleInstallment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", onTimePartialPayment); -// } -// -// /** -// * Scenario 4: Single transaction which is greater than the interest component of the first installment but less than the total due for installment. -// * -// * Expectation: -// * - First installment shows interest completed equal to that interest due, remainder is against principal completed. (payment order interest, principal) -// * - transaction has interest portion equal to interest expected and principal portion of remainder. -// */ -// @Test -// public void givenMultipleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() { -// -// // setup -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// -// Money amount = new MoneyBuilder().with(usDollars).with("300.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("50.00").build(); -// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("150.00", "200.00", singleInstallment); -// -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", onTimePartialPayment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("50.00", "0.00", secondOnTimePartialPayment); -// } -// -// /** -// * Scenario 5:Single transaction which is equal to the total due for installment. -// * -// * Expectation: -// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) -// * - transaction has interest portion and principal portions -// */ -// @Test -// public void givenSingleFullOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponentInFull() { -// -// // setup -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// -// Money amount = new MoneyBuilder().with(usDollars).with("1200.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", onTimePartialPayment); -// } -// -// /** -// * Scenario 6: Multiple transactions which together equal to the total due for installment. -// * -// * Expectation: -// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) -// * - transaction has interest portion and principal portions -// */ -// @Test -// public void givenMuliptleOnTimeLoanTransactionsThatInFullShouldPayoffInterestThenPrincipalComponentInFull() { -// -// // setup -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// -// Money amount = new MoneyBuilder().with(usDollars).with("600.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("600.00").build(); -// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", "200.00", onTimePartialPayment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("600.00", "0.00", secondOnTimePartialPayment); -// } -// -// /** -// * Scenario 7: Single transaction which is greater than total due for first installment. -// * -// * Expectation: -// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) -// * - Second installment shows principal completed equal to the remaining amount -// * - transaction has interest portion and principal portions, the principal portion is the sum of principal completed for first and second installments -// */ -// @Test -// public void givenSingleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() { -// -// // setup -// Money amount = new MoneyBuilder().with(usDollars).with("1300.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", firstInstallment); -// -// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "0.00", secondInstallment); -// -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1100.00", "200.00", onTimePartialPayment); -// } -// -// /** -// * Scenario 8: Multiple transactions which together are greater than total due for first installment. -// * -// * Expectation: -// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) -// * - Second installment shows principal completed equal to the remaining amount -// */ -// @Test -// public void givenMultipleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() { -// -// // setup -// Money amount = new MoneyBuilder().with(usDollars).with("600.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("700.00").build(); -// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment); -// -// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "0.00", secondInstallment); -// -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", "200.00", onTimePartialPayment); -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", "0.00", secondOnTimePartialPayment); -// } -// -// /** -// * Scenario 9: Single transaction which overpays first installment and second installment with outstanding amount been account as principal in third installment. -// * -// * Where an installments principal is paid for fully in advance - the interest component is waived. -// */ -// @Test -// public void givenOverPaymentShouldPayoffInterestThenPrincipalComponentsOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfAllSubsequentInstallments() { -// // setup -// Money amount = new MoneyBuilder().with(usDollars).with("3000.00").build(); -// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); -// -// // execute test -// processor.handleTransaction(onTimePartialPayment, usDollars, installments); -// -// // verification of derived fields on installments -// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); -// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars); -// -// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); -// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("0.00"), interestWaivedOf("200.00"), secondInstallment, usDollars); -// -// LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); -// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("800.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); -// -// assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"), interestOf("200.00"), onTimePartialPayment, usDollars); -// } -// -// /** -// * Scenario 10: Single transaction which is a repayment in advance -// */ -// @Test -// public void givenRepaymentOfInstallmentInAdvanceShouldPayoffOnlyPrincipalComponent() { -// // setup -// installments = LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, usDollars); -// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); -// LocalDate paymentInAdvanceDate = firstInstallment.getDueDate().minusDays(1); -// -// Money amount = new MoneyBuilder().with(usDollars).with("900.00").build(); -// LoanTransaction paymentInAdvance = new LoanTransactionBuilder().repayment().with(paymentInAdvanceDate).with(amount).build(); -// -// // execute test -// processor.handleTransaction(paymentInAdvance, usDollars, installments); -// -// // verification of derived fields on installments -// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("900.00", "0.00", secondInstallment); -// -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("900.00", "0.00", paymentInAdvance); -// } -// -// /** -// * Scenario 11: Single transaction which is a repayment many days early but still does not qualify for 'in advance'. -// */ -// @Test -// public void givenRepaymentOfInstallmentBeforeDueDateButNotInAdvanceShouldPayoffInterestAndPrincipalComponents() { -// // setup -// installments = LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, usDollars); -// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); -// LocalDate paymentBeforeDueDateButNotInAdvanceDate = firstInstallment.getDueDate().plusDays(1); -// -// Money amount = new MoneyBuilder().with(usDollars).with("900.00").build(); -// LoanTransaction paymentBeforeDueDateButNotInAdvance = new LoanTransactionBuilder().repayment().with(paymentBeforeDueDateButNotInAdvanceDate).with(amount).build(); -// -// // execute test -// processor.handleTransaction(paymentBeforeDueDateButNotInAdvance, usDollars, installments); -// -// // verification of derived fields on installments -// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); -// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("700.00", "200.00", secondInstallment); -// -// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", "200.00", paymentBeforeDueDateButNotInAdvance); -// } -// -// -// /** -// * Scenario 12: Single transaction which is a repayment many days early but still does not qualify for 'in advance'. -// */ -// @Test -// public void givenLateRepaymentOfInstallmentShouldPayoffInterestAndPrincipalComponentsOfOverdueInstallmentsWithNoWaiveOfInterest() { -// // setup -// installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars); -// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); -// LocalDate latePaymentDate = firstInstallment.getDueDate().plusMonths(5); -// -// Money amount = new MoneyBuilder().with(usDollars).with("3600.00").build(); -// LoanTransaction lateRepaymentTransaction = new LoanTransactionBuilder().repayment().with(latePaymentDate).with(amount).build(); -// -// // execute test -// processor.handleTransaction(lateRepaymentTransaction, usDollars, installments); -// -// // verification of derived fields on installments -// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars); -// -// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); -// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), secondInstallment, usDollars); -// -// LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); -// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); -// -// assertThatLoanTransactionHasDerivedFieldsOf(principalOf("3000.00"), interestOf("600.00"), lateRepaymentTransaction, usDollars); -// } -// -// -// private void assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf( -// final String principal, final String interest, final LoanTransaction transaction) { -// -// Money expectedInterestPortion = new MoneyBuilder().with(usDollars).with(interest).build(); -// assertThat(transaction.getInterestPortion(usDollars).toString(), is(expectedInterestPortion.toString())); -// -// Money expectedPrincipalPortion = new MoneyBuilder().with(usDollars).with(principal).build(); -// assertThat(transaction.getPrincipalPortion(usDollars).toString(), is(expectedPrincipalPortion.toString())); -// } -// -// private void assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf(final String principal, final String interest, -// final LoanRepaymentScheduleInstallment installment) { -// Money expectedInterestCompleted = new MoneyBuilder().with(usDollars).with(interest).build(); -// assertThat(installment.getInterestCompleted(usDollars).toString(), is(expectedInterestCompleted.toString())); -// -// Money expectedPrincipalCompleted = new MoneyBuilder().with(usDollars).with(principal).build(); -// assertThat(installment.getPrincipalCompleted(usDollars).toString(), is(expectedPrincipalCompleted.toString())); -// } -// -// private void assertThatLoanTransactionHasDerivedFieldsOf( -// final String principal, -// final String interest, -// final LoanTransaction transaction, final MonetaryCurrency currency) { -// -// Money expectedPrincipalPortion = new MoneyBuilder().with(currency).with(principal).build(); -// assertThat("Principal portion of transaction not as expected: ", transaction.getPrincipalPortion(currency).toString(), is(expectedPrincipalPortion.toString())); -// -// Money expectedInterestPortion = new MoneyBuilder().with(currency).with(interest).build(); -// assertThat("Interest portion of transaction not as expected: ", transaction.getInterestPortion(currency).toString(), is(expectedInterestPortion.toString())); -// } -// -// private void assertThatLoanInstallmentHasDerivedFieldsOf( -// final String principal, -// final String interest, -// final String interestWaived, -// final LoanRepaymentScheduleInstallment installment, final MonetaryCurrency currency) { -// -// Money expectedPrincipalCompleted = new MoneyBuilder().with(currency).with(principal).build(); -// assertThat("principal not as expected", installment.getPrincipalCompleted(currency).toString(), is(expectedPrincipalCompleted.toString())); -// -// Money expectedInterestCompleted = new MoneyBuilder().with(currency).with(interest).build(); -// assertThat("interest completed not as expected: ",installment.getInterestCompleted(currency).toString(), is(expectedInterestCompleted.toString())); -// -// Money expectedInterestWaived = new MoneyBuilder().with(currency).with(interestWaived).build(); -// assertThat("interest waived not as expected: ", installment.getInterestWaived(currency).toString(), is(expectedInterestWaived.toString())); -// } -// -// private String principalOf(final String value) { -// return value; -// } -// -// private String interestOf(final String value) { -// return value; -// } -// -// private String interestWaivedOf(final String value) { -// return value; -// } + // class under test + private HeavensFamilyLoanRepaymentScheduleTransactionProcessor processor; + + // + private LocalDate july2nd = new LocalDate(2012, 7, 2); + private MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build(); + private List installments; + + @Before + public void setUpForEachTestCase() { + + installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars); + + processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); + } + + /** + * Scenario 1: Single transaction which is less than the interest component + * of the first installment. + * + * Expectation: - First installment shows interest completed equal to that + * of transactions, zero principal completed. (payment order interest, + * principal) - transaction has interest portion equal to transaction + * amount, and zero principal portion + */ + @Test + public void givenSingleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() { + + // // setup + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // + // Money oneHundredDollars = new + // MoneyBuilder().with(usDollars).with("100.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", + // "100.00", singleInstallment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", + // "100.00", onTimePartialPayment); + } + + // /** + // * Scenario 2: Two transactions which is less than the interest component + // of the first installment. + // * + // * Expectation: + // * - First installment shows interest completed equal to that of + // transactions, zero principal completed. (payment order interest, + // principal) + // * - transactions has interest portion equal to transaction amount, and + // zero principal portion + // */ + // @Test + // public void + // givenMultipleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() { + // + // // setup + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // + // Money oneHundredDollars = new + // MoneyBuilder().with(usDollars).with("100.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build(); + // + // Money fiftyDollars = new + // MoneyBuilder().with(usDollars).with("50.00").build(); + // LoanTransaction secondOnTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(fiftyDollars).build(); + // + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // processor.handleTransaction(secondOnTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", + // "150.00", singleInstallment); + // + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", + // "100.00", onTimePartialPayment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", + // "50.00", secondOnTimePartialPayment); + // } + // + // /** + // * Scenario 3: Single transaction which is greater than the interest + // component of the first installment but less than the total due for + // installment. + // * + // * Expectation: + // * - First installment shows interest completed equal to that interest + // due, remainder is against principal completed. (payment order interest, + // principal) + // * - transaction has interest portion equal to interest expected and + // principal portion of remainder. + // */ + // @Test + // public void + // givenSingleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() + // { + // + // // setup + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // + // Money amount = new MoneyBuilder().with(usDollars).with("300.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", + // "200.00", singleInstallment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", + // "200.00", onTimePartialPayment); + // } + // + // /** + // * Scenario 4: Single transaction which is greater than the interest + // component of the first installment but less than the total due for + // installment. + // * + // * Expectation: + // * - First installment shows interest completed equal to that interest + // due, remainder is against principal completed. (payment order interest, + // principal) + // * - transaction has interest portion equal to interest expected and + // principal portion of remainder. + // */ + // @Test + // public void + // givenMultipleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() + // { + // + // // setup + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // + // Money amount = new MoneyBuilder().with(usDollars).with("300.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // Money secondTransactionAmount = new + // MoneyBuilder().with(usDollars).with("50.00").build(); + // LoanTransaction secondOnTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // processor.handleTransaction(secondOnTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("150.00", + // "200.00", singleInstallment); + // + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", + // "200.00", onTimePartialPayment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("50.00", + // "0.00", secondOnTimePartialPayment); + // } + // + // /** + // * Scenario 5:Single transaction which is equal to the total due for + // installment. + // * + // * Expectation: + // * - First installment shows interest completed and principal completed + // equal to their due amounts. (payment order interest, principal) + // * - transaction has interest portion and principal portions + // */ + // @Test + // public void + // givenSingleFullOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponentInFull() + // { + // + // // setup + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // + // Money amount = new + // MoneyBuilder().with(usDollars).with("1200.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", + // "200.00", singleInstallment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1000.00", + // "200.00", onTimePartialPayment); + // } + // + // /** + // * Scenario 6: Multiple transactions which together equal to the total due + // for installment. + // * + // * Expectation: + // * - First installment shows interest completed and principal completed + // equal to their due amounts. (payment order interest, principal) + // * - transaction has interest portion and principal portions + // */ + // @Test + // public void + // givenMuliptleOnTimeLoanTransactionsThatInFullShouldPayoffInterestThenPrincipalComponentInFull() + // { + // + // // setup + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // + // Money amount = new MoneyBuilder().with(usDollars).with("600.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // Money secondTransactionAmount = new + // MoneyBuilder().with(usDollars).with("600.00").build(); + // LoanTransaction secondOnTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // processor.handleTransaction(secondOnTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", + // "200.00", singleInstallment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", + // "200.00", onTimePartialPayment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("600.00", + // "0.00", secondOnTimePartialPayment); + // } + // + // /** + // * Scenario 7: Single transaction which is greater than total due for + // first installment. + // * + // * Expectation: + // * - First installment shows interest completed and principal completed + // equal to their due amounts. (payment order interest, principal) + // * - Second installment shows principal completed equal to the remaining + // amount + // * - transaction has interest portion and principal portions, the + // principal portion is the sum of principal completed for first and second + // installments + // */ + // @Test + // public void + // givenSingleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() + // { + // + // // setup + // Money amount = new + // MoneyBuilder().with(usDollars).with("1300.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // LoanRepaymentScheduleInstallment firstInstallment = + // this.installments.get(0); + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", + // "200.00", firstInstallment); + // + // LoanRepaymentScheduleInstallment secondInstallment = + // this.installments.get(1); + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", + // "0.00", secondInstallment); + // + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1100.00", + // "200.00", onTimePartialPayment); + // } + // + // /** + // * Scenario 8: Multiple transactions which together are greater than total + // due for first installment. + // * + // * Expectation: + // * - First installment shows interest completed and principal completed + // equal to their due amounts. (payment order interest, principal) + // * - Second installment shows principal completed equal to the remaining + // amount + // */ + // @Test + // public void + // givenMultipleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() + // { + // + // // setup + // Money amount = new MoneyBuilder().with(usDollars).with("600.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // Money secondTransactionAmount = new + // MoneyBuilder().with(usDollars).with("700.00").build(); + // LoanTransaction secondOnTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // processor.handleTransaction(secondOnTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // LoanRepaymentScheduleInstallment singleInstallment = + // this.installments.get(0); + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", + // "200.00", singleInstallment); + // + // LoanRepaymentScheduleInstallment secondInstallment = + // this.installments.get(1); + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", + // "0.00", secondInstallment); + // + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", + // "200.00", onTimePartialPayment); + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", + // "0.00", secondOnTimePartialPayment); + // } + // + // /** + // * Scenario 9: Single transaction which overpays first installment and + // second installment with outstanding amount been account as principal in + // third installment. + // * + // * Where an installments principal is paid for fully in advance - the + // interest component is waived. + // */ + // @Test + // public void + // givenOverPaymentShouldPayoffInterestThenPrincipalComponentsOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfAllSubsequentInstallments() + // { + // // setup + // Money amount = new + // MoneyBuilder().with(usDollars).with("3000.00").build(); + // LoanTransaction onTimePartialPayment = new + // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); + // + // // execute test + // processor.handleTransaction(onTimePartialPayment, usDollars, + // installments); + // + // // verification of derived fields on installments + // LoanRepaymentScheduleInstallment firstInstallment = + // this.installments.get(0); + // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), + // interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, + // usDollars); + // + // LoanRepaymentScheduleInstallment secondInstallment = + // this.installments.get(1); + // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), + // interestOf("0.00"), interestWaivedOf("200.00"), secondInstallment, + // usDollars); + // + // LoanRepaymentScheduleInstallment thirdInstallment = + // this.installments.get(2); + // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("800.00"), + // interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, + // usDollars); + // + // assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"), + // interestOf("200.00"), onTimePartialPayment, usDollars); + // } + // + // /** + // * Scenario 10: Single transaction which is a repayment in advance + // */ + // @Test + // public void + // givenRepaymentOfInstallmentInAdvanceShouldPayoffOnlyPrincipalComponent() + // { + // // setup + // installments = + // LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, + // usDollars); + // LoanRepaymentScheduleInstallment firstInstallment = + // this.installments.get(0); + // LocalDate paymentInAdvanceDate = + // firstInstallment.getDueDate().minusDays(1); + // + // Money amount = new MoneyBuilder().with(usDollars).with("900.00").build(); + // LoanTransaction paymentInAdvance = new + // LoanTransactionBuilder().repayment().with(paymentInAdvanceDate).with(amount).build(); + // + // // execute test + // processor.handleTransaction(paymentInAdvance, usDollars, installments); + // + // // verification of derived fields on installments + // LoanRepaymentScheduleInstallment secondInstallment = + // this.installments.get(1); + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("900.00", + // "0.00", secondInstallment); + // + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("900.00", + // "0.00", paymentInAdvance); + // } + // + // /** + // * Scenario 11: Single transaction which is a repayment many days early + // but still does not qualify for 'in advance'. + // */ + // @Test + // public void + // givenRepaymentOfInstallmentBeforeDueDateButNotInAdvanceShouldPayoffInterestAndPrincipalComponents() + // { + // // setup + // installments = + // LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, + // usDollars); + // LoanRepaymentScheduleInstallment firstInstallment = + // this.installments.get(0); + // LocalDate paymentBeforeDueDateButNotInAdvanceDate = + // firstInstallment.getDueDate().plusDays(1); + // + // Money amount = new MoneyBuilder().with(usDollars).with("900.00").build(); + // LoanTransaction paymentBeforeDueDateButNotInAdvance = new + // LoanTransactionBuilder().repayment().with(paymentBeforeDueDateButNotInAdvanceDate).with(amount).build(); + // + // // execute test + // processor.handleTransaction(paymentBeforeDueDateButNotInAdvance, + // usDollars, installments); + // + // // verification of derived fields on installments + // LoanRepaymentScheduleInstallment secondInstallment = + // this.installments.get(1); + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("700.00", + // "200.00", secondInstallment); + // + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", + // "200.00", paymentBeforeDueDateButNotInAdvance); + // } + // + // + // /** + // * Scenario 12: Single transaction which is a repayment many days early + // but still does not qualify for 'in advance'. + // */ + // @Test + // public void + // givenLateRepaymentOfInstallmentShouldPayoffInterestAndPrincipalComponentsOfOverdueInstallmentsWithNoWaiveOfInterest() + // { + // // setup + // installments = + // LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars); + // LoanRepaymentScheduleInstallment firstInstallment = + // this.installments.get(0); + // LocalDate latePaymentDate = firstInstallment.getDueDate().plusMonths(5); + // + // Money amount = new + // MoneyBuilder().with(usDollars).with("3600.00").build(); + // LoanTransaction lateRepaymentTransaction = new + // LoanTransactionBuilder().repayment().with(latePaymentDate).with(amount).build(); + // + // // execute test + // processor.handleTransaction(lateRepaymentTransaction, usDollars, + // installments); + // + // // verification of derived fields on installments + // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), + // interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, + // usDollars); + // + // LoanRepaymentScheduleInstallment secondInstallment = + // this.installments.get(1); + // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), + // interestOf("200.00"), interestWaivedOf("0.00"), secondInstallment, + // usDollars); + // + // LoanRepaymentScheduleInstallment thirdInstallment = + // this.installments.get(2); + // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), + // interestOf("200.00"), interestWaivedOf("0.00"), thirdInstallment, + // usDollars); + // + // assertThatLoanTransactionHasDerivedFieldsOf(principalOf("3000.00"), + // interestOf("600.00"), lateRepaymentTransaction, usDollars); + // } + // + // + // private void + // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf( + // final String principal, final String interest, final LoanTransaction + // transaction) { + // + // Money expectedInterestPortion = new + // MoneyBuilder().with(usDollars).with(interest).build(); + // assertThat(transaction.getInterestPortion(usDollars).toString(), + // is(expectedInterestPortion.toString())); + // + // Money expectedPrincipalPortion = new + // MoneyBuilder().with(usDollars).with(principal).build(); + // assertThat(transaction.getPrincipalPortion(usDollars).toString(), + // is(expectedPrincipalPortion.toString())); + // } + // + // private void + // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf(final + // String principal, final String interest, + // final LoanRepaymentScheduleInstallment installment) { + // Money expectedInterestCompleted = new + // MoneyBuilder().with(usDollars).with(interest).build(); + // assertThat(installment.getInterestCompleted(usDollars).toString(), + // is(expectedInterestCompleted.toString())); + // + // Money expectedPrincipalCompleted = new + // MoneyBuilder().with(usDollars).with(principal).build(); + // assertThat(installment.getPrincipalCompleted(usDollars).toString(), + // is(expectedPrincipalCompleted.toString())); + // } + // + // private void assertThatLoanTransactionHasDerivedFieldsOf( + // final String principal, + // final String interest, + // final LoanTransaction transaction, final MonetaryCurrency currency) { + // + // Money expectedPrincipalPortion = new + // MoneyBuilder().with(currency).with(principal).build(); + // assertThat("Principal portion of transaction not as expected: ", + // transaction.getPrincipalPortion(currency).toString(), + // is(expectedPrincipalPortion.toString())); + // + // Money expectedInterestPortion = new + // MoneyBuilder().with(currency).with(interest).build(); + // assertThat("Interest portion of transaction not as expected: ", + // transaction.getInterestPortion(currency).toString(), + // is(expectedInterestPortion.toString())); + // } + // + // private void assertThatLoanInstallmentHasDerivedFieldsOf( + // final String principal, + // final String interest, + // final String interestWaived, + // final LoanRepaymentScheduleInstallment installment, final + // MonetaryCurrency currency) { + // + // Money expectedPrincipalCompleted = new + // MoneyBuilder().with(currency).with(principal).build(); + // assertThat("principal not as expected", + // installment.getPrincipalCompleted(currency).toString(), + // is(expectedPrincipalCompleted.toString())); + // + // Money expectedInterestCompleted = new + // MoneyBuilder().with(currency).with(interest).build(); + // assertThat("interest completed not as expected: ",installment.getInterestCompleted(currency).toString(), + // is(expectedInterestCompleted.toString())); + // + // Money expectedInterestWaived = new + // MoneyBuilder().with(currency).with(interestWaived).build(); + // assertThat("interest waived not as expected: ", + // installment.getInterestWaived(currency).toString(), + // is(expectedInterestWaived.toString())); + // } + // + // private String principalOf(final String value) { + // return value; + // } + // + // private String interestOf(final String value) { + // return value; + // } + // + // private String interestWaivedOf(final String value) { + // return value; + // } } \ No newline at end of file