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 }