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.web.struts; 017 018 import java.math.BigDecimal; 019 import java.util.Arrays; 020 import java.util.HashMap; 021 import java.util.List; 022 import java.util.Map; 023 024 import javax.servlet.http.HttpServletRequest; 025 026 import org.apache.commons.lang.StringUtils; 027 import org.kuali.kfs.integration.purap.CapitalAssetLocation; 028 import org.kuali.kfs.module.purap.PurapAuthorizationConstants; 029 import org.kuali.kfs.module.purap.PurapConstants; 030 import org.kuali.kfs.module.purap.PurapWorkflowConstants; 031 import org.kuali.kfs.module.purap.PurapConstants.PaymentRequestStatuses; 032 import org.kuali.kfs.module.purap.PurapConstants.PurchaseOrderStatuses; 033 import org.kuali.kfs.module.purap.businessobject.PaymentRequestView; 034 import org.kuali.kfs.module.purap.businessobject.PurApItem; 035 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderAccount; 036 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderCapitalAssetLocation; 037 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem; 038 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItemCapitalAsset; 039 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderVendorQuote; 040 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderVendorStipulation; 041 import org.kuali.kfs.module.purap.businessobject.RequisitionCapitalAssetLocation; 042 import org.kuali.kfs.module.purap.businessobject.SensitiveData; 043 import org.kuali.kfs.module.purap.businessobject.SensitiveDataAssignment; 044 import org.kuali.kfs.module.purap.document.LineItemReceivingDocument; 045 import org.kuali.kfs.module.purap.document.PaymentRequestDocument; 046 import org.kuali.kfs.module.purap.document.PurchaseOrderAmendmentDocument; 047 import org.kuali.kfs.module.purap.document.PurchaseOrderCloseDocument; 048 import org.kuali.kfs.module.purap.document.PurchaseOrderDocument; 049 import org.kuali.kfs.module.purap.document.PurchaseOrderPaymentHoldDocument; 050 import org.kuali.kfs.module.purap.document.PurchaseOrderRemoveHoldDocument; 051 import org.kuali.kfs.module.purap.document.PurchaseOrderReopenDocument; 052 import org.kuali.kfs.module.purap.document.PurchaseOrderRetransmitDocument; 053 import org.kuali.kfs.module.purap.document.PurchaseOrderSplitDocument; 054 import org.kuali.kfs.module.purap.document.PurchaseOrderVoidDocument; 055 import org.kuali.kfs.module.purap.document.service.PaymentRequestService; 056 import org.kuali.kfs.module.purap.document.service.PurchaseOrderService; 057 import org.kuali.kfs.module.purap.document.service.ReceivingService; 058 import org.kuali.kfs.module.purap.util.PurApItemUtils; 059 import org.kuali.kfs.sys.KFSConstants; 060 import org.kuali.kfs.sys.context.SpringContext; 061 import org.kuali.rice.kns.document.authorization.DocumentAuthorizer; 062 import org.kuali.rice.kns.service.DataDictionaryService; 063 import org.kuali.rice.kns.service.DateTimeService; 064 import org.kuali.rice.kns.service.DocumentHelperService; 065 import org.kuali.rice.kns.util.GlobalVariables; 066 import org.kuali.rice.kns.util.KNSConstants; 067 import org.kuali.rice.kns.util.ObjectUtils; 068 import org.kuali.rice.kns.web.ui.ExtraButton; 069 import org.kuali.rice.kns.web.ui.HeaderField; 070 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 071 072 /** 073 * Struts Action Form for Purchase Order document. 074 */ 075 public class PurchaseOrderForm extends PurchasingFormBase { 076 077 protected PurchaseOrderVendorStipulation newPurchaseOrderVendorStipulationLine; 078 protected PurchaseOrderVendorQuote newPurchaseOrderVendorQuote; 079 protected Long awardedVendorNumber; 080 081 // Retransmit. 082 protected String[] retransmitItemsSelected = {}; 083 protected String retransmitTransmissionMethod; 084 protected String retransmitFaxNumber; 085 protected String retransmitHeader; 086 087 // Need this for amendment for accounting line only 088 protected Map accountingLineEditingMode; 089 090 protected String splitNoteText; 091 092 // Assign Sensitive Data related fields 093 protected String sensitiveDataAssignmentReason = null; // reason for current assignment of sensitive data to the PO 094 protected SensitiveDataAssignment lastSensitiveDataAssignment = null; // last sensitive data assignment info for the PO 095 protected SensitiveData newSensitiveDataLine = null; // new sensitive data entry to be added to the PO 096 protected List<SensitiveData> sensitiveDatasAssigned = null; // sensitive data entries currently assigned to the PO 097 098 /** 099 * Constructs a PurchaseOrderForm instance and sets up the appropriately casted document. 100 */ 101 public PurchaseOrderForm() { 102 super(); 103 104 setNewPurchaseOrderVendorStipulationLine(new PurchaseOrderVendorStipulation()); 105 setNewPurchaseOrderVendorQuote(new PurchaseOrderVendorQuote()); 106 this.accountingLineEditingMode = new HashMap(); 107 } 108 109 @Override 110 protected String getDefaultDocumentTypeName() { 111 return "PO"; 112 } 113 114 public Map getAccountingLineEditingMode() { 115 return accountingLineEditingMode; 116 } 117 118 public void setAccountingLineEditingMode(Map accountingLineEditingMode) { 119 this.accountingLineEditingMode = accountingLineEditingMode; 120 } 121 122 public Long getAwardedVendorNumber() { 123 return awardedVendorNumber; 124 } 125 126 public void setAwardedVendorNumber(Long awardedVendorNumber) { 127 this.awardedVendorNumber = awardedVendorNumber; 128 } 129 130 public PurchaseOrderVendorStipulation getNewPurchaseOrderVendorStipulationLine() { 131 return newPurchaseOrderVendorStipulationLine; 132 } 133 134 public void setNewPurchaseOrderVendorStipulationLine(PurchaseOrderVendorStipulation newPurchaseOrderVendorStipulationLine) { 135 this.newPurchaseOrderVendorStipulationLine = newPurchaseOrderVendorStipulationLine; 136 } 137 138 public PurchaseOrderVendorQuote getNewPurchaseOrderVendorQuote() { 139 return newPurchaseOrderVendorQuote; 140 } 141 142 public void setNewPurchaseOrderVendorQuote(PurchaseOrderVendorQuote newPurchaseOrderVendorQuote) { 143 this.newPurchaseOrderVendorQuote = newPurchaseOrderVendorQuote; 144 } 145 146 public String[] getRetransmitItemsSelected() { 147 return retransmitItemsSelected; 148 } 149 150 public void setRetransmitItemsSelected(String[] retransmitItemsSelected) { 151 this.retransmitItemsSelected = retransmitItemsSelected; 152 } 153 154 public PurchaseOrderDocument getPurchaseOrderDocument() { 155 return (PurchaseOrderDocument) getDocument(); 156 } 157 158 public void setPurchaseOrderDocument(PurchaseOrderDocument purchaseOrderDocument) { 159 setDocument(purchaseOrderDocument); 160 } 161 162 public String getSplitNoteText() { 163 return splitNoteText; 164 } 165 166 public void setSplitNoteText(String splitNoteText) { 167 this.splitNoteText = splitNoteText; 168 } 169 170 public String getSensitiveDataAssignmentReason() { 171 return sensitiveDataAssignmentReason; 172 } 173 174 public void setSensitiveDataAssignmentReason(String sensitiveDataAssignmentReason) { 175 this.sensitiveDataAssignmentReason = sensitiveDataAssignmentReason; 176 } 177 178 public SensitiveDataAssignment getLastSensitiveDataAssignment() { 179 return lastSensitiveDataAssignment; 180 } 181 182 public void setLastSensitiveDataAssignment(SensitiveDataAssignment lastSensitiveDataAssignment) { 183 this.lastSensitiveDataAssignment = lastSensitiveDataAssignment; 184 } 185 186 public SensitiveData getNewSensitiveDataLine() { 187 return newSensitiveDataLine; 188 } 189 190 public void setNewSensitiveDataLine(SensitiveData newSensitiveDataLine) { 191 this.newSensitiveDataLine = newSensitiveDataLine; 192 } 193 194 public List<SensitiveData> getSensitiveDatasAssigned() { 195 return sensitiveDatasAssigned; 196 } 197 198 public void setSensitiveDatasAssigned(List<SensitiveData> poSensitiveData) { 199 this.sensitiveDatasAssigned = poSensitiveData; 200 } 201 202 @Override 203 public Class getCapitalAssetLocationClass() { 204 return PurchaseOrderCapitalAssetLocation.class; 205 } 206 207 @Override 208 public Class getItemCapitalAssetClass() { 209 return PurchaseOrderItemCapitalAsset.class; 210 } 211 212 @Override 213 public CapitalAssetLocation setupNewPurchasingCapitalAssetLocationLine() { 214 CapitalAssetLocation location = new RequisitionCapitalAssetLocation(); 215 return location; 216 } 217 218 /** 219 * @see org.kuali.kfs.module.purap.document.web.struts.PurchasingFormBase#setupNewPurchasingItemLine() 220 */ 221 @Override 222 public PurApItem setupNewPurchasingItemLine() { 223 return new PurchaseOrderItem(); 224 } 225 226 /** 227 * @see org.kuali.kfs.module.purap.document.web.struts.PurchasingFormBase#setupNewPurchasingAccountingLine() 228 */ 229 @Override 230 public PurchaseOrderAccount setupNewPurchasingAccountingLine() { 231 return new PurchaseOrderAccount(); 232 } 233 234 /** 235 * @see org.kuali.kfs.module.purap.document.web.struts.PurchasingFormBase#setupNewAccountDistributionAccountingLine() 236 */ 237 @Override 238 public PurchaseOrderAccount setupNewAccountDistributionAccountingLine() { 239 PurchaseOrderAccount account = setupNewPurchasingAccountingLine(); 240 account.setAccountLinePercent(new BigDecimal(100)); 241 return account; 242 } 243 244 public boolean isReadOnlyReceivingRequired() { 245 246 PurchaseOrderDocument poDoc = getPurchaseOrderDocument(); 247 248 if (poDoc instanceof PurchaseOrderAmendmentDocument){ 249 if (!poDoc.isReceivingDocumentRequiredIndicator()){ 250 return SpringContext.getBean(PaymentRequestService.class).hasActivePaymentRequestsForPurchaseOrder(poDoc.getPurapDocumentIdentifier()); 251 }else{ 252 return true; 253 } 254 } 255 256 return false; 257 } 258 259 /** 260 * Returns the new Purchase Order Vendor Stipulation Line and resets it. 261 * 262 * @return the new Purchase Order Vendor Stipulation Line. 263 */ 264 public PurchaseOrderVendorStipulation getAndResetNewPurchaseOrderVendorStipulationLine() { 265 PurchaseOrderVendorStipulation aPurchaseOrderVendorStipulationLine = getNewPurchaseOrderVendorStipulationLine(); 266 setNewPurchaseOrderVendorStipulationLine(new PurchaseOrderVendorStipulation()); 267 268 aPurchaseOrderVendorStipulationLine.setDocumentNumber(getPurchaseOrderDocument().getDocumentNumber()); 269 aPurchaseOrderVendorStipulationLine.setVendorStipulationAuthorEmployeeIdentifier(GlobalVariables.getUserSession().getPerson().getPrincipalId()); 270 aPurchaseOrderVendorStipulationLine.setVendorStipulationCreateDate(SpringContext.getBean(DateTimeService.class).getCurrentSqlDate()); 271 272 return aPurchaseOrderVendorStipulationLine; 273 } 274 275 public String getStatusChange() { 276 if (StringUtils.isNotEmpty(getPurchaseOrderDocument().getStatusChange())){ 277 return getPurchaseOrderDocument().getStatusChange(); 278 } else { 279 if (StringUtils.equals(getPurchaseOrderDocument().getStatusCode(),PurchaseOrderStatuses.IN_PROCESS)){ 280 return PurchaseOrderStatuses.IN_PROCESS; 281 } else if (StringUtils.equals(getPurchaseOrderDocument().getStatusCode(),PurchaseOrderStatuses.WAITING_FOR_DEPARTMENT)){ 282 return PurchaseOrderStatuses.WAITING_FOR_DEPARTMENT; 283 }else if (StringUtils.equals(getPurchaseOrderDocument().getStatusCode(),PurchaseOrderStatuses.WAITING_FOR_VENDOR)){ 284 return PurchaseOrderStatuses.WAITING_FOR_VENDOR; 285 }else{ 286 return null; 287 } 288 } 289 } 290 291 public void setStatusChange(String statusChange) { 292 getPurchaseOrderDocument().setStatusChange(statusChange); 293 } 294 295 /** 296 * @see org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase#shouldMethodToCallParameterBeUsed(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest) 297 */ 298 @Override 299 public boolean shouldMethodToCallParameterBeUsed(String methodToCallParameterName, String methodToCallParameterValue, HttpServletRequest request) { 300 List<String> methodToCallList = Arrays.asList(new String[]{"printPurchaseOrderPDFOnly", "printingRetransmitPoOnly", "printPoQuoteListOnly"}); 301 302 if (KNSConstants.DISPATCH_REQUEST_PARAMETER.equals(methodToCallParameterName) && methodToCallList.contains(methodToCallParameterValue)) { 303 return true; 304 } 305 return super.shouldMethodToCallParameterBeUsed(methodToCallParameterName, methodToCallParameterValue, request); 306 } 307 308 @Override 309 public void populateHeaderFields(KualiWorkflowDocument workflowDocument) { 310 super.populateHeaderFields(workflowDocument); 311 if (ObjectUtils.isNotNull(getPurchaseOrderDocument().getPurapDocumentIdentifier())) { 312 String poIDstr = getPurchaseOrderDocument().getPurapDocumentIdentifier().toString(); 313 if (getPurchaseOrderDocument().getNeedWarning()) { 314 poIDstr += " UNAPPROVED"; 315 } 316 getDocInfo().add(new HeaderField("DataDictionary.PurchaseOrderDocument.attributes.purapDocumentIdentifier", poIDstr)); 317 } 318 else { 319 getDocInfo().add(new HeaderField("DataDictionary.PurchaseOrderDocument.attributes.purapDocumentIdentifier", "Not Available")); 320 } 321 if (ObjectUtils.isNotNull(getPurchaseOrderDocument().getStatus())) { 322 getDocInfo().add(new HeaderField("DataDictionary.PurchaseOrderDocument.attributes.statusCode", ((PurchaseOrderDocument) this.getDocument()).getStatus().getStatusDescription())); 323 } 324 else { 325 getDocInfo().add(new HeaderField("DataDictionary.PurchaseOrderDocument.attributes.statusCode", "Not Available")); 326 } 327 } 328 329 /** 330 * @see org.kuali.kfs.sys.web.struts.KualiAccountingDocumentFormBase#populate(javax.servlet.http.HttpServletRequest) 331 */ 332 @Override 333 public void populate(HttpServletRequest request) { 334 PurchaseOrderDocument po = (PurchaseOrderDocument) this.getDocument(); 335 336 // call this to make sure it's refreshed from the database if need be since the populate setter doesn't do that 337 po.getDocumentBusinessObject(); 338 339 super.populate(request); 340 341 if (ObjectUtils.isNotNull(po.getPurapDocumentIdentifier())) { 342 po.refreshDocumentBusinessObject(); 343 } 344 345 for (org.kuali.rice.kns.bo.Note note : (java.util.List<org.kuali.rice.kns.bo.Note>) po.getDocumentBusinessObject().getBoNotes()) { 346 note.refreshReferenceObject("attachment"); 347 } 348 } 349 350 /** 351 * Processes validation rules having to do with any payment requests that the given purchase order may have. Specifically, 352 * validates that at least one payment request exists, and makes further checks about the status of such payment requests. 353 * 354 * @param document A PurchaseOrderDocument 355 * @return True if the document passes all the validations. 356 */ 357 protected boolean processPaymentRequestRulesForCanClose(PurchaseOrderDocument document) { 358 boolean valid = true; 359 // The PO must have at least one PREQ against it. 360 Integer poDocId = document.getPurapDocumentIdentifier(); 361 List<PaymentRequestDocument> pReqs = SpringContext.getBean(PaymentRequestService.class).getPaymentRequestsByPurchaseOrderId(poDocId); 362 if (ObjectUtils.isNotNull(pReqs)) { 363 if (pReqs.size() == 0) { 364 valid = false; 365 } 366 else { 367 boolean checkInProcess = true; 368 boolean hasInProcess = false; 369 370 for (PaymentRequestDocument pReq : pReqs) { 371 // skip exception docs 372 if (pReq.getDocumentHeader().getWorkflowDocument().stateIsException()) { 373 continue; 374 } 375 // TODO NOTE for below, this could/should be changed to look at the first route level after full entry instead of 376 // being tied to AwaitingFiscal (in case full entry is moved) 377 // look for a doc that is currently routing, that will probably be the one that called this close if called from 378 // preq (with close po box) 379 if (StringUtils.equalsIgnoreCase(pReq.getStatusCode(), PaymentRequestStatuses.AWAITING_FISCAL_REVIEW) && !StringUtils.equalsIgnoreCase(pReq.getDocumentHeader().getWorkflowDocument().getCurrentRouteNodeNames(), PurapWorkflowConstants.PaymentRequestDocument.NodeDetailEnum.ACCOUNT_REVIEW.getName())) { 380 // terminate the search since this close doc is probably being called by this doc, a doc should never be In 381 // Process and enroute in any other case 382 checkInProcess = false; 383 break; 384 } 385 if (StringUtils.equalsIgnoreCase(pReq.getStatusCode(), PaymentRequestStatuses.IN_PROCESS)) { 386 hasInProcess = true; 387 } 388 } 389 if (checkInProcess && hasInProcess) { 390 valid = false; 391 } 392 } 393 } 394 395 return valid; 396 } 397 398 /** 399 * Determines whether to display the amend button for the purchase order document. The document status must be open, and the 400 * purchase order must be current and not pending, and the user must be in purchasing group. These are same as the conditions 401 * for displaying the payment hold button. In addition to these conditions, we also have to check that there is no In Process 402 * Payment Requests nor Credit Memos associated with the PO. 403 * 404 * @return boolean true if the amend button can be displayed. 405 */ 406 protected boolean canAmend() { 407 boolean can = SpringContext.getBean(PurchaseOrderService.class).isPurchaseOrderOpenForProcessing(getPurchaseOrderDocument()); 408 409 // check user authorization 410 if (can) { 411 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 412 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_AMENDMENT, GlobalVariables.getUserSession().getPerson()); 413 } 414 415 return can; 416 } 417 418 /** 419 * Determines whether to display the void button for the purchase order document. Conditions: 420 * PO is in Pending Print status, or is in Open status and has no PREQs against it; 421 * PO's current indicator is true and pending indicator is false; 422 * and the user is a member of the purchasing group). 423 * 424 * @return boolean true if the void button can be displayed. 425 */ 426 protected boolean canVoid() { 427 // check PO status etc 428 boolean can = getPurchaseOrderDocument().isPurchaseOrderCurrentIndicator() && !getPurchaseOrderDocument().isPendingActionIndicator(); 429 430 if (can) { 431 boolean pendingPrint = PurchaseOrderStatuses.PENDING_PRINT.equals(getPurchaseOrderDocument().getStatusCode()); 432 boolean open = PurchaseOrderStatuses.OPEN.equals(getPurchaseOrderDocument().getStatusCode()); 433 boolean errorCxml = PurchaseOrderStatuses.CXML_ERROR.equals(getPurchaseOrderDocument().getStatusCode()); 434 boolean errorFax = PurchaseOrderStatuses.FAX_ERROR.equals(getPurchaseOrderDocument().getStatusCode()); 435 436 List<PaymentRequestView> preqViews = getPurchaseOrderDocument().getRelatedViews().getRelatedPaymentRequestViews(); 437 boolean hasPaymentRequest = preqViews != null && preqViews.size() > 0; 438 439 can = pendingPrint || (open && !hasPaymentRequest) || errorCxml || errorFax; 440 } 441 442 // check user authorization 443 if (can) { 444 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 445 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_VOID, GlobalVariables.getUserSession().getPerson()); 446 } 447 448 return can; 449 } 450 451 /** 452 * Determines whether to display the close order button to close the purchase order document. Conditions: 453 * PO must be in Open status; must have at least one Payment Request in any status other than "In Process", 454 * and the PO cannot have any Payment Requests in "In Process" status. 455 * This button is available to all faculty/staff. 456 * 457 * @return boolean true if the close order button can be displayed. 458 */ 459 protected boolean canClose() { 460 // check PO status etc 461 boolean can = PurchaseOrderStatuses.OPEN.equals(getPurchaseOrderDocument().getStatusCode()); 462 can = can && getPurchaseOrderDocument().isPurchaseOrderCurrentIndicator() && !getPurchaseOrderDocument().isPendingActionIndicator(); 463 can = can && processPaymentRequestRulesForCanClose(getPurchaseOrderDocument()); 464 465 // check user authorization 466 if (can) { 467 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 468 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_CLOSE, GlobalVariables.getUserSession().getPerson()); 469 } 470 471 return can; 472 } 473 474 /** 475 * Determines whether to display the open order button to reopen the purchase order document. 476 * Conditions: PO status is close, PO is current and not pending, and the user is in purchasing group. 477 * 478 * @return boolean true if the reopen order button can be displayed. 479 */ 480 protected boolean canReopen() { 481 // check PO status etc 482 boolean can = PurchaseOrderStatuses.CLOSED.equals(getPurchaseOrderDocument().getStatusCode()); 483 can = can && getPurchaseOrderDocument().isPurchaseOrderCurrentIndicator() && !getPurchaseOrderDocument().isPendingActionIndicator(); 484 485 // check user authorization 486 if (can) { 487 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 488 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_REOPEN, GlobalVariables.getUserSession().getPerson()); 489 } 490 491 return can; 492 } 493 494 /** 495 * Determines whether to display the payment hold buttons for the purchase order document. 496 * Conditions: PO status must be open, must be current and not pending, and the user must be in purchasing group. 497 * 498 * @return boolean true if the payment hold button can be displayed. 499 */ 500 protected boolean canHoldPayment() { 501 // check PO status etc 502 boolean can = PurchaseOrderStatuses.OPEN.equals(getPurchaseOrderDocument().getStatusCode()); 503 can = can && getPurchaseOrderDocument().isPurchaseOrderCurrentIndicator() && !getPurchaseOrderDocument().isPendingActionIndicator(); 504 505 // check user authorization 506 if (can) { 507 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 508 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_PAYMENT_HOLD, GlobalVariables.getUserSession().getPerson()); 509 } 510 511 return can; 512 } 513 514 /** 515 * Determines whether to display the remove hold button for the purchase order document. 516 * Conditions are: PO status must be payment hold, must be current and not pending, and the user must be in purchasing group. 517 * 518 * @return boolean true if the remove hold button can be displayed. 519 */ 520 protected boolean canRemoveHold() { 521 // check PO status etc 522 boolean can = PurchaseOrderStatuses.PAYMENT_HOLD.equals(getPurchaseOrderDocument().getStatusCode()); 523 can = can && getPurchaseOrderDocument().isPurchaseOrderCurrentIndicator() && !getPurchaseOrderDocument().isPendingActionIndicator(); 524 525 // check user authorization 526 if (can) { 527 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 528 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_REMOVE_HOLD, GlobalVariables.getUserSession().getPerson()); 529 } 530 531 return can; 532 } 533 534 /** 535 * Determines whether to display the retransmit button. Conditions: 536 * PO status must be open, and must be current and not pending, and the last transmit date must not be null. 537 * If the purchase order is an Automated Purchase Order (APO) and does not have any sensitive data set to true, 538 * then any users can see the retransmit button, otherwise, only users in the purchasing group can see it. 539 * 540 * @return boolean true if the retransmit button can be displayed. 541 */ 542 protected boolean canRetransmit() { 543 // check PO status etc 544 boolean can = PurchaseOrderStatuses.OPEN.equals(getPurchaseOrderDocument().getStatusCode()); 545 can = can && getPurchaseOrderDocument().isPurchaseOrderCurrentIndicator() && !getPurchaseOrderDocument().isPendingActionIndicator(); 546 can = can && getPurchaseOrderDocument().getPurchaseOrderLastTransmitTimestamp() != null; 547 can = can && !PurapConstants.RequisitionSources.B2B.equals(getPurchaseOrderDocument().getRequisitionSourceCode()); 548 can = can && !editingMode.containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.DISPLAY_RETRANSMIT_TAB); 549 550 if (!can) { 551 return false; 552 } 553 554 // check user authorization 555 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 556 if (getPurchaseOrderDocument().getPurchaseOrderAutomaticIndicator()) { 557 // for APO use authorization for PurchaseOrderRetransmitDocument, which is anybody 558 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_RETRANSMIT, GlobalVariables.getUserSession().getPerson()); 559 } 560 else { 561 // for NON_APO use authorization for PurchaseOrderDocument, which is purchasing user 562 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER, GlobalVariables.getUserSession().getPerson()); 563 } 564 565 return can; 566 } 567 568 /** 569 * Determines whether to display the button to print the pdf on a retransmit document. 570 * We're currently sharing the same button image as the button for creating a retransmit document but this may change someday. 571 * This button should only appear on Retransmit Document. If it is an Automated Purchase Order (APO) 572 * then any users can see this button, otherwise, only users in the purchasing group can see it. 573 * 574 * @return boolean true if the print retransmit button can be displayed. 575 */ 576 protected boolean canPrintRetransmit() { 577 // check PO status etc 578 boolean can = getPurchaseOrderDocument().getDocumentHeader().getWorkflowDocument().getDocumentType().equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_RETRANSMIT_DOCUMENT); 579 can = can && editingMode.containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.DISPLAY_RETRANSMIT_TAB); 580 581 if (can) { 582 // check user authorization: same as retransmit init, since whoever can init retransmit PO shall be able to print 583 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 584 if (getPurchaseOrderDocument().getPurchaseOrderAutomaticIndicator()) { 585 // for APO use authorization for PurchaseOrderRetransmitDocument, which is anybody 586 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_RETRANSMIT, GlobalVariables.getUserSession().getPerson()); 587 } 588 else { 589 // for NON_APO use authorization for PurchaseOrderDocument, which is purchasing user 590 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER, GlobalVariables.getUserSession().getPerson()); 591 } 592 } 593 594 return can; 595 } 596 597 /** 598 * Determines if a Split PO Document can be created from this purchase order. Conditions: 599 * The parent PO status is either "In Process" or "Awaiting Purchasing Review"; requisition source is not B2B; has at least 2 items, 600 * and PO is not in the process of being split; user must be in purchasing group. 601 * 602 * @return boolean true if the split PO button can be displayed. 603 */ 604 protected boolean canSplitPo() { 605 // PO must be in either "In Process" or "Awaiting Purchasing Review" 606 boolean can = PurchaseOrderStatuses.IN_PROCESS.equals(getPurchaseOrderDocument().getStatusCode()); 607 can = can && !getPurchaseOrderDocument().getDocumentHeader().getWorkflowDocument().stateIsEnroute(); 608 can = can || PurchaseOrderStatuses.AWAIT_PURCHASING_REVIEW.equals(getPurchaseOrderDocument().getStatusCode()); 609 610 // can't split a SplitPO Document, according to new specs 611 can = can && !(getPurchaseOrderDocument() instanceof PurchaseOrderSplitDocument); 612 613 // can't initiate another split during the splitting process. 614 can = can && !editingMode.containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.SPLITTING_ITEM_SELECTION); 615 616 // Requisition Source must not be B2B. 617 can = can && !getPurchaseOrderDocument().getRequisitionSourceCode().equals(PurapConstants.RequisitionSources.B2B); 618 619 // PO must have more than one line item. 620 if (can) { 621 List<PurApItem> items = (List<PurApItem>)getPurchaseOrderDocument().getItems(); 622 int itemsBelowTheLine = PurApItemUtils.countBelowTheLineItems(items); 623 can = items.size() - itemsBelowTheLine > 1; 624 } 625 626 // check user authorization 627 if (can) { 628 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 629 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_SPLIT, GlobalVariables.getUserSession().getPerson()); 630 } 631 632 return can; 633 } 634 635 /** 636 * Determines whether the PO is in a status that signifies it has enough information to generate a Split PO. 637 * 638 * @return True if the PO can continue to be split. 639 */ 640 protected boolean canContinuePoSplit() { 641 boolean can = editingMode.containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.SPLITTING_ITEM_SELECTION); 642 643 // check user authorization 644 if (can) { 645 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 646 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER_SPLIT, GlobalVariables.getUserSession().getPerson()); 647 } 648 649 return can; 650 } 651 652 /** 653 * Determines if a line item receiving document can be created for the purchase order. 654 * 655 * @return boolean true if the receiving document button can be displayed. 656 */ 657 protected boolean canCreateReceiving() { 658 // check PO status and item info 659 boolean can = SpringContext.getBean(ReceivingService.class).canCreateLineItemReceivingDocument(getPurchaseOrderDocument()); 660 661 // check user authorization 662 if (can) { 663 DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(getPurchaseOrderDocument()); 664 can = documentAuthorizer.canInitiate(KFSConstants.FinancialDocumentTypeCodes.LINE_ITEM_RECEIVING, GlobalVariables.getUserSession().getPerson()); 665 } 666 667 return can; 668 } 669 670 /** 671 * Creates a MAP for all the buttons to appear on the Purchase Order Form, and sets the attributes of these buttons. 672 * 673 * @return the button map created. 674 */ 675 protected Map<String, ExtraButton> createButtonsMap() { 676 HashMap<String, ExtraButton> result = new HashMap<String, ExtraButton>(); 677 678 // Retransmit button 679 ExtraButton retransmitButton = new ExtraButton(); 680 retransmitButton.setExtraButtonProperty("methodToCall.retransmitPo"); 681 retransmitButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_retransmit.gif"); 682 retransmitButton.setExtraButtonAltText("Retransmit"); 683 684 // Printing Retransmit button 685 ExtraButton printingRetransmitButton = new ExtraButton(); 686 printingRetransmitButton.setExtraButtonProperty("methodToCall.printingRetransmitPo"); 687 printingRetransmitButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_retransmit.gif"); 688 printingRetransmitButton.setExtraButtonAltText("PrintingRetransmit"); 689 690 // Printing Preview button 691 ExtraButton printingPreviewButton = new ExtraButton(); 692 printingPreviewButton.setExtraButtonProperty("methodToCall.printingPreviewPo"); 693 printingPreviewButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_previewpf.gif"); 694 printingPreviewButton.setExtraButtonAltText("PrintingPreview"); 695 696 // Print button 697 ExtraButton printButton = new ExtraButton(); 698 printButton.setExtraButtonProperty("methodToCall.firstTransmitPrintPo"); 699 printButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_print.gif"); 700 printButton.setExtraButtonAltText("Print"); 701 702 // Reopen PO button 703 ExtraButton reopenButton = new ExtraButton(); 704 reopenButton.setExtraButtonProperty("methodToCall.reopenPo"); 705 reopenButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_openorder.gif"); 706 reopenButton.setExtraButtonAltText("Reopen"); 707 708 // Close PO button 709 ExtraButton closeButton = new ExtraButton(); 710 closeButton.setExtraButtonProperty("methodToCall.closePo"); 711 closeButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_closeorder.gif"); 712 closeButton.setExtraButtonAltText("Close PO"); 713 714 // Void PO button 715 ExtraButton voidButton = new ExtraButton(); 716 voidButton.setExtraButtonProperty("methodToCall.voidPo"); 717 voidButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_voidorder.gif"); 718 voidButton.setExtraButtonAltText("Void PO"); 719 720 // Payment Hold PO button 721 ExtraButton paymentHoldButton = new ExtraButton(); 722 paymentHoldButton.setExtraButtonProperty("methodToCall.paymentHoldPo"); 723 paymentHoldButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_paymenthold.gif"); 724 paymentHoldButton.setExtraButtonAltText("Payment Hold"); 725 726 // Amend button 727 ExtraButton amendButton = new ExtraButton(); 728 amendButton.setExtraButtonProperty("methodToCall.amendPo"); 729 amendButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_amend.gif"); 730 amendButton.setExtraButtonAltText("Amend"); 731 732 // Remove Hold button 733 ExtraButton removeHoldButton = new ExtraButton(); 734 removeHoldButton.setExtraButtonProperty("methodToCall.removeHoldPo"); 735 removeHoldButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_removehold.gif"); 736 removeHoldButton.setExtraButtonAltText("Remove Hold"); 737 738 // Resend PO Cxml button 739 ExtraButton resendPoCxmlButton = new ExtraButton(); 740 resendPoCxmlButton.setExtraButtonProperty("methodToCall.resendPoCxml"); 741 resendPoCxmlButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_resendpo.gif"); 742 resendPoCxmlButton.setExtraButtonAltText("Resend PO CXML"); 743 744 // Receiving button 745 ExtraButton receivingButton = new ExtraButton(); 746 receivingButton.setExtraButtonProperty("methodToCall.createReceivingLine"); 747 receivingButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_receiving.gif"); 748 receivingButton.setExtraButtonAltText("Receiving"); 749 750 // Split PO button 751 ExtraButton splitPoButton = new ExtraButton(); 752 splitPoButton.setExtraButtonProperty("methodToCall.splitPo"); 753 splitPoButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_splitorder.gif"); 754 splitPoButton.setExtraButtonAltText("Split this PO"); 755 756 // Continue button 757 ExtraButton continueButton = new ExtraButton(); 758 continueButton.setExtraButtonProperty("methodToCall.continuePurchaseOrderSplit"); 759 continueButton.setExtraButtonSource("${" + KFSConstants.RICE_EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_continue.gif"); 760 continueButton.setExtraButtonAltText("Continue"); 761 762 // Cancel Split button 763 ExtraButton cancelSplitButton = new ExtraButton(); 764 cancelSplitButton.setExtraButtonProperty("methodToCall.cancelPurchaseOrderSplit"); 765 cancelSplitButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_cancelsplit.gif"); 766 cancelSplitButton.setExtraButtonAltText("Cancel Splitting the PO"); 767 768 // Assign Sensitive Data button 769 ExtraButton assignSensitiveDataButton = new ExtraButton(); 770 assignSensitiveDataButton.setExtraButtonProperty("methodToCall.assignSensitiveData"); 771 assignSensitiveDataButton.setExtraButtonSource("${" + KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_sensitivedata.gif "); 772 assignSensitiveDataButton.setExtraButtonAltText("Assign sensitive data to the PO"); 773 774 // Submit Sensitive Data Assignment button 775 ExtraButton submitSensitiveDataButton = new ExtraButton(); 776 submitSensitiveDataButton.setExtraButtonProperty("methodToCall.submitSensitiveData"); 777 submitSensitiveDataButton.setExtraButtonSource("${" + KFSConstants.RICE_EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_submit.gif"); 778 submitSensitiveDataButton.setExtraButtonAltText("Submit sensitive data assignment"); 779 780 // Cancel Sensitive Data Assignment button 781 ExtraButton cancelSensitiveDataButton = new ExtraButton(); 782 cancelSensitiveDataButton.setExtraButtonProperty("methodToCall.cancelSensitiveData"); 783 cancelSensitiveDataButton.setExtraButtonSource("${" + KFSConstants.RICE_EXTERNALIZABLE_IMAGES_URL_KEY + "}buttonsmall_cancel.gif"); 784 cancelSensitiveDataButton.setExtraButtonAltText("Cancel sensitive data assignment"); 785 786 result.put(retransmitButton.getExtraButtonProperty(), retransmitButton); 787 result.put(printingRetransmitButton.getExtraButtonProperty(), printingRetransmitButton); 788 result.put(printingPreviewButton.getExtraButtonProperty(), printingPreviewButton); 789 result.put(printButton.getExtraButtonProperty(), printButton); 790 result.put(reopenButton.getExtraButtonProperty(), reopenButton); 791 result.put(closeButton.getExtraButtonProperty(), closeButton); 792 result.put(voidButton.getExtraButtonProperty(), voidButton); 793 result.put(paymentHoldButton.getExtraButtonProperty(), paymentHoldButton); 794 result.put(amendButton.getExtraButtonProperty(), amendButton); 795 result.put(removeHoldButton.getExtraButtonProperty(), removeHoldButton); 796 result.put(receivingButton.getExtraButtonProperty(), receivingButton); 797 result.put(splitPoButton.getExtraButtonProperty(), splitPoButton); 798 result.put(continueButton.getExtraButtonProperty(), continueButton); 799 result.put(cancelSplitButton.getExtraButtonProperty(), cancelSplitButton); 800 result.put(assignSensitiveDataButton.getExtraButtonProperty(), assignSensitiveDataButton); 801 result.put(submitSensitiveDataButton.getExtraButtonProperty(), submitSensitiveDataButton); 802 result.put(cancelSensitiveDataButton.getExtraButtonProperty(), cancelSensitiveDataButton); 803 result.put(resendPoCxmlButton.getExtraButtonProperty(), resendPoCxmlButton); 804 805 return result; 806 } 807 808 /** 809 * Override the superclass method to add appropriate buttons for 810 * PurchaseOrderDocument. 811 * 812 * @see org.kuali.rice.kns.web.struts.form.KualiForm#getExtraButtons() 813 */ 814 @Override 815 public List<ExtraButton> getExtraButtons() { 816 super.getExtraButtons(); 817 Map buttonsMap = createButtonsMap(); 818 819 if (getEditingMode().containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.ASSIGN_SENSITIVE_DATA)) { 820 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.assignSensitiveData")); 821 if (getPurchaseOrderDocument().getAssigningSensitiveData()) { 822 // no other extra buttons except the following shall appear on "Assign Sensitive Data" page 823 // and these buttons use the same permissions as the "Assign Sensitive Data" button 824 extraButtons.clear(); 825 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.submitSensitiveData")); 826 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.cancelSensitiveData")); 827 return extraButtons; 828 } 829 } 830 831 if (getEditingMode().containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.PREVIEW_PRINT_PURCHASE_ORDER)) { 832 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.printingPreviewPo")); 833 } 834 835 if (getEditingMode().containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.PRINT_PURCHASE_ORDER)) { 836 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.firstTransmitPrintPo")); 837 } 838 839 if (getEditingMode().containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.RESEND_PURCHASE_ORDER)) { 840 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.resendPoCxml")); 841 } 842 843 if (canRetransmit()) { 844 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.retransmitPo")); 845 } 846 847 if (canPrintRetransmit()) { 848 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.printingRetransmitPo")); 849 } 850 851 if (canReopen()) { 852 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.reopenPo")); 853 } 854 855 if (canClose()) { 856 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.closePo")); 857 } 858 859 if (canHoldPayment()) { 860 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.paymentHoldPo")); 861 } 862 863 if (canAmend()) { 864 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.amendPo")); 865 } 866 867 if (canVoid()) { 868 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.voidPo")); 869 } 870 871 if (canRemoveHold()) { 872 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.removeHoldPo")); 873 } 874 875 if (canCreateReceiving()) { 876 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.createReceivingLine")); 877 } 878 879 if (canSplitPo()) { 880 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.splitPo")); 881 } 882 883 if (canContinuePoSplit()) { 884 extraButtons.clear(); 885 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.continuePurchaseOrderSplit")); 886 extraButtons.add((ExtraButton) buttonsMap.get("methodToCall.cancelPurchaseOrderSplit")); 887 } 888 889 return extraButtons; 890 } 891 892 } 893