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 }