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.purap.document.authorization; 017 018 import java.util.ArrayList; 019 import java.util.Arrays; 020 import java.util.Iterator; 021 import java.util.List; 022 import java.util.Set; 023 024 import org.kuali.kfs.module.purap.PurapAuthorizationConstants; 025 import org.kuali.kfs.module.purap.PurapConstants; 026 import org.kuali.kfs.module.purap.PurapParameterConstants; 027 import org.kuali.kfs.module.purap.PurapAuthorizationConstants.RequisitionEditMode; 028 import org.kuali.kfs.module.purap.PurapConstants.RequisitionSources; 029 import org.kuali.kfs.module.purap.PurapConstants.RequisitionStatuses; 030 import org.kuali.kfs.module.purap.PurapWorkflowConstants.NodeDetails; 031 import org.kuali.kfs.module.purap.PurapWorkflowConstants.RequisitionDocument.NodeDetailEnum; 032 import org.kuali.kfs.module.purap.businessobject.RequisitionItem; 033 import org.kuali.kfs.module.purap.document.RequisitionDocument; 034 import org.kuali.kfs.module.purap.document.service.PurapService; 035 import org.kuali.kfs.sys.context.SpringContext; 036 import org.kuali.kfs.sys.service.impl.KfsParameterConstants; 037 import org.kuali.rice.kew.exception.WorkflowException; 038 import org.kuali.rice.kns.document.Document; 039 import org.kuali.rice.kns.service.KualiConfigurationService; 040 import org.kuali.rice.kns.service.ParameterService; 041 import org.kuali.rice.kns.util.ObjectUtils; 042 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 043 044 045 public class RequisitionDocumentPresentationController extends PurchasingAccountsPayableDocumentPresentationController { 046 047 @Override 048 protected boolean canEdit(Document document) { 049 RequisitionDocument reqDocument = (RequisitionDocument)document; 050 if (!RequisitionStatuses.IN_PROCESS.equals(reqDocument.getStatusCode()) && 051 !RequisitionStatuses.AWAIT_CONTENT_REVIEW.equals(reqDocument.getStatusCode()) && 052 !RequisitionStatuses.AWAIT_HAS_ACCOUNTING_LINES.equals(reqDocument.getStatusCode()) && 053 !RequisitionStatuses.AWAIT_FISCAL_REVIEW.equals(reqDocument.getStatusCode())) { 054 //unless the Requisition is in process, awaiting content, awaiting accounting lines or awaiting fiscal, editing is not allowed 055 return false; 056 } 057 return super.canEdit(document); 058 } 059 060 @Override 061 public Set<String> getEditModes(Document document) { 062 Set<String> editModes = super.getEditModes(document); 063 RequisitionDocument reqDocument = (RequisitionDocument)document; 064 065 //if the ENABLE_COMMODITY_CODE_IND system parameter is Y then add this edit mode so that the commodity code fields would display on the document. 066 boolean enableCommodityCode = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_COMMODITY_CODE_IND); 067 if (enableCommodityCode) { 068 editModes.add(RequisitionEditMode.ENABLE_COMMODITY_CODE); 069 } 070 071 // if vendor has been selected from DB, certain vendor fields are not allowed to be edited 072 if (ObjectUtils.isNotNull(reqDocument.getVendorHeaderGeneratedIdentifier())) { 073 editModes.add(RequisitionEditMode.LOCK_VENDOR_ENTRY); 074 } 075 076 // if B2B requisition, certain fields are not allowed to be edited 077 if (RequisitionSources.B2B.equals(reqDocument.getRequisitionSourceCode())) { 078 editModes.add(RequisitionEditMode.LOCK_B2B_ENTRY); 079 } 080 081 // if not B2B requisition, the posting year cannot be edited if within a given amount of time set in a parameter 082 if (!RequisitionSources.B2B.equals(reqDocument.getRequisitionSourceCode()) && 083 SpringContext.getBean(PurapService.class).allowEncumberNextFiscalYear()) { 084 editModes.add(RequisitionEditMode.ALLOW_POSTING_YEAR_ENTRY); 085 } 086 087 // check if purap tax is enabled 088 boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND); 089 if (salesTaxInd) { 090 editModes.add(PurapAuthorizationConstants.PURAP_TAX_ENABLED); 091 editModes.add(RequisitionEditMode.CLEAR_ALL_TAXES); // always available now if taxes 092 093 if (reqDocument.isUseTaxIndicator()) { 094 // don't allow tax editing if doc using use tax 095 editModes.add(RequisitionEditMode.LOCK_TAX_AMOUNT_ENTRY); 096 } 097 } 098 099 // set display mode for Receiving Address section according to parameter value 100 boolean displayReceivingAddress = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_RECEIVING_ADDRESS_IND); 101 if (displayReceivingAddress) { 102 editModes.add(RequisitionEditMode.DISPLAY_RECEIVING_ADDRESS); 103 } 104 105 // set display mode for Address to Vendor section according to parameter value 106 boolean lockAddressToVendor = !SpringContext.getBean(ParameterService.class).getIndicatorParameter(PurapConstants.PURAP_NAMESPACE, "Requisition", PurapParameterConstants.ENABLE_ADDRESS_TO_VENDOR_SELECTION_IND); 107 if (lockAddressToVendor) { 108 editModes.add(RequisitionEditMode.LOCK_ADDRESS_TO_VENDOR); 109 } 110 111 // CONTENT ROUTE LEVEL - Approvers can edit full detail on Requisition except they cannot change the CHART/ORG. 112 if (reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.CONTENT_REVIEW) || 113 reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.HAS_ACCOUNTING_LINES)) { 114 editModes.add(RequisitionEditMode.LOCK_CONTENT_ENTRY); 115 } 116 117 // FISCAL OFFICER ROUTE LEVEL - Approvers can edit only the accounting lines that they own and no other detail on REQ. 118 else if (reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.ACCOUNT_REVIEW)) { 119 120 // remove FULL_ENTRY because FO cannot edit rest of doc; only their own acct lines 121 editModes.add(RequisitionEditMode.RESTRICT_FISCAL_ENTRY); 122 123 List lineList = new ArrayList(); 124 for (Iterator iter = reqDocument.getItems().iterator(); iter.hasNext();) { 125 RequisitionItem item = (RequisitionItem) iter.next(); 126 lineList.addAll(item.getSourceAccountingLines()); 127 // If FO has deleted the last accounting line for an item, set entry mode to full so they can add another one 128 129 if (item.getSourceAccountingLines().size() == 0) { 130 editModes.add(RequisitionEditMode.RESTRICT_FISCAL_ENTRY); 131 //FIXME hjs-this is a problem because we can't put the id in the map anymore 132 // editModeMap.put(RequisitionEditMode.ALLOW_ITEM_ENTRY, item.getItemIdentifier()); 133 } 134 } 135 136 } 137 138 return editModes; 139 } 140 141 @Override 142 protected boolean canCopy(Document document) { 143 // disallow copying until the doc is saved 144 KualiWorkflowDocument workflowDoc = document.getDocumentHeader().getWorkflowDocument(); 145 if (workflowDoc.stateIsInitiated() && !workflowDoc.stateIsSaved()) { 146 return false; 147 } 148 return super.canCopy(document); 149 } 150 151 @Override 152 protected boolean canReload(Document document) { 153 RequisitionDocument reqDocument = (RequisitionDocument) document; 154 155 // this is a global rule, if the doc is in your queue for ACK, then you lose the reload button 156 KualiWorkflowDocument workflowDoc = document.getDocumentHeader().getWorkflowDocument(); 157 if (workflowDoc.isAcknowledgeRequested()) { 158 return false; 159 } 160 161 // while in subAccountReview ... sub account approvers do NOT get reload button 162 if (reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.SUB_ACCOUNT_REVIEW)) { 163 return false; 164 } 165 // but the non-approvers do 166 else if (isDocInRouteNodeNotForCurrentUser(reqDocument, NodeDetailEnum.SUB_ACCOUNT_REVIEW)) { 167 return true; 168 } 169 170 // while in AccountingHierarchyOrgReview ... org reviewers do NOT get reload button 171 else if (reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.ORG_REVIEW)) { 172 return false; 173 } 174 // but the non-approvers do 175 else if (isDocInRouteNodeNotForCurrentUser(reqDocument, NodeDetailEnum.ORG_REVIEW)) { 176 return true; 177 } 178 179 // while in SeparationOfDuties ... approvers do NOT get reload button 180 else if (reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.SEPARATION_OF_DUTIES_REVIEW)) { 181 return false; 182 } 183 // but the non-approvers do 184 else if (isDocInRouteNodeNotForCurrentUser(reqDocument, NodeDetailEnum.SEPARATION_OF_DUTIES_REVIEW)) { 185 return true; 186 } 187 188 return super.canReload(document); 189 } 190 191 @Override 192 protected boolean canSave(Document document) { 193 RequisitionDocument reqDocument = (RequisitionDocument) document; 194 195 // while in OrgReview ... org reviewers do NOT get reload button 196 if (reqDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.ORG_REVIEW)) { 197 return false; 198 } 199 return super.canSave(document); 200 } 201 202 protected boolean isDocInRouteNodeNotForCurrentUser(Document document, NodeDetails nodeDetails) { 203 List<String> currentRouteLevels = new ArrayList<String>(); 204 KualiWorkflowDocument workflowDoc = document.getDocumentHeader().getWorkflowDocument(); 205 try { 206 currentRouteLevels = Arrays.asList(document.getDocumentHeader().getWorkflowDocument().getNodeNames()); 207 } 208 catch (WorkflowException e) { 209 throw new RuntimeException(e); 210 } 211 if (currentRouteLevels.contains(nodeDetails.getName()) && !workflowDoc.isApprovalRequested()) { 212 return true; 213 } 214 return false; 215 } 216 }