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.coa.document.validation.impl;
017    
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    
023    import org.apache.commons.lang.StringUtils;
024    import org.apache.log4j.Logger;
025    import org.kuali.kfs.coa.identity.KfsKimDocumentAttributeData;
026    import org.kuali.kfs.coa.identity.OrgReviewRole;
027    import org.kuali.kfs.coa.identity.OrgReviewRoleLookupableHelperServiceImpl;
028    import org.kuali.kfs.sys.KFSConstants;
029    import org.kuali.kfs.sys.KFSKeyConstants;
030    import org.kuali.kfs.sys.identity.KfsKimAttributes;
031    import org.kuali.rice.kim.bo.entity.KimPrincipal;
032    import org.kuali.rice.kim.bo.group.dto.GroupInfo;
033    import org.kuali.rice.kim.bo.role.dto.DelegateMemberCompleteInfo;
034    import org.kuali.rice.kim.bo.role.dto.KimRoleInfo;
035    import org.kuali.rice.kim.bo.role.dto.RoleMemberCompleteInfo;
036    import org.kuali.rice.kim.bo.role.dto.RoleMembershipInfo;
037    import org.kuali.rice.kim.bo.types.dto.AttributeSet;
038    import org.kuali.rice.kim.bo.types.dto.KimTypeInfo;
039    import org.kuali.rice.kim.service.GroupService;
040    import org.kuali.rice.kim.service.KIMServiceLocator;
041    import org.kuali.rice.kim.service.KimTypeInfoService;
042    import org.kuali.rice.kim.service.UiDocumentService;
043    import org.kuali.rice.kim.util.KimConstants;
044    import org.kuali.rice.kns.document.Document;
045    import org.kuali.rice.kns.document.MaintenanceDocument;
046    import org.kuali.rice.kns.exception.ValidationException;
047    import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
048    import org.kuali.rice.kns.util.GlobalVariables;
049    import org.kuali.rice.kns.util.KualiDecimal;
050    
051    /**
052     * This class represents the business rules for the maintenance of {@link AccountGlobal} business objects
053     */
054    public class OrgReviewRoleRule extends MaintenanceDocumentRuleBase {
055    
056        protected UiDocumentService uiDocumentService;
057        protected transient static GroupService groupService;
058        protected transient static KimTypeInfoService typeInfoService;
059        protected static Logger LOG = Logger.getLogger(OrgReviewRoleRule.class);
060    
061        /**
062         * Need to override to avoid the primary key check which (wrongly) assumes that the object's PKs can be found in the persistence service.
063         * 
064         * @see org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase#processGlobalSaveDocumentBusinessRules(org.kuali.rice.kns.document.MaintenanceDocument)
065         */
066        @Override
067        protected boolean processGlobalSaveDocumentBusinessRules(MaintenanceDocument document) {
068            return dataDictionaryValidate(document);
069        }
070        
071        @Override
072        public boolean processRouteDocument(Document document) {
073            boolean valid = super.processRouteDocument(document);
074            OrgReviewRole orr = (OrgReviewRole)((MaintenanceDocument)document).getNewMaintainableObject().getBusinessObject();
075            OrgReviewRoleLookupableHelperServiceImpl lookupableHelperService = new OrgReviewRoleLookupableHelperServiceImpl();
076            lookupableHelperService.validateDocumentType(orr.getFinancialSystemDocumentTypeCode());
077            if(orr!=null){
078                if(!orr.hasAnyMember()){
079                    valid = false;
080                    putFieldError("principalMemberPrincipalName", KFSKeyConstants.NO_MEMBER_SELECTED);
081                } else{
082                    validateRoleMembersToSave(orr);
083                    if(orr.isDelegate()){
084                        // Save delegation(s)
085                        valid = validateDelegation(orr, ((MaintenanceDocument)document).isEdit());
086                    } else{
087                        // Save role member(s)
088                        valid = validateRoleMember(orr, ((MaintenanceDocument)document).isEdit());
089                    }
090                }
091            }
092            return valid;
093        }
094        
095        protected void validateRoleMembersToSave(OrgReviewRole orr){
096            if(orr==null) return;
097            boolean valid = true;
098            String memberId;
099            if(StringUtils.isNotEmpty(orr.getPrincipalMemberPrincipalName())){
100                KimPrincipal principal = getIdentityManagementService().getPrincipalByPrincipalName(orr.getPrincipalMemberPrincipalName());
101                if(principal == null || StringUtils.isEmpty(principal.getPrincipalId())){
102                    GlobalVariables.getMessageMap().putError(MAINTAINABLE_ERROR_PATH+"."+OrgReviewRole.PRINCIPAL_NAME_FIELD_NAME, 
103                            KFSKeyConstants.ERROR_DOCUMENT_OBJCODE_MUST_BEVALID, KimConstants.KimUIConstants.MEMBER_TYPE_PRINCIPAL);
104                    valid = false;
105                }
106            }
107            if(StringUtils.isNotEmpty(orr.getRoleMemberRoleName())){
108                memberId = getRoleService().getRoleIdByName(orr.getRoleMemberRoleNamespaceCode(), orr.getRoleMemberRoleName());
109                if(memberId == null){
110                    GlobalVariables.getMessageMap().putError(MAINTAINABLE_ERROR_PATH+"."+OrgReviewRole.ROLE_NAME_FIELD_NAME, 
111                            KFSKeyConstants.ERROR_DOCUMENT_OBJCODE_MUST_BEVALID, KimConstants.KimUIConstants.MEMBER_TYPE_ROLE);
112                    valid = false;
113                }
114            }
115            if(StringUtils.isNotEmpty(orr.getGroupMemberGroupName())){
116                GroupInfo groupInfo = getGroupService().getGroupInfoByName(orr.getGroupMemberGroupNamespaceCode(), orr.getGroupMemberGroupName());
117                if(groupInfo == null || StringUtils.isEmpty(groupInfo.getGroupId())){
118                    GlobalVariables.getMessageMap().putError(MAINTAINABLE_ERROR_PATH+"."+OrgReviewRole.GROUP_NAME_FIELD_NAME, 
119                            KFSKeyConstants.ERROR_DOCUMENT_OBJCODE_MUST_BEVALID, KimConstants.KimUIConstants.MEMBER_TYPE_GROUP);
120                    valid = false;
121                }
122            }
123            if(!valid)
124                throw new ValidationException("Invalid Role Member Data");
125        }
126        
127        protected boolean validateDelegation(OrgReviewRole orr, boolean isEdit){
128            boolean valid = true;
129            String roleId;
130            if(!isEdit && orr.getRoleNamesToConsider()!=null){
131                for(String roleName: orr.getRoleNamesToConsider()){
132                    roleId = KIMServiceLocator.getRoleService().getRoleIdByName(
133                            KFSConstants.SysKimConstants.ORGANIZATION_REVIEWER_ROLE_NAMESPACECODE, roleName);
134                    Map<String, String> criteria = new HashMap<String, String>();
135                    criteria.put(KimConstants.PrimaryKeyConstants.ROLE_ID, roleId);
136                    List<DelegateMemberCompleteInfo> roleDelegationMembers = getRoleService().findDelegateMembersCompleteInfo(criteria);
137                    
138                    DelegateMemberCompleteInfo member;
139                    String memberId;
140                    //validate if the newly entered delegation members are already assigned to the role
141                    if(roleDelegationMembers!=null){
142                        for(DelegateMemberCompleteInfo delegationMember: roleDelegationMembers){
143                            member = orr.getDelegationMemberOfType(delegationMember.getMemberTypeCode());
144                            if(member!=null && StringUtils.isNotEmpty(member.getMemberName())){
145                                memberId = getUiDocumentService().getMemberIdByName(member.getMemberTypeCode(), member.getMemberNamespaceCode(), member.getMemberName());
146                                boolean attributesUnique = areAttributesUnique(orr, delegationMember.getQualifier());
147                                if(!attributesUnique && member!=null && StringUtils.isNotEmpty(memberId) && memberId.equals(delegationMember.getMemberId())
148                                        && (StringUtils.isNotEmpty(orr.getRoleMemberId()) && StringUtils.isNotEmpty(delegationMember.getRoleMemberId()) 
149                                                && orr.getRoleMemberId().equals(delegationMember.getRoleMemberId()))){
150                                   putFieldError(orr.getDelegationMemberFieldName(member), KFSKeyConstants.ALREADY_ASSIGNED_MEMBER);
151                                   valid = false;
152                                }
153                            }
154                        }
155                    }
156                }
157            }
158            if(StringUtils.isNotEmpty(orr.getRoleMemberId())){
159                valid = validateAmounts(orr);
160                //TODO: put from and to amounts validation here
161                Map<String, String> criteria = new HashMap<String, String>();
162                criteria.put("roleMemberId", orr.getRoleMemberId());
163                List<RoleMemberCompleteInfo> roleMembers = getRoleService().findRoleMembersCompleteInfo(criteria);
164                RoleMemberCompleteInfo roleMember = null;
165                if(roleMembers!=null && roleMembers.size()>0)
166                    roleMember = roleMembers.get(0);
167                KimRoleInfo roleInfo = getRoleService().getRole(roleMember.getRoleId());
168                KimTypeInfo typeInfo = getTypeInfoService().getKimType(roleInfo.getKimTypeId());
169                List<KfsKimDocumentAttributeData> attributes = orr.getAttributeSetAsQualifierList(typeInfo, roleMember.getQualifier());
170                if(roleMember!=null && attributes!=null){
171                    for(KfsKimDocumentAttributeData attribute: attributes){
172                        if(KfsKimAttributes.FROM_AMOUNT.equals(attribute.getKimAttribute().getAttributeName())){
173                            KualiDecimal roleMemberFromAmount = new KualiDecimal(attribute.getAttrVal());
174                            if(orr.getFromAmount()!=null){
175                                KualiDecimal inputFromAmount = orr.getFromAmount();
176                                if((roleMemberFromAmount!=null && inputFromAmount==null) || (inputFromAmount!=null && inputFromAmount.isLessThan(roleMemberFromAmount))){
177                                    putFieldError(KfsKimAttributes.FROM_AMOUNT, KFSKeyConstants.FROM_AMOUNT_OUT_OF_RANGE);
178                                    valid = false;
179                                }
180                            }
181                        }
182                        if(KfsKimAttributes.TO_AMOUNT.equals(attribute.getKimAttribute().getAttributeName())){
183                            KualiDecimal roleMemberToAmount = new KualiDecimal(attribute.getAttrVal());
184                            if(orr.getToAmount()!=null){
185                                KualiDecimal inputToAmount = orr.getToAmount();
186                                if((roleMemberToAmount!=null && inputToAmount==null) || (inputToAmount!=null && inputToAmount.isGreaterThan(roleMemberToAmount))){
187                                    putFieldError(KfsKimAttributes.TO_AMOUNT, KFSKeyConstants.TO_AMOUNT_OUT_OF_RANGE);
188                                    valid = false;
189                                }
190                            }
191                        }
192                    }
193                }
194            }
195            //putFieldError("bankOfficeCode", KFSKeyConstants.ERROR_DOCUMENT_ACHBANKMAINT_INVALID_OFFICE_CODE);
196            return valid;
197        }
198    
199        protected boolean validateAmounts(OrgReviewRole orr){
200            boolean valid = true;
201            if(orr.getFromAmount()!=null && orr.getToAmount()!=null && orr.getFromAmount().isGreaterThan(orr.getToAmount())){
202                putFieldError(KfsKimAttributes.FROM_AMOUNT, KFSKeyConstants.FROM_AMOUNT_GREATER_THAN_TO_AMOUNT);
203                valid = false;
204            }
205            return valid;
206        }
207        
208        protected boolean validateRoleMember(OrgReviewRole orr, boolean isEdit){
209            boolean valid = true;
210            String roleId;
211            if(orr==null) return false;
212            boolean attributesUnique = true;
213            valid = validateAmounts(orr);
214            if(!isEdit && orr.getRoleNamesToConsider()!=null){
215                for(String roleName: orr.getRoleNamesToConsider()){
216                    roleId = KIMServiceLocator.getRoleService().getRoleIdByName(
217                            KFSConstants.SysKimConstants.ORGANIZATION_REVIEWER_ROLE_NAMESPACECODE, roleName);
218                    //validate if the newly entered role members are already assigned to the role
219                    Map<String, Object> criteria = new HashMap<String, Object>();
220                    criteria.put(KimConstants.PrimaryKeyConstants.ROLE_ID, roleId);
221                    List<String> roleIds = new ArrayList<String>();
222                    roleIds.add(roleId);
223                    List<RoleMembershipInfo> roleMembershipInfoList = getRoleService().getFirstLevelRoleMembers(roleIds);
224                    RoleMemberCompleteInfo member;
225                    String memberId;
226                    if(roleMembershipInfoList!=null){
227                        for(RoleMembershipInfo roleMembershipInfo: roleMembershipInfoList){
228                            member = orr.getRoleMemberOfType(roleMembershipInfo.getMemberTypeCode());
229                            if(member!=null && StringUtils.isNotEmpty(member.getMemberName())){
230                                memberId = getUiDocumentService().getMemberIdByName(member.getMemberTypeCode(), member.getMemberNamespaceCode(), member.getMemberName());
231                                attributesUnique = areAttributesUnique(orr, roleMembershipInfo.getQualifier());
232                                if(!attributesUnique && member!=null && StringUtils.isNotEmpty(memberId) && memberId.equals(roleMembershipInfo.getMemberId()) && 
233                                        member.getMemberTypeCode().equals(roleMembershipInfo.getMemberTypeCode())){
234                                   putFieldError(orr.getMemberFieldName(member), KFSKeyConstants.ALREADY_ASSIGNED_MEMBER);
235                                   valid = false;
236                                }
237                            }
238                        }
239                    }
240                }
241            }
242            return valid;
243        }
244    
245        protected boolean areAttributesUnique(OrgReviewRole orr, AttributeSet attributeSet){
246            String docTypeName = orr.getFinancialSystemDocumentTypeCode();
247            String chartOfAccountCode = orr.getChartOfAccountsCode();
248            String organizationCode = orr.getOrganizationCode();
249            boolean uniqueAttributes = 
250                !StringUtils.equals(docTypeName, getAttributeValue(attributeSet, KfsKimAttributes.DOCUMENT_TYPE_NAME)) ||
251                !StringUtils.equals(chartOfAccountCode, getAttributeValue(attributeSet, KfsKimAttributes.CHART_OF_ACCOUNTS_CODE)) ||
252                !StringUtils.equals(organizationCode, getAttributeValue(attributeSet, KfsKimAttributes.ORGANIZATION_CODE));
253            return uniqueAttributes;
254        }
255        
256        protected String getAttributeValue(AttributeSet aSet, String attributeName){
257            if(StringUtils.isEmpty(attributeName)) return null;
258            for(String attributeNameKey: aSet.keySet()){
259                if(attributeName.equals(attributeNameKey))
260                    return aSet.get(attributeNameKey);
261            }
262            return null;
263        }
264    
265        protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
266            return super.processCustomRouteDocumentBusinessRules(document);
267        }
268    
269        /**
270         * Gets the uiDocumentService attribute. 
271         * @return Returns the uiDocumentService.
272         */
273        public UiDocumentService getUiDocumentService() {
274            if(this.uiDocumentService==null){
275                this.uiDocumentService = KIMServiceLocator.getUiDocumentService();
276            }
277            return this.uiDocumentService;
278        }
279    
280        /**
281         * Sets the uiDocumentService attribute value.
282         * @param uiDocumentService The uiDocumentService to set.
283         */
284        public void setUiDocumentService(UiDocumentService uiDocumentService) {
285            this.uiDocumentService = uiDocumentService;
286        }
287    
288        protected KimTypeInfoService getTypeInfoService(){
289            if(typeInfoService==null){
290                typeInfoService = KIMServiceLocator.getTypeInfoService();
291            }
292            return typeInfoService;
293        }
294    
295        protected GroupService getGroupService(){
296            if(groupService==null){
297                groupService = KIMServiceLocator.getGroupService();
298            }
299            return groupService;
300        }
301    }