/*
* 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.Bill;
import org.kuali.kfs.module.ar.businessobject.PredeterminedBillingSchedule;
import org.kuali.kfs.module.ar.document.service.PredeterminedBillingScheduleMaintenanceService;
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 PredeterminedBillingSchedule maintenance document.
*/
public class PredeterminedBillingScheduleRule extends KfsMaintenanceDocumentRuleBase {
protected static Logger LOG = org.apache.log4j.Logger.getLogger(PredeterminedBillingScheduleRule.class);
protected PredeterminedBillingSchedule newPredeterminedBillingScheduleCopy;
private static volatile PredeterminedBillingScheduleMaintenanceService predeterminedBillingScheduleMaintenanceService;
/**
* @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();
//for some reason a duplicate message is added to the error map
GlobalVariables.getMessageMap().removeAllErrorMessagesForProperty("document.newMaintainableObject." + ArPropertyConstants.PredeterminedBillingScheduleFields.ESTIMATED_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.BILL_SECTION)) {
Bill bill = (Bill) line;
Long newBillNumber = bill.getBillNumber();
for (Bill existingBill: newPredeterminedBillingScheduleCopy.getBills()) {
if (existingBill.getBillNumber().equals(newBillNumber)) {
isValid = false;
putFieldError(collectionName, ArKeyConstants.ERROR_DUPLICATE_BILL_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 PredeterminedBillingScheduleRule.processCustomSaveDocumentBusinessRules");
processCustomRouteDocumentBusinessRules(document);
LOG.info("Leaving PredeterminedBillingScheduleRule.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 PredeterminedBillingScheduleRule.processCustomRouteDocumentBusinessRules");
boolean success = true;
success &= checkAwardBillingFrequency();
success &= checkForDuplicateBillNumbers();
LOG.info("Leaving PredeterminedBillingScheduleRule.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(newPredeterminedBillingScheduleCopy.getAward().getBillingFrequencyCode())) {
if (StringUtils.equals(newPredeterminedBillingScheduleCopy.getAward().getBillingFrequencyCode(), ArConstants.PREDETERMINED_BILLING_SCHEDULE_CODE)) {
success = true;
}
}
if (!success) {
putFieldError(KFSPropertyConstants.PROPOSAL_NUMBER, ArKeyConstants.ERROR_AWARD_PREDETERMINED_BILLING_SCHEDULE_INCORRECT_BILLING_FREQUENCY, new String[] { newPredeterminedBillingScheduleCopy.getProposalNumber().toString() });
}
return success;
}
/**
* Check to see if there is more than one Bill with the same bill number.
*
* @return true if there is more than one bill with the same bill number, false otherwise
*/
private boolean checkForDuplicateBillNumbers() {
boolean isValid = true;
Set<Long> billNumbers = new HashSet<>();
Set<Long> duplicateBillNumbers = new HashSet<>();
for (Bill bill: newPredeterminedBillingScheduleCopy.getBills()) {
if (!billNumbers.add(bill.getBillNumber())) {
duplicateBillNumbers.add(bill.getBillNumber());
}
}
if (duplicateBillNumbers.size() > 0) {
isValid = false;
int lineNum = 0;
for (Bill bill: newPredeterminedBillingScheduleCopy.getBills()) {
// If the Bill 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(bill.getBillIdentifier())) {
if (getPredeterminedBillingScheduleMaintenanceService().hasBillBeenCopiedToInvoice(bill.getProposalNumber(), bill.getBillIdentifier().toString())) {
copiedToInvoice = true;
}
}
if (!copiedToInvoice) {
if (duplicateBillNumbers.contains(bill.getBillNumber())) {
String errorPath = ArPropertyConstants.PredeterminedBillingScheduleFields.BILLS + "[" + lineNum + "]." + ArPropertyConstants.BillFields.BILL_NUMBER;
putFieldError(errorPath, ArKeyConstants.ERROR_DUPLICATE_BILL_NUMBER);
}
}
lineNum++;
}
}
return isValid;
}
/**
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects()
*/
@Override
public void setupConvenienceObjects() {
newPredeterminedBillingScheduleCopy = (PredeterminedBillingSchedule) super.getNewBo();
}
public static PredeterminedBillingScheduleMaintenanceService getPredeterminedBillingScheduleMaintenanceService() {
if (predeterminedBillingScheduleMaintenanceService == null) {
predeterminedBillingScheduleMaintenanceService = SpringContext.getBean(PredeterminedBillingScheduleMaintenanceService.class);
}
return predeterminedBillingScheduleMaintenanceService;
}
}