/*
* 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.document.validation.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.kuali.kfs.integration.ar.AccountsReceivableCustomer;
import org.kuali.kfs.module.cg.CGConstants;
import org.kuali.kfs.module.cg.CGKeyConstants;
import org.kuali.kfs.module.cg.CGPropertyConstants;
import org.kuali.kfs.module.cg.businessobject.Agency;
import org.kuali.kfs.module.cg.businessobject.AgencyAddress;
import org.kuali.kfs.module.cg.businessobject.AgencyType;
import org.kuali.kfs.sys.KFSKeyConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.rice.kns.document.MaintenanceDocument;
import org.kuali.rice.kns.service.DataDictionaryService;
import org.kuali.rice.krad.bo.PersistableBusinessObject;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.ObjectUtils;
/**
* Rules for processing Agency instances.
*/
public class AgencyRule extends CGMaintenanceDocumentRuleBase {
protected static Logger LOG = org.apache.log4j.Logger.getLogger(AgencyRule.class);
protected Agency newAgency;
protected Agency oldAgency;
BusinessObjectService businessObjectService;
/**
* Default constructor.
*/
public AgencyRule() {
super();
businessObjectService = SpringContext.getBean(BusinessObjectService.class);
}
/**
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomApproveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomApproveDocumentBusinessRules(MaintenanceDocument document) {
LOG.debug("Entering AgencyRule.processCustomApproveDocumentBusinessRules");
boolean success = super.processCustomApproveDocumentBusinessRules(document);
success &= checkAgencyReportsTo(document);
LOG.info("Leaving AgencyRule.processCustomApproveDocumentBusinessRules");
return success;
}
/**
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
LOG.debug("Entering AgencyRule.processCustomRouteDocumentBusinessRules");
boolean success = super.processCustomRouteDocumentBusinessRules(document);
success &= checkAgencyReportsTo(document);
// Only do further custom Contracts & Grants Billing validations for route document, if the enhancements are active
if (contractsGrantsBillingEnhancementActive) {
// There must be at least one primary Agency Address in Agency
success &= checkPrimary(newAgency.getAgencyAddresses(), AgencyAddress.class, KFSPropertyConstants.AGENCY_ADDRESSES, Agency.class);
success &= validateAddresses(newAgency);
// Make sure new agency customers have a Customer Type
success &= validateCustomerType(newAgency);
}
LOG.info("Leaving AgencyRule.processCustomRouteDocumentBusinessRules");
return success;
}
/**
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
*/
@Override
protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
LOG.debug("Entering AgencyRule.processCustomSaveDocumentBusinessRules");
boolean success = super.processCustomSaveDocumentBusinessRules(document);
success &= checkAgencyReportsTo(document);
success &= validateAgencyType(document);
success &= validateAgencyReportingName(document);
LOG.info("Leaving AgencyRule.processCustomSaveDocumentBusinessRules");
return success;
}
/**
* @param document
* @return
*/
protected boolean validateAgencyType(MaintenanceDocument document) {
String agencyType = newAgency.getAgencyTypeCode();
Map params = new HashMap();
params.put("code", agencyType);
Object o = businessObjectService.findByPrimaryKey(AgencyType.class, params);
if (null == o) {
putFieldError("agencyTypeCode", KFSKeyConstants.ERROR_AGENCY_TYPE_NOT_FOUND, agencyType);
return false;
}
return true;
}
/**
* @param document
* @return
*/
protected boolean validateAgencyReportingName(MaintenanceDocument document) {
String agencyReportingName = newAgency.getReportingName();
String agencyExistsValue = newAgency.getCustomerCreationOptionCode();
if (CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE.equalsIgnoreCase(agencyExistsValue)) {
if (agencyReportingName.length() < 3) {
putFieldError("reportingName", CGKeyConstants.AgencyConstants.ERROR_AGENCY_NAME_LESS_THAN_THREE_CHARACTERS);
return false;
}
else if (agencyReportingName.substring(0, 3).contains(" ")) {
putFieldError("reportingName", CGKeyConstants.AgencyConstants.ERROR_AGENCY_NAME_NO_SPACES_IN_FIRST_THREE_CHARACTERS);
return false;
}
}
return true;
}
/**
* @param document
* @return
*/
protected boolean checkAgencyReportsTo(MaintenanceDocument document) {
boolean success = true;
if (newAgency.getReportsToAgencyNumber() != null) {
if (newAgency.getReportsToAgency() == null) { // Agency must exist
putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_NOT_FOUND, newAgency.getReportsToAgencyNumber());
success = false;
}
else if (!newAgency.getReportsToAgency().isActive()) { // Agency must be active. See KULCG-263
putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_INACTIVE, newAgency.getReportsToAgencyNumber());
success = false;
}
else if (newAgency.getAgencyNumber().equals(newAgency.getReportsToAgencyNumber())) {
putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_REPORTS_TO_SELF, newAgency.getAgencyNumber());
success = false;
}
else { // No circular references
List agencies = new ArrayList();
Agency agency = newAgency;
while (agency.getReportsToAgency() != null && success) {
if (!agencies.contains(agency.getAgencyNumber())) {
agencies.add(agency.getAgencyNumber());
}
else {
putFieldError("reportsToAgencyNumber", KFSKeyConstants.ERROR_AGENCY_CIRCULAR_REPORTING, agency.getAgencyNumber());
success = false;
}
agency = agency.getReportsToAgency();
}
}
}
return success;
}
/**
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#setupConvenienceObjects()
*/
@Override
public void setupConvenienceObjects() {
newAgency = (Agency) super.getNewBo();
oldAgency = (Agency) super.getOldBo();
}
/**
* Overrides the method in MaintenanceDocumentRuleBase to give error message to the user when the user tries to add multiple
* Primary Agency Addresses. At most one Primary Agency Address is allowed. contract.
*
* @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processAddCollectionLineBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument,
* java.lang.String, org.kuali.rice.krad.bo.PersistableBusinessObject)
*/
@Override
public boolean processAddCollectionLineBusinessRules(MaintenanceDocument document, String collectionName, PersistableBusinessObject line) {
// Only do if the CG Billing enhancements are turned on
if (contractsGrantsBillingEnhancementActive) {
if (line instanceof AgencyAddress) {
AgencyAddress newAgencyAddress = (AgencyAddress) line;
if (collectionName.equals(KFSPropertyConstants.AGENCY_ADDRESSES)) {
newAgency = (Agency) document.getNewMaintainableObject().getBusinessObject();
List<AgencyAddress> agencyAddresses = newAgency.getAgencyAddresses();
String tmpCode = newAgencyAddress.getCustomerAddressTypeCode();
// Check if there is an Agency Primary Address in the collection lines or not.
for (AgencyAddress agencyAddress : agencyAddresses) {
String customerAddressTypeCode = agencyAddress.getCustomerAddressTypeCode();
if (customerAddressTypeCode != null && customerAddressTypeCode.equals(CGConstants.AGENCY_PRIMARY_ADDRESSES_TYPE_CODE)) {
if (ObjectUtils.isNotNull(tmpCode) && !tmpCode.isEmpty() && tmpCode.equals(CGConstants.AGENCY_PRIMARY_ADDRESSES_TYPE_CODE)) {
String elementLabel = SpringContext.getBean(DataDictionaryService.class).getCollectionElementLabel(Agency.class.getName(), collectionName, AgencyAddress.class);
putFieldError(collectionName, KFSKeyConstants.ERROR_MULTIPLE_PRIMARY, elementLabel);
return false;
}
else {
boolean isValid = checkAddressIsValid(newAgencyAddress);
if (!isValid) {
return isValid;
}
}
}
}
}
}
}
return super.processAddCollectionLineBusinessRules(document, collectionName, line);
}
/**
* This method validates the addresses when Customer is created from Agency
*
* @param agencyAddress
* @return
*/
public boolean checkAddressIsValid(AgencyAddress agencyAddress) {
boolean isValid = true;
// To validate only if the Agency agency exists field says "Create New Customer".
if (CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE.equalsIgnoreCase(newAgency.getCustomerCreationOptionCode())) {
if (CGKeyConstants.AgencyConstants.AGENCY_ADDRESS_TYPE_CODE_US.equalsIgnoreCase(agencyAddress.getAgencyCountryCode())) {
if (StringUtils.isBlank(agencyAddress.getAgencyZipCode())) {
isValid = false;
GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_ZIP_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_ZIP_CODE_REQUIRED_WHEN_COUNTTRY_US);
}
if (StringUtils.isBlank(agencyAddress.getAgencyStateCode())) {
isValid = false;
GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_STATE_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_STATE_CODE_REQUIRED_WHEN_COUNTTRY_US);
}
}
else {
if (StringUtils.isBlank(agencyAddress.getAgencyInternationalMailCode())) {
isValid = false;
GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE_REQUIRED_WHEN_COUNTTRY_NON_US);
}
if (StringUtils.isBlank(agencyAddress.getAgencyAddressInternationalProvinceName())) {
isValid = false;
GlobalVariables.getMessageMap().putError(CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME_REQUIRED_WHEN_COUNTTRY_NON_US);
}
}
}
return isValid;
}
/**
* This method validates the addresses when Customer is created from Agency
*
* @param agencyAddress
* @param ind
* @return
*/
public boolean checkAddressIsValid(AgencyAddress agencyAddress, int ind) {
boolean isValid = true;
String propertyName = CGPropertyConstants.AgencyFields.AGENCY_TAB_ADDRESSES + "[" + ind + "].";
// To validate only if the Agency agencyexists field says "Create New Customer".
if (CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE.equalsIgnoreCase(newAgency.getCustomerCreationOptionCode())) {
if (CGKeyConstants.AgencyConstants.AGENCY_ADDRESS_TYPE_CODE_US.equalsIgnoreCase(agencyAddress.getAgencyCountryCode())) {
if (StringUtils.isBlank(agencyAddress.getAgencyZipCode())) {
isValid = false;
putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_ZIP_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_ZIP_CODE_REQUIRED_WHEN_COUNTTRY_US);
}
if (StringUtils.isBlank(agencyAddress.getAgencyStateCode())) {
isValid = false;
putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_STATE_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_STATE_CODE_REQUIRED_WHEN_COUNTTRY_US);
}
}
else {
if (StringUtils.isBlank(agencyAddress.getAgencyInternationalMailCode())) {
isValid = false;
putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_MAIL_CODE_REQUIRED_WHEN_COUNTTRY_NON_US);
}
if (StringUtils.isBlank(agencyAddress.getAgencyAddressInternationalProvinceName())) {
isValid = false;
putFieldError(propertyName + CGPropertyConstants.AgencyFields.AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ADDRESS_INTERNATIONAL_PROVINCE_NAME_REQUIRED_WHEN_COUNTTRY_NON_US);
}
}
}
return isValid;
}
/**
* This method validates the addresses when Customer is created from Agency
*
* @param agency
* @return
*/
public boolean validateAddresses(Agency agency) {
boolean isValid = true;
int i = 0;
for (AgencyAddress agencyAddress : agency.getAgencyAddresses()) {
isValid &= checkAddressIsValid(agencyAddress, i);
i++;
}
return isValid;
}
/**
* This method validates that a customer type is selected when the create new customer option is selected, and that if existing customer option
* is selected that customer number is filled in with an existing customer.
* @param agency agency record to verify
* @return true if agency passes verification, false otherwise
*/
public boolean validateCustomerType(Agency agency) {
boolean isValid = true;
// Only validate if new customer create option is selected
if ( StringUtils.equalsIgnoreCase(CGConstants.AGENCY_CREATE_NEW_CUSTOMER_CODE, agency.getCustomerCreationOptionCode()) ){
// Customer Type must be filled-in
if( StringUtils.isEmpty(agency.getCustomerTypeCode()) ){
putFieldError(CGPropertyConstants.AgencyFields.AGENCY_CUSTOMER_TYPE_CODE, CGKeyConstants.AgencyConstants.ERROR_AGENCY_CUSTOMER_TYPE_CODE_REQUIRED_WHEN_AGENCY_CUSTOMER_NEW);
isValid &= false;
}
} else if (StringUtils.equalsIgnoreCase(CGConstants.AGENCY_USE_EXISTING_CUSTOMER_CODE, agency.getCustomerCreationOptionCode())) {
if (StringUtils.isBlank(agency.getCustomerNumber())) {
putFieldError(CGPropertyConstants.AgencyFields.AGENCY_CUSTOMER_NUMBER, CGKeyConstants.AgencyConstants.ERROR_AGECNY_CUSTOMER_NUMBER_REQUIRED_WHEN_AGENCY_CUSTOMER_EXISTING);
isValid = false;
} else {
final AccountsReceivableCustomer customer = agency.getCustomer();
if (ObjectUtils.isNull(customer) || !customer.isActive()) {
putFieldError(CGPropertyConstants.AgencyFields.AGENCY_CUSTOMER_NUMBER, CGKeyConstants.AgencyConstants.ERROR_AGENCY_ACTUAL_CUSTOMER_REQUIRED_WHEN_AGENCY_CUSTOMER_EXISTING, new String[] { agency.getCustomerNumber() });
isValid = false;
}
}
}
return isValid;
}
}