/* * 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.ar.document.validation; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.kuali.kfs.module.ar.ArConstants; import org.kuali.kfs.module.ar.ArKeyConstants; import org.kuali.kfs.module.ar.ArPropertyConstants; import org.kuali.kfs.module.ar.businessobject.Milestone; import org.kuali.kfs.module.ar.businessobject.MilestoneSchedule; import org.kuali.kfs.module.ar.document.service.MilestoneScheduleMaintenanceService; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.validation.impl.KfsMaintenanceDocumentRuleBase; import org.kuali.rice.kns.document.MaintenanceDocument; import org.kuali.rice.krad.bo.PersistableBusinessObject; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; /** * Rules for the MilestoneSchedule maintenance document. */ public class MilestoneScheduleRule extends KfsMaintenanceDocumentRuleBase { protected static Logger LOG = org.apache.log4j.Logger.getLogger(MilestoneScheduleRule.class); protected MilestoneSchedule newMilestoneScheduleCopy; private static volatile MilestoneScheduleMaintenanceService milestoneScheduleMaintenanceService; /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override public boolean processCustomAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) { LOG.debug("Entering PredeterminedBillingScheduleRule.processCustomAddCollectionLineBusinessRules"); boolean isValid = true; isValid &= super.processCustomAddCollectionLineBusinessRules(document, collectionName, line); isValid &= checkForDuplicateBillNumber(collectionName, line); isValid &= !GlobalVariables.getMessageMap().hasErrors(); GlobalVariables.getMessageMap().removeAllErrorMessagesForProperty("document.newMaintainableObject." + ArPropertyConstants.MilestoneFields.MILESTONE_AMOUNT); LOG.info("Leaving PredeterminedBillingScheduleRule.processCustomAddCollectionLineBusinessRules"); return isValid; } /** * Check to see if a Bill with the same bill number already exists. * * @param collectionName name of the collection being added to * @param line PersistableBusinessObject being added to the collection * @return true if there isn't already a bill with the same bill number, false otherwise */ private boolean checkForDuplicateBillNumber(String collectionName, PersistableBusinessObject line) { boolean isValid = true; if (StringUtils.equalsIgnoreCase(collectionName, ArConstants.MILESTONES_SECTION)) { Milestone milestone = (Milestone) line; Long newMilestoneNumber = milestone.getMilestoneNumber(); for (Milestone existingMilestone: newMilestoneScheduleCopy.getMilestones()) { if (existingMilestone.getMilestoneNumber().equals(newMilestoneNumber)) { isValid = false; putFieldError(collectionName, ArKeyConstants.ERROR_DUPLICATE_MILESTONE_NUMBER); break; } } } return isValid; } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) { LOG.debug("Entering MilestoneScheduleRule.processCustomSaveDocumentBusinessRules"); processCustomRouteDocumentBusinessRules(document); LOG.info("Leaving MilestoneScheduleRule.processCustomSaveDocumentBusinessRules"); return true; // save despite error messages } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) */ @Override protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { LOG.debug("Entering MilestoneScheduleRule.processCustomRouteDocumentBusinessRules"); boolean success = true; success &= checkAwardBillingFrequency(); success &= checkForDuplicateMilestoneNumbers(); LOG.info("Leaving MilestoneScheduleRule.processCustomRouteDocumentBusinessRules"); return success; } /** * checks to see if the billing frequency on the award is Milestone * * @return */ protected boolean checkAwardBillingFrequency() { boolean success = false; if (ObjectUtils.isNotNull(newMilestoneScheduleCopy.getAward().getBillingFrequencyCode())) { if (StringUtils.equals(newMilestoneScheduleCopy.getAward().getBillingFrequencyCode(), ArConstants.MILESTONE_BILLING_SCHEDULE_CODE)) { success = true; } } if (!success) { putFieldError(KFSPropertyConstants.PROPOSAL_NUMBER, ArKeyConstants.ERROR_AWARD_MILESTONE_SCHEDULE_INCORRECT_BILLING_FREQUENCY, new String[] { newMilestoneScheduleCopy.getProposalNumber().toString() }); } return success; } /** * Check to see if there is more than one Milestone with the same milestone number. * * @return true if there is more than one Milestone with the same milestone number, false otherwise */ private boolean checkForDuplicateMilestoneNumbers() { boolean isValid = true; Set<Long> milestoneNumbers = new HashSet(); Set<Long> duplicateMilestoneNumbers = new HashSet(); for (Milestone milestone: newMilestoneScheduleCopy.getMilestones()) { if (!milestoneNumbers.add(milestone.getMilestoneNumber())) { duplicateMilestoneNumbers.add(milestone.getMilestoneNumber()); } } if (duplicateMilestoneNumbers.size() > 0) { isValid = false; int lineNum = 0; for (Milestone milestone: newMilestoneScheduleCopy.getMilestones()) { // If the Milestone has already been copied to the Invoice, it will be readonly, the user won't have been able to change // it and thus we don't need to highlight it as an error if it's a dupe. There will be another dupe in the list that // we will highlight. boolean copiedToInvoice = false; if (ObjectUtils.isNotNull(milestone.getMilestoneIdentifier())) { if (getMilestoneScheduleMaintenanceService().hasMilestoneBeenCopiedToInvoice(milestone.getProposalNumber(), milestone.getMilestoneIdentifier().toString())) { copiedToInvoice = true; } } if (!copiedToInvoice) { if (duplicateMilestoneNumbers.contains(milestone.getMilestoneNumber())) { String errorPath = ArPropertyConstants.MilestoneScheduleFields.MILESTONES + "[" + lineNum + "]." + ArPropertyConstants.MilestoneFields.MILESTONE_NUMBER; putFieldError(errorPath, ArKeyConstants.ERROR_DUPLICATE_MILESTONE_NUMBER); } } lineNum++; } } return isValid; } /** * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects() */ @Override public void setupConvenienceObjects() { newMilestoneScheduleCopy = (MilestoneSchedule) super.getNewBo(); } public MilestoneScheduleMaintenanceService getMilestoneScheduleMaintenanceService() { if (milestoneScheduleMaintenanceService == null) { milestoneScheduleMaintenanceService = SpringContext.getBean(MilestoneScheduleMaintenanceService.class); } return milestoneScheduleMaintenanceService; } }