tidy up datatables api and ensure principal is paid off before interest in advance and partial payment cases.

This commit is contained in:
Keith Woodlock
2013-01-02 13:40:16 +00:00
parent 578bbc2954
commit 127a5efbc3
4 changed files with 828 additions and 750 deletions
@@ -1,8 +1,6 @@
package org.mifosplatform.infrastructure.dataqueries.api; package org.mifosplatform.infrastructure.dataqueries.api;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
@@ -13,16 +11,10 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; 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 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.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier; 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.data.GenericResultsetData;
import org.mifosplatform.infrastructure.dataqueries.service.GenericDataService; import org.mifosplatform.infrastructure.dataqueries.service.GenericDataService;
import org.mifosplatform.infrastructure.dataqueries.service.ReadWriteNonCoreDataService; import org.mifosplatform.infrastructure.dataqueries.service.ReadWriteNonCoreDataService;
import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; 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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -45,242 +33,143 @@ import org.springframework.stereotype.Component;
@Scope("singleton") @Scope("singleton")
public class DataTableApiResource { public class DataTableApiResource {
private final static Logger logger = LoggerFactory private final PlatformSecurityContext context;
.getLogger(DataTableApiResource.class); private final GenericDataService genericDataService;
private final ReadWriteNonCoreDataService readWriteNonCoreDataService;
private final ToApiJsonSerializer<GenericResultsetData> toApiJsonSerializer;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final PlatformSecurityContext context; @Autowired
private final GenericDataService genericDataService; public DataTableApiResource(final PlatformSecurityContext context, final GenericDataService genericDataService,
private final ReadWriteNonCoreDataService readWriteNonCoreDataService; final ReadWriteNonCoreDataService readWriteNonCoreDataService,
private final ToApiJsonSerializer<GenericResultsetData> toApiJsonSerializer; final ToApiJsonSerializer<GenericResultsetData> toApiJsonSerializer,
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.genericDataService = genericDataService;
this.readWriteNonCoreDataService = readWriteNonCoreDataService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@Autowired @GET
public DataTableApiResource( @Consumes({ MediaType.APPLICATION_JSON })
final PlatformSecurityContext context, @Produces({ MediaType.APPLICATION_JSON })
final GenericDataService genericDataService, public String getDatatables(@QueryParam("apptable") final String apptable, @Context final UriInfo uriInfo) {
final ReadWriteNonCoreDataService readWriteNonCoreDataService,
ToApiJsonSerializer<GenericResultsetData> toApiJsonSerializer,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.genericDataService = genericDataService;
this.readWriteNonCoreDataService = readWriteNonCoreDataService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET final List<DatatableData> result = this.readWriteNonCoreDataService.retrieveDatatableNames(apptable);
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String getDatatables(@QueryParam("apptable") final String apptable,
@Context final UriInfo uriInfo) {
final List<DatatableData> result = this.readWriteNonCoreDataService final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
.retrieveDatatableNames(apptable); return this.toApiJsonSerializer.serializePretty(prettyPrint, result);
}
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo @POST
.getQueryParameters()); @Path("register/{datatable}/{apptable}")
return this.toApiJsonSerializer.serializePretty(prettyPrint, result); @Consumes({ MediaType.APPLICATION_JSON })
} @Produces({ MediaType.APPLICATION_JSON })
public String registerDatatable(@PathParam("datatable") final String datatable, @PathParam("apptable") final String apptable) {
@POST this.readWriteNonCoreDataService.registerDatatable(datatable, apptable);
@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); 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 this.readWriteNonCoreDataService.deregisterDatatable(datatable);
@Path("deregister/{datatable}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deregisterDatatable(
@PathParam("datatable") final String 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 context.authenticatedUser().validateHasDatatableReadPermission(datatable);
@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) {
checkUserPermissionForDatatable(datatable, "READ"); GenericResultsetData results = this.readWriteNonCoreDataService.retrieveDataTableGenericResultSet(datatable, apptableId, order,
null);
GenericResultsetData results = this.readWriteNonCoreDataService String json = "";
.retrieveDataTableGenericResultSet(datatable, apptableId, final boolean genericResultSet = ApiParameterHelper.genericResultSet(uriInfo.getQueryParameters());
order, null); if (genericResultSet) {
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
json = this.toApiJsonSerializer.serializePretty(prettyPrint, results);
} else {
json = this.genericDataService.generateJsonFromGenericResultsetData(results);
}
String json = ""; return 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; @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 final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("CREATE", datatable, "CREATE",
@Path("{datatable}/{apptableId}") "datatables/" + datatable, apptableId, apiRequestBodyAsJson);
@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 return this.toApiJsonSerializer.serialize(entityIdentifier);
.logCommandSource("CREATE", datatable, "CREATE", "datatables/"+datatable, }
apptableId, apiRequestBodyAsJson);
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 final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", datatable, "UPDATE",
@Path("{datatable}/{apptableId}") "datatables/" + datatable, apptableId, apiRequestBodyAsJson);
@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<String, String> queryParams = getQueryParamsFromJsonRequestBody(jsonRequestBody);
final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService return this.toApiJsonSerializer.serialize(entityIdentifier);
.logCommandSource("UPDATE", datatable, "UPDATE", "datatables/"+datatable, }
apptableId, apiRequestBodyAsJson);
// this.readWriteNonCoreDataService.updateDatatableEntryOnetoOne( @PUT
// datatable, apptableId, queryParams); @Path("{datatable}/{apptableId}/{datatableId}")
// @Consumes({ MediaType.APPLICATION_JSON })
// EntityIdentifier entityIdentifier = EntityIdentifier.resourceResult( @Produces({ MediaType.APPLICATION_JSON })
// Long.valueOf(apptableId), null); public String updateDatatableEntryOneToMany(@PathParam("datatable") final String datatable,
@PathParam("apptableId") final Long apptableId, @PathParam("datatableId") final Long datatableId,
final String apiRequestBodyAsJson) {
return this.toApiJsonSerializer.serialize(entityIdentifier); final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", datatable,
} "UPDATE_MULTIPLE", "datatables/" + datatable, apptableId, "datatables/" + datatable, datatableId, apiRequestBodyAsJson);
@PUT return this.toApiJsonSerializer.serialize(entityIdentifier);
@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 @DELETE
.logCommandSource("UPDATE", datatable, "UPDATE_MULTIPLE", "datatables/"+datatable, apptableId, "datatables/"+datatable, datatableId, apiRequestBodyAsJson); @Path("{datatable}/{apptableId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId) {
return this.toApiJsonSerializer.serialize(entityIdentifier); final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("DELETE", datatable, "DELETE",
"datatables/" + datatable, apptableId, "{}");
// checkUserPermissionForDatatable(datatable, "UPDATE"); return this.toApiJsonSerializer.serialize(entityIdentifier);
// Map<String, String> queryParams = getQueryParamsFromJsonRequestBody(jsonRequestBody); }
//
// this.readWriteNonCoreDataService.updateDatatableEntryOnetoMany(
// datatable, apptableId, datatableId, queryParams);
//
// EntityIdentifier entityIdentifier = EntityIdentifier.resourceResult(
// Long.valueOf(apptableId), null);
//
// return this.toApiJsonSerializer.serialize(entityIdentifier);
}
@DELETE @DELETE
@Path("{datatable}/{apptableId}") @Path("{datatable}/{apptableId}/{datatableId}")
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String deleteDatatableEntries( public String deleteDatatableEntries(@PathParam("datatable") final String datatable, @PathParam("apptableId") final Long apptableId,
@PathParam("datatable") final String datatable, @PathParam("datatableId") final Long datatableId) {
@PathParam("apptableId") final Long apptableId) {
final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService.logCommandSource("DELETE", datatable,
.logCommandSource("DELETE", datatable, "DELETE", "datatables/"+datatable, "DELETE_MULTIPLE", "datatables/" + datatable, apptableId, "datatables/" + datatable, datatableId, "{}");
apptableId, "{}");
return this.toApiJsonSerializer.serialize(entityIdentifier); return this.toApiJsonSerializer.serialize(entityIdentifier);
} }
@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) {
final EntityIdentifier entityIdentifier = this.commandsSourceWritePlatformService
.logCommandSource("DELETE", datatable, "DELETE_MULTIPLE", "datatables/"+datatable, apptableId, "datatables/"+datatable, datatableId, "{}");
return this.toApiJsonSerializer.serialize(entityIdentifier);
}
private Map<String, String> getQueryParamsFromJsonRequestBody(
final String jsonRequestBody) {
Map<String, String> queryParams = new HashMap<String, String>();
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);
}
}
} }
@@ -16,144 +16,138 @@ import org.mifosplatform.organisation.monetary.domain.Money;
* installment, the over paid amount is pay off on the principal component of * installment, the over paid amount is pay off on the principal component of
* subsequent installments. * 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") @SuppressWarnings("unused")
public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor { public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
/** /**
* For late repayments, pay off in the same way as on-time payments, * For late repayments, pay off in the same way as on-time payments,
* interest first then principal. * interest first then principal.
*/ */
@Override @Override
protected Money handleTransactionThatIsALateRepaymentOfInstallment( protected Money handleTransactionThatIsALateRepaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
final LoanRepaymentScheduleInstallment currentInstallment, final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final List<LoanRepaymentScheduleInstallment> installments, final Money transactionAmountUnprocessed) {
final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed); return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, transactionAmountUnprocessed);
} }
@Override @Override
protected boolean isTransactionInAdvanceOfInstallment( protected boolean isTransactionInAdvanceOfInstallment(final int currentInstallmentIndex,
final int currentInstallmentIndex, final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate, final Money transactionAmount) {
final List<LoanRepaymentScheduleInstallment> installments,
final LocalDate transactionDate,
final Money transactionAmount) {
boolean isInAdvance = false; boolean isInAdvance = false;
LocalDate lastInstallmentDueDate = null; LocalDate lastInstallmentDueDate = null;
if (currentInstallmentIndex > 0) { int previousInstallmentIndex = 0;
int previousInstallmentIndex = currentInstallmentIndex - 1; if (currentInstallmentIndex > 0) {
LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex); previousInstallmentIndex = currentInstallmentIndex - 1;
lastInstallmentDueDate = previousInstallment.getDueDate(); }
return !transactionDate.isAfter(lastInstallmentDueDate); LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex);
} lastInstallmentDueDate = previousInstallment.getDueDate();
return isInAdvance; 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<LoanRepaymentScheduleInstallment> installments,
final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
final MonetaryCurrency currency = paymentInAdvance.getCurrency(); /**
Money transactionAmountRemaining = paymentInAdvance; * For early/'in advance' repayments, pays off principal component only.
Money principalPortion = Money.zero(currency); */
Money interestPortion = Money.zero(currency); @Override
Money feeChargesPortion = Money.zero(currency); protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
Money penaltyChargesPortion = Money.zero(currency); final List<LoanRepaymentScheduleInstallment> installments, final LoanTransaction loanTransaction,
final LocalDate transactionDate, final Money paymentInAdvance) {
if (loanTransaction.isInterestWaiver()) { final MonetaryCurrency currency = paymentInAdvance.getCurrency();
interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); Money transactionAmountRemaining = paymentInAdvance;
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); Money principalPortion = Money.zero(currency);
} else { Money interestPortion = Money.zero(currency);
Money feeChargesPortion = Money.zero(currency);
Money penaltyChargesPortion = Money.zero(currency);
if (currentInstallment.isPrincipalNotCompleted(currency)) { if (loanTransaction.isInterestWaiver()) {
principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
if (currentInstallment.isPrincipalCompleted(currency)) { transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
// FIXME - KW - if auto waiving interest need to create another transaction to handle this. } else {
currentInstallment.waiveInterestComponent(currentInstallment.getInterest(currency));
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); 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));
}
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
}
penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining); transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); }
feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining); // 1. pay of principal with over payment.
transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion);
}
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining);
return transactionAmountRemaining; transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
} }
/** loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
* For normal on-time repayments, pays off interest first, then principal. return transactionAmountRemaining;
*/ }
@Override
protected Money handleTransactionThatIsOnTimePaymentOfInstallment(
final LoanRepaymentScheduleInstallment currentInstallment,
final LoanTransaction loanTransaction,
final Money transactionAmountUnprocessed) {
final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency(); /**
Money transactionAmountRemaining = transactionAmountUnprocessed; * For normal on-time repayments, pays off interest first, then principal.
Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency()); */
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency()); @Override
Money feeChargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); protected Money handleTransactionThatIsOnTimePaymentOfInstallment(final LoanRepaymentScheduleInstallment currentInstallment,
Money penaltyChargesPortion = Money.zero(transactionAmountRemaining.getCurrency()); final LoanTransaction loanTransaction, final Money transactionAmountUnprocessed) {
if (loanTransaction.isChargesWaiver()) { final MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
penaltyChargesPortion = currentInstallment.waivePenaltyChargesComponent(loanTransaction.getPenaltyChargesPortion(currency)); Money transactionAmountRemaining = transactionAmountUnprocessed;
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion); Money principalPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money interestPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money feeChargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
Money penaltyChargesPortion = Money.zero(transactionAmountRemaining.getCurrency());
feeChargesPortion = currentInstallment.waiveFeeChargesComponent(loanTransaction.getFeeChargesPortion(currency)); if (loanTransaction.isChargesWaiver()) {
transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); penaltyChargesPortion = currentInstallment.waivePenaltyChargesComponent(loanTransaction.getPenaltyChargesPortion(currency));
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
} else if (loanTransaction.isInterestWaiver()) { feeChargesPortion = currentInstallment.waiveFeeChargesComponent(loanTransaction.getFeeChargesPortion(currency));
interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining); transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion);
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
} else {
penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining); } else if (loanTransaction.isInterestWaiver()) {
transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion); interestPortion = currentInstallment.waiveInterestComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
} else {
penaltyChargesPortion = currentInstallment.payPenaltyChargesComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(penaltyChargesPortion);
interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining); feeChargesPortion = currentInstallment.payFeeChargesComponent(transactionAmountRemaining);
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion); transactionAmountRemaining = transactionAmountRemaining.minus(feeChargesPortion);
principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining); // 1. pay of principal before interest.
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion); principalPortion = currentInstallment.payPrincipalComponent(transactionAmountRemaining);
} transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); interestPortion = currentInstallment.payInterestComponent(transactionAmountRemaining);
return transactionAmountRemaining; transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
} }
@Override loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion);
protected void onLoanOverpayment( return transactionAmountRemaining;
final LoanTransaction loanTransaction, }
final Money loanOverPaymentAmount) {
} @Override
protected void onLoanOverpayment(final LoanTransaction loanTransaction, final Money loanOverPaymentAmount) {}
} }
@@ -324,7 +324,7 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "REPAYMENTINPAST_LOAN", "PORTFOLIO_MANAGEMENT_SUPER_USER"); 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; if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "REPORTING_SUPER_USER", "READ_" + reportName)) return true;
@@ -490,4 +490,10 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
throw new NoAuthorizationException(authorizationMessage); throw new NoAuthorizationException(authorizationMessage);
} }
} }
public void validateHasDatatableReadPermission(final String datatable) {
if (hasNotPermissionForDatatable(datatable, "READ")) {
throw new NoAuthorizationException("Not authorised to read datatable: " + datatable);
}
}
} }
@@ -19,403 +19,592 @@ import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest { public class HeavensFamilyLoanRepaymentScheduleTransactionProcessorTest {
// class under test // class under test
private HeavensFamilyLoanRepaymentScheduleTransactionProcessor processor; private HeavensFamilyLoanRepaymentScheduleTransactionProcessor processor;
// //
private LocalDate july2nd = new LocalDate(2012, 7, 2); private LocalDate july2nd = new LocalDate(2012, 7, 2);
private MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build(); private MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build();
private List<LoanRepaymentScheduleInstallment> installments; private List<LoanRepaymentScheduleInstallment> installments;
@Before @Before
public void setUpForEachTestCase() { public void setUpForEachTestCase() {
installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars); installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars);
processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
} }
/** /**
* Scenario 1: Single transaction which is less than the interest component of the first installment. * 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) * Expectation: - First installment shows interest completed equal to that
* - transaction has interest portion equal to transaction amount, and zero principal portion * of transactions, zero principal completed. (payment order interest,
*/ * principal) - transaction has interest portion equal to transaction
@Test * amount, and zero principal portion
public void givenSingleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() { */
@Test
public void givenSingleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() {
// // setup // // setup
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); // 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 oneHundredDollars = new
// // MoneyBuilder().with(usDollars).with("100.00").build();
// // execute test // LoanTransaction onTimePartialPayment = new
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build();
// //
// // verification of derived fields on installments // // execute test
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", singleInstallment); // processor.handleTransaction(onTimePartialPayment, usDollars,
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", onTimePartialPayment); // 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. // * 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) // * Expectation:
// * - transactions has interest portion equal to transaction amount, and zero principal portion // * - First installment shows interest completed equal to that of
// */ // transactions, zero principal completed. (payment order interest,
// @Test // principal)
// public void givenMultipleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() { // * - transactions has interest portion equal to transaction amount, and
// // zero principal portion
// // setup // */
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); // @Test
// // public void
// Money oneHundredDollars = new MoneyBuilder().with(usDollars).with("100.00").build(); // givenMultipleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() {
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build(); //
// // // setup
// Money fiftyDollars = new MoneyBuilder().with(usDollars).with("50.00").build(); // LoanRepaymentScheduleInstallment singleInstallment =
// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(fiftyDollars).build(); // this.installments.get(0);
// //
// // Money oneHundredDollars = new
// // execute test // MoneyBuilder().with(usDollars).with("100.00").build();
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // LoanTransaction onTimePartialPayment = new
// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); // LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build();
// //
// // verification of derived fields on installments // Money fiftyDollars = new
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", "150.00", singleInstallment); // MoneyBuilder().with(usDollars).with("50.00").build();
// // LoanTransaction secondOnTimePartialPayment = new
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", onTimePartialPayment); // LoanTransactionBuilder().repayment().with(july2nd).with(fiftyDollars).build();
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "50.00", secondOnTimePartialPayment); //
// } //
// // // execute test
// /** // processor.handleTransaction(onTimePartialPayment, usDollars,
// * Scenario 3: Single transaction which is greater than the interest component of the first installment but less than the total due for installment. // installments);
// * // processor.handleTransaction(secondOnTimePartialPayment, usDollars,
// * Expectation: // installments);
// * - 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. // // verification of derived fields on installments
// */ // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00",
// @Test // "150.00", singleInstallment);
// public void givenSingleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() { //
// // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00",
// // setup // "100.00", onTimePartialPayment);
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00",
// // "50.00", secondOnTimePartialPayment);
// Money amount = new MoneyBuilder().with(usDollars).with("300.00").build(); // }
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); //
// // /**
// // execute test // * Scenario 3: Single transaction which is greater than the interest
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // component of the first installment but less than the total due for
// // installment.
// // verification of derived fields on installments // *
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", singleInstallment); // * Expectation:
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", onTimePartialPayment); // * - 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
// * Scenario 4: Single transaction which is greater than the interest component of the first installment but less than the total due for installment. // principal portion of remainder.
// * // */
// * Expectation: // @Test
// * - First installment shows interest completed equal to that interest due, remainder is against principal completed. (payment order interest, principal) // public void
// * - transaction has interest portion equal to interest expected and principal portion of remainder. // givenSingleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents()
// */ // {
// @Test //
// public void givenMultipleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() { // // setup
// // LoanRepaymentScheduleInstallment singleInstallment =
// // setup // this.installments.get(0);
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); //
// // Money amount = new MoneyBuilder().with(usDollars).with("300.00").build();
// Money amount = new MoneyBuilder().with(usDollars).with("300.00").build(); // LoanTransaction onTimePartialPayment = new
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// //
// Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("50.00").build(); // // execute test
// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); // processor.handleTransaction(onTimePartialPayment, usDollars,
// // installments);
// // execute test //
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // // verification of derived fields on installments
// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00",
// // "200.00", singleInstallment);
// // verification of derived fields on installments // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00",
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("150.00", "200.00", singleInstallment); // "200.00", onTimePartialPayment);
// // }
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", onTimePartialPayment); //
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("50.00", "0.00", secondOnTimePartialPayment); // /**
// } // * Scenario 4: Single transaction which is greater than the interest
// // component of the first installment but less than the total due for
// /** // installment.
// * Scenario 5:Single transaction which is equal to the total due for installment. // *
// * // * Expectation:
// * Expectation: // * - First installment shows interest completed equal to that interest
// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) // due, remainder is against principal completed. (payment order interest,
// * - transaction has interest portion and principal portions // principal)
// */ // * - transaction has interest portion equal to interest expected and
// @Test // principal portion of remainder.
// public void givenSingleFullOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponentInFull() { // */
// // @Test
// // setup // public void
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); // givenMultipleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents()
// // {
// Money amount = new MoneyBuilder().with(usDollars).with("1200.00").build(); //
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); // // setup
// // LoanRepaymentScheduleInstallment singleInstallment =
// // execute test // this.installments.get(0);
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); //
// // Money amount = new MoneyBuilder().with(usDollars).with("300.00").build();
// // verification of derived fields on installments // LoanTransaction onTimePartialPayment = new
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment); // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", onTimePartialPayment); //
// } // Money secondTransactionAmount = new
// // MoneyBuilder().with(usDollars).with("50.00").build();
// /** // LoanTransaction secondOnTimePartialPayment = new
// * Scenario 6: Multiple transactions which together equal to the total due for installment. // LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build();
// * //
// * Expectation: // // execute test
// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) // processor.handleTransaction(onTimePartialPayment, usDollars,
// * - transaction has interest portion and principal portions // installments);
// */ // processor.handleTransaction(secondOnTimePartialPayment, usDollars,
// @Test // installments);
// public void givenMuliptleOnTimeLoanTransactionsThatInFullShouldPayoffInterestThenPrincipalComponentInFull() { //
// // // verification of derived fields on installments
// // setup // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("150.00",
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); // "200.00", singleInstallment);
// //
// Money amount = new MoneyBuilder().with(usDollars).with("600.00").build(); // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00",
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); // "200.00", onTimePartialPayment);
// // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("50.00",
// Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("600.00").build(); // "0.00", secondOnTimePartialPayment);
// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); // }
// //
// // execute test // /**
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // * Scenario 5:Single transaction which is equal to the total due for
// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); // installment.
// // *
// // verification of derived fields on installments // * Expectation:
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment); // * - First installment shows interest completed and principal completed
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", "200.00", onTimePartialPayment); // equal to their due amounts. (payment order interest, principal)
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("600.00", "0.00", secondOnTimePartialPayment); // * - transaction has interest portion and principal portions
// } // */
// // @Test
// /** // public void
// * Scenario 7: Single transaction which is greater than total due for first installment. // givenSingleFullOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponentInFull()
// * // {
// * Expectation: //
// * - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal) // // setup
// * - Second installment shows principal completed equal to the remaining amount // LoanRepaymentScheduleInstallment singleInstallment =
// * - transaction has interest portion and principal portions, the principal portion is the sum of principal completed for first and second installments // this.installments.get(0);
// */ //
// @Test // Money amount = new
// public void givenSingleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() { // MoneyBuilder().with(usDollars).with("1200.00").build();
// // LoanTransaction onTimePartialPayment = new
// // setup // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// 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,
// // execute test // installments);
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); //
// // // verification of derived fields on installments
// // verification of derived fields on installments // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00",
// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); // "200.00", singleInstallment);
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", firstInstallment); // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1000.00",
// // "200.00", onTimePartialPayment);
// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); // }
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "0.00", secondInstallment); //
// // /**
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1100.00", "200.00", onTimePartialPayment); // * Scenario 6: Multiple transactions which together equal to the total due
// } // for installment.
// // *
// /** // * Expectation:
// * Scenario 8: Multiple transactions which together are greater than total due for first installment. // * - First installment shows interest completed and principal completed
// * // equal to their due amounts. (payment order interest, principal)
// * Expectation: // * - transaction has interest portion and principal portions
// * - 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
// @Test // givenMuliptleOnTimeLoanTransactionsThatInFullShouldPayoffInterestThenPrincipalComponentInFull()
// public void givenMultipleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() { // {
// //
// // setup // // setup
// Money amount = new MoneyBuilder().with(usDollars).with("600.00").build(); // LoanRepaymentScheduleInstallment singleInstallment =
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); // this.installments.get(0);
// //
// Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("700.00").build(); // Money amount = new MoneyBuilder().with(usDollars).with("600.00").build();
// LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build(); // LoanTransaction onTimePartialPayment = new
// // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// // execute test //
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // Money secondTransactionAmount = new
// processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments); // MoneyBuilder().with(usDollars).with("600.00").build();
// // LoanTransaction secondOnTimePartialPayment = new
// // verification of derived fields on installments // LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build();
// LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0); //
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment); // // execute test
// // processor.handleTransaction(onTimePartialPayment, usDollars,
// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); // installments);
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "0.00", secondInstallment); // processor.handleTransaction(secondOnTimePartialPayment, usDollars,
// // installments);
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", "200.00", onTimePartialPayment); //
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", "0.00", secondOnTimePartialPayment); // // verification of derived fields on installments
// } // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00",
// // "200.00", singleInstallment);
// /** // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00",
// * Scenario 9: Single transaction which overpays first installment and second installment with outstanding amount been account as principal in third installment. // "200.00", onTimePartialPayment);
// * // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("600.00",
// * Where an installments principal is paid for fully in advance - the interest component is waived. // "0.00", secondOnTimePartialPayment);
// */ // }
// @Test //
// public void givenOverPaymentShouldPayoffInterestThenPrincipalComponentsOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfAllSubsequentInstallments() { // /**
// // setup // * Scenario 7: Single transaction which is greater than total due for
// Money amount = new MoneyBuilder().with(usDollars).with("3000.00").build(); // first installment.
// LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build(); // *
// // * Expectation:
// // execute test // * - First installment shows interest completed and principal completed
// processor.handleTransaction(onTimePartialPayment, usDollars, installments); // equal to their due amounts. (payment order interest, principal)
// // * - Second installment shows principal completed equal to the remaining
// // verification of derived fields on installments // amount
// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); // * - transaction has interest portion and principal portions, the
// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars); // principal portion is the sum of principal completed for first and second
// // installments
// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); // */
// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("0.00"), interestWaivedOf("200.00"), secondInstallment, usDollars); // @Test
// // public void
// LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); // givenSingleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment()
// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("800.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); // {
// //
// assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"), interestOf("200.00"), onTimePartialPayment, usDollars); // // setup
// } // Money amount = new
// // MoneyBuilder().with(usDollars).with("1300.00").build();
// /** // LoanTransaction onTimePartialPayment = new
// * Scenario 10: Single transaction which is a repayment in advance // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// */ //
// @Test // // execute test
// public void givenRepaymentOfInstallmentInAdvanceShouldPayoffOnlyPrincipalComponent() { // processor.handleTransaction(onTimePartialPayment, usDollars,
// // setup // installments);
// installments = LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, usDollars); //
// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); // // verification of derived fields on installments
// LocalDate paymentInAdvanceDate = firstInstallment.getDueDate().minusDays(1); // LoanRepaymentScheduleInstallment firstInstallment =
// // this.installments.get(0);
// Money amount = new MoneyBuilder().with(usDollars).with("900.00").build(); // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00",
// LoanTransaction paymentInAdvance = new LoanTransactionBuilder().repayment().with(paymentInAdvanceDate).with(amount).build(); // "200.00", firstInstallment);
// //
// // execute test // LoanRepaymentScheduleInstallment secondInstallment =
// processor.handleTransaction(paymentInAdvance, usDollars, installments); // this.installments.get(1);
// // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00",
// // verification of derived fields on installments // "0.00", secondInstallment);
// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); //
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("900.00", "0.00", secondInstallment); // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1100.00",
// // "200.00", onTimePartialPayment);
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("900.00", "0.00", paymentInAdvance); // }
// } //
// // /**
// /** // * Scenario 8: Multiple transactions which together are greater than total
// * Scenario 11: Single transaction which is a repayment many days early but still does not qualify for 'in advance'. // due for first installment.
// */ // *
// @Test // * Expectation:
// public void givenRepaymentOfInstallmentBeforeDueDateButNotInAdvanceShouldPayoffInterestAndPrincipalComponents() { // * - First installment shows interest completed and principal completed
// // setup // equal to their due amounts. (payment order interest, principal)
// installments = LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, usDollars); // * - Second installment shows principal completed equal to the remaining
// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); // amount
// LocalDate paymentBeforeDueDateButNotInAdvanceDate = firstInstallment.getDueDate().plusDays(1); // */
// // @Test
// Money amount = new MoneyBuilder().with(usDollars).with("900.00").build(); // public void
// LoanTransaction paymentBeforeDueDateButNotInAdvance = new LoanTransactionBuilder().repayment().with(paymentBeforeDueDateButNotInAdvanceDate).with(amount).build(); // givenMultipleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment()
// // {
// // execute test //
// processor.handleTransaction(paymentBeforeDueDateButNotInAdvance, usDollars, installments); // // setup
// // Money amount = new MoneyBuilder().with(usDollars).with("600.00").build();
// // verification of derived fields on installments // LoanTransaction onTimePartialPayment = new
// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("700.00", "200.00", secondInstallment); //
// // Money secondTransactionAmount = new
// assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", "200.00", paymentBeforeDueDateButNotInAdvance); // MoneyBuilder().with(usDollars).with("700.00").build();
// } // LoanTransaction secondOnTimePartialPayment = new
// // LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build();
// //
// /** // // execute test
// * Scenario 12: Single transaction which is a repayment many days early but still does not qualify for 'in advance'. // processor.handleTransaction(onTimePartialPayment, usDollars,
// */ // installments);
// @Test // processor.handleTransaction(secondOnTimePartialPayment, usDollars,
// public void givenLateRepaymentOfInstallmentShouldPayoffInterestAndPrincipalComponentsOfOverdueInstallmentsWithNoWaiveOfInterest() { // installments);
// // setup //
// installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars); // // verification of derived fields on installments
// LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0); // LoanRepaymentScheduleInstallment singleInstallment =
// LocalDate latePaymentDate = firstInstallment.getDueDate().plusMonths(5); // this.installments.get(0);
// // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00",
// Money amount = new MoneyBuilder().with(usDollars).with("3600.00").build(); // "200.00", singleInstallment);
// LoanTransaction lateRepaymentTransaction = new LoanTransactionBuilder().repayment().with(latePaymentDate).with(amount).build(); //
// // LoanRepaymentScheduleInstallment secondInstallment =
// // execute test // this.installments.get(1);
// processor.handleTransaction(lateRepaymentTransaction, usDollars, installments); // assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00",
// // "0.00", secondInstallment);
// // verification of derived fields on installments //
// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars); // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00",
// // "200.00", onTimePartialPayment);
// LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1); // assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00",
// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), secondInstallment, usDollars); // "0.00", secondOnTimePartialPayment);
// // }
// LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2); //
// assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars); // /**
// // * Scenario 9: Single transaction which overpays first installment and
// assertThatLoanTransactionHasDerivedFieldsOf(principalOf("3000.00"), interestOf("600.00"), lateRepaymentTransaction, usDollars); // second installment with outstanding amount been account as principal in
// } // third installment.
// // *
// // * Where an installments principal is paid for fully in advance - the
// private void assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf( // interest component is waived.
// final String principal, final String interest, final LoanTransaction transaction) { // */
// // @Test
// Money expectedInterestPortion = new MoneyBuilder().with(usDollars).with(interest).build(); // public void
// assertThat(transaction.getInterestPortion(usDollars).toString(), is(expectedInterestPortion.toString())); // givenOverPaymentShouldPayoffInterestThenPrincipalComponentsOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfAllSubsequentInstallments()
// // {
// Money expectedPrincipalPortion = new MoneyBuilder().with(usDollars).with(principal).build(); // // setup
// assertThat(transaction.getPrincipalPortion(usDollars).toString(), is(expectedPrincipalPortion.toString())); // Money amount = new
// } // MoneyBuilder().with(usDollars).with("3000.00").build();
// // LoanTransaction onTimePartialPayment = new
// private void assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf(final String principal, final String interest, // LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
// final LoanRepaymentScheduleInstallment installment) { //
// Money expectedInterestCompleted = new MoneyBuilder().with(usDollars).with(interest).build(); // // execute test
// assertThat(installment.getInterestCompleted(usDollars).toString(), is(expectedInterestCompleted.toString())); // processor.handleTransaction(onTimePartialPayment, usDollars,
// // installments);
// Money expectedPrincipalCompleted = new MoneyBuilder().with(usDollars).with(principal).build(); //
// assertThat(installment.getPrincipalCompleted(usDollars).toString(), is(expectedPrincipalCompleted.toString())); // // verification of derived fields on installments
// } // LoanRepaymentScheduleInstallment firstInstallment =
// // this.installments.get(0);
// private void assertThatLoanTransactionHasDerivedFieldsOf( // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"),
// final String principal, // interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment,
// final String interest, // usDollars);
// final LoanTransaction transaction, final MonetaryCurrency currency) { //
// // LoanRepaymentScheduleInstallment secondInstallment =
// Money expectedPrincipalPortion = new MoneyBuilder().with(currency).with(principal).build(); // this.installments.get(1);
// assertThat("Principal portion of transaction not as expected: ", transaction.getPrincipalPortion(currency).toString(), is(expectedPrincipalPortion.toString())); // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"),
// // interestOf("0.00"), interestWaivedOf("200.00"), secondInstallment,
// Money expectedInterestPortion = new MoneyBuilder().with(currency).with(interest).build(); // usDollars);
// assertThat("Interest portion of transaction not as expected: ", transaction.getInterestPortion(currency).toString(), is(expectedInterestPortion.toString())); //
// } // LoanRepaymentScheduleInstallment thirdInstallment =
// // this.installments.get(2);
// private void assertThatLoanInstallmentHasDerivedFieldsOf( // assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("800.00"),
// final String principal, // interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment,
// final String interest, // usDollars);
// final String interestWaived, //
// final LoanRepaymentScheduleInstallment installment, final MonetaryCurrency currency) { // assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"),
// // interestOf("200.00"), onTimePartialPayment, usDollars);
// 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(); // * Scenario 10: Single transaction which is a repayment in advance
// assertThat("interest completed not as expected: ",installment.getInterestCompleted(currency).toString(), is(expectedInterestCompleted.toString())); // */
// // @Test
// Money expectedInterestWaived = new MoneyBuilder().with(currency).with(interestWaived).build(); // public void
// assertThat("interest waived not as expected: ", installment.getInterestWaived(currency).toString(), is(expectedInterestWaived.toString())); // givenRepaymentOfInstallmentInAdvanceShouldPayoffOnlyPrincipalComponent()
// } // {
// // // setup
// private String principalOf(final String value) { // installments =
// return value; // LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd,
// } // usDollars);
// // LoanRepaymentScheduleInstallment firstInstallment =
// private String interestOf(final String value) { // this.installments.get(0);
// return value; // LocalDate paymentInAdvanceDate =
// } // firstInstallment.getDueDate().minusDays(1);
// //
// private String interestWaivedOf(final String value) { // Money amount = new MoneyBuilder().with(usDollars).with("900.00").build();
// return value; // 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;
// }
} }