001    /**
002     * Copyright 2004-2014 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.kpme.tklm.leave.timeoff.validation;
017    
018    import java.math.BigDecimal;
019    
020    import org.apache.commons.lang.StringUtils;
021    import org.joda.time.LocalDate;
022    import org.kuali.kpme.core.earncode.EarnCode;
023    import org.kuali.kpme.core.service.HrServiceLocator;
024    import org.kuali.kpme.core.util.HrConstants;
025    import org.kuali.kpme.core.util.ValidationUtils;
026    import org.kuali.kpme.tklm.common.LMConstants;
027    import org.kuali.kpme.tklm.leave.timeoff.SystemScheduledTimeOff;
028    import org.kuali.rice.kns.document.MaintenanceDocument;
029    import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
030    import org.kuali.rice.krad.bo.PersistableBusinessObject;
031    
032    public class SystemScheduledTimeOffValidation extends MaintenanceDocumentRuleBase {      
033            boolean validateEffectiveDate(LocalDate effectiveDate) {
034                    boolean valid = true;
035                    if (effectiveDate != null && !ValidationUtils.validateOneYearFutureDate(effectiveDate)) {
036                            this.putFieldError("effectiveDate", "error.date.exceed.year", "Effective Date");
037                            valid = false;
038                    }
039                    return valid;
040            }
041    
042            boolean validateAccruedDate(LocalDate accruedDate) {
043                    boolean valid = true;
044                    if (accruedDate != null && !ValidationUtils.validateFutureDate(accruedDate)) {
045                            this.putFieldError("accruedDate", "error.future.date", "Accrued Date");
046                            valid = false;
047                    }
048                    return valid;
049            }
050            
051            boolean validateLocation(String location, LocalDate asOfDate) {
052                    boolean valid = true;
053                    if(!StringUtils.isEmpty(location) && location.equals(HrConstants.WILDCARD_CHARACTER)) {
054                            return true;
055                    }
056                    if (!ValidationUtils.validateLocation(location, asOfDate)) {
057                            this.putFieldError("location", "error.existence", "location '"
058                                            + location + "'");
059                            valid = false;
060                    }
061                    return valid;
062            }
063            
064            boolean validateScheduledTimeOffDate(LocalDate scheduledTimeOffDate) {
065                    boolean valid = true;
066                    if (scheduledTimeOffDate!= null && !ValidationUtils.validateFutureDate(scheduledTimeOffDate)) {
067                            this.putFieldError("scheduledTimeOffDate", "error.future.date", "Scheduled Time Off Date");
068                            valid = false;
069                    }
070                    return valid;
071            }
072            
073            boolean validateUnusedTimeForScheduledTimeOffDate(LocalDate scheduledTimeOffDate, String unusedTime) {
074                    boolean valid = true;
075                    if (scheduledTimeOffDate == null && (StringUtils.isEmpty(unusedTime) || StringUtils.equals("T", unusedTime) || StringUtils.equals("NUTA", unusedTime))) {
076                            this.putFieldError("scheduledTimeOffDate", "error.unusedtime.bank.required", LMConstants.UNUSED_TIME_MAP.get(unusedTime));
077                            valid = false;
078                    }               
079                    return valid;
080            }
081            
082            //if no unsued time allowed is selected make sure Accrued date and Schedule Time off date are equal
083            //if not throw an error
084            boolean validateNoUnusedTimeAllowed(LocalDate scheduledTimeOffDate, LocalDate accruedDate, String unusedTime) {
085                    boolean valid = true;
086                    if(scheduledTimeOffDate != null) {
087                            if (scheduledTimeOffDate.equals(accruedDate) == false) {
088                                    this.putFieldError("unusedTime", "error.nounusedtimeallowed.selected", "Unused Time");                  
089                                    valid = false;
090                            }
091                    }
092                    return valid;
093                    
094            }
095                    
096            boolean validateTransfertoEarnCode(String transfertoEarnCode, LocalDate localDate) {
097                    boolean valid = true;
098                    if (StringUtils.isEmpty(transfertoEarnCode)) {
099                            this.putFieldError("transfertoEarnCode", "error.required", "Transfer to Earn Code");
100                            valid = false;
101                    }
102                    else {
103                            valid &= this.validateEarnCode(transfertoEarnCode, localDate);
104                    }
105                    return valid;
106            }
107            
108            boolean validateTransferConversionFactor(BigDecimal transferConversionFactor) {
109                    boolean valid = true;
110                    if (transferConversionFactor == null) {
111                            this.putFieldError("transferConversionFactor", "error.required", "Transfer Conversion Factor");
112                            valid = false;
113                    }
114                    return valid;
115            }
116            
117            boolean validateEarnCode(String earnCode, LocalDate asOfDate) {
118                    boolean valid = true;
119                    if (!ValidationUtils.validateEarnCode(earnCode, asOfDate)) {
120                            this.putFieldError("earnCode", "error.existence", "earnCode '"
121                                            + earnCode + "'");
122                            valid = false;
123                    }
124                    return valid;
125            }
126    
127        private boolean validateFraction(String earnCode, BigDecimal amount, LocalDate asOfDate, String fieldName) {
128            boolean valid = true;
129            if (!ValidationUtils.validateEarnCodeFraction(earnCode, amount, asOfDate)) {
130                EarnCode ec = HrServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
131                if(ec != null && ec.getFractionalTimeAllowed() != null) {
132                    BigDecimal fracAllowed = new BigDecimal(ec.getFractionalTimeAllowed());
133                    String[] parameters = new String[2];
134                    parameters[0] = earnCode;
135                    parameters[1] = Integer.toString(fracAllowed.scale());
136                    this.putFieldError(fieldName, "error.amount.fraction", parameters);
137                    valid = false;
138                }
139            }
140            return valid;
141        }
142        
143            private boolean validateUnusedTime(SystemScheduledTimeOff sysSchTimeOff) {
144                    boolean valid = true;
145                    if(StringUtils.isNotBlank(sysSchTimeOff.getUnusedTime())) {
146                            valid &= this.validateUnusedTimeForScheduledTimeOffDate(sysSchTimeOff.getScheduledTimeOffLocalDate(), sysSchTimeOff.getUnusedTime());
147                            if(StringUtils.equals(sysSchTimeOff.getUnusedTime(),LMConstants.UNUSED_TIME.TRANSFER)) {
148                                    valid &= this.validateTransfertoEarnCode(sysSchTimeOff.getTransfertoEarnCode(), sysSchTimeOff.getEffectiveLocalDate());
149                                    valid &= this.validateTransferConversionFactor(sysSchTimeOff.getTransferConversionFactor());
150                                    if(valid) {
151                                            // transfer to earn code is not blank, and exists.
152                                            // TODO: xref earn code white[black] list? Should this earn code belong to the same leave plan?
153                                    }
154                            }
155                            else if(StringUtils.equals(sysSchTimeOff.getUnusedTime(), LMConstants.UNUSED_TIME.BANK)) {
156                                    //TODO: do "bank" validation
157                                    // can there be a value specified for scheduled time off date, or must this field be left blank?
158                            }
159                            else if(StringUtils.equals(sysSchTimeOff.getUnusedTime(), LMConstants.UNUSED_TIME.NO_UNUSED)) {
160                                    valid &= this.validateNoUnusedTimeAllowed(sysSchTimeOff.getScheduledTimeOffLocalDate(), sysSchTimeOff.getAccruedLocalDate(), sysSchTimeOff.getUnusedTime());
161                            }
162                    }
163                    else {
164                            this.putFieldError("unusedTime", "error.required", "Unused Time");
165                            valid = false;
166                    }
167                    return valid;
168            }
169    
170            @Override
171            protected boolean processCustomRouteDocumentBusinessRules(
172                            MaintenanceDocument document) {
173                    boolean valid = false;
174                    LOG.debug("entering custom validation for SystemScheduledTimeOff");
175                    PersistableBusinessObject pbo = (PersistableBusinessObject) this.getNewBo();
176                    if (pbo instanceof SystemScheduledTimeOff) {
177                            SystemScheduledTimeOff sysSchTimeOff = (SystemScheduledTimeOff) pbo;
178                            if (sysSchTimeOff != null) {
179                                    valid = true;
180                                    valid &= this.validateEffectiveDate(sysSchTimeOff.getEffectiveLocalDate());
181                                    valid &= this.validateAccruedDate(sysSchTimeOff.getAccruedLocalDate());
182                                    valid &= this.validateScheduledTimeOffDate(sysSchTimeOff.getScheduledTimeOffLocalDate());
183                    valid &= this.validateFraction(sysSchTimeOff.getEarnCode(),sysSchTimeOff.getAmountofTime(),sysSchTimeOff.getEffectiveLocalDate(),"amountofTime");
184                                    //valid &= this.validateUnusedTimeForScheduledTimeOffDate(sysSchTimeOff.getScheduledTimeOffLocalDate(), sysSchTimeOff.getUnusedTime());
185                                    valid &= this.validateUnusedTime(sysSchTimeOff);
186                                    //valid &= this.validateNoUnusedTimeAllowed(sysSchTimeOff.getScheduledTimeOffLocalDate(),sysSchTimeOff.getAccruedLocalDate(),sysSchTimeOff.getUnusedTime());
187                                    valid &= this.validateLocation(sysSchTimeOff.getLocation(), sysSchTimeOff.getEffectiveLocalDate());
188                                    valid &= this.validateEarnCode(sysSchTimeOff.getEarnCode(), sysSchTimeOff.getEffectiveLocalDate());
189                            }
190                    }
191                    
192                    return valid;
193            }
194    
195    }