/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.platform.cashflow.ui.model;
import org.apache.commons.lang.StringUtils;
import org.mifos.platform.cashflow.CashFlowConstants;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.binding.message.MessageResolver;
import org.springframework.binding.validation.ValidationContext;
import java.math.BigDecimal;
import java.math.RoundingMode;
import static java.text.MessageFormat.format;
public class CashFlowValidator {
public void validateCaptureCashFlow(CashFlowForm cashFlow, ValidationContext context) {
MessageContext messageContext = context.getMessageContext();
for (MonthlyCashFlowForm monthlyCashFlowForm : cashFlow.getMonthlyCashFlows()) {
validateExpense(messageContext, monthlyCashFlowForm);
validateRevenue(messageContext, monthlyCashFlowForm);
validateNotes(messageContext, monthlyCashFlowForm);
}
validateCumulativeCashFlow(cashFlow, messageContext);
validateTotalCapitalAndLiability(cashFlow, messageContext);
validateIndebtednessRatio(cashFlow, messageContext);
setTotalsOnCashFlowForm(cashFlow, messageContext);
}
private void validateCumulativeCashFlow(CashFlowForm cashFlow, MessageContext messageContext) {
if (!messageContext.hasErrorMessages()) {
for (MonthlyCashFlowForm monthlyCashFlowForm : cashFlow.getMonthlyCashFlows()) {
validateCumulativeCashFlow(messageContext, monthlyCashFlowForm);
}
}
}
private void validateCumulativeCashFlow(MessageContext messageContext, MonthlyCashFlowForm monthlyCashFlowForm) {
if (monthlyCashFlowForm.cumulativeCashFlowIsLessThanOrEqualToZero()) {
String message = format("Cumulative cash flow for {0} {1} should be greater than zero", monthlyCashFlowForm.getMonthInLocale(),
Integer.toString(monthlyCashFlowForm.getYear()));
constructErrorMessage(CashFlowConstants.CUMULATIVE_CASH_FLOW_FOR_MONTH_SHOULD_BE_GREATER_THAN_ZERO, message, messageContext,
monthlyCashFlowForm.getMonthInLocale(), Integer.toString(monthlyCashFlowForm.getYear()));
}
}
private void setTotalsOnCashFlowForm(CashFlowForm cashFlowForm, MessageContext messageContext) {
if (!messageContext.hasErrorMessages()) {
BigDecimal totalExpenses = BigDecimal.ZERO, totalRevenues = BigDecimal.ZERO;
for (MonthlyCashFlowForm monthlyCashFlowForm : cashFlowForm.getMonthlyCashFlows()) {
totalExpenses = totalExpenses.add(monthlyCashFlowForm.getExpense());
totalRevenues = totalRevenues.add(monthlyCashFlowForm.getRevenue());
}
cashFlowForm.setTotalExpenses(totalExpenses);
cashFlowForm.setTotalRevenues(totalRevenues);
}
}
private void validateTotalCapitalAndLiability(CashFlowForm cashFlow, MessageContext messageContext) {
if (cashFlow.isCaptureCapitalLiabilityInfo()) {
validateTotalCapital(messageContext, cashFlow.getTotalCapital());
validateTotalLiability(messageContext, cashFlow.getTotalLiability());
}
}
private void validateIndebtednessRatio(CashFlowForm cashFlowForm, MessageContext messageContext) {
if (cashFlowForm.shouldForValidateIndebtednessRate()) {
Double indebtednessRatio = cashFlowForm.getIndebtednessRatio();
BigDecimal loanAmount = cashFlowForm.getLoanAmount();
BigDecimal totalCapital = cashFlowForm.getTotalCapital();
BigDecimal totalLiability = cashFlowForm.getTotalLiability();
Double calculatedIndebtednessRatio = totalLiability.add(loanAmount).multiply(CashFlowConstants.HUNDRED).
divide(totalCapital,2,RoundingMode.HALF_EVEN).doubleValue();
if (calculatedIndebtednessRatio >= indebtednessRatio) {
String message = format("Indebtedness rate of the client is {0} which should be lesser than the allowable value of {1}",
calculatedIndebtednessRatio, indebtednessRatio);
constructErrorMessage(CashFlowConstants.INDEBTEDNESS_RATIO_MORE_THAN_ALLOWED, message, messageContext, calculatedIndebtednessRatio, indebtednessRatio);
}
}
}
private void validateTotalCapital(MessageContext messageContext, BigDecimal totalCapital) {
if (isNull(totalCapital)) {
String message = format("Please specify the total capital");
constructErrorMessage(CashFlowConstants.TOTAL_CAPITAL_SHOULD_NOT_BE_EMPTY, message, messageContext);
return;
}
if ((totalCapital.doubleValue() <= 0)) {
String message = format("Total Capital needs to be a value greater than zero");
constructErrorMessage(CashFlowConstants.TOTAL_CAPITAL_SHOULD_BE_GREATER_THAN_ZERO, message, messageContext);
}
}
private void validateTotalLiability(MessageContext messageContext, BigDecimal totalLiability) {
if (isNull(totalLiability)) {
String message = format("Please specify the total liability");
constructErrorMessage(CashFlowConstants.TOTAL_LIABILITY_SHOULD_NOT_BE_EMPTY, message, messageContext);
return;
}
if (totalLiability.doubleValue() < 0) {
String message = format("Total Liability needs to be non negative");
constructErrorMessage(CashFlowConstants.TOTAL_LIABILITY_SHOULD_BE_NON_NEGATIVE, message, messageContext);
}
}
private void validateExpense(MessageContext messageContext, MonthlyCashFlowForm monthlyCashFlowForm) {
if (monthlyCashFlowForm.hasNoExpense()) {
String message = format("Please specify expense for {0} {1}.", monthlyCashFlowForm.getMonthInLocale(),
Integer.toString(monthlyCashFlowForm.getYear()));
constructErrorMessage(CashFlowConstants.EMPTY_EXPENSE, message, messageContext,
monthlyCashFlowForm.getMonthInLocale(), Integer.toString(monthlyCashFlowForm.getYear()));
}
}
private void validateRevenue(MessageContext messageContext, MonthlyCashFlowForm monthlyCashFlowForm) {
if (monthlyCashFlowForm.hasNoRevenue()) {
String message = format("Please specify revenue for {0} {1}.", monthlyCashFlowForm.getMonthInLocale(),
Integer.toString(monthlyCashFlowForm.getYear()));
constructErrorMessage(CashFlowConstants.EMPTY_REVENUE, message, messageContext,
monthlyCashFlowForm.getMonthInLocale(), Integer.toString(monthlyCashFlowForm.getYear()));
}
}
private void validateNotes(MessageContext messageContext, MonthlyCashFlowForm monthlyCashFlowForm) {
if (!StringUtils.isEmpty(monthlyCashFlowForm.getNotes()) && monthlyCashFlowForm.getNotes().length() > 300) {
String message = format("Notes should be less than 300 characters for {0} {1}.", monthlyCashFlowForm.getMonthInLocale(),
Integer.toString(monthlyCashFlowForm.getYear()));
constructErrorMessage(CashFlowConstants.EMPTY_NOTES, message, messageContext,
monthlyCashFlowForm.getMonthInLocale(), Integer.toString(monthlyCashFlowForm.getYear()));
}
}
private boolean isNull(BigDecimal value) {
return value == null;
}
void constructErrorMessage(String code, String message, MessageContext context, Object... args) {
MessageResolver messageResolver = new MessageBuilder().error().code(code).defaultText(message).args(args).build();
context.addMessage(messageResolver);
}
}