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.List;
019    import java.util.Set;
020    
021    import org.apache.commons.lang.StringUtils;
022    import org.kuali.kfs.module.purap.PurapAuthorizationConstants;
023    import org.kuali.kfs.module.purap.PurapConstants;
024    import org.kuali.kfs.module.purap.PurapParameterConstants;
025    import org.kuali.kfs.module.purap.PurapWorkflowConstants;
026    import org.kuali.kfs.module.purap.PurapAuthorizationConstants.PurchaseOrderEditMode;
027    import org.kuali.kfs.module.purap.PurapConstants.PurchaseOrderStatuses;
028    import org.kuali.kfs.module.purap.PurapConstants.RequisitionSources;
029    import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
030    import org.kuali.kfs.module.purap.document.service.PurapService;
031    import org.kuali.kfs.sys.context.SpringContext;
032    import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
033    import org.kuali.rice.kns.document.Document;
034    import org.kuali.rice.kns.service.ParameterService;
035    import org.kuali.rice.kns.util.ObjectUtils;
036    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
037    
038    
039    public class PurchaseOrderDocumentPresentationController extends PurchasingAccountsPayableDocumentPresentationController {
040    
041        @Override
042        protected boolean canEdit(Document document) {
043            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
044    
045            if (!PurchaseOrderStatuses.IN_PROCESS.equals(poDocument.getStatusCode()) &&
046                    !PurchaseOrderStatuses.WAITING_FOR_DEPARTMENT.equals(poDocument.getStatusCode()) &&
047                    !PurchaseOrderStatuses.WAITING_FOR_VENDOR.equals(poDocument.getStatusCode()) &&
048                    !PurchaseOrderStatuses.QUOTE.equals(poDocument.getStatusCode()) &&
049                    !PurchaseOrderStatuses.AWAIT_PURCHASING_REVIEW.equals(poDocument.getStatusCode()) &&
050                    !PurchaseOrderStatuses.AWAIT_NEW_UNORDERED_ITEM_REVIEW.equals(poDocument.getStatusCode()) &&
051                    !PurchaseOrderStatuses.CHANGE_IN_PROCESS.equals(poDocument.getStatusCode())) {
052                return false;
053            }
054            return super.canEdit(document);
055        }
056    
057        @Override
058        protected boolean canFyi(Document document) {
059            PurchaseOrderDocument poDocument = (PurchaseOrderDocument) document;
060            if (PurchaseOrderStatuses.PENDING_PRINT.equals(poDocument.getStatusCode())) {
061                return false;
062            }
063            return super.canFyi(document);
064        }
065    
066        @Override
067        protected boolean canCancel(Document document) {
068            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
069    
070            if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
071                return false;
072            }
073    
074            return super.canCancel(document);
075        }
076    
077        @Override
078        protected boolean canClose(Document document) {
079            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
080    
081            if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
082                return false;
083            }
084    
085            return super.canClose(document);
086        }
087    
088        @Override
089        protected boolean canReload(Document document) {
090            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
091    
092            if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
093                return false;
094            }
095    
096            return super.canReload(document);
097        }
098    
099        @Override
100        protected boolean canSave(Document document) {
101            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
102    
103            if (poDocument.isPendingSplit() || poDocument.getAssigningSensitiveData()) {
104                return false;
105            }
106    
107            return super.canSave(document);
108        }
109    
110        @Override
111        protected boolean canRoute(Document document) {
112            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
113            String statusCode = poDocument.getStatusCode();
114    
115            if (StringUtils.equals(statusCode, PurchaseOrderStatuses.WAITING_FOR_DEPARTMENT) || 
116                    StringUtils.equals(statusCode, PurchaseOrderStatuses.WAITING_FOR_VENDOR) || 
117                    StringUtils.equals(statusCode, PurchaseOrderStatuses.QUOTE)) {
118                return false;
119            }
120    
121            if (poDocument.isPendingSplit()) {
122                return false;
123            }
124    
125            return super.canRoute(document);
126        }
127    
128        @Override
129        public Set<String> getEditModes(Document document) {
130            Set<String> editModes = super.getEditModes(document);
131            KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
132            PurchaseOrderDocument poDocument = (PurchaseOrderDocument)document;
133            String statusCode = poDocument.getStatusCode();
134    
135            editModes.add(PurchaseOrderEditMode.ASSIGN_SENSITIVE_DATA);
136    
137            //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.
138            boolean enableCommodityCode = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_COMMODITY_CODE_IND);
139            if (enableCommodityCode) {
140                editModes.add(PurchaseOrderEditMode.ENABLE_COMMODITY_CODE);
141            }
142    
143            if (canFirstTransmitPrintPo(poDocument)) {
144                editModes.add(PurchaseOrderEditMode.PRINT_PURCHASE_ORDER);
145            }
146    
147            if (canPreviewPrintPo(poDocument)) {
148                editModes.add(PurchaseOrderEditMode.PREVIEW_PRINT_PURCHASE_ORDER);
149            }
150    
151            if (canResendCxml(poDocument)) {
152                editModes.add(PurchaseOrderEditMode.RESEND_PURCHASE_ORDER);
153            }
154    
155            // if vendor has been selected from DB, certain vendor fields are not allowed to be edited
156            if (ObjectUtils.isNotNull(poDocument.getVendorHeaderGeneratedIdentifier())) {
157                editModes.add(PurchaseOrderEditMode.LOCK_VENDOR_ENTRY);
158            }
159    
160            // if B2B purchase order, certain fields are not allowed to be edited
161            if (RequisitionSources.B2B.equals(poDocument.getRequisitionSourceCode())) {
162                editModes.add(PurchaseOrderEditMode.LOCK_B2B_ENTRY);
163            }
164    
165            // if not B2B requisition, users can edit the posting year if within a given amount of time set in a parameter
166            if (!RequisitionSources.B2B.equals(poDocument.getRequisitionSourceCode()) && 
167                    SpringContext.getBean(PurapService.class).allowEncumberNextFiscalYear() && 
168                    (PurchaseOrderStatuses.IN_PROCESS.equals(statusCode) || 
169                            PurchaseOrderStatuses.WAITING_FOR_VENDOR.equals(statusCode) ||
170                            PurchaseOrderStatuses.WAITING_FOR_DEPARTMENT.equals(statusCode) ||
171                            PurchaseOrderStatuses.QUOTE.equals(statusCode) ||
172                            PurchaseOrderStatuses.AWAIT_PURCHASING_REVIEW.equals(statusCode))) {
173                editModes.add(PurchaseOrderEditMode.ALLOW_POSTING_YEAR_ENTRY);
174            }
175    
176            // check if purap tax is enabled
177            boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND);                
178            if (salesTaxInd) {
179                editModes.add(PurapAuthorizationConstants.PURAP_TAX_ENABLED);
180    
181                if (poDocument.isUseTaxIndicator()) {
182                    // if use tax, don't allow editing of tax fields
183                    editModes.add(PurchaseOrderEditMode.LOCK_TAX_AMOUNT_ENTRY);
184                }
185                else {
186                    // display the "clear all taxes" button if doc is not using use tax
187                    editModes.add(PurchaseOrderEditMode.CLEAR_ALL_TAXES);
188                }
189            }
190    
191            // set display mode for Receiving Address section according to parameter value
192            boolean displayReceivingAddress = SpringContext.getBean(ParameterService.class).getIndicatorParameter(KfsParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_RECEIVING_ADDRESS_IND);                
193            if (displayReceivingAddress) {
194                editModes.add(PurchaseOrderEditMode.DISPLAY_RECEIVING_ADDRESS);
195            }
196    
197            // PRE_ROUTE_CHANGEABLE mode is used for fields that are editable only before PO is routed
198            // for ex, contract manager, manual status change, and quote etc
199            //if (workflowDocument.stateIsInitiated() || workflowDocument.stateIsSaved()) {
200            if (PurchaseOrderStatuses.IN_PROCESS.equals(statusCode) || 
201                    PurchaseOrderStatuses.WAITING_FOR_VENDOR.equals(statusCode) ||
202                    PurchaseOrderStatuses.WAITING_FOR_DEPARTMENT.equals(statusCode) ||
203                    PurchaseOrderStatuses.QUOTE.equals(statusCode)) {
204                editModes.add(PurchaseOrderEditMode.PRE_ROUTE_CHANGEABLE);
205            }
206    
207            // INTERNAL PURCHASING ROUTE LEVEL - Approvers can edit full detail on Purchase Order except they cannot change the CHART/ORG.
208            if (poDocument.isDocumentStoppedInRouteNode(PurapWorkflowConstants.PurchaseOrderDocument.NodeDetailEnum.INTERNAL_PURCHASING_REVIEW)) {
209                editModes.add(PurchaseOrderEditMode.LOCK_INTERNAL_PURCHASING_ENTRY);
210            }
211    
212            //FIXME figure out how to get this to work
213    //      /**
214    //      * CONTRACTS & GRANTS ROUTE LEVEL, BUDGET OFFICE ROUTE LEVEL, VENDOR TAX ROUTE LEVEL, DOCUMENT TRANSMISSION ROUTE LEVEL,
215    //      * and Adhoc - Approvers in these route levels cannot edit any detail on PO.
216    //      */
217    //      else {
218    //      // VIEW_ENTRY that is already being set is sufficient, but need to remove FULL_ENTRY
219    //      editModeMap.remove(AuthorizationConstants.EditMode.FULL_ENTRY);
220    //      }
221    
222            // Set display mode for Split PO.
223            if (poDocument.isPendingSplit()) {
224                editModes.add(PurchaseOrderEditMode.SPLITTING_ITEM_SELECTION);
225            }
226    
227            return editModes;
228        }
229    
230        /**
231         * Determines whether to display the button to print the pdf for the first time transmit. 
232         * Conditions: PO status is Pending Print or the transmission method is changed to PRINT during the amendment. 
233         * 
234         * @return boolean true if the print first transmit button can be displayed.
235         */
236        protected boolean canFirstTransmitPrintPo(PurchaseOrderDocument poDocument) {
237            // status shall be Pending Print, or the transmission method is changed to PRINT during amendment, 
238            boolean can = PurchaseOrderStatuses.PENDING_PRINT.equals(poDocument.getStatusCode());
239            if (!can) {
240                can = PurchaseOrderStatuses.OPEN.equals(poDocument.getStatusCode());
241                can = can && poDocument.getDocumentHeader().getWorkflowDocument().stateIsFinal();
242                can = can && poDocument.getPurchaseOrderLastTransmitTimestamp() == null;
243                can = can && PurapConstants.POTransmissionMethods.PRINT.equals(poDocument.getPurchaseOrderTransmissionMethodCode());
244            }
245    
246            return can;
247        }
248    
249        /**
250         * Determines whether to display the print preview button for the first time transmit. Conditions are:
251         * available while the document is saved or enroute;
252         * available for only a certain number of PO transmission types which are stored in a parameter (default to PRIN and FAX)
253         * 
254         * @return boolean true if the preview print button can be displayed.
255         */
256        protected boolean canPreviewPrintPo(PurchaseOrderDocument poDocument) {
257            // PO is saved or enroute
258            boolean can = poDocument.getDocumentHeader().getWorkflowDocument().stateIsSaved() || poDocument.getDocumentHeader().getWorkflowDocument().stateIsEnroute();
259    
260            // transmission method must be one of those specified by the parameter
261            if (can) {
262                List<String> methods = SpringContext.getBean(ParameterService.class).getParameterValues(PurchaseOrderDocument.class, PurapParameterConstants.PURAP_PO_PRINT_PREVIEW_TRANSMISSION_METHOD_TYPES);
263                String method = poDocument.getPurchaseOrderTransmissionMethodCode();
264                can = (methods == null || methods.contains(method));
265            }
266    
267            return can;
268        }
269    
270        /**
271         * Determines whether to display the resend po button for the purchase order document.
272         * Conditions: PO status must be error sending cxml and must be current and not pending.
273         * 
274         * @return boolean true if the resend po button shall be displayed.
275         */
276        protected boolean canResendCxml(PurchaseOrderDocument poDocument) {
277            // check PO status etc
278            boolean can = PurchaseOrderStatuses.CXML_ERROR.equals(poDocument.getStatusCode());
279            can = can && poDocument.isPurchaseOrderCurrentIndicator() && !poDocument.isPendingActionIndicator();
280    
281            return can;
282        }
283    
284    }