001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.endow.document.validation.impl; 017 018 import java.math.BigDecimal; 019 import java.sql.Date; 020 021 import org.apache.log4j.Logger; 022 import org.kuali.kfs.module.endow.EndowKeyConstants; 023 import org.kuali.kfs.module.endow.EndowPropertyConstants; 024 import org.kuali.kfs.module.endow.businessobject.PooledFundValue; 025 import org.kuali.kfs.module.endow.document.service.PooledFundValueService; 026 import org.kuali.kfs.module.endow.util.ValidateLastDayOfMonth; 027 import org.kuali.kfs.sys.context.SpringContext; 028 import org.kuali.rice.kns.document.MaintenanceDocument; 029 import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase; 030 import org.kuali.rice.kns.util.GlobalVariables; 031 import org.kuali.rice.kns.util.MessageMap; 032 import org.kuali.rice.kns.util.ObjectUtils; 033 034 public class PooledFundValueRule extends MaintenanceDocumentRuleBase { 035 036 protected static Logger LOG = org.apache.log4j.Logger.getLogger(SecurityRule.class); 037 private PooledFundValue newPooledFundValue; 038 039 /** 040 * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument) 041 */ 042 @Override 043 protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) { 044 045 boolean isValid = true; 046 isValid &= super.processCustomRouteDocumentBusinessRules(document); 047 MessageMap errorMap = GlobalVariables.getMessageMap(); 048 isValid &= errorMap.hasNoErrors(); 049 050 if (isValid) { 051 PooledFundValue newPooledFundValue = (PooledFundValue) document.getNewMaintainableObject().getBusinessObject(); 052 isValid &= checkCustomRequiredFields(newPooledFundValue); 053 } 054 055 return isValid; 056 } 057 058 protected boolean checkCustomRequiredFields(PooledFundValue newPooledFundValue) { 059 boolean isValid = true; 060 061 Date valuationDate = newPooledFundValue.getValuationDate(); 062 String pooledSecurityID = newPooledFundValue.getPooledSecurityID(); 063 BigDecimal unitValue = newPooledFundValue.getUnitValue(); 064 065 isValid &= isValuationDateLastDayOfMonth(valuationDate); 066 isValid &= isValuationDateTheLatest(pooledSecurityID, valuationDate); 067 isValid &= isUnitValuePositive(unitValue); 068 BigDecimal zero = new BigDecimal(0); 069 BigDecimal incomeDistributionPerUnit = newPooledFundValue.getIncomeDistributionPerUnit(); 070 Date distributeIncomeOnDate = newPooledFundValue.getDistributeIncomeOnDate(); 071 if (ObjectUtils.isNotNull(incomeDistributionPerUnit) && (incomeDistributionPerUnit.compareTo(zero) == 1)) { 072 isValid &= isIncomeDistributionPerUnitNotNegative(incomeDistributionPerUnit); 073 isValid &= isDateRequiredField(distributeIncomeOnDate, EndowPropertyConstants.DISTRIBUTE_INCOME_ON_DATE, EndowKeyConstants.PooledFundValueConstants.ERROR_DISTRIBUTE_INCOME_ON_DATE_IS_REQUIRED_FIELD); 074 } 075 076 BigDecimal longTermGainLossDistributionPerUnit = newPooledFundValue.getLongTermGainLossDistributionPerUnit(); 077 Date distributeLongTermGainLossOnDate = newPooledFundValue.getDistributeLongTermGainLossOnDate(); 078 if (ObjectUtils.isNotNull(longTermGainLossDistributionPerUnit) && (longTermGainLossDistributionPerUnit.compareTo(zero) == 1)) { 079 isValid &= isDateRequiredField(distributeLongTermGainLossOnDate, EndowPropertyConstants.DISTRIBUTE_LONG_TERM_GAIN_LOSS_ON_DATE, EndowKeyConstants.PooledFundValueConstants.ERROR_DISTRIBUTE_LONG_TERM_GAIN_LOSS_ON_DATE_IS_REQUIRED_FIELD); 080 } 081 082 BigDecimal shortTermGainLossDistributionPerUnit = newPooledFundValue.getShortTermGainLossDistributionPerUnit(); 083 Date distributeShortTermGainLossOnDate = newPooledFundValue.getDistributeShortTermGainLossOnDate(); 084 if (ObjectUtils.isNotNull(shortTermGainLossDistributionPerUnit) && (shortTermGainLossDistributionPerUnit.compareTo(zero) == 1)) { 085 isValid &= isDateRequiredField(distributeShortTermGainLossOnDate, EndowPropertyConstants.DISTRIBUTE_SHORT_TERM_GAIN_LOSS_ON_DATE, EndowKeyConstants.PooledFundValueConstants.ERROR_DISTRIBUTE_SHORT_TERM_GAIN_LOSS_ON_DATE_IS_REQUIRED_FIELD); 086 } 087 088 089 return isValid; 090 } 091 092 /** 093 * 094 * 095 */ 096 protected boolean isDateRequiredField(Date theDate, String errorField, String errorKey) { 097 boolean isRequiredField = true; 098 if (ObjectUtils.isNull(theDate)) { 099 putFieldError(errorField, errorKey); 100 isRequiredField = false; 101 } 102 return isRequiredField; 103 } 104 105 /** 106 * Checks if the value of the valuation date is the last day of the month. If yes, return true; otherwise, return false. 107 * 108 * @param valuationDate 109 * @return true if valuationDate is the last day of the month, false otherwise 110 */ 111 protected boolean isValuationDateLastDayOfMonth(Date valuationDate) { 112 boolean isLastDay = true; 113 if (!ValidateLastDayOfMonth.validateLastDayOfMonth(valuationDate)) { 114 putFieldError(EndowPropertyConstants.VALUATION_DATE, EndowKeyConstants.PooledFundValueConstants.ERROR_VALUATION_DATE_IS_NOT_THE_END_OF_MONTH); 115 isLastDay = false; 116 } 117 return isLastDay; 118 } 119 120 /** 121 * The rule is "A new record cannot have a VAL_DT that is earlier than the record with the most recent VAL_DT". 122 * 123 * @param pooledSecurityID 124 * @param theValuationDate 125 * @return true if valuationDate is the latest one for the specified pooledSecurityID, false otherwise. 126 */ 127 protected boolean isValuationDateTheLatest(String pooledSecurityID, Date theValuationDate) { 128 PooledFundValueService pooledFundValueService = SpringContext.getBean(PooledFundValueService.class); 129 boolean isLatest = pooledFundValueService.isValuationDateTheLatest(pooledSecurityID, theValuationDate); 130 if (!isLatest) { 131 putFieldError(EndowPropertyConstants.VALUATION_DATE, EndowKeyConstants.PooledFundValueConstants.ERROR_VALUATION_DATE_IS_NOT_LATEST_ONE); 132 } 133 return isLatest; 134 } 135 136 /** 137 * The rule is unitValue can only be positive because unitValue is a required field. 138 * 139 * @param unitValue 140 * @return true if unitValue is a positive value, false otherwise 141 */ 142 protected boolean isUnitValuePositive(BigDecimal unitValue) { 143 boolean isPositive = true; 144 if (unitValue.compareTo(new BigDecimal(0)) != 1) { 145 putFieldError(EndowPropertyConstants.SECURITY_UNIT_VALUE, EndowKeyConstants.PooledFundValueConstants.ERROR_UNIT_VALUE_IS_NOT_POSITIVE); 146 isPositive = false; 147 } 148 return isPositive; 149 } 150 151 /** 152 * The rule is incomeDistributionPerUnit can't be less than zero. Either zero or positive value is an accepted/valid input 153 * because incomeDistributionPerUnit is not a required field. 154 * 155 * @param incomeDistributionPerUnit 156 * @return true if incomeDistributionPerUnit is zero or bigger than zero, false otherwise 157 */ 158 protected boolean isIncomeDistributionPerUnitNotNegative(BigDecimal incomeDistributionPerUnit) { 159 boolean isNotNegative = true; 160 if ((incomeDistributionPerUnit.compareTo(new BigDecimal(0)) == 1) || (incomeDistributionPerUnit.compareTo(new BigDecimal(0)) == 0)) { 161 return isNotNegative; 162 } 163 else { 164 putFieldError(EndowPropertyConstants.INCOME_DISTRIBUTION_PER_UNIT, EndowKeyConstants.PooledFundValueConstants.ERROR_INCOME_DISTRIBUTION_PER_UNIT_IS_NOT_POSITIVE); 165 return false; 166 } 167 } 168 169 }