package gov.va.med.esr.common.rule.service;
import gov.va.med.fw.conversion.ConversionService;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
import gov.va.med.esr.common.ui.form.FinancialDetailsForm;
import sun.misc.BASE64Encoder;
import gov.va.med.fw.service.EntityNotChangedException;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.CatastrophicDisability;
import gov.va.med.esr.common.model.ee.Eligibility;
import gov.va.med.esr.common.model.ee.EnrollmentDetermination;
import gov.va.med.esr.common.model.ee.IneligibilityFactor;
import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.common.model.ee.MonetaryBenefit;
import gov.va.med.esr.common.model.ee.MonetaryBenefitAward;
import gov.va.med.esr.common.model.ee.ServiceConnectionAward;
import gov.va.med.esr.common.model.ee.VerificationInfo;
import gov.va.med.esr.common.model.financials.Asset;
import gov.va.med.esr.common.model.financials.Debt;
import gov.va.med.esr.common.model.financials.DependentFinancials;
import gov.va.med.esr.common.model.financials.Expense;
import gov.va.med.esr.common.model.financials.FinancialInformation;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.GMTThreshold;
import gov.va.med.esr.common.model.financials.InProcessFinancialInfo;
import gov.va.med.esr.common.model.financials.Income;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.financials.SpouseFinancials;
import gov.va.med.esr.common.model.lookup.AssetType;
import gov.va.med.esr.common.model.lookup.CDDeterminationMethod;
import gov.va.med.esr.common.model.lookup.EligibilityFactor;
import gov.va.med.esr.common.model.lookup.EligibilityStatus;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.lookup.ExpenseType;
import gov.va.med.esr.common.model.lookup.IncomeTestSource;
import gov.va.med.esr.common.model.lookup.IncomeTestType;
import gov.va.med.esr.common.model.lookup.IncomeType;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.lookup.MeansTestStatus;
import gov.va.med.esr.common.model.lookup.MonetaryBenefitType;
import gov.va.med.esr.common.model.lookup.Relationship;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.person.Dependent;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.Spouse;
import gov.va.med.esr.common.rule.data.FinancialInputData;
import gov.va.med.esr.common.rule.parameter.FinancialInputParameter;
import gov.va.med.esr.service.FinancialsHelperService;
import gov.va.med.esr.service.UnknownLookupCodeException;
import gov.va.med.esr.service.UnknownLookupTypeException;
import gov.va.med.esr.service.impl.FinancialsHelperServiceImpl;
import gov.va.med.fw.model.lookup.AbstractCode;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.util.SerializationUtils;
import gov.va.med.fw.util.StringUtils;
import gov.va.med.fw.validation.ValidationFieldMessage;
import gov.va.med.fw.validation.ValidationMessages;
import gov.va.med.fw.validation.ValidationServiceException;

/**
 * Financials Test
 * @author DNS   MANSOG
 * @version 1.0
 */
public class ManageFinancialTest extends AbstractFinancialTest {

    private static final BigDecimal   MEDICAL_DEDUCATION_PERCENT = new BigDecimal(0.05);

    private static final ExpenseType.Code[]     EXPENSE_TYPES_VETERAN      = {
            ExpenseType.EXPENSE_TYPE_FUNERAL_AND_BURIAL,
            ExpenseType.EXPENSE_TYPE_COLLEGE_AND_VOCATION};

    private static final ExpenseType.Code[]     EXPENSE_TYPES_DEPENDENT    = { ExpenseType.EXPENSE_TYPE_EDUCATIONAL_EXPENSES_BY_DEPENDENT};
    private static final Relationship.Code[]     DEPENDENT_RELATIONSHIPS    = { Relationship.CODE_DAUGHTER,
            Relationship.CODE_SON, Relationship.CODE_STEPSON,
            Relationship.CODE_STEPDAUGHTER};

    private FinancialsHelperService financialsHelperService = null;
    /**
     * Constructor for ManageFinancialTest.
     * @param testName
     * @throws Exception
     */
    public ManageFinancialTest(String testName) throws Exception {
        super(testName);
        // super.setDefaultRollback(false);
    }

	/*
	 * CCR 11781
	 * 4.60 [2897] Determine the Date/Time Completed SUC79.9.5 - [2897]
	 * Determine the Date/Time Completed If an existing test is being edited the
	 * Date /Time completed remains unchanged.
	 * 
	 * If a new test is being added the Date/Time Completed is the date/time the
	 * test is being added.
	 */
    public void testVfaEditNotAllowedDateTimeCompleted() throws Exception {
		VAFacility fac = this.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getCode());
		Date completed = this.getDate(2012, 2, 2);
		Integer incomeYear2011 = new Integer(2011);
		Person onFile = this.buildSimplePerson();		
		this.attachVerifiedEnrollment(onFile);
		this.addPermanentAddress(onFile, Calendar.getInstance().getTime(),null);
		this.setEligibilityStatusToVerified(onFile);
		this.attachVerifiedEnrollment(onFile);
		attachIncomeTest(onFile, incomeYear2011, fac, MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED);
		onFile.getIncomeTest(incomeYear2011).setSiteConductingTest(fac);
		onFile.getIncomeTest(incomeYear2011).setCompletedDate(completed);		
		onFile.setFinancialStatement(incomeYear2011, this.createFinancialStatement());
		IncomeTest current = this.getPersonHelperService().getCurrentIncomeTest(onFile);
		System.out.println("current income test type="+current.getType().getDescription() );		
		System.out.println("current income test type code="+current.getType().getCode() );
		System.out.println("income test year ="+current.getIncomeYear() );
		
		Person incoming = (Person)savePerson(onFile).clone();
		
		IncomeTest updatedTest = this.getPersonHelperService().getCurrentIncomeTest(incoming);
		updatedTest.setDeductibleExpenses(new BigDecimal(333));
		Person updated = null;
		try {
		 updated = this.getFinancialsService().updateFinancialAssessment( incomeYear2011, incoming);
		}
		catch( ValidationServiceException e ) {
			ValidationMessages messages = e.getValidationMessages();
			assertTrue( !messages.isEmpty() );
			assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), "INCOME_TEST_CANNOT_BE_EDITED" );
			return;
		}

		this.fail("should have thrown exception");
    }
    
    public void testVfaGetCurrentOrFutureIncomeTest() throws Exception{
    	// Used a modifed VFA Start Date = 1/1/2012 instead of 1/1/2013
    	
    	// Unfortunately, had to modify an existing method, getCurrentOrFutureIncomeTest, that was almost
    	// a duplicate of the getCurrentIncomeTest.  This test makes sure that
    	// the method still works at a unit test level and that it uses the new Vfa rules.
		VAFacility fac = this.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getCode());		
		Integer incomeYear2011 = new Integer(2011);
		Integer incomeYear2010 = new Integer(2010);
		
		Person onFile = this.buildSimplePerson();		
		this.attachVerifiedEnrollment(onFile);
		this.addPermanentAddress(onFile, Calendar.getInstance().getTime(),null);
		this.setEligibilityStatusToVerified(onFile);
		this.attachVerifiedEnrollment(onFile);		
		
		attachIncomeTest(onFile, incomeYear2010, fac, MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED);
		onFile.getIncomeTest(incomeYear2010).setEffectiveDate(getDate(2011, 1, 23));
		onFile.getIncomeTest(incomeYear2010).setLastEditedDate(getDate(2010, 1, 25));
		onFile.setFinancialStatement(incomeYear2010,this.createFinancialStatement());

		IncomeTest current = this.getPersonHelperService().getCurrentIncomeTest(onFile);
		
		System.out.println("FIRST current income test type="+current.getType().getDescription() );		
		System.out.println("FIRST current income test type code="+current.getType().getCode() );
		System.out.println("FIRST income test year ="+current.getIncomeYear() );
		Person incoming = (Person)savePerson(onFile).clone();
		
		attachIncomeTest(incoming, incomeYear2011, fac, MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED);
		incoming.getIncomeTest(incomeYear2011).setSiteConductingTest(fac);
		IncomeTest  secondTest = this.getPersonHelperService().getCurrentIncomeTest(incoming);
		System.out.println("SECOND incoming income test type="+secondTest.getType().getDescription() );		
		System.out.println("SECOND incoming income test type code="+secondTest.getType().getCode() );
		System.out.println("SECOND incomingtest year ="+secondTest.getIncomeYear() );		
		secondTest.setEffectiveDate(getDate(2013, 1, 23));
		secondTest.setFutureTest(Boolean.TRUE);
		incoming.setFinancialStatement(incomeYear2011, this.createFinancialStatement());
		
		IncomeTest test = this.getPersonHelperService().getCurrentOrFutureIncomeTest(incoming, onFile);
		System.out.println("RESULT 1 income test year ="+test.getIncomeYear() );
		assertTrue(test.getFutureTest());
		assertTrue(incomeYear2011.equals(test.getIncomeYear()));		
		test.setFutureTest(Boolean.FALSE);
		test = this.getPersonHelperService().getCurrentOrFutureIncomeTest(incoming, onFile);
		System.out.println("RESULT 2 income test year ="+test.getIncomeYear() );			
		assertTrue(incomeYear2010.equals(test.getIncomeYear()));		
    }
	/*
	 * CCR 11781
	 * 4.60 [2897] Determine the Date/Time Completed SUC79.9.5 - [2897]
	 * Determine the Date/Time Completed If an existing test is being edited the
	 * Date /Time completed remains unchanged.
	 * 
	 * If a new test is being added the Date/Time Completed is the date/time the
	 * test is being added.
	 */
    public void testVfaAllowEditDateTimeCompleted() throws Exception {
		VAFacility fac = this.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getCode());
		Date completed = this.getDate(2012, 2, 2);
		Integer incomeYear2011 = new Integer(2011);
		Person onFile = this.buildSimplePerson();		
		this.attachVerifiedEnrollment(onFile);
		this.addPermanentAddress(onFile, Calendar.getInstance().getTime(),null);
		this.setEligibilityStatusToVerified(onFile);
		this.attachVerifiedEnrollment(onFile);
		attachIncomeTest(onFile, incomeYear2011, fac, MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED);
		onFile.getIncomeTest(incomeYear2011).setSiteConductingTest(fac);
		onFile.getIncomeTest(incomeYear2011).setEffectiveDate(this.getDate(2012, 4, 2));		
		onFile.getIncomeTest(incomeYear2011).setCompletedDate(completed);		
		onFile.setFinancialStatement(incomeYear2011, this.createFinancialStatement());
		IncomeTest current = this.getPersonHelperService().getCurrentIncomeTest(onFile);
		System.out.println("current income test type="+current.getType().getDescription() );		
		System.out.println("current income test type code="+current.getType().getCode() );
		System.out.println("income test year ="+current.getIncomeYear() );
		System.out.println("completed date ="+current.getCompletedDate().toString() );		
		Person incoming = (Person)savePerson(onFile).clone();
		
		IncomeTest updatedTest = this.getPersonHelperService().getCurrentIncomeTest(incoming);
		updatedTest.setDeductibleExpenses(new BigDecimal(333));
		FinancialStatement holdFin = incoming.getFinancialStatement(incomeYear2011);
		holdFin.setDebt(null);
		Person updated = null;
		try {
		 updated = this.getFinancialsService().updateFinancialAssessment( incomeYear2011, incoming);
		}
		catch( ValidationServiceException e ) {
			this.fail("should not throw an exception");
		}
		
		IncomeTest result = this.getPersonHelperService().getCurrentIncomeTest(updated);
		System.out.println("RESULT income test type="+result.getType().getDescription() );		
		System.out.println("RESULT income test type code="+result.getType().getCode() );		
		System.out.println("RESULT income test future="+result.getFutureTest() );
		System.out.println("RESULT income test year ="+result.getIncomeYear() );
		System.out.println("RESULT completed date ="+result.getCompletedDate().toString() );		
		assertTrue("should be 2011",incomeYear2011.equals(result.getIncomeYear()));
		assertTrue("complete date be same",completed.equals(result.getCompletedDate()));
    }
    public void testVfaInProcess() throws Exception {
    	// This requirement states that "in process" test can't be edited when > year old. UI
    	// just takes "in process" data and populates a persons financials and submits
    	// to business service for financial processing. That layer does not care about the concept
    	// of "in process" once the test is part of person graph. Therefore, this requirement 
    	// can be checked by running a test such as following: 
    	testVfaNetWorthAdjudicationEditNotAllowed();
    }    
    /*
    private void saveInProcessInfo(Person person, Integer incomeYear ) throws Exception  {
        FinancialDetailsForm detailsForm = new FinancialDetailsForm();
        detailsForm.setIncomeYear(incomeYear.toString());
        ConversionService conversionService = (ConversionService)this.applicationContext.getBean("commonFinancialDetailsConversionService");
        conversionService.convert(person,detailsForm);

        byte[] data = SerializationUtils.serialize(detailsForm.getFinancialsData());
        InProcessFinancialInfo inProcessFinancial = person.getInProcessFinancial(incomeYear);
        if (inProcessFinancial == null) {
            inProcessFinancial = new InProcessFinancialInfo();
            inProcessFinancial.setIncomeYear(incomeYear);
            person.setInProcessFinancial(incomeYear, inProcessFinancial);
        }
        inProcessFinancial.setInProcessData(new BASE64Encoder().encode(data));
        
        getFinancialsService().updateInProcess(incomeYear, person, true);
    } 
    */
    
	/*
	 * CCR 11781 
	 * 5.2 [4429] SUC79.17 - [4429] The actor chooses to perform Net Worth
	 * Adjudication to a Veteran Record.
	 * 
	 * The Means Test Status must be equal to Pending Adjudication <****and the
	 * Means Test cannot be older than one year from the effective date of the
	 * test****> in order to perform this action.
	 */
    public void testVfaNetWorthAdjudicationEditNotAllowed() throws Exception {
    	try {
    		processVfaNetWorthAdjudication(this.getDate(2011, 1, 23));
    	}
    	catch( ValidationServiceException e ) {
    		ValidationMessages messages = e.getValidationMessages();
    		assertTrue( !messages.isEmpty() );
    		assertEquals( ((ValidationFieldMessage)messages.get().next()).getKey(), "INCOME_TEST_CANNOT_BE_EDITED" );
    		return;
    	}    	
    	fail("should have thrown ValidationServiceException");
    }
    public void testVfaNetWorthAdjudicationEditAllowed() throws Exception {
    	try {
    		processVfaNetWorthAdjudication(this.getDate(2012, 1, 23));
    	}
    	catch( Exception e ) {
    		fail("should NOT have thrown any exception");
    	}    	
    	
    }    
    private void processVfaNetWorthAdjudication(Date effective) throws Exception {
    	VAFacility fac = this.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getCode());
    	Date completed = this.getDate(2012, 2, 2);
    	Integer incomeYear2011 = new Integer(2011);
    	Person onFile = this.buildSimplePerson();		
    	this.attachVerifiedEnrollment(onFile);
    	this.addPermanentAddress(onFile, Calendar.getInstance().getTime(),null);
    	this.setEligibilityStatusToVerified(onFile);
    	this.attachVerifiedEnrollment(onFile);
    	attachIncomeTest(onFile, incomeYear2011, fac, MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION);
    	onFile.getIncomeTest(incomeYear2011).setEffectiveDate(effective);
    	onFile.getIncomeTest(incomeYear2011).setSiteConductingTest(fac);
    	onFile.getIncomeTest(incomeYear2011).setCompletedDate(completed);		
    	onFile.setFinancialStatement(incomeYear2011, this.createFinancialStatement());
    	IncomeTest current = this.getPersonHelperService().getCurrentIncomeTest(onFile);
    	System.out.println("current income test type="+current.getType().getDescription() );		
    	System.out.println("current income test type code="+current.getType().getCode() );
    	System.out.println("income test year ="+current.getIncomeYear() );
    	Person incoming = (Person)savePerson(onFile).clone();
    	IncomeTest updatedTest = this.getPersonHelperService().getCurrentIncomeTest(incoming);
    	updatedTest.setDeductibleExpenses(new BigDecimal(333));
		FinancialStatement holdFin = incoming.getFinancialStatement(incomeYear2011);
		holdFin.setDebt(null);
    	this.getFinancialsService().updateFinancialAssessment( incomeYear2011, incoming);
    }    
  
    /*
	 * CCR 11781 Notice that the following requirement did not need
     * any specific change since it works based on VFA "never expires"
     * change.
	 * 5.6 [2913] Delete Income Test SUC79.18 - [2913] Delete Income Test If the
	 * actor chooses to delete an active current Income Year Income Test then
	 * the latest remaining income year test becomes the current income test
	 * <****if that test was less than one year old on the VFA Start Date.***>
	 * The latest income test on file could be expired.
	 */
    public void testVfaDeleteMtIncomeTest() throws Exception {
		VAFacility fac = this.getLookupService().getVaFacilityByCode(VAFacility.CODE_HEC.getCode());		
		Integer incomeYear2011 = new Integer(2011);
		Integer incomeYear2010 = new Integer(2010);
		
		Person onFile = this.buildSimplePerson();		
		this.attachVerifiedEnrollment(onFile);
		this.addPermanentAddress(onFile, Calendar.getInstance().getTime(),null);
		this.setEligibilityStatusToVerified(onFile);
		attachIncomeTest(onFile, incomeYear2010, fac, MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED);
		onFile.getIncomeTest(incomeYear2010).setEffectiveDate(getDate(2012, 1, 23));
		onFile.getIncomeTest(incomeYear2010).setLastEditedDate(getDate(2011, 1, 25));
		onFile.setFinancialStatement(incomeYear2010,
				this.createFinancialStatement());
		this.attachVerifiedEnrollment(onFile);
		IncomeTest current = this.getPersonHelperService().getCurrentIncomeTest(onFile);
		System.out.println("FIRST current income test type="+current.getType().getDescription() );		
		System.out.println("FIRST current income test type code="+current.getType().getCode() );
		System.out.println("FIRST income test year ="+current.getIncomeYear() );
///////////////////////////////////////////////		
		attachIncomeTest(onFile, incomeYear2011, fac, MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED);
		onFile.getIncomeTest(incomeYear2011).setSiteConductingTest(fac);
		IncomeTest  secondTest = this.getPersonHelperService().getCurrentIncomeTest(onFile);
		System.out.println("SECOND incoming income test type="+secondTest.getType().getDescription() );		
		System.out.println("SECOND incoming income test type code="+secondTest.getType().getCode() );
		System.out.println("SECOND incomingtest year ="+secondTest.getIncomeYear() );		
		secondTest.setEffectiveDate(getDate(2012, 5, 23));
		onFile.setFinancialStatement(incomeYear2011, this.createFinancialStatement());
		Person incoming = (Person)savePerson(onFile).clone();
		IncomeTest hold = incoming.getIncomeTest(incomeYear2010);
		FinancialStatement holdFin = incoming.getFinancialStatement(incomeYear2010);
		holdFin.setDebt(null);
		hold.setEffectiveDate(new Date());
		incoming.removeAllIncomeTests();
		incoming.removeAllFinancialStatements();
		incoming.setIncomeTest(incomeYear2010, hold);
		incoming.setFinancialStatement(incomeYear2010, holdFin);
        FinancialStatement stmt = incoming.getFinancialStatement(incomeYear2010);
        setExpense(stmt, 8455, ExpenseType.EXPENSE_TYPE_NON_REIMBURSED_MEDICAL);

		Person updated = this.getFinancialsService().updateFinancialAssessment( incomeYear2011, incoming); 
		IncomeTest result = this.getPersonHelperService().getCurrentIncomeTest(updated);
		System.out.println("RESULT income test type="+result.getType().getDescription() );		
		System.out.println("RESULT income test type code="+result.getType().getCode() );		
		System.out.println("RESULT income test future="+result.getFutureTest() );
		System.out.println("RESULT income test year ="+result.getIncomeYear() );
		assertTrue("should be 2010",incomeYear2010.equals(result.getIncomeYear()));
		assertNull(result.getFutureTest());
    }
    
    

    /*
	 * CCR 11781 
     * 
     * 5.9 [2914] Delete Pharmacy Copay Test SUC79.19 – [2914] Delete Pharmacy
     * Copay test If the actor chooses to delete an active current pharmacy
     * copay Test then the latest remaining income year test becomes the current
     * pharmacy copay test if that test was less than one year old on the VFA
     * start date. The latest pharmacy copay test on file could be expired.
     * 
     * SUC79.19.1 - [4428] If a Pharmacy Copay Test is deleted and there is a
     * LTC 4 Test then the LTC4 test is also deleted.
     * 
     * SUC79.19.2 – [4477] The actor may only delete a Pharmacy Copay test if
     * the source of the test is = HEC.
     */    
    public void testVfaDeleteRxIncomeTest() throws Exception {
    	// USED vfa start date = 1/1/2012
    	processVfaDeleteRxCommon(IncomeTestSource.CODE_HEC.getCode());
    }
    private void processVfaDeleteRxCommon(String source) throws Exception {
      	// USED vfa start date = 1/1/2012
    	Person onFile = buildSimplePerson();
    	this.attachVerifiedEnrollment(onFile);
    	this.setEligibilityStatusToVerified(onFile);
    	VAFacility fac = getVaFacility(VAFacility.CODE_HEC);
    	IncomeTestSource sourceOfTest = this.getLookupService().getIncomeTestSourceByCode(source);    	
    	onFile.getEligibilityVerification().setVerificationFacility(fac);    	
    	Integer incomeYear2011 = new Integer(2011);
		Integer incomeYear2010 = new Integer(2010);		
		attachIncomeTest(onFile, incomeYear2010, fac, MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED);
		IncomeTest oldTst = onFile.getIncomeTest(incomeYear2010);
		oldTst.setSource(sourceOfTest);
		oldTst.setLastEditedDate(getDate(2008,1,1));
		oldTst.setDiscloseFinancialInformation(Boolean.TRUE);
		oldTst.setEffectiveDate(getDate(2011,2,11));
		oldTst.setThresholdA(new BigDecimal(500));		
		oldTst.setSiteConductingTest(null);		
		onFile.setFinancialStatement(incomeYear2010,this.createFinancialStatement());
		onFile.setFinancialStatement(incomeYear2011,this.createFinancialStatement());		

		IncomeTest incomeTest = this.createIncomeTest(
	                IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST,
	                MeansTestStatus.MT_STATUS_EXEMPT, incomeYear2011);
		incomeTest.setSource(sourceOfTest);
        onFile.setIncomeTest(incomeYear2011, incomeTest);
		onFile.getIncomeTest(incomeYear2011).setSiteConductingTest(null);
		onFile.getIncomeTest(incomeYear2011).setIncomeYear(incomeYear2011);
		onFile.getIncomeTest(incomeYear2011).setEffectiveDate(getDate(2012,2,11));        
		onFile.getIncomeTest(incomeYear2011).setThresholdA(new BigDecimal(500));
        Person incoming = (Person)savePerson(onFile).clone();
        IncomeTest before = getPersonHelperService().getCurrentIncomeTest(incoming);
        assertTrue(incomeYear2011.equals(before.getIncomeYear()));        
		IncomeTest hold = incoming.getIncomeTest(incomeYear2010);        
		incoming.removeAllIncomeTests();
		incoming.setIncomeTest(incomeYear2010, hold);
        VerificationInfo vi = new VerificationInfo();
        vi.setSiteNumber(incoming.getEligibilityVerification()
                .getVerificationFacility().getCode());

        Person updated = this.getFinancialsService().updateFinancialAssessment( incomeYear2011, incoming);
        
        IncomeTest res = updated.getIncomeTest(incomeYear2011);
        assertNull(res);

        assertTrue(updated.getEligibilityVerification().getEligibilityStatus()
                .getCode().equals(EligibilityStatus.CODE_VERIFIED.getName()));

        IncomeTest after = getPersonHelperService().getCurrentIncomeTest(updated);
        assertTrue(incomeYear2010.equals(after.getIncomeYear()));
    }    
    public void testVfaDeleteRxIncomeTestFromVAMC() throws Exception {
    	// USED vfa start date = 1/1/2012
    	
    	try {
    		processVfaDeleteRxCommon(IncomeTestSource.CODE_VAMC.getCode());
   		}
   		catch(EntityNotChangedException e ) {
			// Test passed
			return;
   		}
		this.fail("should have thrown EntityNotChangedException");   		
    }    
    
    public void testAdjustedMedicalExpense() throws Exception {
        Integer incomeYear = new Integer(2003);
        Person person = savePerson(buildSimplePerson());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);
        IncomeTestType testType = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus testStatus = getMeansTestStatus(MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT);

        buildIncomeTestData(incomeYear, person, testType, testSource, testStatus, getHECFacility());

        FinancialStatement stmt = buildFinancialStatementData(incomeYear, person);
        setExpense(stmt, 8000, ExpenseType.EXPENSE_TYPE_NON_REIMBURSED_MEDICAL);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());
        Person pristine = (Person) person.clone();

        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear,
                getHECFacility(), true);
        FinancialInputParameter fip = buildFinancialInputParameter(data);

        BigDecimal adjustedMedExp = fip.getCalculatedAdjustableMedicalExpense();
        
        assertNotNull("Adjusted Med Exp can not be null.", adjustedMedExp);
        //assertEquals(adjustedMedExp.doubleValue(), );

        System.out.println(adjustedMedExp);
    }
    
    public void testEffectiveImmediately1() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_NO_LONGER_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 30000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately1_1() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_NO_LONGER_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 15000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately1_2() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_NO_LONGER_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 0;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately1_3() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_NO_LONGER_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 30000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately2() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT;
        MeansTestStatus.Code currentRxCode = MeansTestStatus.MT_STATUS_NON_EXEMPT;
        double incomeAmount = 5000; //income < pension th
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT;
        //@todo: check the result rx status equals to exempt
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }
    
    public void testEffectiveImmediately3() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 0;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }
    
    public void testEffectiveImmediately3_1() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 0;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }
    
    public void testEffectiveImmediately3_2() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 0;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately4() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 30000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately5() throws Exception {        
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 30000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }
    
    public void testEffectiveImmediately6() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_MEANS_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 30000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately7() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_INCOMPLETE_RX_COPAY_ONLY;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 0;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }
    
    public void testEffectiveImmediately8() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_INCOMPLETE_RX_COPAY_ONLY;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 15000;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_NON_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    public void testEffectiveImmediately9() throws Exception {
        IncomeTestType.Code currentTestType = IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST;
        MeansTestStatus.Code currentMTCode = MeansTestStatus.MT_STATUS_NON_EXEMPT;
        MeansTestStatus.Code currentRxCode = null;
        double incomeAmount = 0;
        double expenseAmount = 0;
        double assetAmount = 0;
        MeansTestStatus.Code resultStatus = MeansTestStatus.MT_STATUS_EXEMPT;
        
        effectiveImmediatelyTest(currentTestType, currentMTCode, currentRxCode, incomeAmount, expenseAmount, assetAmount, resultStatus);
    }

    private void effectiveImmediatelyTest(IncomeTestType.Code itTypeCode, MeansTestStatus.Code currentMTStatus, MeansTestStatus.Code currentRxStatus, MeansTestStatus.Code resultStatus) throws Exception {
        effectiveImmediatelyTest(itTypeCode, currentMTStatus, currentRxStatus, 0, 0, 0, resultStatus);               
    }
    
//    private void effectiveImmediatelyTest(IncomeTestType.Code itTypeCode, 
//            MeansTestStatus.Code currentMTStatus, 
//            MeansTestStatus.Code incomingMTStatus, 
//            BigDecimal currentGMTThreshold,
//            BigDecimal incomingGMTThreshold, 
//            BigDecimal currentMTThreshold, BigDecimal incomingMTThreshold) throws Exception {
//        
//        effectiveImmediatelyTest(itTypeCode, currentMTStatus, null);               
//    }
    
    private void effectiveImmediatelyTest(IncomeTestType.Code itTypeCode, 
                                            MeansTestStatus.Code currentMTStatus, 
                                            MeansTestStatus.Code currentRxStatus,  
                                            double incomeAmount, 
                                            double expenseAmount,
                                            double assetAmount, 
                                            MeansTestStatus.Code resultStatus) throws Exception {
        
        Integer prevYear = new Integer(2002);
        VAFacility prevFacility = getVaFacility(VAFacility.CODE_CONNECTICUT_HCS);

        Person person = buildSimplePerson();
        IncomeTestSource src = getTestSource(IncomeTestSource.CODE_IVM);
        IncomeTestType type = getTestType(itTypeCode);
        MeansTestStatus status = getMeansTestStatus(currentMTStatus);

        IncomeTest tst = buildIncomeTestData(prevYear, person, type, src, status, prevFacility);     
        tst.setEffectiveDate(this.getDate(2011, 10, 1));
        setRxCopayStatus(tst, currentRxStatus);
        tst.setGmtThresholdAmount(new BigDecimal(7000));
        tst.setThresholdA(new BigDecimal(9000));
        
        if (IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.equals(itTypeCode)) {
            person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT,
                    null, new Integer(10), Boolean.FALSE, null, null);
            boolean mtPermitted = executeDetermineMTPermitted(person, prevYear)
                    || executeisMeansTestRequired(person, prevYear);
            assertEquals(mtPermitted, false);
            
        }
        else if (IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.equals(itTypeCode)) {
            person = createDataforMTAndRxCopayTest(person, EligibilityType.NSC, null, null, null, null, null);
            IneligibilityFactor ief = new IneligibilityFactor();
            person.setIneligibilityFactor(ief);
            ief = new IneligibilityFactor();
            person.setIneligibilityFactor(ief);
            ief.setIneligibleDate(new Date());
            boolean mtPermitted = executeDetermineMTPermitted(person, prevYear)
                                    || executeisMeansTestRequired(person, prevYear);
            assertEquals(mtPermitted, true);
        }
        assertEquals(executeisPhramacyCoPayApplicable(person, prevYear), true);
        person = savePerson(person);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(
                person.getPersonEntityKey());

        Integer incomeYear = new Integer(2003);
        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);

        IncomeTest incomingTest =  buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());
        if (MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED.equals(resultStatus)) {
            incomingTest.setDiscloseFinancialInformation(Boolean.FALSE);
        }
        incomingTest.setAgreesToPayDeductible(Boolean.TRUE);
        incomingTest.setSendForAdjudication(Boolean.FALSE);

        FinancialStatement stmt = buildLimitedFinancialData(incomeYear, incoming);
        if (MeansTestStatus.MT_STATUS_PENDING_ADJUDICATION.equals(resultStatus)) {
            setFinancialInfo(stmt, 0, expenseAmount, assetAmount, 0);
            createIncome(stmt, incomeAmount, IncomeType.INCOME_TYPE_FARM_RANCH_PROPERTY_OR_BUSINESS_INCOME);
            createIncome(stmt, incomeAmount, IncomeType.INCOME_TYPE_TOTAL_ALL_OTHER_INCOME);            
            incomingTest.setSendForAdjudication(Boolean.TRUE);
        } else {
            setFinancialInfo(stmt, incomeAmount, expenseAmount, assetAmount, 0);
        }
        
        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Incoming IncomeTest should not be null", incomingIncomeTest);
            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertEquals(resultStatus.getCode(), resultIncomeTest.getIncomeTestStatus().getStatus().getCode());
            // OK to use DateUtils.isEqualOrAfterIgnoreTime since the incoming time is 1 hour in the past (never will be after)
            assertTrue(DateUtils.isEqualOrAfterIgnoreTime(incomingIncomeTest.getEffectiveDate(), resultIncomeTest.getEffectiveDate()));
        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    private void setRxCopayStatus(IncomeTest test, MeansTestStatus.Code status) throws Exception {
        if (status != null) {
            IncomeTestType rxType = getTestType(IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST);
            MeansTestStatus rxStatus = getMeansTestStatus(status);
            setIncomeTestStatusProps(test, rxType, rxStatus);
        }
    }
    
    protected FinancialStatement buildLimitedFinancialData(Integer incomeYear, Person person)
            throws Exception {
        FinancialStatement stmt = person.getFinancialStatement(incomeYear);
        if (stmt == null) {
            stmt = createFinancialStatement();
//            setFinancialInfo(stmt, 50000, 0, 0, 2000);
//            createAsset(stmt, 50000, AssetType.CODE_CASH);
//            createAsset(stmt, 100000, AssetType.CODE_REAL_ESTATE);
//            createAsset(stmt, 10000, AssetType.CODE_OTHER);
//            setExpense(stmt, 2000, ExpenseType.EXPENSE_TYPE_FUNERAL_AND_BURIAL);
//            setExpense(stmt, 4000, ExpenseType.EXPENSE_TYPE_NON_REIMBURSED_MEDICAL);
            person.setFinancialStatement(incomeYear, stmt);
        }
        return stmt;
    }

    public void testActiveRelation() throws Exception {
        Integer incomeYear = new Integer(2002);
        Person person = buildSimplePerson();
        Person incoming = (Person) person.clone();
        Person onFile = (Person) person.clone();
        Person pristine = (Person) person.clone();
        
        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear, getHECFacility(), true);
        FinancialInputParameter fip = buildFinancialInputParameter(data);

        Dependent dependent = createDependent();

        Calendar startDate = Calendar.getInstance();
        Calendar endDate = Calendar.getInstance();

        startDate.set(Calendar.YEAR, incomeYear.intValue() - 1);
        dependent.setStartDate(new ImpreciseDate(startDate));
        dependent.setEndDate(null);
        assertTrue(fip.isActiveRelation(dependent));

        startDate.set(Calendar.YEAR, incomeYear.intValue());
        dependent.setStartDate(new ImpreciseDate(startDate));
        dependent.setEndDate(null);
        assertTrue(fip.isActiveRelation(dependent));

        startDate.set(Calendar.YEAR, incomeYear.intValue() + 1);
        dependent.setStartDate(new ImpreciseDate(startDate));
        dependent.setEndDate(null);
        assertFalse(fip.isActiveRelation(dependent));

        startDate.set(Calendar.YEAR, incomeYear.intValue() - 1);
        endDate.set(Calendar.YEAR, incomeYear.intValue());
        dependent.setStartDate(new ImpreciseDate(startDate));
        dependent.setEndDate(endDate.getTime());
        assertTrue(fip.isActiveRelation(dependent));

        startDate.set(Calendar.YEAR, incomeYear.intValue() - 2);
        endDate.set(Calendar.YEAR, incomeYear.intValue() -1);
        dependent.setStartDate(new ImpreciseDate(startDate));
        dependent.setEndDate(endDate.getTime());
        assertFalse(fip.isActiveRelation(dependent));

        startDate.set(Calendar.YEAR, incomeYear.intValue() - 1);
        endDate.set(Calendar.YEAR, incomeYear.intValue() + 1);
        dependent.setStartDate(new ImpreciseDate(startDate));
        dependent.setEndDate(endDate.getTime());
        assertTrue(fip.isActiveRelation(dependent));
    }
    
    public void testValidSpouse() throws Exception {
        Integer incomeYear = new Integer(2002);
        Person person = buildSimplePerson();
        Person incoming = (Person) person.clone();
        Person onFile = (Person) person.clone();
        Person pristine = (Person) person.clone();
        
        
        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear, getHECFacility(), true);
        FinancialInputParameter fip = buildFinancialInputParameter(data);

        FinancialStatement stmt = buildFinancialStatementData(incomeYear, incoming);
            
        SpouseFinancials sf = stmt.getActiveSpouseFinancials();

        sf.setLivedWithPatient(Boolean.TRUE);
        stmt.setContributionToSpouse(null);
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertTrue(fip.isSpouseValidDependent(sf));

        sf.setLivedWithPatient(Boolean.TRUE);
        stmt.setContributionToSpouse(new BigDecimal(1000));
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertTrue(fip.isSpouseValidDependent(sf));

        sf.setLivedWithPatient(Boolean.FALSE);
        stmt.setContributionToSpouse(new BigDecimal(1000));
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertTrue(fip.isSpouseValidDependent(sf));

        sf.setLivedWithPatient(Boolean.FALSE);
        stmt.setContributionToSpouse(new BigDecimal(100));
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertFalse(fip.isSpouseValidDependent(sf));

        sf.setLivedWithPatient(Boolean.TRUE);
        stmt.setContributionToSpouse(new BigDecimal(100));
        stmt.setMarriedLastCalendarYear(Boolean.FALSE);        
        assertFalse(fip.isSpouseValidDependent(sf));

        sf.setLivedWithPatient(Boolean.TRUE);
        stmt.setContributionToSpouse(new BigDecimal(1000));
        stmt.setMarriedLastCalendarYear(Boolean.FALSE);        
        assertFalse(fip.isSpouseValidDependent(sf));
        
        // ES 4.2_CodeCR13338_CR_Rule Layer Modifications for Decommissioning Spousal/Dependent Support
        
        stmt.setContributionToSpouse(null); // was 1000
        stmt.setContributedToSpouseInd(Boolean.TRUE);
        sf.setLivedWithPatient(Boolean.FALSE);        
        stmt.setMarriedLastCalendarYear(Boolean.FALSE);        
        assertFalse(fip.isSpouseValidDependent(sf));        
        
        stmt.setContributionToSpouse(null); 
        stmt.setContributedToSpouseInd(null);
        sf.setLivedWithPatient(Boolean.TRUE);        
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertTrue(fip.isSpouseValidDependent(sf));        
        
        stmt.setContributionToSpouse(null);
        stmt.setContributedToSpouseInd(Boolean.TRUE);
        sf.setLivedWithPatient(Boolean.FALSE);        
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertTrue(fip.isSpouseValidDependent(sf));
        
        stmt.setContributionToSpouse(null);
        stmt.setContributedToSpouseInd(null);
        sf.setLivedWithPatient(Boolean.TRUE);        
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);        
        assertTrue(fip.isSpouseValidDependent(sf));        
    }
    
    public void testAddFinancialsMeansTestStatus() throws Exception {
        Integer incomeYear = new Integer(2004);
        Person person = savePerson(buildSimplePerson());
        String zipCode = person.getPermanentAddress().getZipCode();

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);

        IncomeTest test = buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());
        test.setSendForAdjudication(Boolean.FALSE);

        FinancialStatement stmt = buildFinancialStatementData(incomeYear, incoming);
        stmt.setMarriedLastCalendarYear(Boolean.FALSE);

        boolean permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, true);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());

            assertNotNull(resultIncomeTest.getGmtAddress());
            assertEquals(resultIncomeTest.getGmtThresholdAmount(), new BigDecimal(getGMTThreshold(incomeYear,
                    zipCode, 2).toString()));

            assertEquals(IncomeTestType.CODE_MEANS_TEST.getName(), resultIncomeTest.getType().getCode());
            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());

            FinancialStatement incomingStmt = incoming.getFinancialStatement(incomeYear);
            FinancialStatement resultStmt = result.getFinancialStatement(incomeYear);
            assertNotNull("Result FinancialStatement should not be null", resultStmt);
            assertEquals(incomingStmt.getMarriedLastCalendarYear(), resultStmt.getMarriedLastCalendarYear());

            SpouseFinancials sf = resultStmt.getActiveSpouseFinancials();
            Set dfSet = resultStmt.getDependentFinancials();
            assertNotNull(sf);
            assertNotNull(dfSet);
            assertEquals(dfSet.size(), 2);
            assertNull(sf.getLivedWithPatient());
            DependentFinancials df1 = ((DependentFinancials) dfSet.iterator().next());
            assertNotNull(df1.getLivedWithPatient());

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    public void testAddDeclineToDiscloseFinancials() throws Exception {
        Integer incomeYear = new Integer(2004);
        Person person = savePerson(buildSimplePerson());

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);

        IncomeTest test = buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());
        test.setDiscloseFinancialInformation(Boolean.FALSE);
        test.setAgreesToPayDeductible(Boolean.FALSE);

        buildFinancialStatementData(incomeYear, incoming);
        boolean permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, true);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());
            assertEquals(IncomeTestType.CODE_MEANS_TEST.getName(), resultIncomeTest.getType().getCode());

            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(MeansTestStatus.MT_STATUS_MT_COPAY_REQUIRED.getName(), resultIncomeTest.getStatus()
                    .getCode());

            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());
            assertNotNull(resultIncomeTest.getGmtAddress());

        } catch (Exception e) {
            fail("Failed due to exception: ", e);
        }
    }

    public void testEditFinancialsMeansTestStatus() throws Exception {
        Integer incomeYear = new Integer(2004);

        Person p = buildSimplePerson();
        String zipCode = p.getPermanentAddress().getZipCode();

        IncomeTestSource src = getTestSource(IncomeTestSource.CODE_VAMC);
        IncomeTestType typ = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus status = getMeansTestStatus(MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED);

        buildIncomeTestData(incomeYear, p, typ, src, status, getVaFacility(VAFacility.CODE_ALBUQUERQUE));
        Person person = savePerson(p);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);

        buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());

        buildFinancialStatementData(incomeYear, incoming);
        boolean permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, true);
        incoming.getIncomeTest(incomeYear).setSendForAdjudication(Boolean.TRUE);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());

            assertEquals(resultIncomeTest.getGmtThresholdAmount(), new BigDecimal(getGMTThreshold(incomeYear,
                    zipCode, 3).toString()));
            assertEquals(IncomeTestType.CODE_MEANS_TEST.getName(), resultIncomeTest.getType().getCode());
            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());
            assertNotNull(resultIncomeTest.getGmtAddress());

            FinancialStatement incomingStmt = incoming.getFinancialStatement(incomeYear);
            FinancialStatement resultStmt = result.getFinancialStatement(incomeYear);
            assertNotNull("Result FinancialStatement should not be null", resultStmt);
            assertEquals(incomingStmt.getMarriedLastCalendarYear(), resultStmt.getMarriedLastCalendarYear());
            assertNotNull(resultStmt.getSpouseFinancials());
            assertNotNull(resultStmt.getDependentFinancials());
            assertEquals(resultStmt.getDependentFinancials().size(), 2);

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    public void testEditCopayTestBecomeMTTest() throws Exception {
        Integer incomeYear = new Integer(2004);

        Person p = buildSimplePerson();
        String zipCode = p.getPermanentAddress().getZipCode();

        IncomeTestSource src = getTestSource(IncomeTestSource.CODE_VAMC);
        IncomeTestType typ = getTestType(IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST);
        MeansTestStatus status = getMeansTestStatus(MeansTestStatus.MT_STATUS_EXEMPT);

        buildIncomeTestData(incomeYear, p, typ, src, status, getVaFacility(VAFacility.CODE_ALBUQUERQUE));
        Person person = savePerson(p);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);

        buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());

        buildFinancialStatementData(incomeYear, incoming);
        
        boolean permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, true);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());

            assertEquals(resultIncomeTest.getGmtThresholdAmount(), new BigDecimal(getGMTThreshold(incomeYear,
                    zipCode, 3).toString()));
            assertEquals(IncomeTestType.CODE_MEANS_TEST.getName(), resultIncomeTest.getType().getCode());
            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());
            assertNotNull(resultIncomeTest.getGmtAddress());

            FinancialStatement incomingStmt = incoming.getFinancialStatement(incomeYear);
            FinancialStatement resultStmt = result.getFinancialStatement(incomeYear);
            assertNotNull("Result FinancialStatement should not be null", resultStmt);
            assertEquals(incomingStmt.getMarriedLastCalendarYear(), resultStmt.getMarriedLastCalendarYear());
            assertNotNull(resultStmt.getSpouseFinancials());
            assertNotNull(resultStmt.getDependentFinancials());
            assertEquals(resultStmt.getDependentFinancials().size(), 2);

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    public void testEditFinancialsWithNewDependentMeansTestStatus() throws Exception {
        Integer incomeYear = new Integer(2004);

        Person p = buildSimplePerson();
        String zipCode = p.getPermanentAddress().getZipCode();

        IncomeTestSource src = getTestSource(IncomeTestSource.CODE_VAMC);
        IncomeTestType typ = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus status = getMeansTestStatus(MeansTestStatus.MT_STATUS_GMT_COPAY_REQUIRED);

        buildIncomeTestData(incomeYear, p, typ, src, status, getVaFacility(VAFacility.CODE_ALBUQUERQUE));
        Person person = savePerson(p);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);

        buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());

        buildFinancialStatementData(incomeYear, incoming);
        boolean permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, true);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());

            assertEquals(resultIncomeTest.getGmtThresholdAmount(), new BigDecimal(getGMTThreshold(incomeYear,
                    zipCode, 3).toString()));
            assertEquals(IncomeTestType.CODE_MEANS_TEST.getName(), resultIncomeTest.getType().getCode());
            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());
            assertNotNull(resultIncomeTest.getGmtAddress());

            FinancialStatement incomingStmt = incoming.getFinancialStatement(incomeYear);
            FinancialStatement resultStmt = result.getFinancialStatement(incomeYear);
            assertNotNull("Result FinancialStatement should not be null", resultStmt);
            assertEquals(incomingStmt.getMarriedLastCalendarYear(), resultStmt.getMarriedLastCalendarYear());
            assertNotNull(resultStmt.getSpouseFinancials());
            assertNotNull(resultStmt.getDependentFinancials());
            assertEquals(resultStmt.getDependentFinancials().size(), 2);

            EnrollmentDetermination ed = createEnrollmentDetermination();
            ed.getEgtSetting().setCurrent(Boolean.TRUE);
            result.setEnrollmentDetermination(ed);
            savePerson(result);
        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }

        onFile = getPersonService().getPerson(person.getPersonEntityKey());
        incoming = (Person) onFile.clone();

        FinancialStatement stmt = incoming.getFinancialStatement(incomeYear);
        stmt.addDependentFinancials(createDependentFinancials(incomeYear, Relationship.CODE_STEPSON));
        permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, true);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());

            assertEquals(resultIncomeTest.getGmtThresholdAmount(), new BigDecimal(getGMTThreshold(incomeYear,
                    zipCode, 3).toString()));
            assertEquals(IncomeTestType.CODE_MEANS_TEST.getName(), resultIncomeTest.getType().getCode());
            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());
            assertNotNull(resultIncomeTest.getGmtAddress());

            FinancialStatement incomingStmt = incoming.getFinancialStatement(incomeYear);
            FinancialStatement resultStmt = result.getFinancialStatement(incomeYear);
            assertNotNull("Result FinancialStatement should not be null", resultStmt);
            assertEquals(incomingStmt.getMarriedLastCalendarYear(), resultStmt.getMarriedLastCalendarYear());
            assertNotNull(resultStmt.getSpouseFinancials());
            assertNotNull(resultStmt.getDependentFinancials());
            assertEquals(resultStmt.getDependentFinancials().size(), 3);

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    public void testAddFinancialsPharmacyCopay() throws Exception {
        Integer incomeYear = new Integer(2002);
        String zipCode = "22003";
        Person person = buildSimplePerson();

        person.getPermanentAddress().setZipCode(zipCode);
        MilitaryService ms = person.getMilitaryService();
        if (ms == null) {
            ms = new MilitaryService();
            person.setMilitaryService(ms);
        }
        ms.setDisabilityRetirementIndicator(Boolean.TRUE);
        person = savePerson(person);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);
        buildIncomeTestData(incomeYear, incoming, testSource, getHECFacility());
        buildFinancialStatementData(incomeYear, incoming);

        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), true);
        boolean permitted = executeDetermineMTPermitted(person, incomeYear)
                || executeisMeansTestRequired(person, incomeYear);

        assertEquals(permitted, false);
        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest incomingIncomeTest = incoming.getIncomeTest(incomeYear);
            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);

            assertNotNull("Result IncomeTest should not be null", resultIncomeTest);
            assertNotNull(resultIncomeTest.getCompletedDate());
            assertNotNull(resultIncomeTest.getLastEditedDate());
            assertEquals(resultIncomeTest.getGmtThresholdAmount(), new BigDecimal(getGMTThreshold(incomeYear,
                    zipCode, 3).toString()));
            assertEquals(IncomeTestType.CODE_CO_PAY_EXEMPTION_TEST.getName(), resultIncomeTest.getType()
                    .getCode());
            assertNotNull(resultIncomeTest.getStatus());
            assertEquals(incomingIncomeTest.getSource(), resultIncomeTest.getSource());
            assertEquals(testSource, resultIncomeTest.getSource());
            assertNull(resultIncomeTest.getSiteConductingTest());
            assertNotNull(resultIncomeTest.getGmtAddress());

            FinancialStatement incomingStmt = incoming.getFinancialStatement(incomeYear);
            FinancialStatement resultStmt = result.getFinancialStatement(incomeYear);
            assertNotNull("Result FinancialStatement should not be null", resultStmt);
            assertEquals(incomingStmt.getMarriedLastCalendarYear(), resultStmt.getMarriedLastCalendarYear());
            assertNotNull(resultStmt.getSpouseFinancials());
            assertNotNull(resultStmt.getDependentFinancials());
            assertEquals(resultStmt.getDependentFinancials().size(), 2);

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    /**
     * Test for sites that have support for new spouse indicator
     * and HEC is editing file
     * 
     * @throws Exception
     */    
    public void testDependentCalculationDeployedSites() throws Exception {
        Integer incomeYear = new Integer(2013);
        Person person = savePerson(buildSimplePerson());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);
        IncomeTestType testType = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus testStatus = getMeansTestStatus(MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT);

        buildIncomeTestData(incomeYear, person, testType, testSource, testStatus, getHECFacility());

        buildFinancialStatementData(incomeYear, person);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());
        Person pristine = (Person) person.clone();

        incoming.getFinancialStatement(incomeYear).setContributionToSpouse(null);
        incoming.getFinancialStatement(incomeYear).setContributedToSpouseInd(Boolean.TRUE);
        
        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear,
                getHECFacility(), true);
        FinancialInputParameter fip = buildFinancialInputParameter(data);

        BigDecimal totalIncome = fip.getCalculatedTotalIncome();
        Integer depCount = fip.getCalculatedNumberOfDependents();
        Integer depChildCount = fip.getCalculatedNumberOfDependentChildren();
        System.out.println("depCount="+depCount);
        System.out.println("depChildCount="+depChildCount);
        assertTrue(depCount == 3);
        assertTrue(depChildCount == 2);
        logger.debug(depCount);
        logger.debug(depChildCount);
        logger.debug(totalIncome);
        logger.debug(fip.getCalculatedAdjustableMedicalExpense());
        logger.debug(fip.getCalculatedNetworth());
    }    
    
    /**
     * Test for sites that don't have support for new spouse indicator
     * and HEC is editing file
     * 
     * @throws Exception
     */
    public void testDependentCalculationNonDeployedSites() throws Exception {
        Integer incomeYear = new Integer(2013);
        Person person = savePerson(buildSimplePerson());

        IncomeTestSource testSource = getTestSource(IncomeTestSource.CODE_HEC);
        IncomeTestType testType = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus testStatus = getMeansTestStatus(MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT);

        buildIncomeTestData(incomeYear, person, testType, testSource, testStatus, getHECFacility());

        buildFinancialStatementData(incomeYear, person);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());
        Person pristine = (Person) person.clone();

        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear,
                getHECFacility(), true);
        FinancialInputParameter fip = buildFinancialInputParameter(data);

        BigDecimal totalIncome = fip.getCalculatedTotalIncome();
        Integer depCount = fip.getCalculatedNumberOfDependents();
        Integer depChildCount = fip.getCalculatedNumberOfDependentChildren();
        System.out.println("depCount="+depCount);
        System.out.println("depChildCount="+depChildCount);
        logger.debug(depCount);
        logger.debug(depChildCount);
        logger.debug(totalIncome);
        logger.debug(fip.getCalculatedAdjustableMedicalExpense());
        logger.debug(fip.getCalculatedNetworth());
    }

    // start public law test case
    private Person createDataforMTAndRxCopayTestWithCD(Person person, EligibilityType.Code primary,
            EligibilityType.Code secondary, Integer svcConnectionAwardPercent, Boolean unEmployable, MonetaryBenefitType.Code mbType, BigDecimal checkAmount, Boolean CDIndicator)
            throws Exception {

        EnrollmentDetermination enrollDet = new EnrollmentDetermination();
        enrollDet.setEgtSetting(getEgtService().getCurrentEGTSetting());
        person.setEnrollmentDetermination(enrollDet);
        
        if (CDIndicator!=null){
            // CatastrophicDisability cd = new CatastrophicDisability();
        	CatastrophicDisability cd = person.getCatastrophicDisability();
        	if (cd==null){
        		cd = new CatastrophicDisability();
        	}
        	person.removeClinicalDeterminationByType(CatastrophicDisability.class);
            cd.setCatastrophicallyDisabled(CDIndicator);
            // cd.setCatastrophicallyDisabled(Boolean.TRUE);
            VAFacility facility= (VAFacility)this.getLookupService().getByCode(VAFacility.class,VAFacility.CODE_IRON_MOUNTAIN_VA_MEDICAL_CENTER);
            cd.setDeterminationFacility(facility);
            CDDeterminationMethod method= (CDDeterminationMethod)this.getLookupService().getByCode(CDDeterminationMethod.class,CDDeterminationMethod.CODE_PHYSICAL_EXAMINATION);
            cd.setDeterminationMethod(method);
            cd.setDeterminedBy("Tester");
            cd.setVeteranRequestedCDReviewDate(this.getDate(2005,6,10));
            cd.setFacilityInitiatedCDReviewDate(this.getDate(2005,6,11));
            cd.setReviewDate(this.getDate(2005,6,16));
            cd.setDecisionDate(this.getDate(2005,5,16));
            person.addClinicalDetermination(cd);  
        }
        return person;
    }
    
    public void testPhramacyCopyTestApplicableWithCD() throws Exception {
        Integer incomeYear = new Integer(2002);
        
        //      catastrophically disabled is YES
        Person person = buildSimplePerson();
        person = createDataforMTAndRxCopayTestWithCD(person, null,
                null, null, null, null, null,Boolean.TRUE);
        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), false);
        
        //      catastrophically disabled is NO
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTestWithCD(person, null,
                null, null, null, null, null,Boolean.FALSE);
        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), true);  
    }

    public void testMeansTestRequiredWithCD() throws Exception {
        Integer incomeYear = new Integer(2002);
        
        // catastrophically disabled is YES
        Person person = buildSimplePerson();
        person = createDataforMTAndRxCopayTestWithCD(person, null,
                null, null, null, null, null,Boolean.TRUE);
        assertEquals(executeisMeansTestRequired(person, incomeYear), false);
        
        // catastrophically disabled is NO
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTestWithCD(person, null,
                null, null, null, null, null,Boolean.FALSE);
        assertEquals(executeisMeansTestRequired(person, incomeYear), true);
    }
    // end of public law test case
    
    public void testPhramacyCopyTestApplicable() throws Exception {
        Integer incomeYear = new Integer(2002);
     
        // Case 1 (Rule 3)
        Person person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT,
                EligibilityType.AID_AND_ATTENDANCE, new Integer(0), null, null, null);
        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), false);
        // Case 2 (Rule 7)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person,
                EligibilityType.SERVICE_CONNECTED_50_TO_100_PERCENT, null, null, null, null, null);
        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), false);
        // Case 3 (Rule 21)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT,
                null, new Integer(10), Boolean.TRUE, null, null);
        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), false);

        // Case 4 (yes)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT,
                null, new Integer(10), Boolean.FALSE, null, null);
        assertEquals(executeisPhramacyCoPayApplicable(person, incomeYear), true);
    }

    public void testMeansTestRequired() throws Exception {
        Integer incomeYear = new Integer(2002);

        Person person = buildSimplePerson();
        MilitaryService ms = person.getMilitaryService();
        if (ms == null)
            ms = new MilitaryService();
        ms.setDisabilityRetirementIndicator(Boolean.TRUE);
        person.setMilitaryService(ms);
        assertEquals(executeisMeansTestRequired(person, incomeYear), false);

        // Case 1 (Rule 5) not required
        person = buildSimplePerson();
        person = createDataforMTRequired(person, EligibilityType.SERVICE_CONNECTED_50_TO_100_PERCENT,
                new Integer(0));
        assertEquals(executeisMeansTestRequired(person, incomeYear), false);

        // Case 2 (Rule 1) required
        person = buildSimplePerson();
        person = createDataforMTRequired(person, EligibilityType.SC_LESS_THAN_50_PERCENT, new Integer(0));
        assertEquals(executeisMeansTestRequired(person, incomeYear), true);

        // Case 3 (Rule 1) required
        person = buildSimplePerson();
        person = createDataforMTRequired(person, EligibilityFactor.AGENT_ORANGE_EXPOSURE, new Integer(10));
        assertEquals(executeisMeansTestRequired(person, incomeYear), true);

        // Case 4 (Rule 12) not required
        person = buildSimplePerson();
        person = createDataforMTRequired(person, EligibilityType.WORLD_WAR_I, new Integer(10));
        assertEquals(executeisMeansTestRequired(person, incomeYear), false);

        // Case 5 (Rule 15) not required
        person = buildSimplePerson();
        person = createDataforMTRequired(person, EligibilityType.TRICARE_CHAMPUS, new Integer(10));
        assertEquals(executeisMeansTestRequired(person, incomeYear), false);
    }

    public void testDetermineMTPermitted() throws Exception {
        Integer incomeYear = new Integer(2002);

        // Rule 1 
        Person person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT,
                EligibilityType.AID_AND_ATTENDANCE, new Integer(0), null, 
                MonetaryBenefitType.CODE_DISABILITY_COMPENSATION, new BigDecimal(5));        
         assertEquals(executeDetermineMTPermitted(person, incomeYear), true);

        // Rule 1 (fail)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT,
                EligibilityType.AID_AND_ATTENDANCE, new Integer(0), null, null, null);
        assertEquals(executeDetermineMTPermitted(person, incomeYear), false);

        // Rule 2 
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.WORLD_WAR_I,
                null, null, null, null, new BigDecimal(0));
        person.setMilitaryService(new MilitaryService());
        person.getMilitaryService().setDisabilityRetirementIndicator(Boolean.FALSE);
        assertEquals(executeDetermineMTPermitted(person, incomeYear), true);

        // Rule 3
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, 
                EligibilityType.SC_LESS_THAN_50_PERCENT, 
                EligibilityType.WORLD_WAR_I, 
                new Integer(0), null, null, null);
        person.setMilitaryService(new MilitaryService());
        person.getMilitaryService().setDisabilityRetirementIndicator(Boolean.TRUE);
        assertEquals(executeDetermineMTPermitted(person, incomeYear), true);

        // Rule 4
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT, null,
                new Integer(0), null, null, null);
        IneligibilityFactor ief = new IneligibilityFactor();
        person.setIneligibilityFactor(ief);
        ief.setIneligibleDate(new Date());
        assertEquals(executeDetermineMTPermitted(person, incomeYear), true);

        // Rule 4 (fail)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT, null,
                new Integer(0), null, null, null);
        ief = new IneligibilityFactor();
        person.setIneligibilityFactor(ief);
        assertEquals(executeDetermineMTPermitted(person, incomeYear), false); //ineligible date is null

        // Rule 4 (fail)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.SC_LESS_THAN_50_PERCENT, null,
                new Integer(2), null, null, null);
        ief = new IneligibilityFactor();
        person.setIneligibilityFactor(ief);
        ief.setIneligibleDate(new Date());
        assertEquals(executeDetermineMTPermitted(person, incomeYear), false); //2percent 

        // Rule 5
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.NSC, null,
                null, null, null, null);
        ief = new IneligibilityFactor();
        person.setIneligibilityFactor(ief);
        ief.setIneligibleDate(new Date());
        assertEquals(executeDetermineMTPermitted(person, incomeYear), true);

        // Rule 5 (fail)
        person = buildSimplePerson();
        person = createDataforMTAndRxCopayTest(person, EligibilityType.NSC, null,
                null, null, null, null);
        ief = new IneligibilityFactor();
        person.setIneligibilityFactor(ief);
        assertEquals(executeDetermineMTPermitted(person, incomeYear), false); //ineligible date is null
    }

    public void testDeleteHECIncomeTest() throws Exception {
        Integer incomeYear = new Integer(2003);
        VAFacility facility = getVaFacility(VAFacility.CODE_ALBUQUERQUE);

        IncomeTestSource src = getTestSource(IncomeTestSource.CODE_HEC);
        IncomeTestType typ = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus status = getMeansTestStatus(MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT);

        Person p = buildSimplePerson();
        buildIncomeTestData(incomeYear, p, typ, src, status, facility);
        Person person = savePerson(p);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        // remove the income test in the incoming person.
        incoming.setIncomeTest(incomeYear, null);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);
            assertNull("Result IncomeTest should be null (should have been deleted)", resultIncomeTest);

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }
    }

    public void testDeleteVAMCIncomeTest() throws Exception {
        Integer incomeYear = new Integer(2003);
        VAFacility facility = getVaFacility(VAFacility.CODE_ALBUQUERQUE);

        IncomeTestSource src = getTestSource(IncomeTestSource.CODE_VAMC);
        IncomeTestType typ = getTestType(IncomeTestType.CODE_MEANS_TEST);
        MeansTestStatus status = getMeansTestStatus(MeansTestStatus.MT_STATUS_MT_COPAY_EXEMPT);

        Person p = buildSimplePerson();
        buildIncomeTestData(incomeYear, p, typ, src, status, facility);
        Person person = savePerson(p);

        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = getPersonService().getPerson(person.getPersonEntityKey());

        // remove the income test in the incoming person.
        incoming.setIncomeTest(incomeYear, null);

        try {
            Person result = invokeFinancialRuleService(incomeYear, getHECFacility(), incoming, onFile);

            IncomeTest resultIncomeTest = result.getIncomeTest(incomeYear);
            assertNotNull("Result IncomeTest should not be null (Only HEC test can be deleted)",
                    resultIncomeTest);

        } catch (Exception e) {
            this.fail("Failed due to exception ", e);
        }

    }

    private boolean executeDetermineMTPermitted(Person person, Integer incomeYear) throws Exception {
        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = (Person) person.clone();
        Person pristine = (Person) person.clone();

        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear, getHECFacility(), true);
        return buildFinancialInputParameter(data).isMTPermitted();
    }
    private Person createDataforMTRequired(Person person, AbstractCode primary,
            Integer svcConnectionAwardPercent) throws Exception {

        EnrollmentDetermination enrollDet = new EnrollmentDetermination();
        person.setEnrollmentDetermination(enrollDet);
        // Primary
        if (primary != null) {
            Eligibility eligibility = new Eligibility();
            if(primary instanceof EligibilityType.Code)
            	eligibility.setType(getLookupService().getEligibilityTypeByCode(primary.getCode()));
            else if(primary instanceof EligibilityFactor.Code)
            	eligibility.setFactor(getLookupService().getEligibilityFactorByCode(primary.getCode()));
            
            if (eligibility.getType() == null) {
            	Eligibility primaryElig = new Eligibility();
            	primaryElig.setType(getLookupService().getEligibilityTypeByCode(EligibilityType.NSC.getCode()));
            	enrollDet.setPrimaryEligiblity(primaryElig);
            	enrollDet.addOtherEligibility(eligibility);
            }
            else {
            	enrollDet.setPrimaryEligiblity(eligibility);
            }
        }

        ServiceConnectionAward serviceConnectionAward = new ServiceConnectionAward();
        person.setServiceConnectionAward(serviceConnectionAward);

        if (svcConnectionAwardPercent != null)
            serviceConnectionAward.setServiceConnectedPercentage(svcConnectionAwardPercent);

        return person;
    }

    private boolean executeisMeansTestRequired(Person person, Integer incomeYear) throws Exception {
        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = (Person) person.clone();
        Person pristine = (Person) person.clone();

        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear,
                getHECFacility(), true);
        return buildFinancialInputParameter(data).isVeteranSubjectToMeansTesting();
    }

    private boolean executeisPhramacyCoPayApplicable(Person person, Integer incomeYear) throws Exception {
        // Clone the pristine to have a working version
        Person incoming = (Person) person.clone();
        Person onFile = (Person) person.clone();
        Person pristine = (Person) person.clone();

        FinancialInputData data = new FinancialInputData(incoming, onFile, pristine, incomeYear,
                getHECFacility(), true);
        return buildFinancialInputParameter(data).isRXCopayApplicableForVeteran();
    }

    private Person createDataforMTAndRxCopayTest(Person person, EligibilityType.Code primary,
            EligibilityType.Code secondary, Integer svcConnectionAwardPercent, Boolean unEmployable, MonetaryBenefitType.Code mbType, BigDecimal checkAmount)
            throws Exception {

        EnrollmentDetermination enrollDet = new EnrollmentDetermination();
        enrollDet.setEgtSetting(getEgtService().getCurrentEGTSetting());
        person.setEnrollmentDetermination(enrollDet);
        // Primary
        if (primary != null) {
            Eligibility eligibility = new Eligibility();
            eligibility.setType(getLookupService().getEligibilityTypeByCode(primary.getName()));
            enrollDet.setPrimaryEligiblity(eligibility);
        }
        // get secondary eligibilities and add
        if (secondary != null) {
            Eligibility secEligibility1 = new Eligibility();
            secEligibility1.setType(getLookupService().getEligibilityTypeByCode(secondary.getName()));
            enrollDet.addSecondaryEligibility(secEligibility1);
        }

        ServiceConnectionAward serviceConnectionAward = new ServiceConnectionAward();
        person.setServiceConnectionAward(serviceConnectionAward);

        if (svcConnectionAwardPercent != null)
            serviceConnectionAward.setServiceConnectedPercentage(svcConnectionAwardPercent);

        if (unEmployable != null)
            serviceConnectionAward.setUnemployable(unEmployable);
        
        if (mbType!= null || checkAmount != null) {
            MonetaryBenefitAward mba = new MonetaryBenefitAward();
            if (checkAmount != null)
                mba.setCheckAmount(checkAmount);
            if (mbType != null) {
                MonetaryBenefit mb = new MonetaryBenefit();
                mb.setType(getLookupService().getMonetaryBenefitTypeByCode(mbType.getCode()));
                mb.setMonetaryBenefitIndicator(getLookupService().getIndicatorByCode(Indicator.YES));
                mba.setDisabilityCompensation(mb);
            }
            person.setMonetaryBenefitAward(mba);
       }
 
        return person;
    }

    protected void setFinancialInfo(FinancialInformation finInfo, double incomeAmount, double expenseAmount,
            double assetAmount, double debtAmount) throws Exception {
        Asset asset = (Asset) finInfo.getAssets().values().iterator().next();
        asset.setAmount(new BigDecimal(assetAmount));
        Income income = (Income) finInfo.getIncome().values().iterator().next();
        income.setAmount(new BigDecimal(incomeAmount));
        Expense expense = (Expense) finInfo.getExpenses().values().iterator().next();
        expense.setAmount(new BigDecimal(expenseAmount));
        Debt debt = finInfo.getDebt();
        debt.setAmount(new BigDecimal(debtAmount));
    }

    protected FinancialStatement buildFinancialStatementData(Integer incomeYear, Person person)
            throws Exception {
        FinancialStatement stmt = person.getFinancialStatement(incomeYear);
        if (stmt == null) {
            stmt = createFinancialStatement();
            setFinancialInfo(stmt, 50000, 0, 0, 2000);
            createAsset(stmt, 50000, AssetType.CODE_CASH);
            createAsset(stmt, 100000, AssetType.CODE_REAL_ESTATE);
            createAsset(stmt, 10000, AssetType.CODE_OTHER);
            setExpense(stmt, 2000, ExpenseType.EXPENSE_TYPE_FUNERAL_AND_BURIAL);
            setExpense(stmt, 4000, ExpenseType.EXPENSE_TYPE_NON_REIMBURSED_MEDICAL);
            person.setFinancialStatement(incomeYear, stmt);
        }
        Calendar startDate = Calendar.getInstance();
        startDate.set(Calendar.YEAR, incomeYear.intValue() - 1);
        Spouse spouse = createSpouse();
        spouse.setStartDate(new ImpreciseDate(startDate));

        SpouseFinancials sf = createSpouseFinancials(spouse);
        setFinancialInfo(sf, 30000, 500, 5000, 1000);
        createAsset(sf, 5000, AssetType.CODE_OTHER);
        stmt.setMarriedLastCalendarYear(Boolean.TRUE);
        stmt.removeActiveSpouseFinancials();
        stmt.addSpouseFinancials(sf);

        DependentFinancials df1 = createDependentFinancials(incomeYear, Relationship.CODE_DAUGHTER);
        stmt.addDependentFinancials(df1);

        Dependent dependent2 = createDependent();
        DependentFinancials df2 = createDependentFinancials(dependent2);
        dependent2.setRelationship(getLookupService().getRelationshipByCode(Relationship.CODE_SON.getName()));
        dependent2.setStartDate(new ImpreciseDate(startDate));
        df2.setLivedWithPatient(Boolean.FALSE);
        df2.setHasIncome(Boolean.TRUE);
        df2.setIncomeAvailableToPatient(Boolean.TRUE);
        df2.setContributedToSupport(Boolean.TRUE);
        setFinancialInfo(df2, 20000, 1200, 2050, 1000);
        createIncome(df2, 2000, IncomeType.INCOME_TYPE_TOTAL_INCOME_FROM_EMPLOYMENT);
        stmt.addDependentFinancials(df2);

        return stmt;
    }

    /**
     * @param startDate
     * @param relationship
     * @return
     * @throws Exception
     * @throws UnknownLookupTypeException
     * @throws UnknownLookupCodeException
     */
    private DependentFinancials createDependentFinancials(Integer incomeYear, Relationship.Code relationship)
            throws Exception, UnknownLookupTypeException, UnknownLookupCodeException {
        Calendar startDate = Calendar.getInstance();
        startDate.set(Calendar.YEAR, incomeYear.intValue() - 1);

        Dependent dependent1 = createDependent();
        DependentFinancials df1 = createDependentFinancials(dependent1);
        dependent1.setRelationship(getLookupService().getRelationshipByCode(relationship.getName()));
        dependent1.setStartDate(new ImpreciseDate(startDate));
        df1.setLivedWithPatient(Boolean.TRUE);
        df1.setHasIncome(Boolean.TRUE);
        df1.setIncomeAvailableToPatient(Boolean.TRUE);
        setFinancialInfo(df1, 10000, 1500, 1750, 750);
        createIncome(df1, 5000, IncomeType.INCOME_TYPE_TOTAL_INCOME_FROM_EMPLOYMENT);
        setExpense(df1, 500, ExpenseType.EXPENSE_TYPE_EDUCATIONAL_EXPENSES_BY_DEPENDENT);
        return df1;
    }

    protected IncomeTest buildIncomeTestData(Integer incomeYear, Person person, IncomeTestSource source,
            VAFacility facility) throws Exception {
        IncomeTest incomeTest = person.getIncomeTest(incomeYear);
        if (incomeTest == null) {
            incomeTest = new IncomeTest();
            incomeTest.setIncomeYear(incomeYear);
            person.setIncomeTest(incomeYear, incomeTest);
        }
        incomeTest.setSource(source);
        incomeTest.setSiteConductingTest(facility);
        incomeTest.setAgreesToPayDeductible(Boolean.FALSE);
        
        incomeTest.setEffectiveDate(getPastTime().getTime());

        return incomeTest;
    }

    protected Person invokeFinancialRuleService(Integer incomeYear, VAFacility facility, Person incoming,
            Person onFile) throws Exception {
        return getFinancialInfoRuleService()
                .manageFinancialAssessment(incomeYear, facility, incoming, onFile);
    }

    private Integer getGMTThreshold(Integer incomeYear, String zipCode, int dependents) throws Exception {
        Integer thresholdAmount = null;
        if (zipCode == null)
            return thresholdAmount;

        String fipsCode = null;
        // TODO do we need throw runtime exception or ignore ??
        try {
            fipsCode = getLookupService().getFipsCode(zipCode);
        } catch (Exception e) {
        }
        if (fipsCode == null)
            return thresholdAmount;

        String msaCode = null;
        List gmtThresholds = null;

        if (StringUtils.isEmpty(msaCode)) {
            // No MSA Code
            gmtThresholds = getLookupService().getGMTThreshold(incomeYear, fipsCode);
        } else // with MSA Code
        {
            gmtThresholds = getLookupService().getGMTThreshold(incomeYear, fipsCode, msaCode);
        }

        // Get the first one from the list
        if (gmtThresholds != null && gmtThresholds.size() > 0) {
            GMTThreshold gmtThreshold = (GMTThreshold) gmtThresholds.get(0);

            return calculateThresholdAmount(gmtThreshold, dependents);
        }
        // return default amount 0
        return thresholdAmount;
    }

    private Integer calculateThresholdAmount(GMTThreshold gmtThreshold, int totalDependents) {
        BigDecimal totalAmount = null;
        if (totalDependents > 7) {
            BigDecimal amountFor4 = gmtThreshold.getThresholdValue(3);
            BigDecimal amountFor8 = gmtThreshold.getThresholdValue(7);
            // 8% of 4 person base is added for each additional person over 8
            double excessAmount = (totalDependents - 7) * amountFor4.doubleValue() * 0.08;
            totalAmount = amountFor8.add(new BigDecimal(excessAmount));
        } else {
            totalAmount = gmtThreshold.getThresholdValue(totalDependents);// TODO
                                                                            // need
                                                                            // to
                                                                            // change
        }
        // Round to the closest $50
        return new Integer((int) (Math.floor((totalAmount.doubleValue() + 25.0) / 50) * 50));
    }

    private FinancialInputParameter buildFinancialInputParameter(FinancialInputData data) throws ServiceException {
        FinancialInputParameter fip = new FinancialInputParameter();//(FinancialInputParameter) applicationContext.getBean("financialRuleParameter"); //new FinancialInputParameter();
        fip.setRuleDataAware(data);
        fip.setLookupService(getLookupService());
        fip.setHelperService(getPersonHelperService());
        fip.setFinancialsHelperService(new FinancialsHelperServiceImpl());
        fip.setVeteranExpenseTypes(EXPENSE_TYPES_VETERAN);
        fip.setChildExpenseTypes(EXPENSE_TYPES_DEPENDENT);
        fip.setChildRelationships(DEPENDENT_RELATIONSHIPS);
        return fip;
    }
    
    /**
     * @return Returns the financialHelperService.
     * @throws ServiceException 
     */
    public FinancialsHelperService getFinancialsHelperService() throws ServiceException {
        if (financialsHelperService == null) {
            financialsHelperService = (FinancialsHelperService) applicationContext.getBean("financialsHelperService");
        }
        return financialsHelperService;
    }
    
    /**
     * @param financialHelperService The financialHelperService to set.
     */
    public void setFinancialsHelperService(FinancialsHelperService financialHelperService) {
        this.financialsHelperService = financialHelperService;
    }
	private void attachIncomeTest(Person person, Integer incomeYear,
			VAFacility facAO, MeansTestStatus.Code status) throws Exception {
		attachIncomeTest(this.getDate(incomeYear.intValue(), 3, 1), person,
				incomeYear, facAO, status);
	}
	private void attachIncomeTest(Date effective, Person person,
			Integer incomeYear, VAFacility facAO, MeansTestStatus.Code status)
			throws Exception {
		person.setIncomeTest(incomeYear, this.createIncomeTest(
				IncomeTestType.CODE_MEANS_TEST, status, incomeYear));
		person.setFinancialStatement(incomeYear,
				this.createFinancialStatement());
		person.getIncomeTest(incomeYear).setCompletedDate(
				this.getDate(incomeYear.intValue(), 11, 1));
		person.getIncomeTest(incomeYear).setEffectiveDate(effective);
		person.getIncomeTest(incomeYear).setLastEditedDate(effective);
		person.getIncomeTest(incomeYear).setSiteConductingTest(facAO);
		person.getIncomeTest(incomeYear).setSource(
				this.getLookupService().getIncomeTestSourceByCode(
						IncomeTestSource.CODE_VAMC.getCode()));
	}	
	
}