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.Iterator; 020 import java.util.List; 021 import java.util.Set; 022 023 import org.apache.commons.lang.StringUtils; 024 import org.kuali.kfs.module.purap.PurapConstants; 025 import org.kuali.kfs.module.purap.PurapParameterConstants; 026 import org.kuali.kfs.module.purap.PurapAuthorizationConstants.PaymentRequestEditMode; 027 import org.kuali.kfs.module.purap.PurapConstants.PaymentRequestStatuses; 028 import org.kuali.kfs.module.purap.PurapWorkflowConstants.PaymentRequestDocument.NodeDetailEnum; 029 import org.kuali.kfs.module.purap.businessobject.PaymentRequestItem; 030 import org.kuali.kfs.module.purap.document.PaymentRequestDocument; 031 import org.kuali.kfs.module.purap.document.service.PurapService; 032 import org.kuali.kfs.sys.KFSConstants; 033 import org.kuali.kfs.sys.KfsAuthorizationConstants; 034 import org.kuali.kfs.sys.context.SpringContext; 035 import org.kuali.kfs.sys.service.impl.KfsParameterConstants; 036 import org.kuali.rice.kns.document.Document; 037 import org.kuali.rice.kns.service.ParameterService; 038 import org.kuali.rice.kns.util.ObjectUtils; 039 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 040 041 042 public class PaymentRequestDocumentPresentationController extends PurchasingAccountsPayableDocumentPresentationController { 043 044 045 @Override 046 protected boolean canSave(Document document) { 047 PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument) document; 048 049 if (StringUtils.equals(paymentRequestDocument.getStatusCode(), PaymentRequestStatuses.INITIATE)) { 050 return false; 051 } 052 053 if (canEditPreExtraction(paymentRequestDocument)) { 054 return true; 055 } 056 057 return super.canSave(document); 058 } 059 060 @Override 061 protected boolean canReload(Document document) { 062 PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument) document; 063 064 if (StringUtils.equals(paymentRequestDocument.getStatusCode(), PaymentRequestStatuses.INITIATE)) { 065 return false; 066 } 067 068 if (canEditPreExtraction(paymentRequestDocument)) { 069 return true; 070 } 071 072 return super.canReload(document); 073 } 074 075 @Override 076 protected boolean canCancel(Document document) { 077 //controlling the cancel button through getExtraButtons in PaymentRequestForm 078 return false; 079 } 080 081 @Override 082 public boolean canApprove(Document document) { 083 PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument) document; 084 085 if (paymentRequestDocument.isPaymentRequestedCancelIndicator() || paymentRequestDocument.isHoldIndicator()) { 086 return false; 087 } 088 089 return super.canApprove(document); 090 } 091 092 @Override 093 protected boolean canDisapprove(Document document) { 094 //disapprove is never allowed for PREQ 095 return false; 096 } 097 098 /** 099 * @see org.kuali.rice.kns.document.authorization.DocumentPresentationControllerBase#canEdit(org.kuali.rice.kns.document.Document) 100 */ 101 @Override 102 protected boolean canEdit(Document document) { 103 PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument) document; 104 boolean fullDocEntryCompleted = SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(paymentRequestDocument); 105 KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); 106 107 // fiscal officer review gets the doc editable once its enroute, but no one else does 108 if (fullDocEntryCompleted) { 109 if (paymentRequestDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.ACCOUNT_REVIEW)) { 110 return true; 111 } 112 return false; 113 } 114 115 // if the hold or cancel indicator is true, don't allow editing 116 if (paymentRequestDocument.isHoldIndicator() || paymentRequestDocument.isPaymentRequestedCancelIndicator()) { 117 return false; 118 } 119 120 // in general, the doc should not be editable once its enroute 121 if (workflowDocument.stateIsEnroute() || workflowDocument.stateIsException()) { 122 return false; 123 } 124 return super.canEdit(document); 125 } 126 127 /** 128 * 129 * @see org.kuali.rice.kns.document.authorization.TransactionalDocumentPresentationControllerBase#getEditModes(org.kuali.rice.kns.document.Document) 130 */ 131 @Override 132 public Set<String> getEditModes(Document document) { 133 Set<String> editModes = super.getEditModes(document); 134 KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); 135 PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument)document; 136 137 if (canProcessorCancel(paymentRequestDocument)) { 138 editModes.add(PaymentRequestEditMode.ACCOUNTS_PAYABLE_PROCESSOR_CANCEL); 139 } 140 141 if (canManagerCancel(paymentRequestDocument)) { 142 editModes.add(PaymentRequestEditMode.ACCOUNTS_PAYABLE_MANAGER_CANCEL); 143 } 144 145 if (canHold(paymentRequestDocument)) { 146 editModes.add(PaymentRequestEditMode.HOLD); 147 } 148 149 if (canRequestCancel(paymentRequestDocument)) { 150 editModes.add(PaymentRequestEditMode.REQUEST_CANCEL); 151 } 152 153 if (canRemoveHold(paymentRequestDocument)) { 154 editModes.add(PaymentRequestEditMode.REMOVE_HOLD); 155 } 156 157 if (canRemoveRequestCancel(paymentRequestDocument)) { 158 editModes.add(PaymentRequestEditMode.REMOVE_REQUEST_CANCEL); 159 } 160 161 if (paymentRequestDocument.getStatusCode().equals(PurapConstants.PaymentRequestStatuses.INITIATE)) { 162 editModes.add(PaymentRequestEditMode.DISPLAY_INIT_TAB); 163 } 164 165 if (ObjectUtils.isNotNull(paymentRequestDocument.getVendorHeaderGeneratedIdentifier())) { 166 editModes.add(PaymentRequestEditMode.LOCK_VENDOR_ENTRY); 167 } 168 169 if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(paymentRequestDocument)) { 170 editModes.add(PaymentRequestEditMode.FULL_DOCUMENT_ENTRY_COMPLETED); 171 } 172 else if (ObjectUtils.isNotNull(paymentRequestDocument.getPurchaseOrderDocument()) && PurapConstants.PurchaseOrderStatuses.OPEN.equals(paymentRequestDocument.getPurchaseOrderDocument().getStatusCode())) { 173 editModes.add(PaymentRequestEditMode.ALLOW_CLOSE_PURCHASE_ORDER); 174 } 175 176 //FIXME hjs: alter to restrict what AP shouldn't be allowed to edit 177 if (canEditPreExtraction(paymentRequestDocument)) { 178 editModes.add(PaymentRequestEditMode.EDIT_PRE_EXTRACT); 179 } 180 181 // See if purap tax is enabled 182 boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND); 183 if (salesTaxInd) { 184 editModes.add(PaymentRequestEditMode.PURAP_TAX_ENABLED); 185 186 if (paymentRequestDocument.isUseTaxIndicator()) { 187 // if use tax, don't allow editing of tax fields 188 editModes.add(PaymentRequestEditMode.LOCK_TAX_AMOUNT_ENTRY); 189 } 190 else { 191 // display the "clear all taxes" button if doc is not using use tax 192 editModes.add(PaymentRequestEditMode.CLEAR_ALL_TAXES); 193 194 } 195 } 196 197 // tax area tab is editable while waiting for tax review 198 if (paymentRequestDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.VENDOR_TAX_REVIEW)) { 199 editModes.add(PaymentRequestEditMode.TAX_AREA_EDITABLE); 200 } 201 /* 202 if (PaymentRequestStatuses.AWAITING_TAX_REVIEW.equals(paymentRequestDocument.getStatusCode())) { 203 editModes.add(PaymentRequestEditMode.TAX_AREA_EDITABLE); 204 } 205 */ 206 207 // the tax tab is viewable to everyone after tax is approved 208 if (PaymentRequestStatuses.DEPARTMENT_APPROVED.equals(paymentRequestDocument.getStatusCode()) && 209 // if and only if the preq has gone through tax review would TaxClassificationCode be non-empty 210 !StringUtils.isEmpty(paymentRequestDocument.getTaxClassificationCode())) { 211 editModes.add(PaymentRequestEditMode.TAX_INFO_VIEWABLE); 212 } 213 214 if (paymentRequestDocument.isDocumentStoppedInRouteNode(NodeDetailEnum.ACCOUNT_REVIEW)) { 215 // remove FULL_ENTRY because FO cannot edit rest of doc; only their own acct lines 216 editModes.add(PaymentRequestEditMode.RESTRICT_FISCAL_ENTRY); 217 218 // only do line item check if the hold/cancel indicator is false, otherwise document editing should be turned off. 219 if (!paymentRequestDocument.isHoldIndicator() && !paymentRequestDocument.isPaymentRequestedCancelIndicator()) { 220 List lineList = new ArrayList(); 221 for (Iterator iter = paymentRequestDocument.getItems().iterator(); iter.hasNext();) { 222 PaymentRequestItem item = (PaymentRequestItem) iter.next(); 223 lineList.addAll(item.getSourceAccountingLines()); 224 // If FO has deleted the last accounting line for an item, set entry mode to full so they can add another one 225 if (item.getItemType().isLineItemIndicator() && item.getSourceAccountingLines().size() == 0) { 226 editModes.add(KfsAuthorizationConstants.TransactionalEditMode.EXPENSE_ENTRY); 227 } 228 } 229 } 230 } 231 232 // Remove editBank edit mode if the document has been extracted 233 if (paymentRequestDocument.isExtracted()) { 234 editModes.remove(KFSConstants.BANK_ENTRY_EDITABLE_EDITING_MODE); 235 } 236 237 return editModes; 238 } 239 240 241 protected boolean canProcessorCancel(PaymentRequestDocument paymentRequestDocument) { 242 // if Payment Request is in INITIATE status, user cannot cancel doc 243 if (StringUtils.equals(paymentRequestDocument.getStatusCode(), PaymentRequestStatuses.INITIATE)) { 244 return false; 245 } 246 247 String docStatus = paymentRequestDocument.getStatusCode(); 248 boolean requestCancelIndicator = paymentRequestDocument.getPaymentRequestedCancelIndicator(); 249 boolean holdIndicator = paymentRequestDocument.isHoldIndicator(); 250 boolean extracted = paymentRequestDocument.isExtracted(); 251 252 boolean preroute = 253 PaymentRequestStatuses.IN_PROCESS.equals(docStatus) || 254 PaymentRequestStatuses.AWAITING_ACCOUNTS_PAYABLE_REVIEW.equals(docStatus); 255 boolean enroute = 256 PaymentRequestStatuses.AWAITING_SUB_ACCT_MGR_REVIEW.equals(docStatus) || 257 PaymentRequestStatuses.AWAITING_FISCAL_REVIEW.equals(docStatus) || 258 PaymentRequestStatuses.AWAITING_ORG_REVIEW.equals(docStatus) || 259 PaymentRequestStatuses.AWAITING_TAX_REVIEW.equals(docStatus); 260 boolean postroute = 261 PaymentRequestStatuses.DEPARTMENT_APPROVED.equals(docStatus) || 262 PaymentRequestStatuses.AUTO_APPROVED.equals(docStatus); 263 264 boolean can = false; 265 if (preroute) { 266 can = true; 267 } 268 else if (enroute) { 269 can = requestCancelIndicator; 270 } 271 else if (postroute) { 272 can = !requestCancelIndicator && !holdIndicator && !extracted; 273 } 274 275 return can; 276 } 277 278 protected boolean canManagerCancel(PaymentRequestDocument paymentRequestDocument) { 279 // if Payment Request is in INITIATE status, user cannot cancel doc 280 if (StringUtils.equals(paymentRequestDocument.getStatusCode(), PaymentRequestStatuses.INITIATE)) { 281 return false; 282 } 283 284 String docStatus = paymentRequestDocument.getStatusCode(); 285 boolean requestCancelIndicator = paymentRequestDocument.getPaymentRequestedCancelIndicator(); 286 boolean holdIndicator = paymentRequestDocument.isHoldIndicator(); 287 boolean extracted = paymentRequestDocument.isExtracted(); 288 289 boolean preroute = 290 PaymentRequestStatuses.IN_PROCESS.equals(docStatus) || 291 PaymentRequestStatuses.AWAITING_ACCOUNTS_PAYABLE_REVIEW.equals(docStatus); 292 boolean enroute = 293 PaymentRequestStatuses.AWAITING_SUB_ACCT_MGR_REVIEW.equals(docStatus) || 294 PaymentRequestStatuses.AWAITING_FISCAL_REVIEW.equals(docStatus) || 295 PaymentRequestStatuses.AWAITING_ORG_REVIEW.equals(docStatus) || 296 PaymentRequestStatuses.AWAITING_TAX_REVIEW.equals(docStatus); 297 boolean postroute = 298 PaymentRequestStatuses.DEPARTMENT_APPROVED.equals(docStatus) || 299 PaymentRequestStatuses.AUTO_APPROVED.equals(docStatus); 300 301 boolean can = false; 302 if (preroute || enroute) { 303 can = true; 304 } 305 else if (postroute) { 306 can = !requestCancelIndicator && !holdIndicator && !extracted; 307 } 308 309 return can; 310 } 311 312 /** 313 * Determines whether the PaymentRequest Hold button shall be available. Conditions: 314 * - Payment Request is not already on hold, and 315 * - Payment Request is not already being requested to be canceled, and 316 * - Payment Request has not already been extracted to PDP, and 317 * - Payment Request status is not in the list of "STATUSES_DISALLOWING_HOLD" or document is being adhoc routed; and 318 * 319 * @return True if the document state allows placing the Payment Request on hold. 320 */ 321 protected boolean canHold(PaymentRequestDocument paymentRequestDocument) { 322 boolean can = !paymentRequestDocument.isHoldIndicator() && !paymentRequestDocument.isPaymentRequestedCancelIndicator() && !paymentRequestDocument.isExtracted(); 323 if (can) { 324 can = paymentRequestDocument.getDocumentHeader().getWorkflowDocument().isAdHocRequested(); 325 can = can || !PaymentRequestStatuses.STATUSES_DISALLOWING_HOLD.contains(paymentRequestDocument.getStatusCode()); 326 } 327 328 return can; 329 } 330 331 /** 332 * Determines whether the Request Cancel PaymentRequest button shall be available. Conditions: 333 * - Payment Request is not already on hold, and 334 * - Payment Request is not already being requested to be canceled, and 335 * - Payment Request has not already been extracted to PDP, and 336 * - Payment Request status is not in the list of "STATUSES_DISALLOWING_REQUEST_CANCEL" or document is being adhoc routed; and 337 * 338 * @return True if the document state allows placing the request that the Payment Request be canceled. 339 */ 340 protected boolean canRequestCancel(PaymentRequestDocument paymentRequestDocument) { 341 boolean can = !paymentRequestDocument.isPaymentRequestedCancelIndicator() && !paymentRequestDocument.isHoldIndicator() && !paymentRequestDocument.isExtracted(); 342 if (can) { 343 can = paymentRequestDocument.getDocumentHeader().getWorkflowDocument().isAdHocRequested(); 344 can = can || !PaymentRequestStatuses.STATUSES_DISALLOWING_REQUEST_CANCEL.contains(paymentRequestDocument.getStatusCode()); 345 } 346 347 return can; 348 } 349 350 /** 351 * Determines whether the Remove Hold button shall be available. Conditions: 352 * - the hold indicator is set to true 353 * 354 * Because the state of the Payment Request cannot be changed while the document is on hold, 355 * we should not have to check the state of the document to remove the hold. 356 * For example, the document should not be allowed to be approved or extracted while on hold. 357 * 358 * @return True if the document state allows removing the Payment Request from hold. 359 */ 360 protected boolean canRemoveHold(PaymentRequestDocument paymentRequestDocument) { 361 return paymentRequestDocument.isHoldIndicator(); 362 } 363 364 /** 365 * Determines whether the Remove Request Cancel button shall be available. Conditions: 366 * - the request cancel indicator is set to true; and 367 * 368 * Because the state of the Payment Request cannot be changed while the document is set to request cancel, 369 * we should not have to check the state of the document to remove the request cancel. 370 * For example, the document should not be allowed to be approved or extracted while set to request cancel. 371 * 372 * @return True if the document state allows removing a request that the Payment Request be canceled. 373 */ 374 protected boolean canRemoveRequestCancel(PaymentRequestDocument paymentRequestDocument) { 375 return paymentRequestDocument.isPaymentRequestedCancelIndicator(); 376 } 377 378 protected boolean canEditPreExtraction(PaymentRequestDocument paymentRequestDocument) { 379 return (!paymentRequestDocument.isExtracted() && 380 !paymentRequestDocument.getDocumentHeader().getWorkflowDocument().isAdHocRequested() && 381 !PurapConstants.PaymentRequestStatuses.CANCELLED_STATUSES.contains(paymentRequestDocument.getStatusCode())); 382 } 383 384 }