001/* 002 * Copyright 2008-2009 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 */ 016package org.kuali.ole.module.purap.document.authorization; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.ole.module.purap.PurapAuthorizationConstants.InvoiceEditMode; 020import org.kuali.ole.module.purap.PurapConstants.InvoiceStatuses; 021import org.kuali.ole.module.purap.PurapConstants.PurchaseOrderStatuses; 022import org.kuali.ole.module.purap.PurapParameterConstants; 023import org.kuali.ole.module.purap.businessobject.InvoiceItem; 024import org.kuali.ole.module.purap.document.InvoiceDocument; 025import org.kuali.ole.module.purap.document.service.PurapService; 026import org.kuali.ole.sys.OLEConstants; 027import org.kuali.ole.sys.OleAuthorizationConstants; 028import org.kuali.ole.sys.context.SpringContext; 029import org.kuali.ole.sys.service.FinancialSystemWorkflowHelperService; 030import org.kuali.ole.sys.service.impl.OleParameterConstants; 031import org.kuali.rice.coreservice.framework.parameter.ParameterService; 032import org.kuali.rice.kew.api.WorkflowDocument; 033import org.kuali.rice.kew.api.action.ActionType; 034import org.kuali.rice.kew.api.action.ValidActions; 035import org.kuali.rice.krad.document.Document; 036import org.kuali.rice.krad.util.GlobalVariables; 037import org.kuali.rice.krad.util.ObjectUtils; 038 039import java.util.ArrayList; 040import java.util.Iterator; 041import java.util.List; 042import java.util.Set; 043 044 045public class InvoiceDocumentPresentationController extends PurchasingAccountsPayableDocumentPresentationController { 046 047 Boolean canHold; 048 Boolean canRequestCancel; 049 Boolean canEditPreExtraction; 050 051 @Override 052 public boolean canSave(Document document) { 053 InvoiceDocument invoiceDocument = (InvoiceDocument) document; 054 055 if (!StringUtils.equalsIgnoreCase(invoiceDocument.getDocumentHeader().getWorkflowDocument().getStatus().name(), InvoiceStatuses.APPDOC_INITIATE) 056 && !StringUtils.equalsIgnoreCase(invoiceDocument.getDocumentHeader().getWorkflowDocument().getStatus().name(), OLEConstants.OleInvoice.INVOICE_SAVED)) { 057 return false; 058 } 059 060 if (canEditPreExtraction(invoiceDocument)) { 061 return true; 062 } 063 064 return super.canSave(document); 065 } 066 067 @Override 068 public boolean canReload(Document document) { 069 InvoiceDocument invoiceDocument = (InvoiceDocument) document; 070 071 if (StringUtils.equals(invoiceDocument.getApplicationDocumentStatus(), InvoiceStatuses.APPDOC_INITIATE)) { 072 return false; 073 } 074 075 if (canEditPreExtraction(invoiceDocument)) { 076 return true; 077 } 078 079 return super.canReload(document); 080 } 081 082 @Override 083 public boolean canCancel(Document document) { 084 //controlling the cancel button through getExtraButtons in InvoiceForm 085 return false; 086 } 087 088 @Override 089 public boolean canApprove(Document document) { 090 InvoiceDocument invoiceDocument = (InvoiceDocument) document; 091 092 if (invoiceDocument.isInvoiceCancelIndicator() || invoiceDocument.isHoldIndicator()) { 093 return false; 094 } 095 096 return super.canApprove(document); 097 } 098 099 @Override 100 public boolean canCopy (Document document) { 101 InvoiceDocument invoiceDocument = (InvoiceDocument) document; 102 if (super.canCopy(document)) { 103 if (!StringUtils.equalsIgnoreCase(invoiceDocument.getDocumentHeader().getWorkflowDocument().getStatus().name(), InvoiceStatuses.APPDOC_INITIATE)) { 104 return true; 105 } 106 } 107 return false; 108 109 } 110 111 @Override 112 public boolean canDisapprove(Document document) { 113 114 WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); 115 if (workflowDocument.isEnroute()) { 116 ValidActions validActions = workflowDocument.getValidActions(); 117 return validActions.getValidActions().contains(ActionType.DISAPPROVE); 118 } 119 120 return super.canDisapprove(document); 121 } 122 123 /** 124 * @see org.kuali.rice.krad.document.DocumentPresentationControllerBase#canEdit(org.kuali.rice.krad.document.Document) 125 */ 126 @Override 127 public boolean canEdit(Document document) { 128 InvoiceDocument invoiceDocument = (InvoiceDocument) document; 129 boolean fullDocEntryCompleted = SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(invoiceDocument); 130 131 // if the hold or cancel indicator is true, don't allow editing 132 if (invoiceDocument.isHoldIndicator() || invoiceDocument.isInvoiceCancelIndicator()) { 133 return false; 134 } 135 if (fullDocEntryCompleted) { 136 // after fullDocEntry is completed, only fiscal officer reviewers can edit 137 if (invoiceDocument.isDocumentStoppedInRouteNode(InvoiceStatuses.NODE_ACCOUNT_REVIEW)) { 138 return true; 139 } 140 return false; 141 } else { 142 //before fullDocEntry is completed, document can be edited (could be preroute or enroute) 143 return true; 144 } 145 } 146 147 /** 148 * @see org.kuali.rice.kns.document.authorization.TransactionalDocumentPresentationControllerBase#getEditModes(org.kuali.rice.krad.document.Document) 149 */ 150 @Override 151 public Set<String> getEditModes(Document document) { 152 Set<String> editModes = super.getEditModes(document); 153 154 InvoiceDocument invoiceDocument = (InvoiceDocument) document; 155 156 if (canProcessorCancel(invoiceDocument)) { 157 editModes.add(InvoiceEditMode.ACCOUNTS_PAYABLE_PROCESSOR_CANCEL); 158 } 159 160 if (canManagerCancel(invoiceDocument)) { 161 editModes.add(InvoiceEditMode.ACCOUNTS_PAYABLE_MANAGER_CANCEL); 162 } 163 164 if (canHold(invoiceDocument)) { 165 editModes.add(InvoiceEditMode.HOLD); 166 } 167 168 if (canRequestCancel(invoiceDocument)) { 169 editModes.add(InvoiceEditMode.REQUEST_CANCEL); 170 } 171 172 if (canRemoveHold(invoiceDocument)) { 173 editModes.add(InvoiceEditMode.REMOVE_HOLD); 174 } 175 176 if (canRemoveRequestCancel(invoiceDocument)) { 177 editModes.add(InvoiceEditMode.REMOVE_REQUEST_CANCEL); 178 } 179 180 if (canProcessorInit(invoiceDocument)) { 181 editModes.add(InvoiceEditMode.DISPLAY_INIT_TAB); 182 } 183 184 if (ObjectUtils.isNotNull(invoiceDocument.getVendorHeaderGeneratedIdentifier())) { 185 editModes.add(InvoiceEditMode.LOCK_VENDOR_ENTRY); 186 } 187 188 if (SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(invoiceDocument)) { 189 editModes.add(InvoiceEditMode.FULL_DOCUMENT_ENTRY_COMPLETED); 190 } 191 //else if (ObjectUtils.isNotNull(invoiceDocument.getPurchaseOrderDocument()) && PurchaseOrderStatuses.APPDOC_OPEN.equals(invoiceDocument.getPurchaseOrderDocument().getApplicationDocumentStatus())) { 192 /* 193 String documentTypeName = OLEConstants.FinancialDocumentTypeCodes.PAYMENT_REQUEST; 194 String nameSpaceCode = OLEConstants.CoreModuleNamespaces.SELECT; 195 196 AttributeSet permissionDetails = new AttributeSet(); 197 permissionDetails.put(KimAttributes.DOCUMENT_TYPE_NAME,documentTypeName); 198 199 boolean canClosePO = KIMServiceLocator.getIdentityManagementService().hasPermission(GlobalVariables.getUserSession().getPerson().getPrincipalId(), nameSpaceCode, 200 OLEConstants.OleInvoice.CAN_CLOSE_PO, permissionDetails); 201 if(canClosePO) { 202 editModes.add(InvoiceEditMode.ALLOW_CLOSE_PURCHASE_ORDER); 203 }*/ 204 // editModes.add(InvoiceEditMode.ALLOW_CLOSE_PURCHASE_ORDER); 205 // } 206 207 //FIXME hjs: alter to restrict what AP shouldn't be allowed to edit 208 if (canEditPreExtraction(invoiceDocument)) { 209 editModes.add(InvoiceEditMode.EDIT_PRE_EXTRACT); 210 } 211 212 // See if purap tax is enabled 213 boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND); 214 if (salesTaxInd) { 215 editModes.add(InvoiceEditMode.PURAP_TAX_ENABLED); 216 217 if (invoiceDocument.isUseTaxIndicator()) { 218 // if use tax, don't allow editing of tax fields 219 editModes.add(InvoiceEditMode.LOCK_TAX_AMOUNT_ENTRY); 220 } else { 221 // display the "clear all taxes" button if doc is not using use tax 222 editModes.add(InvoiceEditMode.CLEAR_ALL_TAXES); 223 224 } 225 } 226 227 // tax area tab is editable while waiting for tax review 228 if (invoiceDocument.isDocumentStoppedInRouteNode(InvoiceStatuses.NODE_VENDOR_TAX_REVIEW)) { 229 editModes.add(InvoiceEditMode.TAX_AREA_EDITABLE); 230 } 231 232 if (PurchaseOrderStatuses.APPDOC_AWAIT_TAX_REVIEW 233 .equals(invoiceDocument.getApplicationDocumentStatus())) { 234 editModes.add(InvoiceEditMode.TAX_AREA_EDITABLE); 235 } 236 237 238 // the tax tab is viewable to everyone after tax is approved 239 if (InvoiceStatuses.APPDOC_DEPARTMENT_APPROVED.equals(invoiceDocument.getApplicationDocumentStatus()) && 240 // if and only if the invoice has gone through tax review would TaxClassificationCode be non-empty 241 !StringUtils.isEmpty(invoiceDocument.getTaxClassificationCode())) { 242 editModes.add(InvoiceEditMode.TAX_INFO_VIEWABLE); 243 } 244 245 if (invoiceDocument.isDocumentStoppedInRouteNode(InvoiceStatuses.NODE_ACCOUNT_REVIEW)) { 246 // remove FULL_ENTRY because FO cannot edit rest of doc; only their own acct lines 247 editModes.add(InvoiceEditMode.RESTRICT_FISCAL_ENTRY); 248 249 // only do line item check if the hold/cancel indicator is false, otherwise document editing should be turned off. 250 if (!invoiceDocument.isHoldIndicator() && !invoiceDocument.isInvoiceCancelIndicator()) { 251 List lineList = new ArrayList(); 252 for (Iterator iter = invoiceDocument.getItems().iterator(); iter.hasNext(); ) { 253 InvoiceItem item = (InvoiceItem) iter.next(); 254 lineList.addAll(item.getSourceAccountingLines()); 255 // If FO has deleted the last accounting line for an item, set entry mode to full so they can add another one 256 if (item.getItemType().isLineItemIndicator() && item.getSourceAccountingLines().size() == 0) { 257 editModes.add(OleAuthorizationConstants.TransactionalEditMode.EXPENSE_ENTRY); 258 } 259 } 260 } 261 } 262 263 // Remove editBank edit mode if the document has been extracted 264 if (invoiceDocument.isExtracted()) { 265 editModes.remove(OLEConstants.BANK_ENTRY_EDITABLE_EDITING_MODE); 266 } 267 268 return editModes; 269 } 270 271 protected boolean canProcessorInit(InvoiceDocument invoiceDocument) { 272 // if Payment Request is in INITIATE status or NULL returned from getAppDocStatus 273 String status = invoiceDocument.getApplicationDocumentStatus(); 274 if (StringUtils.equals(status, InvoiceStatuses.APPDOC_INITIATE)) { 275 return true; 276 } 277 return false; 278 } 279 280 281 protected boolean canProcessorCancel(InvoiceDocument invoiceDocument) { 282 // if Payment Request is in INITIATE status, user cannot cancel doc 283 if (canProcessorInit(invoiceDocument)) { 284 return false; 285 } 286 287 String docStatus = invoiceDocument.getApplicationDocumentStatus(); 288 boolean requestCancelIndicator = invoiceDocument.getInvoiceCancelIndicator(); 289 boolean holdIndicator = invoiceDocument.isHoldIndicator(); 290 boolean extracted = invoiceDocument.isExtracted(); 291 292 boolean preroute = 293 InvoiceStatuses.APPDOC_IN_PROCESS.equals(docStatus) || 294 InvoiceStatuses.APPDOC_AWAITING_ACCOUNTS_PAYABLE_REVIEW.equals(docStatus); 295 boolean enroute = 296 InvoiceStatuses.APPDOC_AWAITING_SUB_ACCT_MGR_REVIEW.equals(docStatus) || 297 InvoiceStatuses.APPDOC_AWAITING_FISCAL_REVIEW.equals(docStatus) || 298 InvoiceStatuses.APPDOC_AWAITING_ORG_REVIEW.equals(docStatus) || 299 InvoiceStatuses.APPDOC_AWAITING_PAYMENT_REVIEW.equals(docStatus) 300 || 301 InvoiceStatuses.APPDOC_AWAITING_TAX_REVIEW.equals(docStatus); 302 boolean postroute = 303 InvoiceStatuses.APPDOC_DEPARTMENT_APPROVED.equals(docStatus) || 304 InvoiceStatuses.APPDOC_AUTO_APPROVED.equals(docStatus); 305 306 boolean can = false; 307 if (InvoiceStatuses.STATUSES_PREROUTE.contains(docStatus)) { 308 can = true; 309 } else if (InvoiceStatuses.STATUSES_ENROUTE.contains(docStatus)) { 310 can = requestCancelIndicator; 311 } else if (InvoiceStatuses.STATUSES_POSTROUTE.contains(docStatus)) { 312 can = !requestCancelIndicator && !holdIndicator && !extracted; 313 } 314 315 return can; 316 } 317 318 protected boolean canManagerCancel(InvoiceDocument invoiceDocument) { 319 // if Payment Request is in INITIATE status, user cannot cancel doc 320 if (canProcessorInit(invoiceDocument)) { 321 return false; 322 } 323 324 String docStatus = invoiceDocument.getApplicationDocumentStatus(); 325 boolean requestCancelIndicator = invoiceDocument.getInvoiceCancelIndicator(); 326 boolean holdIndicator = invoiceDocument.isHoldIndicator(); 327 boolean extracted = invoiceDocument.isExtracted(); 328 329 boolean preroute = 330 InvoiceStatuses.APPDOC_IN_PROCESS.equals(docStatus) || 331 InvoiceStatuses.APPDOC_AWAITING_ACCOUNTS_PAYABLE_REVIEW.equals(docStatus); 332 boolean enroute = 333 InvoiceStatuses.APPDOC_AWAITING_SUB_ACCT_MGR_REVIEW.equals(docStatus) || 334 InvoiceStatuses.APPDOC_AWAITING_FISCAL_REVIEW.equals(docStatus) || 335 InvoiceStatuses.APPDOC_AWAITING_ORG_REVIEW.equals(docStatus) || 336 InvoiceStatuses.APPDOC_AWAITING_PAYMENT_REVIEW.equals(docStatus) 337 || 338 InvoiceStatuses.APPDOC_AWAITING_TAX_REVIEW.equals(docStatus); 339 boolean postroute = 340 InvoiceStatuses.APPDOC_DEPARTMENT_APPROVED.equals(docStatus) || 341 InvoiceStatuses.APPDOC_AUTO_APPROVED.equals(docStatus); 342 343 boolean can = false; 344 if (InvoiceStatuses.STATUSES_PREROUTE.contains(docStatus) || 345 InvoiceStatuses.STATUSES_ENROUTE.contains(docStatus)) { 346 can = true; 347 } else if (InvoiceStatuses.STATUSES_POSTROUTE.contains(docStatus)) { 348 can = !requestCancelIndicator && !holdIndicator && !extracted; 349 } 350 351 return can; 352 } 353 354 /** 355 * Determines whether the Invoice Hold button shall be available. Conditions: 356 * - Payment Request is not already on hold, and 357 * - Payment Request is not already being requested to be canceled, and 358 * - Payment Request has not already been extracted to PDP, and 359 * - Payment Request status is not in the list of "STATUSES_DISALLOWING_HOLD" or document is being adhoc routed; and 360 * 361 * @return True if the document state allows placing the Payment Request on hold. 362 */ 363 protected boolean canHold(InvoiceDocument invoiceDocument) { 364 if (canHold == null) { 365 366 boolean can = !invoiceDocument.isHoldIndicator() 367 && !invoiceDocument.isInvoiceCancelIndicator() 368 && !invoiceDocument.isExtracted(); 369 if (can) { 370 can = SpringContext.getBean(FinancialSystemWorkflowHelperService.class) 371 .isAdhocApprovalRequestedForPrincipal( 372 invoiceDocument.getFinancialSystemDocumentHeader().getWorkflowDocument(), 373 GlobalVariables.getUserSession().getPrincipalId()); 374 can = can 375 || !InvoiceStatuses.STATUSES_DISALLOWING_HOLD.contains(invoiceDocument 376 .getApplicationDocumentStatus()); 377 } 378 canHold = can; 379 } 380 381 return canHold; 382 } 383 384 /** 385 * Determines whether the Request Cancel Invoice button shall be available. Conditions: 386 * - Payment Request is not already on hold, and 387 * - Payment Request is not already being requested to be canceled, and 388 * - Payment Request has not already been extracted to PDP, and 389 * - Payment Request status is not in the list of "STATUSES_DISALLOWING_REQUEST_CANCEL" or document is being adhoc routed; and 390 * 391 * @return True if the document state allows placing the request that the Payment Request be canceled. 392 */ 393 protected boolean canRequestCancel(InvoiceDocument invoiceDocument) { 394 if (canRequestCancel == null) { 395 boolean can = !invoiceDocument.isInvoiceCancelIndicator() 396 && !invoiceDocument.isHoldIndicator() && !invoiceDocument.isExtracted(); 397 if (can) { 398 can = SpringContext.getBean(FinancialSystemWorkflowHelperService.class) 399 .isAdhocApprovalRequestedForPrincipal( 400 invoiceDocument.getFinancialSystemDocumentHeader().getWorkflowDocument(), 401 GlobalVariables.getUserSession().getPrincipalId()); 402 can = can 403 || !InvoiceStatuses.STATUSES_DISALLOWING_REQUEST_CANCEL.contains(invoiceDocument 404 .getApplicationDocumentStatus()); 405 } 406 canRequestCancel = can; 407 } 408 return canRequestCancel; 409 } 410 411 /** 412 * Determines whether the Remove Hold button shall be available. Conditions: 413 * - the hold indicator is set to true 414 * <p/> 415 * Because the state of the Payment Request cannot be changed while the document is on hold, 416 * we should not have to check the state of the document to remove the hold. 417 * For example, the document should not be allowed to be approved or extracted while on hold. 418 * 419 * @return True if the document state allows removing the Payment Request from hold. 420 */ 421 protected boolean canRemoveHold(InvoiceDocument invoiceDocument) { 422 return invoiceDocument.isHoldIndicator(); 423 } 424 425 /** 426 * Determines whether the Remove Request Cancel button shall be available. Conditions: 427 * - the request cancel indicator is set to true; and 428 * <p/> 429 * Because the state of the Payment Request cannot be changed while the document is set to request cancel, 430 * we should not have to check the state of the document to remove the request cancel. 431 * For example, the document should not be allowed to be approved or extracted while set to request cancel. 432 * 433 * @return True if the document state allows removing a request that the Payment Request be canceled. 434 */ 435 protected boolean canRemoveRequestCancel(InvoiceDocument invoiceDocument) { 436 return invoiceDocument.isInvoiceCancelIndicator(); 437 } 438 439 protected boolean canEditPreExtraction(InvoiceDocument invoiceDocument) { 440 if (canEditPreExtraction == null) { 441 boolean can = (!invoiceDocument.isExtracted() 442 && !SpringContext.getBean(FinancialSystemWorkflowHelperService.class) 443 .isAdhocApprovalRequestedForPrincipal( 444 invoiceDocument.getFinancialSystemDocumentHeader().getWorkflowDocument(), 445 GlobalVariables.getUserSession().getPrincipalId()) && !InvoiceStatuses.CANCELLED_STATUSES 446 .contains(invoiceDocument.getApplicationDocumentStatus())); 447 canEditPreExtraction = can; 448 } 449 return canEditPreExtraction; 450 } 451 452}