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 }