/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.module.cg.service;
import static org.kuali.kfs.sys.fixture.UserNameFixture.khuntley;
import java.sql.Date;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Vector;
import org.kuali.kfs.module.cg.businessobject.Award;
import org.kuali.kfs.module.cg.businessobject.Proposal;
import org.kuali.kfs.module.cg.businessobject.defaultvalue.NextProposalNumberFinder;
import org.kuali.kfs.module.cg.document.ProposalAwardCloseDocument;
import org.kuali.kfs.sys.ConfigureContext;
import org.kuali.kfs.sys.DocumentTestUtils;
import org.kuali.kfs.sys.context.KualiTestBase;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.core.api.datetime.DateTimeService;
import org.kuali.rice.core.api.util.type.KualiDecimal;
import org.kuali.rice.kew.api.document.DocumentStatus;
import org.kuali.rice.kew.api.exception.WorkflowException;
import org.kuali.rice.krad.document.Document;
import org.kuali.rice.krad.exception.ValidationException;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.DocumentService;
import org.kuali.rice.krad.util.GlobalVariables;
@ConfigureContext(session = khuntley)
public class CloseServiceTest extends KualiTestBase {
private static final String VALID_AWARD_STATUS_CODE = "R";
private static final String INVALID_AWARD_STATUS_CODE = "U";
private static final Long thirteen = new Long(13);
private static final Long fourteen = new Long(14);
private static final Long fifteen = new Long(15);
private DateFormat dateFormat;
private Date today;
private Date tomorrow;
private int timeout = 0;
@Override
protected void setUp() throws Exception {
super.setUp();
dateFormat = DateFormat.getDateInstance();
today = SpringContext.getBean(DateTimeService.class).getCurrentSqlDateMidnight();
Calendar calendar = Calendar.getInstance();
calendar.setTime(today);
calendar.add(Calendar.DAY_OF_YEAR, 1);
tomorrow = new Date(calendar.getTime().getTime());
}
public void testClose_awardEntryDateLessThanCloseOnOrBeforeDate() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = new Date(dateFormat.parse("May 20, 2000").getTime()); // must be <= closeCloseOnOrBeforeDate
Date proposalSubmissionDate = new Date(dateFormat.parse("May 2, 1999").getTime()); // must be less than
// closeCloseOnOrBeforeDate
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime()); // not relevant
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime()); // not relevant
Date proposalClosingDate = null; // must be null
Date awardClosingDate = null; // must be null
//
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, VALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close);
// Run the close.
SpringContext.getBean(CloseService.class).close();
// Verify.
assertEquals("Awards were not closed properly.", fourteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fifteen, close.getProposalClosedCount());
}
public void testClose_awardEntryDateEqualToCloseOnOrBeforeDate() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = new Date(dateFormat.parse("June 1, 2000").getTime()); // must be <= closeCloseOnOrBeforeDate
Date proposalSubmissionDate = new Date(dateFormat.parse("May 2, 1999").getTime()); // must be less than
// closeCloseOnOrBeforeDate
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime()); // not relevant
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime()); // not relevant
Date proposalClosingDate = null; // must be null
Date awardClosingDate = null; // must be null
//
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, VALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close);
// Run the close.
SpringContext.getBean(CloseService.class).close();
// Verify.
assertEquals("Awards were not closed properly.", fourteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fifteen, close.getProposalClosedCount());
}
public void testClose_awardClosingDateNotNull() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = new Date(dateFormat.parse("June 1, 2000").getTime());
Date proposalSubmissionDate = new Date(dateFormat.parse("May 2, 1999").getTime()); // must be less than
// closeCloseOnOrBeforeDate
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime()); // not relevant
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime()); // not relevant
Date proposalClosingDate = null; // must be null
Date awardClosingDate = today;
// Create and save objects for closing.
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, VALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close, false, true, true);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close);
// Run the close.
SpringContext.getBean(CloseService.class).close();
assertEquals("Awards were not closed properly.", thirteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fifteen, close.getProposalClosedCount());
}
public void testClose_awardStatusCodeInvalid() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = new Date(dateFormat.parse("June 1, 2000").getTime());
Date proposalSubmissionDate = new Date(dateFormat.parse("May 2, 1999").getTime()); // must be less than
// closeCloseOnOrBeforeDate
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime()); // not relevant
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime()); // not relevant
Date proposalClosingDate = null;
Date awardClosingDate = null;
// Create and save objects for closing.
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, INVALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close, true, false, true);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close);
// Run the close.
SpringContext.getBean(CloseService.class).close();
assertEquals("Awards were not closed properly.", thirteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fifteen, close.getProposalClosedCount());
}
public void testClose_awardEntryDateGreaterThanCloseOnOrBeforeDate() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = tomorrow;
Date proposalSubmissionDate = new Date(dateFormat.parse("May 2, 1999").getTime()); // must be less than
// closeCloseOnOrBeforeDate
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime()); // not relevant
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime()); // not relevant
Date proposalClosingDate = null; // must be null
Date awardClosingDate = null; // must be null
// Create and save objects for closing.
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, VALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close, true, true, false);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close);
// Run the close.
SpringContext.getBean(CloseService.class).close();
assertEquals("Awards were not closed properly.", thirteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fifteen, close.getProposalClosedCount());
}
public void testClose_proposalClosingDateNotNull() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = new Date(dateFormat.parse("June 1, 2000").getTime());
Date proposalSubmissionDate = new Date(dateFormat.parse("May 2, 1999").getTime()); // must be less than
// closeCloseOnOrBeforeDate
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime()); // not relevant
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime()); // not relevant
Date proposalClosingDate = today;
Date awardClosingDate = null;
// Create and save objects for closing.
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, VALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close, false, true);
// Run the close.
SpringContext.getBean(CloseService.class).close();
assertEquals("Awards were not closed properly.", fourteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fourteen, close.getProposalClosedCount());
}
public void testClose_proposalSubmissionDateGreaterThanCloseCloseOnOrBeforeDate() throws Exception {
Date closeInitiatedDate = today; // must be today, close will abort if not
Date closeCloseOnOrBeforeDate = today;
Date awardEntryDate = new Date(dateFormat.parse("June 1, 2000").getTime());
Date proposalSubmissionDate = tomorrow;
Date proposalBeginningDate = new Date(dateFormat.parse("Jul 1, 1999").getTime());
Date proposalEndingDate = new Date(dateFormat.parse("Aug 1, 1999").getTime());
Date proposalClosingDate = null;
Date awardClosingDate = null;
// Create and save objects for closing.
Proposal proposal = createProposal(proposalBeginningDate, proposalEndingDate, proposalSubmissionDate, proposalClosingDate);
SpringContext.getBean(BusinessObjectService.class).save(proposal);
Award award = createAward(proposal, awardEntryDate, awardClosingDate, VALID_AWARD_STATUS_CODE);
SpringContext.getBean(BusinessObjectService.class).save(award);
ProposalAwardCloseDocument close = createClose(closeCloseOnOrBeforeDate);
saveAndRoute(close);
// SpringContext.getBean(CloseService.class).save(close);
// Verify that everything should be OK for the close.
// Be sure that the award should be closed.
verifyAwardWillBeIncludedInClose(award, close);
// Be sure that the proposal should be closed.
verifyProposalWillBeIncludedInClose(proposal, close, true, false);
// Run the close.
SpringContext.getBean(CloseService.class).close();
assertEquals("Awards were not closed properly.", fourteen, close.getAwardClosedCount());
assertEquals("Proposals were not closed properly.", fourteen, close.getProposalClosedCount());
}
private void verifyAwardWillBeIncludedInClose(Award award, ProposalAwardCloseDocument close) {
verifyAwardWillBeIncludedInClose(award, close, true, true, true);
}
private void verifyAwardWillBeIncludedInClose(Award award, ProposalAwardCloseDocument close, boolean verifyAwardClosingDate, boolean verifyAwardStatusCode, boolean verifyAwardEntryDate) {
if (verifyAwardClosingDate) {
assertNull("Award closing date must be null to be included in closing.", award.getAwardClosingDate());
}
if (verifyAwardStatusCode) {
assertNotSame("Award status code must not be 'U' to be included in closing.", award.getAwardStatusCode(), "U");
}
if (verifyAwardEntryDate) {
assertTrue("Award entry date must be less than or equal to the close last closed date.", award.getAwardEntryDate().getTime() <= close.getCloseOnOrBeforeDate().getTime());
}
}
private void verifyProposalWillBeIncludedInClose(Proposal proposal, ProposalAwardCloseDocument close) {
verifyProposalWillBeIncludedInClose(proposal, close, true, true);
}
private void verifyProposalWillBeIncludedInClose(Proposal proposal, ProposalAwardCloseDocument close, boolean verifyProposalClosingDate, boolean verifyProposalSubmissionDate) {
if (verifyProposalClosingDate) {
assertNull("Proposal closing date must be null to be included in closing.", proposal.getProposalClosingDate());
}
if (verifyProposalSubmissionDate) {
assertTrue("Proposal submission date must be less than or equal to closing last closed date.", proposal.getProposalSubmissionDate().getTime() <= close.getCloseOnOrBeforeDate().getTime());
}
}
private Proposal createProposal(Date proposalBeginningDate, Date proposalEndingDate, Date proposalSubmissionDate, Date proposalClosingDate) {
// Create and save a proposal
Proposal proposal = new Proposal();
proposal.setProposalNumber(NextProposalNumberFinder.getLongValue());
// set required fields
proposal.setAgencyNumber("12851");
proposal.setProposalProjectTitle("Testing CG Close Process");
proposal.setProposalBeginningDate(proposalBeginningDate);
proposal.setProposalEndingDate(proposalEndingDate);
proposal.setProposalDirectCostAmount(new KualiDecimal("3840.00"));
proposal.setProposalIndirectCostAmount(new KualiDecimal("2016.00"));
proposal.setProposalTotalAmount(proposal.getProposalDirectCostAmount().add(proposal.getProposalIndirectCostAmount()));
proposal.setProposalSubmissionDate(proposalSubmissionDate);
proposal.setProposalClosingDate(proposalClosingDate);
proposal.setProposalAwardTypeCode("N");
proposal.setProposalPurposeCode("C");
return proposal;
}
private Award createAward(Proposal proposal, Date awardEntryDate, Date awardClosingDate, String awardStatusCode) {
// Create and save an award
Award award = new Award(proposal);
award.setAwardEntryDate(awardEntryDate);
award.setAwardClosingDate(awardClosingDate);
award.setAwardStatusCode(awardStatusCode);
return award;
}
private ProposalAwardCloseDocument createClose(Date closeCloseOnOrBeforeDate) throws WorkflowException {
Document document = DocumentTestUtils.createDocument(SpringContext.getBean(DocumentService.class), ProposalAwardCloseDocument.class);
ProposalAwardCloseDocument close = (ProposalAwardCloseDocument) document;// SpringContext.getBean(DocumentService.class).getNewDocument(Close.class);
close.setUserInitiatedCloseDate(today);
close.setCloseOnOrBeforeDate(closeCloseOnOrBeforeDate);
return close;
}
private void saveAndRoute(ProposalAwardCloseDocument close) throws Exception {
DocumentService documentService = SpringContext.getBean(DocumentService.class);
saveDocument(close, documentService);
close = (ProposalAwardCloseDocument) documentService.getByDocumentHeaderId(close.getDocumentNumber());
routeDocument(close, documentService);
}
public static void routeDocument(Document document, DocumentService documentService) throws Exception {
// Verify that the doc isn't yet routed.
assertFalse("Document should not be already ENROUTE: " + document,DocumentStatus.ENROUTE.equals(document.getDocumentHeader().getWorkflowDocument().getStatus()));
// Route the doc.
try {
documentService.routeDocument(document, "routing test doc", new Vector());
} catch ( ValidationException e ) {
// If the business rule evaluation fails then give us more info for debugging this test.
fail(e.getMessage() + ", " + GlobalVariables.getMessageMap());
}
// Routing should be configured to go straight to final.
// assertTrue(FINAL_STATUS.equals(document.getDocumentHeader().getWorkflowDocument().getStatus()));
}
public static void saveDocument(Document document, DocumentService documentService) throws WorkflowException {
try {
documentService.saveDocument(document);
}
catch (ValidationException e) {
// If the business rule evaluation fails then give us more info for debugging this test.
fail(e.getMessage() + ", " + GlobalVariables.getMessageMap());
}
}
}