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.bc.document.service.impl;
017
018 import static org.kuali.kfs.module.bc.BCConstants.AppointmentFundingDurationCodes.LWPA;
019 import static org.kuali.kfs.module.bc.BCConstants.AppointmentFundingDurationCodes.LWPF;
020 import static org.kuali.kfs.module.bc.BCConstants.AppointmentFundingDurationCodes.NONE;
021
022 import java.math.BigDecimal;
023 import java.util.List;
024
025 import org.apache.commons.lang.ObjectUtils;
026 import org.apache.commons.lang.StringUtils;
027 import org.kuali.kfs.module.bc.BCConstants;
028 import org.kuali.kfs.module.bc.BCKeyConstants;
029 import org.kuali.kfs.module.bc.BCPropertyConstants;
030 import org.kuali.kfs.module.bc.BCConstants.SynchronizationCheckType;
031 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding;
032 import org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService;
033 import org.kuali.kfs.module.bc.document.service.SalarySettingService;
034 import org.kuali.kfs.module.bc.service.HumanResourcesPayrollService;
035 import org.kuali.kfs.sys.KFSConstants;
036 import org.kuali.kfs.sys.KFSPropertyConstants;
037 import org.kuali.rice.kns.util.KualiDecimal;
038 import org.kuali.rice.kns.util.KualiInteger;
039 import org.kuali.rice.kns.util.MessageMap;
040
041 /**
042 * provide a set of rule elements for salary setting.
043 */
044 public class SalarySettingRuleHelperServiceImpl implements SalarySettingRuleHelperService {
045 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SalarySettingRuleHelperServiceImpl.class);
046
047 private SalarySettingService salarySettingService;
048 private HumanResourcesPayrollService humanResourcesPayrollService;
049
050 /**
051 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#canBeAdjusted(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding, org.kuali.rice.kns.util.ErrorMap)
052 */
053 public boolean canBeAdjusted(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
054 if (appointmentFunding.getEffectiveCSFTracker() == null) {
055 // These error messages should not be displayed since the reported condition is obvious and benign.
056 //errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_AMOUNT, BCKeyConstants.ERROR_CANNOT_ADJUST_FUNDING_WITHOUT_EFFECTIVE_CSF_TRACKER);
057 return false;
058 }
059
060 if (appointmentFunding.isAppointmentFundingDeleteIndicator()) {
061 // These error messages should not be displayed since the reported condition is obvious and benign.
062 //errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_AMOUNT, BCKeyConstants.ERROR_CANNOT_ADJUST_FUNDING_MARKED_AS_DELETE);
063 return false;
064 }
065
066 return true;
067 }
068
069 /**
070 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasActiveJob(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
071 * org.kuali.rice.kns.util.ErrorMap)
072 */
073 public boolean hasActiveJob(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
074 Integer fiscalYear = appointmentFunding.getUniversityFiscalYear();
075 String emplid = appointmentFunding.getEmplid();
076 String positionNumber = appointmentFunding.getPositionNumber();
077
078 boolean hasActiveJob = humanResourcesPayrollService.isActiveJob(emplid, positionNumber, fiscalYear, SynchronizationCheckType.ALL);
079 if (!hasActiveJob) {
080 errorMap.putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_NO_ACTIVE_JOB_FOUND, appointmentFunding.getEmplid(), appointmentFunding.getPositionNumber());
081 return false;
082 }
083
084 return true;
085 }
086
087 /**
088 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasObjectCodeMatchingDefaultOfPosition(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
089 * org.kuali.core.util.ErrorMap)
090 */
091 public boolean hasObjectCodeMatchingDefaultOfPosition(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
092 String defaultObjectCode = appointmentFunding.getBudgetConstructionPosition().getIuDefaultObjectCode();
093 String objectCode = appointmentFunding.getFinancialObjectCode();
094
095 if (!StringUtils.equals(objectCode, defaultObjectCode)) {
096 errorMap.putError(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, BCKeyConstants.ERROR_NOT_DEFAULT_OBJECT_CODE, defaultObjectCode);
097 return false;
098 }
099
100 return true;
101 }
102
103 /**
104 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasRequestedAmountZeroWhenFullYearLeave(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
105 * org.kuali.core.util.ErrorMap)
106 */
107 public boolean hasRequestedAmountZeroWhenFullYearLeave(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
108 String leaveDurationCode = appointmentFunding.getAppointmentFundingDurationCode();
109
110 // Request Salary Amount must be zero because these leave codes are for full year leave without pay.
111 if (StringUtils.equals(leaveDurationCode, LWPA.durationCode) || StringUtils.equals(leaveDurationCode, LWPF.durationCode)) {
112 KualiInteger requestedAmount = appointmentFunding.getAppointmentRequestedAmount();
113
114 if (!requestedAmount.isZero()) {
115 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_AMOUNT, BCKeyConstants.ERROR_REQUEST_AMOUNT_NOT_ZERO_WHEN_FULL_YEAR_LEAVE);
116 return false;
117 }
118 }
119
120 return true;
121 }
122
123 /**
124 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasRequestedFteQuantityZeroWhenFullYearLeave(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
125 * org.kuali.core.util.ErrorMap)
126 */
127 public boolean hasRequestedFteQuantityZeroWhenFullYearLeave(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
128 String leaveDurationCode = appointmentFunding.getAppointmentFundingDurationCode();
129
130 // Request Salary Amount must be zero because these leave codes are for full year leave without pay.
131 if (StringUtils.equals(leaveDurationCode, LWPA.durationCode) || StringUtils.equals(leaveDurationCode, LWPF.durationCode)) {
132 BigDecimal requestedFteQuantity = appointmentFunding.getAppointmentRequestedFteQuantity();
133
134 if (requestedFteQuantity.compareTo(BigDecimal.ZERO) != 0) {
135 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_FTE_QUANTITY, BCKeyConstants.ERROR_REQUEST_FTE_NOT_ZERO_WHEN_FULL_YEAR_LEAVE);
136 return false;
137 }
138
139 return true;
140 }
141
142 return true;
143 }
144
145 /**
146 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasNoExistingLine(java.util.List,
147 * org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding, org.kuali.rice.kns.util.ErrorMap)
148 */
149 public boolean hasNoExistingLine(List<PendingBudgetConstructionAppointmentFunding> appointmentFundings, PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
150 boolean hasNoExistingLine = salarySettingService.findAppointmentFunding(appointmentFundings, appointmentFunding) == null;
151 if (!hasNoExistingLine) {
152 errorMap.putError(BCPropertyConstants.NEW_BCAF_LINE, BCKeyConstants.ERROR_DUPLICATE_FUNDING_LINE);
153 return false;
154 }
155
156 return true;
157 }
158
159 /**
160 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidRequestedAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
161 * org.kuali.core.util.ErrorMap)
162 */
163 public boolean hasValidRequestedAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
164 KualiInteger requestedAmount = appointmentFunding.getAppointmentRequestedAmount();
165 if (requestedAmount == null || requestedAmount.isNegative()) {
166 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_AMOUNT, BCKeyConstants.ERROR_REQUESTED_AMOUNT_NONNEGATIVE_REQUIRED);
167 return false;
168 }
169
170 return true;
171 }
172
173 public boolean hasValidRequestedAmountQuickSalarySetting(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
174
175 if (this.hasValidRequestedAmount(appointmentFunding, errorMap)){
176 KualiInteger requestedAmount = appointmentFunding.getAppointmentRequestedAmount();
177 BigDecimal requestedFteQuantity = appointmentFunding.getAppointmentRequestedFteQuantity();
178 if (requestedAmount.isPositive() && (requestedFteQuantity != null && requestedFteQuantity.compareTo(BigDecimal.ZERO) == 0)) {
179 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_AMOUNT, BCKeyConstants.ERROR_REQUESTED_AMOUNT_NEEDS_FTE_FIRST);
180 return false;
181 }
182 }
183
184 return true;
185 }
186
187 /**
188 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidRequestedCsfAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
189 * org.kuali.core.util.ErrorMap)
190 */
191 public boolean hasValidRequestedCsfAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
192 KualiInteger csfAmount = appointmentFunding.getAppointmentRequestedCsfAmount();
193 String leaveDurationCode = appointmentFunding.getAppointmentFundingDurationCode();
194
195 // Requested csf amount must be greater than 0 if there is a leave
196 if (!StringUtils.equals(leaveDurationCode, NONE.durationCode)) {
197 if (csfAmount == null || !csfAmount.isPositive()) {
198 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_CSF_AMOUNT, BCKeyConstants.ERROR_FTE_GREATER_THAN_ZERO_REQUIRED);
199 return false;
200 }
201
202 return true;
203 }
204
205 return true;
206 }
207
208 /**
209 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidRequestedCsfTimePercent(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
210 * org.kuali.core.util.ErrorMap)
211 */
212 public boolean hasValidRequestedCsfTimePercent(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
213 BigDecimal csfTimePercent = appointmentFunding.getAppointmentRequestedCsfTimePercent();
214 String leaveDurationCode = appointmentFunding.getAppointmentFundingDurationCode();
215
216 // Requested csf amount must be greater than 0 if there is a leave
217 if (!StringUtils.equals(leaveDurationCode, NONE.durationCode)) {
218 if (csfTimePercent == null || csfTimePercent.compareTo(BigDecimal.ZERO) <= 0 || csfTimePercent.compareTo(BCConstants.ONE_HUNDRED) > 0 ) {
219 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_CSF_TIME_PERCENT, BCKeyConstants.ERROR_LEAVE_TIME_PERCENT_NOT_IN_RANGE, BigDecimal.ZERO.toPlainString(), BCConstants.ONE_HUNDRED.toPlainString());
220 return false;
221 }
222
223 return true;
224 }
225
226 return true;
227 }
228
229 /**
230 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidRequestedFteQuantity(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
231 * org.kuali.core.util.ErrorMap)
232 */
233 public boolean hasValidRequestedFteQuantity(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
234 BigDecimal requestedFteQuantity = appointmentFunding.getAppointmentRequestedFteQuantity();
235 if (requestedFteQuantity == null || requestedFteQuantity.compareTo(BigDecimal.ZERO) < 0 || requestedFteQuantity.compareTo(BigDecimal.ONE) > 0) {
236 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_FTE_QUANTITY, BCKeyConstants.ERROR_FTE_QUANTITY_NOT_IN_RANGE, BigDecimal.ZERO.toPlainString(), BigDecimal.ONE.toPlainString());
237 return false;
238 }
239
240 return true;
241 }
242
243 /**
244 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidRequestedFundingMonth(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
245 * org.kuali.core.util.ErrorMap)
246 */
247 public boolean hasValidRequestedFundingMonth(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
248 Integer fundingMonths = appointmentFunding.getAppointmentFundingMonth();
249 if (fundingMonths == null) {
250 errorMap.putError(BCPropertyConstants.APPOINTMENT_FUNDING_MONTH, BCKeyConstants.ERROR_EMPTY_FUNDIN_MONTH);
251 return false;
252 }
253
254 // Requested funding months must be between 0 and position normal work months if there is a leave
255 String leaveDurationCode = appointmentFunding.getAppointmentFundingDurationCode();
256 Integer normalWorkMonths = appointmentFunding.getBudgetConstructionPosition().getIuNormalWorkMonths();
257 if (!StringUtils.equals(leaveDurationCode, NONE.durationCode)) {
258 if (fundingMonths < 0 || fundingMonths > normalWorkMonths) {
259 errorMap.putError(BCPropertyConstants.APPOINTMENT_FUNDING_MONTH, BCKeyConstants.ERROR_FUNDIN_MONTH_NOT_IN_RANGE, ObjectUtils.toString(fundingMonths), "0", ObjectUtils.toString(normalWorkMonths));
260 return false;
261 }
262
263 return true;
264 }
265
266 // Requested funding months must equal to position normal work months if no leave
267 if (!fundingMonths.equals(normalWorkMonths)) {
268 errorMap.putError(BCPropertyConstants.APPOINTMENT_FUNDING_MONTH, BCKeyConstants.ERROR_NOT_EQUAL_NORMAL_WORK_MONTHS, ObjectUtils.toString(fundingMonths), ObjectUtils.toString(normalWorkMonths));
269 return false;
270 }
271
272 return true;
273 }
274
275 /**
276 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidRequestedTimePercent(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
277 * org.kuali.core.util.ErrorMap)
278 */
279 public boolean hasValidRequestedTimePercent(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
280 KualiInteger requestedAmount = appointmentFunding.getAppointmentRequestedAmount();
281 BigDecimal requestedTimePercent = appointmentFunding.getAppointmentRequestedTimePercent();
282
283 if (requestedTimePercent == null) {
284 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_TIME_PERCENT, BCKeyConstants.ERROR_EMPTY_REQUESTED_TIME_PERCENT);
285 return false;
286 }
287
288 if (requestedTimePercent.compareTo(BigDecimal.ZERO) < 0 || requestedTimePercent.compareTo(BCConstants.ONE_HUNDRED) > 0 ) {
289 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_TIME_PERCENT, BCKeyConstants.ERROR_TIME_PERCENT_NOT_IN_RANGE, BigDecimal.ZERO.toPlainString(), BCConstants.ONE_HUNDRED.toPlainString());
290 return false;
291 }
292
293 if (requestedAmount.isPositive() && requestedTimePercent.compareTo(BigDecimal.ZERO) <= 0) {
294 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_TIME_PERCENT, BCKeyConstants.ERROR_TIME_PERCENT_GREATER_THAN_ZERO_REQUIRED);
295 return false;
296 }
297
298 return true;
299 }
300
301 /**
302 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidAdjustmentAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
303 * org.kuali.rice.kns.util.ErrorMap)
304 */
305 public boolean hasValidAdjustmentAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
306 KualiDecimal adjustmentAmount = appointmentFunding.getAdjustmentAmount();
307
308 if (adjustmentAmount == null) {
309 errorMap.putError(BCPropertyConstants.ADJUSTMENT_AMOUNT, BCKeyConstants.ERROR_ADJUSTMENT_AMOUNT_REQUIRED);
310 return false;
311 }
312
313 return true;
314 }
315
316 /**
317 * @see org.kuali.kfs.module.bc.document.service.SalarySettingRuleHelperService#hasValidAdjustmentAmount(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding,
318 * org.kuali.rice.kns.util.ErrorMap)
319 */
320 public boolean hasValidPayRateOrAnnualAmount(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
321 BigDecimal payRate = appointmentFunding.getAppointmentRequestedPayRate();
322 KualiInteger requestedAmount = appointmentFunding.getAppointmentRequestedAmount();
323
324 if (requestedAmount == null && payRate == null) {
325 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_PAY_RATE, BCKeyConstants.ERROR_EMPTY_PAY_RATE_ANNUAL_AMOUNT);
326 errorMap.putError(BCPropertyConstants.APPOINTMENT_REQUESTED_AMOUNT, BCKeyConstants.ERROR_EMPTY_PAY_RATE_ANNUAL_AMOUNT);
327 return false;
328 }
329
330 return true;
331 }
332
333 /**
334 * Sets the salarySettingService attribute value.
335 *
336 * @param salarySettingService The salarySettingService to set.
337 */
338 public void setSalarySettingService(SalarySettingService salarySettingService) {
339 this.salarySettingService = salarySettingService;
340 }
341
342 /**
343 * Sets the humanResourcesPayrollService attribute value.
344 *
345 * @param humanResourcesPayrollService The humanResourcesPayrollService to set.
346 */
347 public void setHumanResourcesPayrollService(HumanResourcesPayrollService humanResourcesPayrollService) {
348 this.humanResourcesPayrollService = humanResourcesPayrollService;
349 }
350 }