View Javadoc
1   /*
2    * Copyright 2008-2009 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.module.purap.document.authorization;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.ole.module.purap.PurapAuthorizationConstants;
20  import org.kuali.ole.module.purap.PurapAuthorizationConstants.PurchaseOrderEditMode;
21  import org.kuali.ole.module.purap.PurapConstants;
22  import org.kuali.ole.module.purap.PurapConstants.PurchaseOrderStatuses;
23  import org.kuali.ole.module.purap.PurapConstants.RequisitionSources;
24  import org.kuali.ole.module.purap.PurapParameterConstants;
25  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
26  import org.kuali.ole.module.purap.document.service.PurapService;
27  import org.kuali.ole.sys.context.SpringContext;
28  import org.kuali.ole.sys.service.impl.OleParameterConstants;
29  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
30  import org.kuali.rice.kew.api.WorkflowDocument;
31  import org.kuali.rice.krad.document.Document;
32  import org.kuali.rice.krad.util.ObjectUtils;
33  
34  import java.util.ArrayList;
35  import java.util.List;
36  import java.util.Set;
37  
38  
39  public class PurchaseOrderDocumentPresentationController extends PurchasingAccountsPayableDocumentPresentationController {
40  
41      @Override
42      public boolean canEdit(Document document) {
43          PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
44  
45          //Check whether the document is created from a requisition.
46          //if not make it editable
47  
48          if (!poDocument.isCreatedFromRequisition()) {
49              return true;
50          }
51  
52          if (!PurchaseOrderStatuses.APPDOC_IN_PROCESS.equals(poDocument.getApplicationDocumentStatus()) &&
53                  !PurchaseOrderStatuses.APPDOC_WAITING_FOR_DEPARTMENT.equals(poDocument.getApplicationDocumentStatus()) &&
54                  !PurchaseOrderStatuses.APPDOC_WAITING_FOR_VENDOR.equals(poDocument.getApplicationDocumentStatus()) &&
55                  !PurchaseOrderStatuses.APPDOC_QUOTE.equals(poDocument.getApplicationDocumentStatus()) &&
56                  !PurchaseOrderStatuses.APPDOC_AWAIT_PURCHASING_REVIEW.equals(poDocument.getApplicationDocumentStatus()) &&
57                  !PurchaseOrderStatuses.APPDOC_AWAIT_NEW_UNORDERED_ITEM_REVIEW.equals(poDocument.getApplicationDocumentStatus()) &&
58                  !PurchaseOrderStatuses.APPDOC_CHANGE_IN_PROCESS.equals(poDocument.getApplicationDocumentStatus())) {
59              return false;
60          }
61          return super.canEdit(document);
62      }
63  
64      @Override
65      public boolean canFyi(Document document) {
66          PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
67          if (PurchaseOrderStatuses.APPDOC_PENDING_PRINT.equals(poDocument.getApplicationDocumentStatus())) {
68              return false;
69          }
70          return super.canFyi(document);
71      }
72  
73      @Override
74      public boolean canCancel(Document document) {
75          PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
76  
77          if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
78              return false;
79          }
80  
81          return super.canCancel(document);
82      }
83  
84      @Override
85      public boolean canClose(Document document) {
86          PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
87  
88          if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
89              return false;
90          }
91  
92          return super.canClose(document);
93      }
94  
95      @Override
96      public boolean canReload(Document document) {
97          PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
98  
99          if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
100             return false;
101         }
102 
103         return super.canReload(document);
104     }
105 
106     @Override
107     public boolean canSave(Document document) {
108         PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
109 
110         if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
111             return false;
112         }
113 
114         return super.canSave(document);
115     }
116 
117     @Override
118     public boolean canRoute(Document document) {
119         PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
120         String statusCode = poDocument.getApplicationDocumentStatus();
121 
122         if (StringUtils.equals(statusCode, PurchaseOrderStatuses.APPDOC_WAITING_FOR_DEPARTMENT) ||
123                 StringUtils.equals(statusCode, PurchaseOrderStatuses.APPDOC_WAITING_FOR_VENDOR) ||
124                 StringUtils.equals(statusCode, PurchaseOrderStatuses.APPDOC_QUOTE)) {
125             return false;
126         }
127 
128         if (poDocument.isPendingSplit()) {
129             return false;
130         }
131 
132         return super.canRoute(document);
133     }
134 
135     @Override
136     public Set<String> getEditModes(Document document) {
137         Set<String> editModes = super.getEditModes(document);
138         PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
139 
140         WorkflowDocument workflowDocument = poDocument.getFinancialSystemDocumentHeader().getWorkflowDocument();
141 
142         String statusCode = poDocument.getApplicationDocumentStatus();
143 
144         editModes.add(PurchaseOrderEditMode.ASSIGN_SENSITIVE_DATA);
145 
146         //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.
147         boolean enableCommodityCode = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_COMMODITY_CODE_IND);
148         if (enableCommodityCode) {
149             editModes.add(PurchaseOrderEditMode.ENABLE_COMMODITY_CODE);
150         }
151 
152         if (poDocument.isCreatedFromRequisition()) {
153             editModes.add(PurchaseOrderEditMode.EDITABLE_FUNDING_SOURCE);
154         }
155 
156         if (canFirstTransmitPrintPo(poDocument)) {
157             editModes.add(PurchaseOrderEditMode.PRINT_PURCHASE_ORDER);
158         }
159 
160         if (canPreviewPrintPo(poDocument)) {
161             editModes.add(PurchaseOrderEditMode.PREVIEW_PRINT_PURCHASE_ORDER);
162         }
163 
164         if (canResendCxml(poDocument)) {
165             editModes.add(PurchaseOrderEditMode.RESEND_PURCHASE_ORDER);
166         }
167 
168         // if vendor has been selected from DB, certain vendor fields are not allowed to be edited
169         if (ObjectUtils.isNotNull(poDocument.getVendorHeaderGeneratedIdentifier())) {
170             editModes.add(PurchaseOrderEditMode.LOCK_VENDOR_ENTRY);
171         }
172 
173         // if B2B purchase order, certain fields are not allowed to be edited
174         if (RequisitionSources.B2B.equals(poDocument.getRequisitionSourceCode())) {
175             editModes.add(PurchaseOrderEditMode.LOCK_B2B_ENTRY);
176         }
177 
178         // if not B2B requisition, users can edit the posting year if within a given amount of time set in a parameter
179         if (!RequisitionSources.B2B.equals(poDocument.getRequisitionSourceCode()) &&
180                 SpringContext.getBean(PurapService.class).allowEncumberNextFiscalYear() &&
181                 (PurchaseOrderStatuses.APPDOC_IN_PROCESS.equals(statusCode) ||
182                         PurchaseOrderStatuses.APPDOC_WAITING_FOR_VENDOR.equals(statusCode) ||
183                         PurchaseOrderStatuses.APPDOC_WAITING_FOR_DEPARTMENT.equals(statusCode) ||
184                         PurchaseOrderStatuses.APPDOC_QUOTE.equals(statusCode) ||
185                         PurchaseOrderStatuses.APPDOC_AWAIT_PURCHASING_REVIEW.equals(statusCode))) {
186             editModes.add(PurchaseOrderEditMode.ALLOW_POSTING_YEAR_ENTRY);
187         }
188 
189         // check if purap tax is enabled
190         boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND);
191         if (salesTaxInd) {
192             editModes.add(PurapAuthorizationConstants.PURAP_TAX_ENABLED);
193 
194             if (poDocument.isUseTaxIndicator()) {
195                 // if use tax, don't allow editing of tax fields
196                 editModes.add(PurchaseOrderEditMode.LOCK_TAX_AMOUNT_ENTRY);
197             } else {
198                 // display the "clear all taxes" button if doc is not using use tax
199                 editModes.add(PurchaseOrderEditMode.CLEAR_ALL_TAXES);
200             }
201         }
202 
203         // set display mode for Receiving Address section according to parameter value
204         boolean displayReceivingAddress = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_RECEIVING_ADDRESS_IND);
205         if (displayReceivingAddress) {
206             editModes.add(PurchaseOrderEditMode.DISPLAY_RECEIVING_ADDRESS);
207         }
208 
209         // PRE_ROUTE_CHANGEABLE mode is used for fields that are editable only before PO is routed
210         // for ex, contract manager, manual status change, and APPDOC_QUOTE etc
211         //if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
212         if (PurchaseOrderStatuses.APPDOC_IN_PROCESS.equals(statusCode) ||
213                 PurchaseOrderStatuses.APPDOC_WAITING_FOR_VENDOR.equals(statusCode) ||
214                 PurchaseOrderStatuses.APPDOC_WAITING_FOR_DEPARTMENT.equals(statusCode) ||
215                 PurchaseOrderStatuses.APPDOC_QUOTE.equals(statusCode)) {
216             editModes.add(PurchaseOrderEditMode.PRE_ROUTE_CHANGEABLE);
217         }
218 
219         // INTERNAL PURCHASING ROUTE LEVEL - Approvers can edit full detail on Purchase Order except they cannot change the CHART/ORG.
220         if (poDocument.isDocumentStoppedInRouteNode(PurapConstants.PurchaseOrderStatuses.NODE_CONTRACT_MANAGEMENT)) {
221             editModes.add(PurchaseOrderEditMode.LOCK_INTERNAL_PURCHASING_ENTRY);
222         }
223 
224         //FIXME figure out how to get this to work
225 //      /**
226 //      * CONTRACTS & GRANTS ROUTE LEVEL, BUDGET OFFICE ROUTE LEVEL, VENDOR TAX ROUTE LEVEL, DOCUMENT TRANSMISSION ROUTE LEVEL,
227 //      * and Adhoc - Approvers in these route levels cannot edit any detail on PO.
228 //      */
229 //      else {
230 //      // VIEW_ENTRY that is already being set is sufficient, but need to remove FULL_ENTRY
231 //      editModeMap.remove(AuthorizationConstants.EditMode.FULL_ENTRY);
232 //      }
233 
234         // Set display mode for Split PO.
235         if (poDocument.isPendingSplit()) {
236             editModes.add(PurchaseOrderEditMode.SPLITTING_ITEM_SELECTION);
237         }
238 
239         return editModes;
240     }
241 
242     /**
243      * Determines whether to display the button to print the pdf for the first time transmit.
244      * Conditions: PO status is Pending Print or the transmission method is changed to PRINT during the amendment.
245      *
246      * @return boolean true if the print first transmit button can be displayed.
247      */
248     protected boolean canFirstTransmitPrintPo(PurchaseOrderDocument poDocument) {
249         // status shall be Pending Print, or the transmission method is changed to PRINT during amendment,
250         boolean can = PurchaseOrderStatuses.APPDOC_PENDING_PRINT.equals(poDocument.getApplicationDocumentStatus());
251         if (!can) {
252             can = PurchaseOrderStatuses.APPDOC_OPEN.equals(poDocument.getApplicationDocumentStatus());
253             can = can && poDocument.getFinancialSystemDocumentHeader().getWorkflowDocument().isFinal();
254             can = can && poDocument.getPurchaseOrderLastTransmitTimestamp() == null;
255             can = can && PurapConstants.POTransmissionMethods.PRINT.equals(poDocument.getPurchaseOrderTransmissionMethodCode());
256         }
257 
258         return can;
259     }
260 
261     /**
262      * Determines whether to display the print preview button for the first time transmit. Conditions are:
263      * available while the document is saved or enroute;
264      * available for only a certain number of PO transmission types which are stored in a parameter (default to PRIN and FAX)
265      *
266      * @return boolean true if the preview print button can be displayed.
267      */
268     protected boolean canPreviewPrintPo(PurchaseOrderDocument poDocument) {
269         // PO is saved or enroute
270         boolean can = poDocument.getFinancialSystemDocumentHeader().getWorkflowDocument().isSaved() || poDocument.getFinancialSystemDocumentHeader().getWorkflowDocument().isEnroute();
271 
272         // transmission method must be one of those specified by the parameter
273         if (can) {
274             List<String> methods = new ArrayList<String>(SpringContext.getBean(ParameterService.class).getParameterValuesAsString(PurchaseOrderDocument.class, PurapParameterConstants.PURAP_PO_PRINT_PREVIEW_TRANSMISSION_METHOD_TYPES));
275             String method = poDocument.getPurchaseOrderTransmissionMethodCode();
276             can = (methods == null || methods.contains(method));
277         }
278 
279         return can;
280     }
281 
282     /**
283      * Determines whether to display the resend po button for the purchase order document.
284      * Conditions: PO status must be error sending cxml and must be current and not pending.
285      *
286      * @return boolean true if the resend po button shall be displayed.
287      */
288     protected boolean canResendCxml(PurchaseOrderDocument poDocument) {
289         // check PO status etc
290         boolean can = PurchaseOrderStatuses.APPDOC_CXML_ERROR.equals(poDocument.getApplicationDocumentStatus());
291         can = can && poDocument.isPurchaseOrderCurrentIndicator() && !poDocument.isPendingActionIndicator();
292 
293         return can;
294     }
295 }