package org.mifos.platform.cashflow.ui.model; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mifos.platform.cashflow.CashFlowConstants; import org.mifos.platform.cashflow.service.CashFlowDetail; import org.mifos.platform.cashflow.service.MonthlyCashFlowDetail; import org.mifos.platform.matchers.MessageMatcher; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.binding.message.MessageContext; import org.springframework.binding.message.MessageResolver; import org.springframework.binding.validation.ValidationContext; import java.math.BigDecimal; import static java.util.Arrays.asList; import static java.util.Collections.EMPTY_LIST; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.*; @SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.class) public class CashFlowValidatorTest { private CashFlowValidator cashFlowValidator; @Mock private ValidationContext validationContext; @Mock private MessageContext messageContext; @Before public void setUp() throws Exception { cashFlowValidator = new CashFlowValidator(); } @Test public void validateCaptureCashFlow() throws Exception { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(new BigDecimal(123d)); cashFlowDetail.setTotalLiability(new BigDecimal(456d)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, null, 0d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext, never()).addMessage(Matchers.<MessageResolver>anyObject()); } @Test public void doNotValidateTotalCapitalAndLiabilityIfCaptureCapitalLiabilityInfoIsNotSet() throws Exception { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(null); cashFlowDetail.setTotalLiability(null); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, false, null, 0d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext, never()).addMessage(Matchers.<MessageResolver>anyObject()); } @Test public void validateCaptureCashFlowWhenTotalCapitalIsZero() throws Exception { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(new BigDecimal(0)); cashFlowDetail.setTotalLiability(new BigDecimal(0)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, null, 0d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.TOTAL_CAPITAL_SHOULD_BE_GREATER_THAN_ZERO))); } @Test public void validateCaptureCashFlowWhenTotalCapitalAndLiabilityIsNull() throws Exception { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(null); cashFlowDetail.setTotalLiability(null); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, null, 0d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.TOTAL_CAPITAL_SHOULD_NOT_BE_EMPTY))); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.TOTAL_LIABILITY_SHOULD_NOT_BE_EMPTY))); } @Test public void validateCaptureCashFlowWhenTotalCapitalAndTotalLiabilityIsNegative() throws Exception { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(new BigDecimal(-23)); cashFlowDetail.setTotalLiability(new BigDecimal(-1)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, null, 0d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.TOTAL_CAPITAL_SHOULD_BE_GREATER_THAN_ZERO))); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.TOTAL_LIABILITY_SHOULD_BE_NON_NEGATIVE))); } @Test public void validateForCalculatedIndebtednessRateGreaterThanOrEqualToIndebtednessRate() { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(new BigDecimal(100d)); cashFlowDetail.setTotalLiability(new BigDecimal(5d)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, new BigDecimal(1000d), 1000d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.INDEBTEDNESS_RATIO_MORE_THAN_ALLOWED))); } @Test public void indebtednessRateCalculationShouldNotThrowAnyExceptionsOnUnterminatedDecimalPlaceCalculation() { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(new BigDecimal(33d)); cashFlowDetail.setTotalLiability(new BigDecimal(5d)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, new BigDecimal(1000d), 1000d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext).addMessage(argThat(new MessageMatcher(CashFlowConstants.INDEBTEDNESS_RATIO_MORE_THAN_ALLOWED))); } @Test public void shouldNotValidateForCalculatedIndebtednessRateLessThanIndebtednessRate() { when(validationContext.getMessageContext()).thenReturn(messageContext); CashFlowDetail cashFlowDetail = new CashFlowDetail(EMPTY_LIST); cashFlowDetail.setTotalCapital(new BigDecimal(1000d)); cashFlowDetail.setTotalLiability(new BigDecimal(5d)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, true, new BigDecimal(1000d), 1000d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(validationContext).getMessageContext(); verify(messageContext, never()).addMessage(Matchers.<MessageResolver>anyObject()); } @Test public void shouldComputeTotalExpenseAndTotalRevenueForAllMonthlyCashFlows() { when(validationContext.getMessageContext()).thenReturn(messageContext); when(messageContext.hasErrorMessages()).thenReturn(false); MonthlyCashFlowDetail cashFlowDetail1 = new MonthlyCashFlowDetail(new DateTime(), new BigDecimal(12), new BigDecimal(12), "notes"); MonthlyCashFlowDetail cashFlowDetail2 = new MonthlyCashFlowDetail(new DateTime(), new BigDecimal(23), new BigDecimal(34), "notes"); MonthlyCashFlowDetail cashFlowDetail3 = new MonthlyCashFlowDetail(new DateTime(), new BigDecimal(20), new BigDecimal(30), "notes"); CashFlowDetail cashFlowDetail = new CashFlowDetail(asList(cashFlowDetail1, cashFlowDetail2, cashFlowDetail3)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, false, new BigDecimal(1000), 10d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); assertThat(cashFlowForm.getTotalExpenses().doubleValue(), is(76d)); assertThat(cashFlowForm.getTotalRevenues().doubleValue(), is(55d)); verify(messageContext, times(2)).hasErrorMessages(); verify(validationContext).getMessageContext(); } @Test public void cumulativeCashFlowShouldBeGreaterThanZero() { when(validationContext.getMessageContext()).thenReturn(messageContext); when(messageContext.hasErrorMessages()).thenReturn(false); DateTime may = new DateTime(2001, 5, 12, 0, 0, 0, 0); DateTime june = new DateTime(2001, 6, 12, 0, 0, 0, 0); DateTime july = new DateTime(2001, 7, 12, 0, 0, 0, 0); MonthlyCashFlowDetail cashFlowDetail1 = new MonthlyCashFlowDetail(may, new BigDecimal(12), new BigDecimal(13), "notes"); MonthlyCashFlowDetail cashFlowDetail2 = new MonthlyCashFlowDetail(june, new BigDecimal(120), new BigDecimal(12), "notes"); MonthlyCashFlowDetail cashFlowDetail3 = new MonthlyCashFlowDetail(july, new BigDecimal(1), new BigDecimal(108), "notes"); CashFlowDetail cashFlowDetail = new CashFlowDetail(asList(cashFlowDetail1, cashFlowDetail2, cashFlowDetail3)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, false, new BigDecimal(1000), 10d); assertEquals(new BigDecimal("-1"), cashFlowForm.getMonthlyCashFlows().get(0).getCumulativeCashFlow()); assertEquals(new BigDecimal("107"), cashFlowForm.getMonthlyCashFlows().get(1).getCumulativeCashFlow()); assertEquals(new BigDecimal("0"), cashFlowForm.getMonthlyCashFlows().get(2).getCumulativeCashFlow()); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(messageContext, times(2)).hasErrorMessages(); verify(validationContext).getMessageContext(); verify(messageContext, times(2)).addMessage(argThat(new MessageMatcher(CashFlowConstants.CUMULATIVE_CASH_FLOW_FOR_MONTH_SHOULD_BE_GREATER_THAN_ZERO))); } @Test public void doNotValidateCumulativeCashIfRevenueOrExpenseNotGiven() { when(validationContext.getMessageContext()).thenReturn(messageContext); when(messageContext.hasErrorMessages()).thenReturn(true); DateTime may = new DateTime(2001, 5, 12, 0, 0, 0, 0); DateTime june = new DateTime(2001, 6, 12, 0, 0, 0, 0); DateTime july = new DateTime(2001, 7, 12, 0, 0, 0, 0); MonthlyCashFlowDetail cashFlowDetail1 = new MonthlyCashFlowDetail(may, new BigDecimal(12), new BigDecimal(13), "notes"); MonthlyCashFlowDetail cashFlowDetail2 = new MonthlyCashFlowDetail(june, null, null, "notes"); CashFlowDetail cashFlowDetail = new CashFlowDetail(asList(cashFlowDetail1, cashFlowDetail2)); CashFlowForm cashFlowForm = new CashFlowForm(cashFlowDetail, false, new BigDecimal(1000), 10d); cashFlowValidator.validateCaptureCashFlow(cashFlowForm, validationContext); verify(messageContext, times(2)).hasErrorMessages(); verify(validationContext).getMessageContext(); verify(messageContext, never()).addMessage(argThat(new MessageMatcher(CashFlowConstants.CUMULATIVE_CASH_FLOW_FOR_MONTH_SHOULD_BE_GREATER_THAN_ZERO))); } }