/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.purap.document.authorization; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.kuali.kfs.module.purap.PurapAuthorizationConstants; import org.kuali.kfs.module.purap.PurapAuthorizationConstants.RequisitionEditMode; import org.kuali.kfs.module.purap.PurapConstants; import org.kuali.kfs.module.purap.PurapConstants.RequisitionSources; import org.kuali.kfs.module.purap.PurapConstants.RequisitionStatuses; import org.kuali.kfs.module.purap.PurapParameterConstants; import org.kuali.kfs.module.purap.businessobject.RequisitionItem; import org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument; import org.kuali.kfs.module.purap.document.RequisitionDocument; import org.kuali.kfs.module.purap.document.service.PurapService; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.service.impl.KfsParameterConstants; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kew.api.WorkflowDocument; import org.kuali.rice.krad.document.Document; import org.kuali.rice.krad.util.ObjectUtils; public class RequisitionDocumentPresentationController extends PurchasingAccountsPayableDocumentPresentationController { @Override public boolean canEdit(Document document) { RequisitionDocument reqDocument = (RequisitionDocument)document; if (!RequisitionStatuses.APPDOC_IN_PROCESS.equals(reqDocument.getApplicationDocumentStatus()) && !RequisitionStatuses.APPDOC_AWAIT_CONTENT_REVIEW.equals(reqDocument.getApplicationDocumentStatus()) && !RequisitionStatuses.APPDOC_AWAIT_HAS_ACCOUNTING_LINES.equals(reqDocument.getApplicationDocumentStatus()) && !RequisitionStatuses.APPDOC_AWAIT_FISCAL_REVIEW.equals(reqDocument.getApplicationDocumentStatus())) { //unless the Requisition is in process, awaiting content, awaiting accounting lines or awaiting fiscal, editing is not allowed return false; } return super.canEdit(document); } @Override public Set<String> getEditModes(Document document) { Set<String> editModes = super.getEditModes(document); RequisitionDocument reqDocument = (RequisitionDocument)document; //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. boolean enableCommodityCode = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_COMMODITY_CODE_IND); if (enableCommodityCode) { editModes.add(RequisitionEditMode.ENABLE_COMMODITY_CODE); } // if vendor has been selected from DB, certain vendor fields are not allowed to be edited if (ObjectUtils.isNotNull(reqDocument.getVendorHeaderGeneratedIdentifier())) { editModes.add(RequisitionEditMode.LOCK_VENDOR_ENTRY); } // if B2B requisition, certain fields are not allowed to be edited if (RequisitionSources.B2B.equals(reqDocument.getRequisitionSourceCode())) { editModes.add(RequisitionEditMode.LOCK_B2B_ENTRY); } // if not B2B requisition, the posting year cannot be edited if within a given amount of time set in a parameter if (!RequisitionSources.B2B.equals(reqDocument.getRequisitionSourceCode()) && SpringContext.getBean(PurapService.class).allowEncumberNextFiscalYear()) { editModes.add(RequisitionEditMode.ALLOW_POSTING_YEAR_ENTRY); } // check if purap tax is enabled boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND); if (salesTaxInd) { editModes.add(PurapAuthorizationConstants.PURAP_TAX_ENABLED); editModes.add(RequisitionEditMode.CLEAR_ALL_TAXES); // always available now if taxes if (reqDocument.isUseTaxIndicator()) { // don't allow tax editing if doc using use tax editModes.add(RequisitionEditMode.LOCK_TAX_AMOUNT_ENTRY); } } // set display mode for Receiving Address section according to parameter value boolean displayReceivingAddress = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_RECEIVING_ADDRESS_IND); if (displayReceivingAddress) { editModes.add(RequisitionEditMode.DISPLAY_RECEIVING_ADDRESS); } // set display mode for Address to Vendor section according to parameter value boolean lockAddressToVendor = !SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(PurapConstants.PURAP_NAMESPACE, "Requisition", PurapParameterConstants.ENABLE_ADDRESS_TO_VENDOR_SELECTION_IND); if (lockAddressToVendor) { editModes.add(RequisitionEditMode.LOCK_ADDRESS_TO_VENDOR); } // CONTENT ROUTE LEVEL - Approvers can edit full detail on Requisition except they cannot change the CHART/ORG. //to be removed //for app doc status if (reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_CONTENT_REVIEW) || reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_HAS_ACCOUNTING_LINES)) { editModes.add(RequisitionEditMode.LOCK_CONTENT_ENTRY); } // FISCAL OFFICER ROUTE LEVEL - Approvers can edit only the accounting lines that they own and no other detail on REQ. // to be removed //for app doc status else if (reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_ACCOUNT)) { // remove FULL_ENTRY because FO cannot edit rest of doc; only their own acct lines editModes.add(RequisitionEditMode.RESTRICT_FISCAL_ENTRY); List lineList = new ArrayList(); for (Iterator iter = reqDocument.getItems().iterator(); iter.hasNext();) { RequisitionItem item = (RequisitionItem) iter.next(); lineList.addAll(item.getSourceAccountingLines()); // If FO has deleted the last accounting line for an item, set entry mode to full so they can add another one if (item.getSourceAccountingLines().size() == 0) { editModes.add(RequisitionEditMode.RESTRICT_FISCAL_ENTRY); //FIXME hjs-this is a problem because we can't put the id in the map anymore // editModeMap.put(RequisitionEditMode.ALLOW_ITEM_ENTRY, item.getItemIdentifier()); } } } // allow capital asset tab to be editable based on requisition status String reqDocumentStatus = reqDocument.getApplicationDocumentStatus(); if (RequisitionStatuses.APPDOC_AWAIT_FISCAL_REVIEW.equals(reqDocumentStatus) || RequisitionStatuses.APPDOC_IN_PROCESS.equals(reqDocumentStatus)) { editModes.add(RequisitionEditMode.ALLOW_CAPITAL_ASSET_EDITS); } WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); if (workflowDocument.isEnroute()) { Set<String> nodeNames = workflowDocument.getNodeNames(); for (Iterator<String> iterator = nodeNames.iterator(); iterator.hasNext();) { String nodeNamesNode = iterator.next(); if (RequisitionStatuses.NODE_ACCOUNT.equals(nodeNamesNode)) { // disable the button for setup distribution editModes.add(RequisitionEditMode.DISABLE_SETUP_ACCT_DISTRIBUTION); // disable the button for remove accounts from all items editModes.add(RequisitionEditMode.DISABLE_REMOVE_ACCTS); // disable the button for remove commodity codes from all items if (editModes.contains(RequisitionEditMode.ENABLE_COMMODITY_CODE)) { editModes.remove(RequisitionEditMode.ENABLE_COMMODITY_CODE); } } } } return editModes; } @Override public boolean canCopy(Document document) { // disallow copying until the doc is saved // WorkflowDocument workflowDocument = ((PurchasingAccountsPayableDocument) document).getFinancialSystemDocumentHeader().getWorkflowDocument(); WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); if (workflowDocument.isInitiated() && !workflowDocument.isSaved()) { return false; } return super.canCopy(document); } @Override public boolean canReload(Document document) { RequisitionDocument reqDocument = (RequisitionDocument) document; // this is a global rule, if the doc is in your queue for ACK, then you lose the reload button WorkflowDocument workflowDocument = ((PurchasingAccountsPayableDocument) document).getFinancialSystemDocumentHeader().getWorkflowDocument(); if (workflowDocument.isAcknowledgeRequested()) { return false; } if (reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_SUBACCOUNT)) { return false; } // but the non-approvers do else if (isDocInRouteNodeNotForCurrentUser(reqDocument, RequisitionStatuses.NODE_SUBACCOUNT)) { return true; } // while in AccountingHierarchyOrgReview ... org reviewers do NOT get reload button else if (reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_ORG_REVIEW)) { return false; } // but the non-approvers do else if (isDocInRouteNodeNotForCurrentUser(reqDocument, RequisitionStatuses.NODE_ORG_REVIEW)) { return true; } // while in SeparationOfDuties ... approvers do NOT get reload button else if (reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_SEPARATION_OF_DUTIES)) { return false; } // but the non-approvers do else if (isDocInRouteNodeNotForCurrentUser(reqDocument, RequisitionStatuses.NODE_SEPARATION_OF_DUTIES)) { return true; } return super.canReload(document); } @Override public boolean canSave(Document document) { RequisitionDocument reqDocument = (RequisitionDocument) document; if (reqDocument.isDocumentStoppedInRouteNode(RequisitionStatuses.NODE_ORG_REVIEW)) { return false; } return super.canSave(document); } /** * * @param document * @param nodeDetails * @return */ protected boolean isDocInRouteNodeNotForCurrentUser(Document document, String nodeName) { List<String> currentRouteLevels = new ArrayList<String>(); WorkflowDocument workflowDocument = ((PurchasingAccountsPayableDocument) document).getFinancialSystemDocumentHeader().getWorkflowDocument(); Set<String> names = workflowDocument.getCurrentNodeNames(); if (CollectionUtils.isNotEmpty(names)) { currentRouteLevels = new ArrayList<String>(names); if (currentRouteLevels.contains(nodeName) && !workflowDocument.isApprovalRequested()) { return true; } } return false; } }