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.transfer.validation;
017    
018    import java.math.BigDecimal;
019    import java.util.ArrayList;
020    import java.util.Date;
021    import java.util.HashMap;
022    import java.util.HashSet;
023    import java.util.List;
024    import java.util.Map;
025    import java.util.Set;
026    
027    import org.apache.commons.lang.StringUtils;
028    import org.apache.commons.lang.time.DateUtils;
029    import org.joda.time.DateTime;
030    import org.joda.time.LocalDate;
031    import org.kuali.kpme.core.KPMENamespace;
032    import org.kuali.kpme.core.accrualcategory.AccrualCategory;
033    import org.kuali.kpme.core.accrualcategory.rule.AccrualCategoryRule;
034    import org.kuali.kpme.core.assignment.Assignment;
035    import org.kuali.kpme.core.department.Department;
036    import org.kuali.kpme.core.job.Job;
037    import org.kuali.kpme.core.permission.KPMEPermissionTemplate;
038    import org.kuali.kpme.core.principal.PrincipalHRAttributes;
039    import org.kuali.kpme.core.role.KPMERole;
040    import org.kuali.kpme.core.role.KPMERoleMemberAttribute;
041    import org.kuali.kpme.core.service.HrServiceLocator;
042    import org.kuali.kpme.core.util.HrConstants;
043    import org.kuali.kpme.core.util.HrContext;
044    import org.kuali.kpme.core.util.ValidationUtils;
045    import org.kuali.kpme.tklm.common.TkConstants;
046    import org.kuali.kpme.tklm.leave.override.EmployeeOverride;
047    import org.kuali.kpme.tklm.leave.service.LmServiceLocator;
048    import org.kuali.kpme.tklm.leave.summary.LeaveSummary;
049    import org.kuali.kpme.tklm.leave.summary.LeaveSummaryRow;
050    import org.kuali.kpme.tklm.leave.transfer.BalanceTransfer;
051    import org.kuali.kpme.tklm.time.service.TkServiceLocator;
052    import org.kuali.kpme.tklm.time.util.TkContext;
053    import org.kuali.rice.kim.api.KimConstants;
054    import org.kuali.rice.kim.api.identity.Person;
055    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
056    import org.kuali.rice.kns.document.MaintenanceDocument;
057    import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
058    import org.kuali.rice.krad.bo.PersistableBusinessObject;
059    import org.kuali.rice.krad.util.GlobalVariables;
060    import org.kuali.rice.krad.util.ObjectUtils;
061    
062    public class BalanceTransferValidation extends MaintenanceDocumentRuleBase {
063    
064            /*
065            //the "to" and "from" accrual categories should be in the supplied principal's leave plan as of the effective date.
066            private boolean validateLeavePlan(PrincipalHRAttributes pha,
067                            AccrualCategory fromAccrualCategory, AccrualCategory toAccrualCategory, LocalDate effectiveDate) {
068                    boolean isValid = true;
069                    if(fromAccrualCategory == null || toAccrualCategory == null) {
070                            return false;
071                    }
072                    List<AccrualCategory> accrualCategories = HrServiceLocator.getAccrualCategoryService().getActiveAccrualCategoriesForLeavePlan(pha.getLeavePlan(), effectiveDate);
073                    if(accrualCategories.size() > 0) {
074                            boolean isFromInLeavePlan = false;
075                            boolean isToInLeavePlan = false;
076                            for(AccrualCategory activeAccrualCategory : accrualCategories) {
077                                    if(StringUtils.equals(activeAccrualCategory.getLmAccrualCategoryId(),fromAccrualCategory.getLmAccrualCategoryId())) {
078                                            isFromInLeavePlan = true;
079                                    }
080                                    if(StringUtils.equals(activeAccrualCategory.getLmAccrualCategoryId(), toAccrualCategory.getLmAccrualCategoryId())) {
081                                            isToInLeavePlan = true;
082                                    }
083                            }
084                            if(!isFromInLeavePlan) {
085                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.accrualCategory.notInLeavePlan", fromAccrualCategory.getAccrualCategory());
086                                    isValid &= false;
087                            }
088                            if(!isToInLeavePlan) {
089                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.toAccrualCategory", "balanceTransfer.accrualCategory.notInLeavePlan", toAccrualCategory.getAccrualCategory());
090                                    isValid &= false;                   
091                            }
092                    }
093                    else {
094                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId", "balanceTransfer.principal.noACinLeavePlan");
095                            isValid &=false;
096                    }
097                    return isValid;
098            }
099            
100            //See isTransferAmountUnderMaxLimit for futher validation
101            private boolean validateTransferAmount(BigDecimal transferAmount,
102                            AccrualCategory debitedAccrualCategory,
103                            AccrualCategory creditedAccrualCategory, String principalId, LocalDate effectiveDate) {
104                    if(transferAmount != null) {
105                            if(transferAmount.compareTo(BigDecimal.ZERO) < 0 ) {
106                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.transferAmount", "balanceTransfer.amount.negative");
107                                    return false;
108                            }
109                    }
110    
111                    return true;
112            }
113    
114            //Effective date not more than one year in advance
115            private boolean validateEffectiveDate(LocalDate date) {
116                    if(date != null) {
117                            if(DateUtils.addYears(LocalDate.now().toDate(), 1).compareTo(date.toDate()) > 0)
118                                    return true;
119                            else
120                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.effectiveDate", "balanceTransfer.effectiveDate.error");
121                            }
122                    return false;
123            }
124            
125            private boolean validateTransferFromAccrualCategory(AccrualCategory accrualCategory, String principalId,
126                            LocalDate effectiveDate, AccrualCategoryRule acr, String fromAccrualCategory) {
127                    boolean isValid = true;
128                    if(accrualCategory == null) {
129                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.accrualcategory.exists",fromAccrualCategory);
130                            isValid &= false;
131                    }
132                    return isValid;
133            }
134            
135            //Transfer to accrual category should match the value defined in the accrual category rule
136            private boolean validateTransferToAccrualCategory(AccrualCategory accrualCategory, String principalId, LocalDate effectiveDate, AccrualCategoryRule acr, String toAccrualCategory, boolean isSomeAdmin) {
137                    boolean isValid = true;
138                    if(accrualCategory != null) {
139                            if(acr != null) {
140                                    //processCustomRouteDocumentBusinessRule will provide the invalidation on system triggered transfers
141                                    //if the accrual category rule is null, i.o.w. this code block should never be reached when acr is null on sys triggered transfers.
142                                    AccrualCategory maxBalTranToAccCat = HrServiceLocator.getAccrualCategoryService().getAccrualCategory(acr.getMaxBalanceTransferToAccrualCategory(),effectiveDate);
143                                    if(!StringUtils.equals(maxBalTranToAccCat.getLmAccrualCategoryId(),accrualCategory.getLmAccrualCategoryId()) && !isSomeAdmin) {
144                                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.toAccrualCategory", "balanceTransfer.toAccrualCategory.noMatch",accrualCategory.getAccrualCategory());
145                                            isValid &= false;
146                                    }
147                            }
148                    }
149                    else {
150                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.toAccrualCategory", "balanceTransfer.accrualcategory.exists",toAccrualCategory);
151                            isValid &= false;
152                    }
153                    return isValid;
154            }
155    
156            //transfer amount must be under max limit when submitted via max balance triggered action or by a work area approver.
157            private boolean isTransferAmountUnderMaxLimit(String principalId, LocalDate effectiveDate, String accrualCategory,
158                            BigDecimal transferAmount, AccrualCategoryRule accrualRule, String leavePlan) {
159            
160                    if(ObjectUtils.isNotNull(accrualRule)) {
161    
162                            BigDecimal maxTransferAmount = null;
163                            if(ObjectUtils.isNotNull(accrualRule.getMaxTransferAmount())) {
164                                    maxTransferAmount = new BigDecimal(accrualRule.getMaxTransferAmount());
165                            }
166                            if(ObjectUtils.isNotNull(maxTransferAmount)) {
167                                    EmployeeOverride eo = LmServiceLocator.getEmployeeOverrideService().getEmployeeOverride(principalId, leavePlan, accrualCategory, TkConstants.EMPLOYEE_OVERRIDE_TYPE.get("MTA"), effectiveDate);
168                                    if(ObjectUtils.isNotNull(eo))
169                                            if(ObjectUtils.isNull(eo.getOverrideValue()))
170                                                    maxTransferAmount = new BigDecimal(Long.MAX_VALUE);
171                                            else
172                                                    maxTransferAmount = new BigDecimal(eo.getOverrideValue());
173                                    else {
174                                            BigDecimal fteSum = HrServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);
175                                            maxTransferAmount = maxTransferAmount.multiply(fteSum);
176                                    }
177                                    if(transferAmount.compareTo(maxTransferAmount) > 0) {
178                                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.transferAmount","balanceTransfer.exceeds.transferLimit");
179                                            return false;
180                                    }
181                            }
182                    }
183                    return true;
184            }
185            
186            @Override
187            public boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
188                    boolean isValid = super.processCustomRouteDocumentBusinessRules(document);
189                    LOG.debug("entering custom validation for Balance Transfer");
190    
191                    PersistableBusinessObject pbo = (PersistableBusinessObject) this.getNewBo();
192    
193                    if(pbo instanceof BalanceTransfer) {
194    
195                            BalanceTransfer balanceTransfer = (BalanceTransfer) pbo;
196                            
197                            // if this balance transfer is on a system scheduled time off, then don't do further validation
198                            if(StringUtils.isNotEmpty(balanceTransfer.getSstoId())) {
199                                    isValid &= BalanceTransferValidationUtils.validateSstoTranser(balanceTransfer);
200                                    return isValid;
201                            }
202                            if(isValid) {
203    
204                                    *//**
205                                     * Validation is basically governed by accrual category rules. Get accrual category
206                                     * rules for both the "To" and "From" accrual categories, pass to validators along with the
207                                     * values needing to be validated.
208                                     * 
209                                     * Balance transfers initiated from the leave calendar display should already have all values
210                                     * populated, thus validated, including the accrual category rule for the "From" accrual category.
211                                     * 
212                                     * Balance transfers initiated via the Maintenance tab will have no values populated.
213                                     *//*
214                                    String principalId = balanceTransfer.getPrincipalId();
215                                    LocalDate effectiveDate = balanceTransfer.getEffectiveLocalDate();
216                                    String fromAccrualCategory = balanceTransfer.getFromAccrualCategory();
217                                    String toAccrualCategory = balanceTransfer.getToAccrualCategory();
218                                    AccrualCategory fromCat = HrServiceLocator.getAccrualCategoryService().getAccrualCategory(fromAccrualCategory, effectiveDate);
219                                    AccrualCategory toCat = HrServiceLocator.getAccrualCategoryService().getAccrualCategory(toAccrualCategory, effectiveDate);
220                                    PrincipalHRAttributes pha = HrServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId,effectiveDate);
221                                    
222                                    // TODO Check for role in specific dept / location
223                                    boolean isDeptAdmin = TkContext.isDepartmentAdmin();
224                                    boolean isSysAdmin = HrContext.isSystemAdmin();
225                                    boolean isLocAdmin = TkContext.isLocationAdmin();
226                                    
227                                    if(ObjectUtils.isNotNull(pha)) {
228                                            if(isDeptAdmin || isSysAdmin || isLocAdmin) {
229                                                    isValid &= validateLeavePlan(pha,fromCat,toCat,effectiveDate);
230                                                    isValid &= validatePrincipal(pha,principalId);
231                                                    isValid &= validateTransferFromAccrualCategory(fromCat,principalId,effectiveDate,null,fromAccrualCategory);
232                                                    isValid &= validateTransferToAccrualCategory(toCat,principalId,effectiveDate,null,toAccrualCategory,true);
233                                                    isValid &= validateTransferAmount(balanceTransfer.getTransferAmount(),fromCat,toCat, principalId, effectiveDate);
234                                            }
235                                            else {
236                                                    if(ObjectUtils.isNotNull(pha.getLeavePlan())) {
237                                                            AccrualCategoryRule acr = HrServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(fromCat,
238                                                                            effectiveDate, pha.getServiceLocalDate());
239                                                            if(ObjectUtils.isNotNull(acr)) {
240                                                                    if(StringUtils.isNotBlank(acr.getMaxBalFlag())
241                                                                                    && StringUtils.equals(acr.getMaxBalFlag(), "Y")) {
242                                                                            if(ObjectUtils.isNotNull(toCat)) {
243                                                                                    
244                                                                                    isValid &= validatePrincipal(pha,principalId);
245                                                                                    isValid &= validateEffectiveDate(effectiveDate);
246                                                                                    isValid &= validateLeavePlan(pha,fromCat,toCat,effectiveDate);
247                                                                                    isValid &= validateTransferFromAccrualCategory(fromCat,principalId,effectiveDate,acr,fromAccrualCategory);
248                                                                                    isValid &= validateTransferToAccrualCategory(toCat,principalId,effectiveDate,acr,toAccrualCategory,false);
249                                                                                    isValid &= validateTransferAmount(balanceTransfer.getTransferAmount(),fromCat,toCat, null, null);
250                                                                                    isValid &= isTransferAmountUnderMaxLimit(principalId,effectiveDate,fromAccrualCategory,balanceTransfer.getTransferAmount(),acr,pha.getLeavePlan());
251                                                                            }
252                                                                            else {
253                                                                                    //should never be the case if accrual category rules are validated correctly.
254                                                                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
255                                                                                                    "balanceTransfer.fromAccrualCategory.rules.transferToAccrualCategory",
256                                                                                                    fromAccrualCategory);
257                                                                                    isValid &= false;
258                                                                            }
259                                                                    }
260                                                                    else {
261                                                                            //max bal flag null, blank, empty, or "N"
262                                                                            GlobalVariables.getMessageMap().putError("document.newMaintinableObject.fromAccrualCategory",
263                                                                                            "balanceTransfer.fromAccrualCategory.rules.maxBalFlag", fromAccrualCategory);
264                                                                            isValid &= false;
265                                                                    }
266                                                            }
267                                                            else {
268                                                                    //department admins must validate amount to transfer does not exceed current balance.
269                                                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory",
270                                                                                    "balanceTransfer.fromAccrualCategory.rules.exist",fromCat.getAccrualCategory());
271                                                                    isValid &= false;
272                                                            }
273                                                    }
274                                                    else {
275                                                            //if the principal doesn't have a leave plan, there aren't any accrual categories that can be debited/credited.
276                                                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","balanceTransfer.principal.noLeavePlan");
277                                                            isValid &=false;
278                                                    }
279                                            }
280                                    }
281                                    else  {
282                                            //if the principal has no principal hr attributes, they're not a principal.
283                                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId","balanceTransfer.principal.noAttributes");
284                                            isValid &= false;
285                                    }
286    
287                            }
288                    }
289                    return isValid; 
290            }*/
291            
292            @Override
293            protected boolean processCustomRouteDocumentBusinessRules(
294                            MaintenanceDocument document) {
295                    boolean isValid = super.processCustomRouteDocumentBusinessRules(document);
296    
297                    LOG.debug("entering custom validation for Balance Transfer");
298    
299                    PersistableBusinessObject pbo = (PersistableBusinessObject) this.getNewBo();
300    
301                    if(pbo instanceof BalanceTransfer) {
302    
303                            BalanceTransfer balanceTransfer = (BalanceTransfer) pbo;
304                            String fromAccrualCat = balanceTransfer.getFromAccrualCategory();
305                            String toAccrualCat = balanceTransfer.getToAccrualCategory();
306                            String principalId = balanceTransfer.getPrincipalId();
307                            BigDecimal transferAmount = balanceTransfer.getTransferAmount();
308                            
309                            isValid &= validateEffectiveDate(balanceTransfer.getEffectiveLocalDate());
310                            isValid &= validateFromAccrualCateogry(fromAccrualCat,balanceTransfer.getEffectiveLocalDate());
311                            isValid &= validateToAccrualCateogry(toAccrualCat,balanceTransfer.getEffectiveLocalDate());
312                            isValid &= validateTransferAmount(principalId,transferAmount,fromAccrualCat,balanceTransfer.getEffectiveLocalDate());
313                            if(validatePrincipalId(principalId,balanceTransfer.getEffectiveLocalDate())) {
314                                    isValid &= validatePrincipal(principalId,balanceTransfer.getEffectiveDate(),GlobalVariables.getUserSession().getPrincipalId());
315                            }
316                            else {
317                                    isValid &= false;
318                            }
319                    }
320                    return isValid;
321            }
322    
323            //Effective date not more than one year in advance
324            private boolean validateEffectiveDate(LocalDate date) {
325                    if(date != null) {
326                            if(date.isAfter(LocalDate.now().plusYears(1))) {
327                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.effectiveDate", "balanceTransfer.effectiveDate.error");
328                                    return false;
329                            }
330                    }
331                    return true;
332            }
333            
334            private boolean validateFromAccrualCateogry(String fromAccrualCat,
335                            LocalDate effectiveLocalDate) {
336                    boolean isValid = true;
337                    if(StringUtils.isNotEmpty(fromAccrualCat)) {
338                            isValid &= ValidationUtils.validateAccCategory(fromAccrualCat, effectiveLocalDate);
339                            if(!isValid) {
340                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.fromAccrualCategory", "balanceTransfer.accrualcategory.exists", fromAccrualCat);
341                            }
342                    }
343                    return isValid;
344            }
345            
346            private boolean validateToAccrualCateogry(String toAccrualCat,
347                            LocalDate effectiveLocalDate) {
348                    boolean isValid = true;
349                    if(StringUtils.isNotEmpty(toAccrualCat)) {
350                            isValid &= ValidationUtils.validateAccCategory(toAccrualCat, effectiveLocalDate);
351                            if(!isValid) {
352                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.toAccrualCategory", "balanceTransfer.accrualcategory.exists", toAccrualCat);
353                            }
354                    }
355                    return isValid;
356            }
357            
358            private boolean validateTransferAmount(String principalId, BigDecimal transferAmount,
359                            String fromAccrualCat, LocalDate effectiveLocalDate) {
360                    boolean isValid = true;
361                    if(transferAmount != null) {
362                            LeaveSummary leaveSummary = LmServiceLocator.getLeaveSummaryService().getLeaveSummaryAsOfDateForAccrualCategory(principalId, effectiveLocalDate, fromAccrualCat);
363                            if(leaveSummary != null) {
364                                    LeaveSummaryRow leaveSummaryRow = leaveSummary.getLeaveSummaryRowForAccrualCtgy(fromAccrualCat);
365                                    if(leaveSummaryRow != null) {
366                                            BigDecimal accruedBalance = leaveSummaryRow.getAccruedBalance();
367                                            if(transferAmount.compareTo(accruedBalance) > 0) {
368                                                    isValid &= false;
369                                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.transferAmount", "balanceTransfer.transferAmount.exceedsBalance");
370                                            }
371                                    }
372                            }
373                            if(transferAmount.compareTo(BigDecimal.ZERO) < 0 ) {
374                                    isValid  &= false;
375                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.transferAmount", "balanceTransfer.transferAmount.negative");
376                            }
377                    }
378                    return isValid;
379            }
380    
381            private boolean validatePrincipalId(String principalId,
382                            LocalDate effectiveLocalDate) {
383                    boolean isValid = true;
384                    if(StringUtils.isNotEmpty(principalId)) {
385                            isValid &= ValidationUtils.validatePrincipalId(principalId);
386                            if(!isValid) {
387                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId", "balanceTransfer.principal.exists");
388                            }
389                    }
390                    return isValid;
391            }
392    
393            private boolean validatePrincipal(String principalId, Date effectiveDate, String userPrincipalId) {
394                    boolean isValid = true;
395                    PrincipalHRAttributes pha = HrServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(principalId, LocalDate.fromDateFields(effectiveDate));
396                    
397                    if(pha == null) {
398                            GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId", "balanceTransfer.principal.noAttributes");
399                            isValid &= false;
400                    }
401                    else {
402                            boolean canCreate = false;
403                            if(!StringUtils.equals(principalId,userPrincipalId)) {
404                                    List<Job> principalsJobs = HrServiceLocator.getJobService().getActiveLeaveJobs(principalId, LocalDate.fromDateFields(effectiveDate));
405    
406                                    for(Job job : principalsJobs) {
407                                            
408                                            if(job.isEligibleForLeave()) {
409                                                    
410                                                    String department = job != null ? job.getDept() : null;
411                                                    Department departmentObj = job != null ? HrServiceLocator.getDepartmentService().getDepartmentWithoutRoles(department, LocalDate.fromDateFields(effectiveDate)) : null;
412                                                    String location = departmentObj != null ? departmentObj.getLocation() : null;
413                                                    //logged in user may only submit documents for principals in authorized departments / location.
414                                            if (LmServiceLocator.getLMPermissionService().isAuthorizedInDepartment(userPrincipalId, "Create Balance Transfer", department, new DateTime(effectiveDate.getTime()))
415                                                            || LmServiceLocator.getLMPermissionService().isAuthorizedInLocation(userPrincipalId, "Create Balance Transfer", location, new DateTime(effectiveDate.getTime()))) {
416                                                                    canCreate = true;
417                                                                    break;
418                                                    }
419                                            else {
420                                                    //do NOT block approvers, processors, delegates from approving the document.
421                                                            List<Assignment> assignments = HrServiceLocator.getAssignmentService().getActiveAssignmentsForJob(principalId, job.getJobNumber(), LocalDate.fromDateFields(effectiveDate));
422                                                            for(Assignment assignment : assignments) {
423                                                                    if(HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(userPrincipalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.APPROVER.getRoleName(), assignment.getWorkArea(), new DateTime(effectiveDate))
424                                                                                    || HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(userPrincipalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.APPROVER_DELEGATE.getRoleName(), assignment.getWorkArea(), new DateTime(effectiveDate))
425                                                                                    || HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(userPrincipalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR.getRoleName(), assignment.getWorkArea(), new DateTime(effectiveDate))
426                                                                                    || HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(userPrincipalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR_DELEGATE.getRoleName(), assignment.getWorkArea(), new DateTime(effectiveDate))) {
427                                                                            canCreate = true;
428                                                                            break;
429                                                                    }
430                                                            }
431                                            }
432                                            }
433                                    }                               
434                            }
435                            else {
436                                    //should be able to submit their own transaction documents...
437                                    //max balance triggered transactions go through this validation. Set a userPrincipal to system and deny LEAVE DEPT/LOC Admins ability to submit their own
438                                    //transactions these simplified rules??
439                                    canCreate = false;
440                            }
441                            
442                            if(!canCreate) {
443                                    GlobalVariables.getMessageMap().putError("document.newMaintainableObject.principalId", "balanceTransfer.userNotAuthorized");
444                                    isValid &= false;
445                            }
446                    }
447                    return isValid;
448            }
449            
450    }