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.fp.document.validation.impl;
017    
018    import java.util.Arrays;
019    import java.util.Calendar;
020    import java.util.Date;
021    import java.util.GregorianCalendar;
022    import java.util.Iterator;
023    import java.util.List;
024    
025    import org.apache.log4j.Logger;
026    import org.kuali.kfs.fp.businessobject.CashDrawer;
027    import org.kuali.kfs.fp.businessobject.CashieringItemInProcess;
028    import org.kuali.kfs.fp.businessobject.CashieringTransaction;
029    import org.kuali.kfs.fp.businessobject.Check;
030    import org.kuali.kfs.fp.businessobject.CoinDetail;
031    import org.kuali.kfs.fp.businessobject.CurrencyDetail;
032    import org.kuali.kfs.fp.businessobject.Deposit;
033    import org.kuali.kfs.fp.businessobject.DepositCashReceiptControl;
034    import org.kuali.kfs.fp.document.CashManagementDocument;
035    import org.kuali.kfs.fp.document.CashReceiptDocument;
036    import org.kuali.kfs.fp.document.service.CashManagementService;
037    import org.kuali.kfs.fp.document.service.CashReceiptService;
038    import org.kuali.kfs.fp.document.validation.CashManagingRule;
039    import org.kuali.kfs.fp.service.CashDrawerService;
040    import org.kuali.kfs.sys.KFSConstants;
041    import org.kuali.kfs.sys.KFSKeyConstants;
042    import org.kuali.kfs.sys.KFSPropertyConstants;
043    import org.kuali.kfs.sys.KFSConstants.DocumentStatusCodes.CashReceipt;
044    import org.kuali.kfs.sys.context.SpringContext;
045    import org.kuali.kfs.sys.document.validation.impl.BankCodeValidation;
046    import org.kuali.kfs.sys.document.validation.impl.GeneralLedgerPostingDocumentRuleBase;
047    import org.kuali.rice.kim.bo.Person;
048    import org.kuali.rice.kns.document.Document;
049    import org.kuali.rice.kns.service.DictionaryValidationService;
050    import org.kuali.rice.kns.util.GlobalVariables;
051    import org.kuali.rice.kns.util.KualiDecimal;
052    
053    /**
054     * Business rule(s) applicable to Cash Management Document.
055     */
056    public class CashManagementDocumentRule extends GeneralLedgerPostingDocumentRuleBase implements CashManagingRule {
057        private static final Logger LOG = Logger.getLogger(CashManagementDocumentRule.class);
058    
059        /**
060         * Overrides to validate that the person saving the document is the initiator, validates that the cash drawer is open for
061         * initial creation, validates that the cash drawer for the specific verification unit is closed for subsequent saves, and
062         * validates that the associate cash receipts are still verified.
063         * 
064         * @param document submitted cash management document
065         * @return true if there are no issues processing rules associated with saving a cash management document
066         * @see org.kuali.rice.kns.rule.DocumentRuleBase#processCustomSaveDocumentBusinessRules(org.kuali.rice.kns.document.Document)
067         */
068        @Override
069        protected boolean processCustomSaveDocumentBusinessRules(Document document) {
070            boolean isValid = super.processCustomSaveDocumentBusinessRules(document);
071    
072            CashManagementDocument cmd = (CashManagementDocument) document;
073    
074            // verify the cash drawer for the verification unit is closed for post-initialized saves
075            verifyCashDrawerForVerificationUnitIsOpenForPostInitiationSaves(cmd);
076    
077            // verify deposits
078            isValid &= validateDeposits(cmd);
079    
080            return isValid;
081        }
082    
083        /**
084         * Overrides to validate that all cash receipts are deposited when routing cash management document.
085         * 
086         * @param document submitted cash management document
087         * @return true if there are no issues processing rules associated with routing a cash management document
088         * @see org.kuali.rice.kns.rules.DocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.Document)
089         */
090        @Override
091        protected boolean processCustomRouteDocumentBusinessRules(Document document) {
092            boolean isValid = true;
093    
094            CashManagementDocument cmDoc = (CashManagementDocument) document;
095            isValid &= verifyAllVerifiedCashReceiptsDeposited(cmDoc);
096    
097            return isValid;
098        }
099    
100        /**
101         * This method checks to make sure that the current system user is the person that initiated this document in the first place.
102         * 
103         * @param cmd submitted cash management document
104         */
105        protected void verifyUserIsDocumentInitiator(CashManagementDocument cmd) {
106            Person currentUser = GlobalVariables.getUserSession().getPerson();
107            if (cmd.getDocumentHeader() != null && cmd.getDocumentHeader().getWorkflowDocument() != null) {
108                String cmdInitiatorNetworkId = cmd.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId();
109                if (!cmdInitiatorNetworkId.equalsIgnoreCase(currentUser.getPrincipalName())) {
110                    throw new IllegalStateException("The current user (" + currentUser.getPrincipalName() + ") is not the individual (" + cmdInitiatorNetworkId + ") that initiated this document.");
111                }
112            }
113        }
114    
115        /**
116         * This method checks to make sure that the cash drawer is closed for the associated verification unit, for post initiation
117         * saves for CashManagementDocuments which don't have Final
118         * 
119         * @param cmd submitted cash management document
120         */
121        protected void verifyCashDrawerForVerificationUnitIsOpenForPostInitiationSaves(CashManagementDocument cmd) {
122            if (cmd.getDocumentHeader() != null && cmd.getDocumentHeader().getWorkflowDocument() != null && cmd.getDocumentHeader().getWorkflowDocument().getRouteHeader() != null) {
123                if (cmd.getDocumentHeader().getWorkflowDocument().stateIsSaved()) {
124                    // now verify that the associated cash drawer is in the appropriate state
125                    CashDrawer cd = SpringContext.getBean(CashDrawerService.class).getByCampusCode(cmd.getCampusCode());
126                    if (cd == null) {
127                        // we got the rule without having a cash drawer?  freaky...
128                        throw new RuntimeException("No cash drawer exists for campus code "+cmd.getCampusCode()+"; please create on via the Cash Drawer Maintenance Document before attemping to create a CashManagementDocument for campus "+cmd.getCampusCode());
129                    }
130                    if (!cmd.hasFinalDeposit()) {
131                        if (!cd.isOpen()) {
132                            throw new IllegalStateException("The cash drawer for verification unit \"" + cd.getCampusCode() + "\" is closed.  It should be open when a cash management document for that verification unit is open and being saved.");
133                        }
134                    }
135                    else {
136                        if (!cd.isLocked()) {
137                            throw new IllegalStateException("The cash drawer for verification unit \"" + cd.getCampusCode() + "\" is closed.  It should be open when a cash management document for that verification unit is open and being saved.");
138                        }
139                    }
140                }
141            }
142        }
143    
144    
145        /**
146         * Validates all Deposits associated with the given CashManagementDocument
147         * 
148         * @param cmd submitted cash management document
149         * @return true if all deposits in a cash management are valid
150         */
151        protected boolean validateDeposits(CashManagementDocument cmd) {
152            boolean isValid = true;
153            boolean isInitiated = cmd.getDocumentHeader().getWorkflowDocument().stateIsInitiated();
154    
155            GlobalVariables.getMessageMap().addToErrorPath(KFSPropertyConstants.DOCUMENT);
156    
157            int index = 0;
158            for (Iterator deposits = cmd.getDeposits().iterator(); deposits.hasNext(); index++) {
159                Deposit deposit = (Deposit) deposits.next();
160    
161                GlobalVariables.getMessageMap().addToErrorPath(KFSPropertyConstants.DEPOSIT + "[" + index + "]");
162                isValid &= validateDeposit(deposit, isInitiated);
163                GlobalVariables.getMessageMap().removeFromErrorPath(KFSPropertyConstants.DEPOSIT + "[" + index + "]");
164            }
165    
166            GlobalVariables.getMessageMap().removeFromErrorPath(KFSPropertyConstants.DOCUMENT);
167    
168            return isValid;
169        }
170    
171        /**
172         * If documentIsInitiated, performs complete dataDictionary-driven validation of the given Deposit. Unconditionally validates
173         * the CashReceipts associated with the given Deposit.
174         * 
175         * @param deposit individual deposit from cash management document
176         * @param documentIsInitiated if document is initiated
177         * @return true if deposit is valid
178         */
179        protected boolean validateDeposit(Deposit deposit, boolean documentIsInitiated) {
180            boolean isValid = true;
181    
182            verifyCashReceipts(deposit, documentIsInitiated);
183    
184            if (!documentIsInitiated) {
185                isValid = performDataDictionaryValidation(deposit);
186            }
187    
188            return isValid;
189        }
190    
191    
192        private static final List INITIATED_STATES = Arrays.asList(new String[] { CashReceipt.VERIFIED });
193        private static final List UNINITIATED_STATES = Arrays.asList(new String[] { CashReceipt.INTERIM, CashReceipt.FINAL });
194    
195        /**
196         * Verifies that all CashReceipts associated with the given document are of an appropriate status for the given
197         * CashManagementDocument state
198         * 
199         * @param deposit deposit from cash management document
200         * @param documentIsInitiated if document is initiated
201         */
202        protected void verifyCashReceipts(Deposit deposit, boolean documentIsInitiated) {
203            List desiredCRStates = null;
204            if (documentIsInitiated) {
205                desiredCRStates = INITIATED_STATES;
206            }
207            else {
208                desiredCRStates = UNINITIATED_STATES;
209            }
210    
211            for (Iterator depositCashReceiptControls = deposit.getDepositCashReceiptControl().iterator(); depositCashReceiptControls.hasNext();) {
212                DepositCashReceiptControl depositCashReceiptControl = (DepositCashReceiptControl) depositCashReceiptControls.next();
213                CashReceiptDocument cashReceipt = depositCashReceiptControl.getCashReceiptDocument();
214                String crState = cashReceipt.getDocumentHeader().getFinancialDocumentStatusCode();
215                if (!desiredCRStates.contains(crState)) {
216                    throw new IllegalStateException("Cash receipt document number " + cashReceipt.getDocumentNumber() + " is not in an appropriate state for the associated CashManagementDocument to be submitted.");
217                }
218            }
219        }
220    
221        /**
222         * Verifies that all verified cash receipts have been deposited
223         * 
224         * @param cmDoc the cash management document that is about to be routed
225         * @return true if there are no outstanding verified cash receipts that are not part of a deposit, false if otherwise
226         */
227        protected boolean verifyAllVerifiedCashReceiptsDeposited(CashManagementDocument cmDoc) {
228            boolean allCRsDeposited = true;
229            CashManagementService cms = SpringContext.getBean(CashManagementService.class);
230            List verifiedReceipts = SpringContext.getBean(CashReceiptService.class).getCashReceipts(cmDoc.getCampusCode(), KFSConstants.DocumentStatusCodes.CashReceipt.VERIFIED);
231            for (Object o : verifiedReceipts) {
232                if (!cms.verifyCashReceiptIsDeposited(cmDoc, (CashReceiptDocument) o)) {
233                    allCRsDeposited = false;
234                    GlobalVariables.getMessageMap().putError(KFSConstants.CASH_MANAGEMENT_DEPOSIT_ERRORS, KFSKeyConstants.CashManagement.ERROR_NON_DEPOSITED_VERIFIED_CASH_RECEIPT, new String[] { ((CashReceiptDocument) o).getDocumentNumber() });
235                }
236            }
237            return allCRsDeposited;
238        }
239    
240        /**
241         * Performs complete, recursive dataDictionary-driven validation of the given Deposit.
242         * 
243         * @param deposit deposit from cash management document
244         * @return true if deposit is validated against data dictionary entry
245         */
246        protected boolean performDataDictionaryValidation(Deposit deposit) {
247            // check for required fields
248            SpringContext.getBean(DictionaryValidationService.class).validateBusinessObject(deposit);
249    
250            // validate foreign-key relationships
251            //KFSMI-798 - refresh() changed to refreshNonUpdateableReferences()
252            //Deposit has updatable references, but for validation we do not need to refresh the updatable references. 
253            //E.g. updatable collections - they might have been set by the user and we would not want to overwrite their changes.
254            deposit.refreshNonUpdateableReferences();
255            
256            // validate bank code
257            BankCodeValidation.validate(deposit.getDepositBankCode(), KFSPropertyConstants.DEPOSIT_BANK_CODE, true, false);
258    
259            return GlobalVariables.getMessageMap().hasNoErrors();
260        }
261    
262        /**
263         * Processes the checks to validate that the application of the given cashiering transaction will be valid
264         * @see org.kuali.kfs.fp.document.validation.CashManagingRule#processCashieringTransactionApplication(org.kuali.kfs.fp.businessobject.CashieringTransaction)
265         */
266        public boolean processCashieringTransactionApplication(CashDrawer cashDrawer, CashieringTransaction cashieringTransaction) {
267            boolean success = true;
268            success &= checkMoneyInNoNegatives(cashieringTransaction);
269            success &= checkMoneyOutNoNegatives(cashieringTransaction);
270            success &= checkAllPaidBackItemsInProcess(cashieringTransaction);
271            success &= checkNewItemInProcessDoesNotExceedCashDrawer(cashDrawer, cashieringTransaction);
272            success &= checkNewItemInProcessInPast(cashieringTransaction);
273            success &= checkTransactionCheckTotalDoesNotExceedCashDrawer(cashDrawer, cashieringTransaction);
274            success &= checkItemInProcessIsNotPayingOffItemInProcess(cashieringTransaction);
275            if (success) {
276                success = checkEnoughCashForMoneyOut(cashDrawer, cashieringTransaction);
277            }
278            if (success) {
279                success &= checkMoneyInMoneyOutBalance(cashieringTransaction);
280            }
281            return success;
282        }
283        
284        /**
285         * Returns true if none of the entered money-in amounts (cash and coin) are not negative in a cashiering transaction
286         * 
287         * @param trans represents cashiering transaction from document
288         * @return true if none of the amounts are negative
289         */
290        public boolean checkMoneyInNoNegatives(CashieringTransaction trans) {
291            boolean success = true;
292    
293            // money in currency
294            if (trans.getMoneyInCurrency().getFinancialDocumentHundredDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentHundredDollarAmount().isNegative()) {
295                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.hundredDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getHundredDollarCount().toString(), "hundred dollar count" });
296                success = false;
297            }
298            if (trans.getMoneyInCurrency().getFinancialDocumentFiftyDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentFiftyDollarAmount().isNegative()) {
299                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.fiftyDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getFiftyDollarCount().toString(), "fifty dollar count" });
300                success = false;
301            }
302            if (trans.getMoneyInCurrency().getFinancialDocumentTwentyDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentTwentyDollarAmount().isNegative()) {
303                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.twentyDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getTwentyDollarCount().toString(), "twenty dollar count" });
304                success = false;
305            }
306            if (trans.getMoneyInCurrency().getFinancialDocumentTenDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentTenDollarAmount().isNegative()) {
307                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.tenDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getTenDollarCount().toString(), "ten dollar count" });
308                success = false;
309            }
310            if (trans.getMoneyInCurrency().getFinancialDocumentFiveDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentFiveDollarAmount().isNegative()) {
311                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.fiveDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getFiveDollarCount().toString(), "five dollar count" });
312                success = false;
313            }
314            if (trans.getMoneyInCurrency().getFinancialDocumentTwoDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentTwoDollarAmount().isNegative()) {
315                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.twoDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getTwoDollarCount().toString(), "two dollar count" });
316                success = false;
317            }
318            if (trans.getMoneyInCurrency().getFinancialDocumentOneDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentOneDollarAmount().isNegative()) {
319                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.oneDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getOneDollarCount().toString(), "one dollar count" });
320                success = false;
321            }
322            if (trans.getMoneyInCurrency().getFinancialDocumentOtherDollarAmount() != null && trans.getMoneyInCurrency().getFinancialDocumentOtherDollarAmount().isNegative()) {
323                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.financialDocumentOtherDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getFinancialDocumentOtherDollarAmount().toString(), "other dollar amount" });
324                success = false;
325            }
326    
327            // money in coin
328            if (trans.getMoneyInCoin().getFinancialDocumentHundredCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentHundredCentAmount().isNegative()) {
329                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.hundredCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getHundredCentCount().toString(), "hundred cent count" });
330                success = false;
331            }
332            if (trans.getMoneyInCoin().getFinancialDocumentFiftyCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentFiftyCentAmount().isNegative()) {
333                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.fiftyCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getFiftyCentCount().toString(), "fifty cent count" });
334                success = false;
335            }
336            if (trans.getMoneyInCoin().getFinancialDocumentTenCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentTenCentAmount().isNegative()) {
337                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.tenCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getTenCentCount().toString(), "ten cent count" });
338                success = false;
339            }
340            if (trans.getMoneyInCoin().getFinancialDocumentTwentyFiveCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentTwentyFiveCentAmount().isNegative()) {
341                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.twentyFiveCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getTwentyFiveCentCount().toString(), "twenty five cent count" });
342                success = false;
343            }
344            if (trans.getMoneyInCoin().getFinancialDocumentFiveCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentFiveCentAmount().isNegative()) {
345                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.fiveCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getFiveCentCount().toString(), "five cent count" });
346                success = false;
347            }
348            if (trans.getMoneyInCoin().getFinancialDocumentOneCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentOneCentAmount().isNegative()) {
349                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.oneCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getOneCentCount().toString(), "one cent count" });
350                success = false;
351            }
352            if (trans.getMoneyInCoin().getFinancialDocumentOtherCentAmount() != null && trans.getMoneyInCoin().getFinancialDocumentOtherCentAmount().isNegative()) {
353                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCoin.financialDocumentOtherCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getFinancialDocumentOtherCentAmount().toString(), "other cent amount" });
354                success = false;
355            }
356    
357            // newItemInProcess amount
358            if (trans.getNewItemInProcess() != null && trans.getNewItemInProcess().isPopulated() && trans.getNewItemInProcess().getItemAmount().isNegative()) {
359                GlobalVariables.getMessageMap().putError("document.currentTransaction.newItemInProcess.itemAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_NEW_ITEM_IN_PROCESS_NOT_NEGATIVE, new String[0]);
360                success = false;
361            }
362    
363            // checks
364            int count = 0;
365            for (Check check : trans.getMoneyInChecks()) {
366                if (check.getAmount() != null && check.getAmount().isNegative()) {
367                    GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInChecks[" + count + "].amount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CHECK_AMOUNT_NOT_NEGATIVE, new String[] { check.getAmount().toString(), check.getDescription() });
368                    success = false;
369                }
370                count += 1;
371            }
372    
373            return success;
374        }
375    
376        /**
377         * Returns true if none of the entered money-out amounts (cash and coin) are not negative in a cashiering transaction
378         * 
379         * @param trans represents cashiering transaction from document
380         * @return true if none of the amounts are negative
381         */
382        public boolean checkMoneyOutNoNegatives(CashieringTransaction trans) {
383            boolean success = true;
384    
385            // money out currency
386            if (trans.getMoneyOutCurrency().getFinancialDocumentHundredDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentHundredDollarAmount().isNegative()) {
387                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.hundredDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyOutCurrency().getHundredDollarCount().toString(), "hundred dollar count" });
388                success = false;
389            }
390            if (trans.getMoneyOutCurrency().getFinancialDocumentFiftyDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentFiftyDollarAmount().isNegative()) {
391                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.fiftyDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyOutCurrency().getFiftyDollarCount().toString(), "fifty dollar count" });
392                success = false;
393            }
394            if (trans.getMoneyOutCurrency().getFinancialDocumentTwentyDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentTwentyDollarAmount().isNegative()) {
395                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.twentyDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyOutCurrency().getTwentyDollarCount().toString(), "twenty dollar count" });
396                success = false;
397            }
398            if (trans.getMoneyOutCurrency().getFinancialDocumentTenDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentTenDollarAmount().isNegative()) {
399                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.tenDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getTenDollarCount().toString(), "ten dollar count" });
400                success = false;
401            }
402            if (trans.getMoneyOutCurrency().getFinancialDocumentFiveDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentFiveDollarAmount().isNegative()) {
403                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.fiveDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyOutCurrency().getFiveDollarCount().toString(), "five dollar count" });
404                success = false;
405            }
406            if (trans.getMoneyOutCurrency().getFinancialDocumentTwoDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentTwoDollarAmount().isNegative()) {
407                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.twoDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyOutCurrency().getTwoDollarCount().toString(), "two dollar count" });
408                success = false;
409            }
410            if (trans.getMoneyOutCurrency().getFinancialDocumentOneDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentOneDollarAmount().isNegative()) {
411                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.oneDollarCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getOneDollarCount().toString(), "one dollar count" });
412                success = false;
413            }
414            if (trans.getMoneyOutCurrency().getFinancialDocumentOtherDollarAmount() != null && trans.getMoneyOutCurrency().getFinancialDocumentOtherDollarAmount().isNegative()) {
415                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentOtherDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCurrency().getFinancialDocumentOtherDollarAmount().toString(), "other dollar amount" });
416                success = false;
417            }
418    
419            // money out coin
420            if (trans.getMoneyOutCoin().getFinancialDocumentHundredCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentHundredCentAmount().isNegative()) {
421                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.hundredCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getHundredCentCount().toString(), "hundred cent count" });
422                success = false;
423            }
424            if (trans.getMoneyOutCoin().getFinancialDocumentFiftyCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentFiftyCentAmount().isNegative()) {
425                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.fiftyCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getFiftyCentCount().toString(), "fifty cent count" });
426                success = false;
427            }
428            if (trans.getMoneyOutCoin().getFinancialDocumentTenCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentTenCentAmount().isNegative()) {
429                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.tenCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getTenCentCount().toString(), "ten cent count" });
430                success = false;
431            }
432            if (trans.getMoneyOutCoin().getFinancialDocumentTwentyFiveCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentTwentyFiveCentAmount().isNegative()) {
433                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.twentyFiveCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getTwentyFiveCentCount().toString(), "twenty five cent count" });
434                success = false;
435            }
436            if (trans.getMoneyOutCoin().getFinancialDocumentFiveCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentFiveCentAmount().isNegative()) {
437                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.fiveCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getFiveCentCount().toString(), "five cent count" });
438                success = false;
439            }
440            if (trans.getMoneyOutCoin().getFinancialDocumentOneCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentOneCentAmount().isNegative()) {
441                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.oneCentCount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyInCoin().getOneCentCount().toString(), "one cent count" });
442                success = false;
443            }
444            if (trans.getMoneyOutCoin().getFinancialDocumentOtherCentAmount() != null && trans.getMoneyOutCoin().getFinancialDocumentOtherCentAmount().isNegative()) {
445                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentOtherCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_NOT_NEGATIVE, new String[] { trans.getMoneyOutCoin().getFinancialDocumentOtherCentAmount().toString(), "other cent amount" });
446                success = false;
447            }
448    
449            // open items in process amounts
450            int count = 0;
451            if (trans.getOpenItemsInProcess() != null) {
452                for (CashieringItemInProcess itemInProc : trans.getOpenItemsInProcess()) {
453                    if (itemInProc.getCurrentPayment() != null && itemInProc.getCurrentPayment().isNegative()) {
454                        GlobalVariables.getMessageMap().putError("document.currentTransaction.openItemsInProcess[" + count + "].currentPayment", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_REDUCED_ITEM_IN_PROCESS_NOT_NEGATIVE, new String[] { itemInProc.getItemIdentifier().toString() });
455                        success = false;
456                    }
457                    count += 1;
458                }
459            }
460    
461            return success;
462        }
463    
464        /**
465         * Returns true if money-in and money-out are in balance with each other
466         * 
467         * @param trans represents cashiering transaction from cash management document
468         * @return true if money-in and money-out are balanced
469         */
470        public boolean checkMoneyInMoneyOutBalance(CashieringTransaction trans) {
471            boolean success = true;
472            if (!trans.getMoneyInTotal().equals(trans.getMoneyOutTotal())) {
473                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyInCurrency.financialDocumentHundredDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_IN_OUT_DO_NOT_BALANCE, new String[0]);
474                success = false;
475            }
476            return success;
477        }
478    
479        /**
480         * This method returns true if none of the coin (1 cent, 5 cents, etc) and cash increments (1 dollar, 2 dollars, 5 dollars etc. )
481         * from ( money-in + cash drawer ) exceed the amount for that increment from the money-out.
482         * 
483         * @param cmDoc represents cash management document
484         * @param trans represents cash transaction from cash management document
485         * @return true if none of the coin and cash increments from money-in + cash drawer excreed amount for increments in money-out 
486         */
487        public boolean checkEnoughCashForMoneyOut(CashDrawer cashDrawer, CashieringTransaction trans) {
488            boolean success = true;
489    
490            // money out currency
491            CurrencyDetail moneyInCurrency = trans.getMoneyInCurrency();
492            CurrencyDetail moneyOutCurrency = trans.getMoneyOutCurrency();
493    
494            KualiDecimal existingHundredDollarAmount = KualiDecimal.ZERO;
495            if (cashDrawer.getFinancialDocumentHundredDollarAmount() != null) {
496                existingHundredDollarAmount = existingHundredDollarAmount.add(cashDrawer.getFinancialDocumentHundredDollarAmount());
497            }
498            if (moneyInCurrency.getFinancialDocumentHundredDollarAmount() != null) {
499                existingHundredDollarAmount = existingHundredDollarAmount.add(moneyInCurrency.getFinancialDocumentHundredDollarAmount());
500            }
501            if (moneyOutCurrency.getFinancialDocumentHundredDollarAmount() != null && existingHundredDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentHundredDollarAmount())) {
502                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentHundredDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "hundred dollar", moneyOutCurrency.getFinancialDocumentHundredDollarAmount().toString(), cashDrawer.getFinancialDocumentHundredDollarAmount().toString() });
503                success = false;
504            }
505    
506            KualiDecimal existingOtherDollarAmount = KualiDecimal.ZERO;
507            if (cashDrawer.getFinancialDocumentOtherDollarAmount() != null) {
508                existingOtherDollarAmount = existingOtherDollarAmount.add(cashDrawer.getFinancialDocumentOtherDollarAmount());
509            }
510            if (moneyInCurrency.getFinancialDocumentOtherDollarAmount() != null) {
511                existingOtherDollarAmount = existingOtherDollarAmount.add(moneyInCurrency.getFinancialDocumentOtherDollarAmount());
512            }
513            if (moneyOutCurrency.getFinancialDocumentOtherDollarAmount() != null && existingOtherDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentOtherDollarAmount())) {
514                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentOtherDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "other dollar", moneyOutCurrency.getFinancialDocumentOtherDollarAmount().toString(), cashDrawer.getFinancialDocumentOtherDollarAmount().toString() });
515                success = false;
516            }
517    
518            KualiDecimal existingTwoDollarAmount = KualiDecimal.ZERO;
519            if (cashDrawer.getFinancialDocumentTwoDollarAmount() != null) {
520                existingTwoDollarAmount = existingTwoDollarAmount.add(cashDrawer.getFinancialDocumentTwoDollarAmount());
521            }
522            if (moneyInCurrency.getFinancialDocumentTwoDollarAmount() != null) {
523                existingTwoDollarAmount = existingTwoDollarAmount.add(moneyInCurrency.getFinancialDocumentTwoDollarAmount());
524            }
525            if (moneyOutCurrency.getFinancialDocumentTwoDollarAmount() != null && existingTwoDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentTwoDollarAmount())) {
526                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentTwoDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "two dollar", moneyOutCurrency.getFinancialDocumentTwoDollarAmount().toString(), cashDrawer.getFinancialDocumentTwoDollarAmount().toString() });
527                success = false;
528            }
529    
530            KualiDecimal existingFiftyDollarAmount = KualiDecimal.ZERO;
531            if (cashDrawer.getFinancialDocumentFiftyDollarAmount() != null) {
532                existingFiftyDollarAmount = existingFiftyDollarAmount.add(cashDrawer.getFinancialDocumentFiftyDollarAmount());
533            }
534            if (moneyInCurrency.getFinancialDocumentFiftyDollarAmount() != null) {
535                existingFiftyDollarAmount = existingFiftyDollarAmount.add(moneyInCurrency.getFinancialDocumentFiftyDollarAmount());
536            }
537            if (moneyOutCurrency.getFinancialDocumentFiftyDollarAmount() != null && existingFiftyDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentFiftyDollarAmount())) {
538                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentFiftyDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "fifty dollar", moneyOutCurrency.getFinancialDocumentFiftyDollarAmount().toString(), cashDrawer.getFinancialDocumentFiftyDollarAmount().toString() });
539                success = false;
540            }
541    
542            KualiDecimal existingTwentyDollarAmount = KualiDecimal.ZERO;
543            if (cashDrawer.getFinancialDocumentTwentyDollarAmount() != null) {
544                existingTwentyDollarAmount = existingTwentyDollarAmount.add(cashDrawer.getFinancialDocumentTwentyDollarAmount());
545            }
546            if (moneyInCurrency.getFinancialDocumentTwentyDollarAmount() != null) {
547                existingTwentyDollarAmount = existingTwentyDollarAmount.add(moneyInCurrency.getFinancialDocumentTwentyDollarAmount());
548            }
549            if (moneyOutCurrency.getFinancialDocumentTwentyDollarAmount() != null && existingTwentyDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentTwentyDollarAmount())) {
550                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentTwentyDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "twenty dollar", moneyOutCurrency.getFinancialDocumentTwentyDollarAmount().toString(), cashDrawer.getFinancialDocumentTwentyDollarAmount().toString() });
551                success = false;
552            }
553    
554            KualiDecimal existingTenDollarAmount = KualiDecimal.ZERO;
555            if (cashDrawer.getFinancialDocumentTenDollarAmount() != null) {
556                existingTenDollarAmount = existingTenDollarAmount.add(cashDrawer.getFinancialDocumentTenDollarAmount());
557            }
558            if (moneyInCurrency.getFinancialDocumentTenDollarAmount() != null) {
559                existingTenDollarAmount = existingTenDollarAmount.add(moneyInCurrency.getFinancialDocumentTenDollarAmount());
560            }
561            if (moneyOutCurrency.getFinancialDocumentTenDollarAmount() != null && existingTenDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentTenDollarAmount())) {
562                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentTenDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "ten dollar", moneyOutCurrency.getFinancialDocumentTenDollarAmount().toString(), cashDrawer.getFinancialDocumentTenDollarAmount().toString() });
563                success = false;
564            }
565    
566            KualiDecimal existingFiveDollarAmount = KualiDecimal.ZERO;
567            if (cashDrawer.getFinancialDocumentFiveDollarAmount() != null) {
568                existingFiveDollarAmount = existingFiveDollarAmount.add(cashDrawer.getFinancialDocumentFiveDollarAmount());
569            }
570            if (moneyInCurrency.getFinancialDocumentFiveDollarAmount() != null) {
571                existingFiveDollarAmount = existingFiveDollarAmount.add(moneyInCurrency.getFinancialDocumentFiveDollarAmount());
572            }
573            if (moneyOutCurrency.getFinancialDocumentFiveDollarAmount() != null && existingFiveDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentFiveDollarAmount())) {
574                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentFiveDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "five dollar", moneyOutCurrency.getFinancialDocumentFiveDollarAmount().toString(), cashDrawer.getFinancialDocumentFiveDollarAmount().toString() });
575                success = false;
576            }
577    
578            KualiDecimal existingOneDollarAmount = KualiDecimal.ZERO;
579            if (cashDrawer.getFinancialDocumentOneDollarAmount() != null) {
580                existingOneDollarAmount = existingOneDollarAmount.add(cashDrawer.getFinancialDocumentOneDollarAmount());
581            }
582            if (moneyInCurrency.getFinancialDocumentOneDollarAmount() != null) {
583                existingOneDollarAmount = existingOneDollarAmount.add(moneyInCurrency.getFinancialDocumentOneDollarAmount());
584            }
585            if (moneyOutCurrency.getFinancialDocumentOneDollarAmount() != null && existingOneDollarAmount.isLessThan(moneyOutCurrency.getFinancialDocumentOneDollarAmount())) {
586                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCurrency.financialDocumentOneDollarAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "one dollar", moneyOutCurrency.getFinancialDocumentOneDollarAmount().toString(), cashDrawer.getFinancialDocumentOneDollarAmount().toString() });
587                success = false;
588            }
589    
590            // money out coin
591            CoinDetail moneyOutCoin = trans.getMoneyOutCoin();
592            CoinDetail moneyInCoin = trans.getMoneyInCoin();
593            KualiDecimal existingHundredCentAmount = KualiDecimal.ZERO;
594            if (cashDrawer.getFinancialDocumentHundredCentAmount() != null) {
595                existingHundredCentAmount = existingHundredCentAmount.add(cashDrawer.getFinancialDocumentHundredCentAmount());
596            }
597            if (moneyInCoin.getFinancialDocumentHundredCentAmount() != null) {
598                existingHundredCentAmount = existingHundredCentAmount.add(moneyInCoin.getFinancialDocumentHundredCentAmount());
599            }
600            if (moneyOutCoin.getFinancialDocumentHundredCentAmount() != null && existingHundredCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentHundredCentAmount())) {
601                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentHundredCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "hundred cent", moneyOutCoin.getFinancialDocumentHundredCentAmount().toString(), cashDrawer.getFinancialDocumentHundredCentAmount().toString() });
602                success = false;
603            }
604    
605            KualiDecimal existingOtherCentAmount = KualiDecimal.ZERO;
606            if (cashDrawer.getFinancialDocumentOtherCentAmount() != null) {
607                existingOtherCentAmount = existingOtherCentAmount.add(cashDrawer.getFinancialDocumentOtherCentAmount());
608            }
609            if (moneyInCoin.getFinancialDocumentOtherCentAmount() != null) {
610                existingOtherCentAmount = existingOtherCentAmount.add(moneyInCoin.getFinancialDocumentOtherCentAmount());
611            }
612            if (moneyOutCoin.getFinancialDocumentOtherCentAmount() != null && existingOtherCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentOtherCentAmount())) {
613                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentOtherCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "other cent", moneyOutCoin.getFinancialDocumentOtherCentAmount().toString(), cashDrawer.getFinancialDocumentOtherCentAmount().toString() });
614                success = false;
615            }
616    
617            KualiDecimal existingFiftyCentAmount = KualiDecimal.ZERO;
618            if (cashDrawer.getFinancialDocumentFiftyCentAmount() != null) {
619                existingFiftyCentAmount = existingFiftyCentAmount.add(cashDrawer.getFinancialDocumentFiftyCentAmount());
620            }
621            if (moneyInCoin.getFinancialDocumentFiftyCentAmount() != null) {
622                existingFiftyCentAmount = existingFiftyCentAmount.add(moneyInCoin.getFinancialDocumentFiftyCentAmount());
623            }
624            if (moneyOutCoin.getFinancialDocumentFiftyCentAmount() != null && existingFiftyCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentFiftyCentAmount())) {
625                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentFiftyCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "fifty cent", moneyOutCoin.getFinancialDocumentFiftyCentAmount().toString(), cashDrawer.getFinancialDocumentFiftyCentAmount().toString() });
626                success = false;
627            }
628    
629            KualiDecimal existingTwentyFiveCentAmount = KualiDecimal.ZERO;
630            if (cashDrawer.getFinancialDocumentTwentyFiveCentAmount() != null) {
631                existingTwentyFiveCentAmount = existingTwentyFiveCentAmount.add(cashDrawer.getFinancialDocumentTwentyFiveCentAmount());
632            }
633            if (moneyInCoin.getFinancialDocumentTwentyFiveCentAmount() != null) {
634                existingTwentyFiveCentAmount = existingTwentyFiveCentAmount.add(moneyInCoin.getFinancialDocumentTwentyFiveCentAmount());
635            }
636            if (moneyOutCoin.getFinancialDocumentTwentyFiveCentAmount() != null && existingTwentyFiveCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentTwentyFiveCentAmount())) {
637                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentTwentyFiveCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "twenty five cent", moneyOutCoin.getFinancialDocumentTwentyFiveCentAmount().toString(), cashDrawer.getFinancialDocumentTwentyFiveCentAmount().toString() });
638                success = false;
639            }
640    
641            KualiDecimal existingTenCentAmount = KualiDecimal.ZERO;
642            if (cashDrawer.getFinancialDocumentTenCentAmount() != null) {
643                existingTenCentAmount = existingTenCentAmount.add(cashDrawer.getFinancialDocumentTenCentAmount());
644            }
645            if (moneyInCoin.getFinancialDocumentTenCentAmount() != null) {
646                existingTenCentAmount = existingTenCentAmount.add(moneyInCoin.getFinancialDocumentTenCentAmount());
647            }
648            if (moneyOutCoin.getFinancialDocumentTenCentAmount() != null && existingTenCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentTenCentAmount())) {
649                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentTenCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "ten cent", moneyOutCoin.getFinancialDocumentTenCentAmount().toString(), cashDrawer.getFinancialDocumentTenCentAmount().toString() });
650                success = false;
651            }
652    
653            KualiDecimal existingFiveCentAmount = KualiDecimal.ZERO;
654            if (cashDrawer.getFinancialDocumentFiveCentAmount() != null) {
655                existingFiveCentAmount = existingFiveCentAmount.add(cashDrawer.getFinancialDocumentFiveCentAmount());
656            }
657            if (moneyInCoin.getFinancialDocumentFiveCentAmount() != null) {
658                existingFiveCentAmount = existingFiveCentAmount.add(moneyInCoin.getFinancialDocumentFiveCentAmount());
659            }
660            if (moneyOutCoin.getFinancialDocumentFiveCentAmount() != null && existingFiveCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentFiveCentAmount())) {
661                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentFiveCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "five cent", moneyOutCoin.getFinancialDocumentFiveCentAmount().toString(), cashDrawer.getFinancialDocumentFiveCentAmount().toString() });
662                success = false;
663            }
664    
665            KualiDecimal existingOneCentAmount = KualiDecimal.ZERO;
666            if (cashDrawer.getFinancialDocumentOneCentAmount() != null) {
667                existingOneCentAmount = existingOneCentAmount.add(cashDrawer.getFinancialDocumentOneCentAmount());
668            }
669            if (moneyInCoin.getFinancialDocumentOneCentAmount() != null) {
670                existingOneCentAmount = existingOneCentAmount.add(moneyInCoin.getFinancialDocumentOneCentAmount());
671            }
672            if (moneyOutCoin.getFinancialDocumentOneCentAmount() != null && existingOneCentAmount.isLessThan(moneyOutCoin.getFinancialDocumentOneCentAmount())) {
673                GlobalVariables.getMessageMap().putError("document.currentTransaction.moneyOutCoin.financialDocumentOneCentAmount", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CASH_COUNT_EXCEEDS_DRAWER, new String[] { "one cent", moneyOutCoin.getFinancialDocumentOneCentAmount().toString(), cashDrawer.getFinancialDocumentOneCentAmount().toString() });
674                success = false;
675            }
676    
677            return success;
678        }
679    
680        /**
681         * This method returns true if the new item in process does not exceed the current amount in the cash drawer reserves
682         * 
683         * @param cmDoc submitted cash management document
684         * @param trans transaction from cash management document
685         * @return true if the new item in process does not exceed the current amount in the cash drawer reserves
686         */
687        public boolean checkNewItemInProcessDoesNotExceedCashDrawer(CashDrawer cashDrawer, CashieringTransaction trans) {
688            boolean success = true;
689    
690            if (trans.getNewItemInProcess().getItemAmount() != null && trans.getNewItemInProcess().getItemAmount().isGreaterThan(calculateTotalCashDrawerReserves(cashDrawer, trans))) {
691                GlobalVariables.getMessageMap().putError("document.currentTransaction.newItemInProcess", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_AMOUNT_EXCEEDS_DRAWER, new String[] { "new Item In Process", trans.getNewItemInProcess().getItemAmount().toString(), calculateTotalCashDrawerReserves(cashDrawer, trans).toString() });
692                success = false;
693            }
694    
695            return success;
696        }
697    
698        /**
699         * This method returns true if check total from transaction does not exceed the current amount in the cash drawer reserves 
700         * 
701         * @param cmDoc submitted cash management document
702         * @param trans transaction from cash management document
703         * @return true if check total from transaction does not exceed the current amount in the cash drawer reserves
704         */
705        public boolean checkTransactionCheckTotalDoesNotExceedCashDrawer(CashDrawer cashDrawer, CashieringTransaction trans) {
706            boolean success = true;
707    
708            if (trans.getTotalCheckAmount().isGreaterThan(calculateTotalCashDrawerReserves(cashDrawer, trans))) {
709                GlobalVariables.getMessageMap().putError("document.currentTransaction.newCheck", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_AMOUNT_EXCEEDS_DRAWER, new String[] { "given checks", trans.getTotalCheckAmount().toString(), calculateTotalCashDrawerReserves(cashDrawer, trans).toString() });
710                success = false;
711            }
712    
713            return success;
714        }
715     
716        /**
717         * This method returns true if the current payment amount for the cashiering item in process does not exceed
718         * the actual item amount for the item in process
719         * 
720         * @param itemInProc cashiering item in process
721         * @param cashieringItemNumber cashiering item number
722         * @return true if the current payment amount for the cashiering item in process does not exceed
723         *          the actual item amount for the item in process
724         */
725        public boolean checkPaidBackItemInProcessDoesNotExceedTotal(CashieringItemInProcess itemInProc, int cashieringItemNumber) {
726            boolean success = true;
727            if (itemInProc.getCurrentPayment() != null && itemInProc.getCurrentPayment().isGreaterThan(itemInProc.getItemAmount())) {
728                GlobalVariables.getMessageMap().putError(KFSConstants.CASHIERING_TRANSACTION_OPEN_ITEM_IN_PROCESS_PROPERTY + "[" + cashieringItemNumber + "]", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_AMOUNT_PAID_BACK_EXCEEDS_AMOUNT_LEFT, new String[] { itemInProc.getItemIdentifier().toString() });
729                success = false;
730            }
731            return success;
732        }
733    
734        /**
735         * This method returns true if a new item in process is populated and none of the open item in process' amounts are greater than zero.
736         * 
737         * @param cmDoc submitted cash management document
738         * @param trans transaction from cash management document
739         * @return true if a new item in process is populated and none of the open item in process' amounts are greater than zero.
740         */
741        public boolean checkItemInProcessIsNotPayingOffItemInProcess(CashieringTransaction trans) {
742            boolean success = true;
743            if (trans.getNewItemInProcess().isPopulated()) {
744                int count = 0;
745                for (CashieringItemInProcess advance : trans.getOpenItemsInProcess()) {
746                    if (advance.getCurrentPayment() != null && advance.getCurrentPayment().isGreaterThan(KualiDecimal.ZERO)) {
747                        GlobalVariables.getMessageMap().putError(KFSConstants.CASHIERING_TRANSACTION_OPEN_ITEM_IN_PROCESS_PROPERTY + "[" + count + "]", KFSKeyConstants.CashManagement.ERROR_DOCUMENT_CASHIERING_TRANSACTION_CANNOT_PAY_OFF_ADVANCE_WITH_ADVANCE, new String[] { advance.getItemIdentifier().toString() });
748                        success = false;
749                    }
750                    count += 1;
751                }
752            }
753            return success;
754        }
755    
756        /**
757         * This method returns true if all open items in process amounts do not exceed the total for each specific item's amount total
758         * 
759         * @param trans transaction from cash management document
760         * @return true if all open items in process amounts do not exceed the total for each specific item's amount total
761         */
762        public boolean checkAllPaidBackItemsInProcess(CashieringTransaction trans) {
763            boolean success = true;
764            int count = 0;
765            if (trans.getOpenItemsInProcess() != null) {
766                for (CashieringItemInProcess itemInProc : trans.getOpenItemsInProcess()) {
767                    success &= checkPaidBackItemInProcessDoesNotExceedTotal(itemInProc, count);
768                    count += 1;
769                }
770            }
771            return success;
772        }
773    
774        /**
775         * This method returns true if the current date is after all new items in process' open dates
776         * 
777         * @param trans transaction from cash management document
778         * @return true if the current date is after all new items in process' open dates
779         */
780        public boolean checkNewItemInProcessInPast(CashieringTransaction trans) {
781            boolean success = true;
782            if (trans.getNewItemInProcess().isPopulated()) {
783                if (trans.getNewItemInProcess().getItemOpenDate() != null && convertDateToDayYear(trans.getNewItemInProcess().getItemOpenDate()) > convertDateToDayYear(new Date())) {
784                    GlobalVariables.getMessageMap().putError("document.currentTransaction.newItemInProcess.itemOpenDate", KFSKeyConstants.CashManagement.ERROR_NEW_ITEM_IN_PROCESS_IN_FUTURE, new String[] {});
785                    success = false;
786                }
787            }
788            return success;
789        }
790    
791        /**
792         * This method calculates the total cash drawer reserves amount
793         * 
794         * @param cmDoc
795         * @param trans
796         * @return KualiDecimal as total from cash drawer reserves
797         */
798        protected KualiDecimal calculateTotalCashDrawerReserves(CashDrawer cashDrawer, CashieringTransaction trans) {
799            KualiDecimal reserves = new KualiDecimal(cashDrawer.getTotalAmount().bigDecimalValue());
800            reserves = reserves.add(trans.getMoneyInCurrency().getTotalAmount());
801            reserves = reserves.add(trans.getMoneyInCoin().getTotalAmount());
802            return reserves;
803        }
804    
805        /**
806         * This method returns the current day of year as an int for a specific date.
807         * 
808         * @param d date
809         * @return int as day of year
810         */
811        protected int convertDateToDayYear(Date d) {
812            Calendar cal = new GregorianCalendar();
813            cal.setTime(d);
814            return cal.get(Calendar.YEAR) * 366 + cal.get(Calendar.DAY_OF_YEAR);
815        }
816        
817    }
818