001/*
002 * Copyright 2009 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 */
016package org.kuali.ole.fp.document.authorization;
017
018import java.util.Set;
019
020import org.apache.commons.lang.StringUtils;
021import org.kuali.ole.fp.businessobject.CashDrawer;
022import org.kuali.ole.fp.document.CashManagementDocument;
023import org.kuali.ole.fp.document.service.CashManagementService;
024import org.kuali.ole.fp.service.CashDrawerService;
025import org.kuali.ole.sys.OLEConstants;
026import org.kuali.ole.sys.OLEConstants.CashDrawerConstants;
027import org.kuali.ole.sys.OleAuthorizationConstants;
028import org.kuali.ole.sys.context.SpringContext;
029import org.kuali.ole.sys.document.authorization.LedgerPostingDocumentPresentationControllerBase;
030import org.kuali.rice.kew.api.WorkflowDocument;
031import org.kuali.rice.kew.api.action.ActionType;
032import org.kuali.rice.kew.api.action.ValidActions;
033import org.kuali.rice.kns.service.DataDictionaryService;
034import org.kuali.rice.krad.document.Document;
035import org.kuali.rice.krad.service.MaintenanceDocumentService;
036
037public class CashManagementDocumentPresentationControllerBase extends LedgerPostingDocumentPresentationControllerBase implements CashManagementDocumentPresentationController {
038
039    /**
040     * @see org.kuali.ole.sys.document.authorization.FinancialSystemTransactionalDocumentPresentationControllerBase#getEditModes(org.kuali.rice.krad.document.Document)
041     */
042    @Override
043    public Set<String> getEditModes(Document document) {
044        Set<String> editModes = super.getEditModes(document);
045
046        if (!this.canHaveBankEntry(document)) {
047            editModes.add(OLEConstants.BANK_ENTRY_VIEWABLE_EDITING_MODE);
048        }
049
050        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
051        if (workflowDocument.isSaved()) {
052            editModes.add(OleAuthorizationConstants.CashManagementEditMode.ALLOW_CANCEL_DEPOSITS);
053
054            CashManagementDocument cashManagementDocument = (CashManagementDocument) document;
055            if (!cashManagementDocument.hasFinalDeposit()) {
056                editModes.add(OleAuthorizationConstants.CashManagementEditMode.ALLOW_ADDITIONAL_DEPOSITS);
057            }
058        }
059
060        return editModes;
061    }
062
063    /**
064     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canApprove(org.kuali.rice.krad.document.Document)
065     */
066    @Override
067    public boolean canApprove(Document document) {
068        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
069        if (workflowDocument.isEnroute()) {
070            ValidActions validActions = workflowDocument.getValidActions();
071            return validActions.getValidActions().contains(ActionType.APPROVE);
072        }
073
074        return super.canApprove(document);
075    }
076
077    /**
078     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canBlanketApprove(org.kuali.rice.krad.document.Document)
079     */
080    @Override
081    public boolean canBlanketApprove(Document document) {
082        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
083        if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
084            CashManagementDocument cmDoc = (CashManagementDocument) document;
085            if (!cmDoc.hasFinalDeposit() || !SpringContext.getBean(CashManagementService.class).allVerifiedCashReceiptsAreDeposited(cmDoc)) {
086                return false;
087            }
088
089            // CM document can only be routed if it contains a Final Deposit
090            ValidActions validActions = workflowDocument.getValidActions();
091            return validActions.getValidActions().contains(ActionType.BLANKET_APPROVE);
092        }
093
094        return super.canBlanketApprove(document);
095    }
096
097    /**
098     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canCancel(org.kuali.rice.krad.document.Document)
099     */
100    @Override
101    public boolean canCancel(Document document) {
102        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
103        if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
104            CashManagementDocument cmDoc = (CashManagementDocument) document;
105            if (!SpringContext.getBean(CashManagementService.class).allowDocumentCancellation(cmDoc)) {
106                return false;
107            }
108
109            // CM document can only be routed if it contains a Final Deposit
110            ValidActions validActions = workflowDocument.getValidActions();
111            return validActions.getValidActions().contains(ActionType.CANCEL);
112        }
113
114        return super.canCancel(document);
115    }
116
117    /**
118     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canDisapprove(org.kuali.rice.krad.document.Document)
119     */
120    @Override
121    public boolean canDisapprove(Document document) {
122        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
123        if (workflowDocument.isEnroute()) {
124            ValidActions validActions = workflowDocument.getValidActions();
125            return validActions.getValidActions().contains(ActionType.DISAPPROVE);
126        }
127
128        return super.canDisapprove(document);
129    }
130
131    /**
132     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canRoute(org.kuali.rice.krad.document.Document)
133     */
134    @Override
135    public boolean canRoute(Document document) {
136        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
137        if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
138            CashManagementDocument cmDoc = (CashManagementDocument) document;
139            if (!cmDoc.hasFinalDeposit() || !SpringContext.getBean(CashManagementService.class).allVerifiedCashReceiptsAreDeposited(cmDoc)) {
140                return false;
141            }
142
143            // CM document can only be routed if it contains a Final Deposit
144            ValidActions validActions = workflowDocument.getValidActions();
145            return validActions.getValidActions().contains(ActionType.ROUTE);
146        }
147
148        return super.canRoute(document);
149    }
150
151    /**
152     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canSave(org.kuali.rice.krad.document.Document)
153     */
154    @Override
155    public boolean canSave(Document document) {
156        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
157        if (workflowDocument.isInitiated() || workflowDocument.isSaved()) {
158            CashManagementDocument cmDoc = (CashManagementDocument) document;
159            if (cmDoc.getCashDrawerStatus() == null || cmDoc.getCashDrawerStatus().equals(CashDrawerConstants.STATUS_CLOSED)) {
160                return false;
161            }
162
163            // CM document can only be saved (via the save button) if the CashDrawer is not closed
164            ValidActions validActions = workflowDocument.getValidActions();
165            return validActions.getValidActions().contains(ActionType.SAVE);
166        }
167
168        return super.canRoute(document);
169    }
170
171    /**
172     * @see org.kuali.rice.krad.document.authorization.DocumentPresentationControllerBase#canAdHocRoute(org.kuali.rice.krad.document.Document)
173     */
174    @Override
175    public boolean canAddAdhocRequests(Document document) {
176        WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
177        if (workflowDocument.isEnroute()) {
178            ValidActions validActions = workflowDocument.getValidActions();
179            return validActions.getValidActions().contains(ActionType.ADHOC_REQUEST);
180        }
181
182        return super.canAddAdhocRequests(document);
183    }
184
185    /**
186     * Determines if the cash drawer can be opened by testing two things:
187     * <ol>
188     *  <li>That the cash drawer is currently closed.</li>
189     *  <li>That no cash drawer maintenance documents have a lock on the cash drawer.</li>
190     * </ol>
191     * @param document the document that wishes to open the cash drawer
192     * @return true if the cash drawer can be opened, false otherwise
193     */
194    @Override
195    public boolean canOpenCashDrawer(Document document) {
196        final CashDrawer cashDrawer = retrieveCashDrawer(document);
197        return cashDrawer.isClosed() && noExistCashDrawerMaintLocks(cashDrawer, document.getDocumentNumber());
198    }
199
200    /**
201     * Retrieves the cash drawer associated with the given cash management document
202     * @param document a CashManagementDocument with an associated cash drawer
203     * @return the associated cash drawer
204     */
205    protected CashDrawer retrieveCashDrawer(Document document) {
206        final CashManagementDocument cmDoc = (CashManagementDocument)document;
207        final CashDrawer cashDrawer = SpringContext.getBean(CashDrawerService.class).getByCampusCode(cmDoc.getCampusCode());
208        return cashDrawer;
209    }
210
211    /**
212     * Determines that no maintenance documents have locks on the given cash drawer
213     * @param cashDrawer the cash drawer that may have locks on it
214     * @return true if there are no maintenance documents with locks on the cash drawer, false otherwise
215     */
216    protected boolean noExistCashDrawerMaintLocks(CashDrawer cashDrawer, String documentNumber) {
217       final org.kuali.rice.krad.datadictionary.MaintenanceDocumentEntry cashDrawerMaintDocEntry = SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getMaintenanceDocumentEntryForBusinessObjectClass(cashDrawer.getClass());
218       org.kuali.rice.krad.maintenance.Maintainable cashDrawerMaintainable = createCashDrawerMaintainable(cashDrawerMaintDocEntry);
219       cashDrawerMaintainable.setDataObjectClass(cashDrawer.getClass());
220       cashDrawerMaintainable.setDataObject(cashDrawer);
221       cashDrawerMaintainable.setDocumentNumber(documentNumber);
222
223       final String lockingDocument = SpringContext.getBean(MaintenanceDocumentService.class).getLockingDocumentId(cashDrawerMaintainable, documentNumber);
224       return StringUtils.isBlank(lockingDocument);
225    }
226
227    /**
228     * Builds an instance of the appropriate Maintainable implementation for the Cash Drawer Maintainable
229     * @param cashDrawerMaintenanceDocumentEntry the data dictionary entry from the Cash Drawer's maintenance document
230     * @return an appropriate Maintainable
231     */
232    protected org.kuali.rice.krad.maintenance.Maintainable createCashDrawerMaintainable(org.kuali.rice.krad.datadictionary.MaintenanceDocumentEntry cashDrawerMaintenanceDocumentEntry) {
233        org.kuali.rice.krad.maintenance.Maintainable cashDrawerMaintainable;
234        try {
235            cashDrawerMaintainable = cashDrawerMaintenanceDocumentEntry.getMaintainableClass().newInstance();
236        }
237        catch (InstantiationException ie) {
238            throw new RuntimeException("Cannot instantiate instance of maintainable implementation "+cashDrawerMaintenanceDocumentEntry.getMaintainableClass().getName(), ie);
239        }
240        catch (IllegalAccessException iae) {
241            throw new RuntimeException("Illegal access occurred while instantiating instance of maintainable implementation "+cashDrawerMaintenanceDocumentEntry.getMaintainableClass().getName(), iae);
242        }
243        return cashDrawerMaintainable;
244    }
245
246    @Override
247    public Set<String> getDocumentActions(Document document) {
248        Set<String> documentActions = super.getDocumentActions(document);
249
250        if (!canHaveBankEntry(document)) {
251            documentActions.add(OLEConstants.KFS_ACTION_CAN_EDIT_BANK);
252        }
253
254        return documentActions;
255    }
256}