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.endow.document.validation.impl;
017    
018    import java.math.BigDecimal;
019    import java.util.List;
020    
021    import org.kuali.kfs.module.endow.EndowConstants;
022    import org.kuali.kfs.module.endow.EndowKeyConstants;
023    import org.kuali.kfs.module.endow.EndowPropertyConstants;
024    import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine;
025    import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine;
026    import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionSecurity;
027    import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionTaxLotLine;
028    import org.kuali.kfs.module.endow.businessobject.HoldingTaxLot;
029    import org.kuali.kfs.module.endow.document.EndowmentSecurityDetailsDocument;
030    import org.kuali.kfs.module.endow.document.EndowmentTaxLotLinesDocument;
031    import org.kuali.kfs.module.endow.document.EndowmentTransactionLinesDocument;
032    import org.kuali.kfs.module.endow.document.HoldingAdjustmentDocument;
033    import org.kuali.kfs.module.endow.document.service.HoldingTaxLotService;
034    import org.kuali.kfs.module.endow.document.validation.DeleteTaxLotLineRule;
035    import org.kuali.kfs.sys.context.SpringContext;
036    import org.kuali.rice.kns.document.Document;
037    import org.kuali.rice.kns.util.ObjectUtils;
038    
039    public class HoldingAdjustmentDocumentRules extends EndowmentTransactionLinesDocumentBaseRules implements DeleteTaxLotLineRule<EndowmentTaxLotLinesDocument, EndowmentTransactionTaxLotLine, EndowmentTransactionLine, Number, Number> {
040    
041        /**
042         * @see org.kuali.kfs.module.endow.document.validation.impl.EndowmentTransactionLinesDocumentBaseRules#processAddTransactionLineRules(org.kuali.kfs.module.endow.document.EndowmentTransactionLinesDocument,
043         *      org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine)
044         */
045        @Override
046        public boolean processAddTransactionLineRules(EndowmentTransactionLinesDocument document, EndowmentTransactionLine line) {
047            boolean isValid = true;
048    
049            HoldingAdjustmentDocument holdingAdjustmentDocument = (HoldingAdjustmentDocument) document;
050    
051            isValid &= validateSecurity(isValid, holdingAdjustmentDocument, true);
052            isValid &= validateSecurityClassCodeTypeNotLiability(holdingAdjustmentDocument, true);
053    
054            isValid &= validateRegistration(isValid, holdingAdjustmentDocument, true);
055    
056            isValid &= canOnlyAddSourceOrTargetTransactionLines(holdingAdjustmentDocument, line, -1);
057    
058            isValid &= !checkIfBothTransactionAmountAndUnitAdjustmentAmountEmpty(line, -1);
059            isValid &= !checkIfBothTransactionAmountAndUnitAdjustmentAmountEntered(line, -1);
060    
061            if (isValid) {
062                isValid &= super.processAddTransactionLineRules(holdingAdjustmentDocument, line);
063    
064                if (isValid) {
065                    isValid &= validateKemidHasTaxLots(holdingAdjustmentDocument, line, -1);
066                }
067            }
068    
069            return isValid;
070    
071        }
072    
073        /**
074         * Check if the transaction amount and unit adjustment amount are empty
075         * 
076         * @return true if valid, false otherwise
077         */
078        protected boolean checkIfBothTransactionAmountAndUnitAdjustmentAmountEmpty(EndowmentTransactionLine line, int index) {
079            if ((ObjectUtils.isNull(line.getTransactionAmount()) || line.getTransactionAmount().isZero()) && (ObjectUtils.isNull(line.getUnitAdjustmentAmount()) || (line.getUnitAdjustmentAmount().compareTo(BigDecimal.ZERO) == 0))) {
080                putFieldError(getErrorPrefix(line, index) + EndowConstants.TRANSACTION_LINE_ERRORS, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_LINE_BOTH_AMOUNTS_BLANK);
081                return true;
082            }
083            return false;
084        }
085    
086        /**
087         * Check if the transaction amount and unit adjustment amount are filled in then do not allow the validation to succeed
088         * 
089         * @return true if valid, false otherwise
090         */
091        protected boolean checkIfBothTransactionAmountAndUnitAdjustmentAmountEntered(EndowmentTransactionLine line, int index) {
092            if ((ObjectUtils.isNotNull(line.getTransactionAmount()) && !line.getTransactionAmount().isZero()) && (ObjectUtils.isNotNull(line.getUnitAdjustmentAmount()) && (line.getUnitAdjustmentAmount().compareTo(BigDecimal.ZERO) == 0))) {
093                putFieldError(getErrorPrefix(line, index) + EndowConstants.TRANSACTION_LINE_ERRORS, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_TRANSACTION_LINE_BOTH_AMOUNTS_ENTERED);
094                return true;
095            }
096            return false;
097        }
098    
099        /**
100         * @see org.kuali.kfs.module.endow.document.validation.impl.EndowmentTransactionLinesDocumentBaseRules#validateTransactionLine(org.kuali.kfs.module.endow.document.EndowmentTransactionLinesDocument,
101         *      org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine, int)
102         */
103        @Override
104        protected boolean validateTransactionLine(EndowmentTransactionLinesDocument endowmentTransactionLinesDocument, EndowmentTransactionLine line, int index) {
105    
106            boolean isValid = !checkIfBothTransactionAmountAndUnitAdjustmentAmountEmpty(line, index);
107            // isValid &= !checkIfBothTransactionAmountAndUnitAdjustmentAmountEntered(line, index);
108            if (isValid) {
109                isValid &= super.validateTransactionLine(endowmentTransactionLinesDocument, line, index);
110            }
111    
112            return isValid;
113        }
114    
115        /**
116         * @see org.kuali.rice.kns.rules.DocumentRuleBase#processCustomRouteDocumentBusinessRules(org.kuali.rice.kns.document.Document)
117         */
118        @Override
119        protected boolean processCustomRouteDocumentBusinessRules(Document document) {
120            boolean isValid = true;
121            HoldingAdjustmentDocument holdingAdjustmentDocument = (HoldingAdjustmentDocument) document;
122    
123            isValid &= validateSecurity(isValid, holdingAdjustmentDocument, true);
124            isValid &= validateSecurityClassCodeTypeNotLiability(holdingAdjustmentDocument, true);
125    
126            isValid &= validateRegistration(isValid, holdingAdjustmentDocument, true);
127    
128            if (isValid) {
129                isValid &= hasOnlySourceOrTargetTransactionLines(holdingAdjustmentDocument);
130                isValid &= super.processCustomRouteDocumentBusinessRules(document);
131    
132                List<EndowmentTransactionLine> transLines = (holdingAdjustmentDocument.getSourceTransactionLines() != null && holdingAdjustmentDocument.getSourceTransactionLines().size() > 0) ? holdingAdjustmentDocument.getSourceTransactionLines() : holdingAdjustmentDocument.getTargetTransactionLines();
133    
134                if (transLines.isEmpty()) {
135                    putFieldError(EndowConstants.TRANSACTION_LINE_ERRORS, EndowKeyConstants.HoldingAdjustmentConstants.ERROR_HOLDING_ADJUSTMENT_BOTH_SOURCE_AND_TARGET_TRAN_LINES_BLANK);
136                    isValid =  false;
137                } else {
138                    for (int i = 0; i < transLines.size(); i++) {
139                        EndowmentTransactionLine transLine = transLines.get(i);
140                        isValid &= validateTaxLots(holdingAdjustmentDocument, transLine, i);
141                    }
142                }
143            }
144    
145            return isValid;
146        }
147    
148        /**
149         * @see org.kuali.kfs.module.endow.document.validation.impl.EndowmentTransactionalDocumentBaseRule#validateSecurityClassTypeCode(org.kuali.kfs.module.endow.document.EndowmentSecurityDetailsDocument,
150         *      boolean, java.lang.String)
151         */
152        @Override
153        protected boolean validateSecurityClassTypeCode(EndowmentSecurityDetailsDocument document, boolean isSource, String classCodeType) {
154            return true;
155        }
156    
157        /**
158         * Validates that the document has only source or target transaction lines, not both.
159         * 
160         * @param endowmentTransactionLinesDocument
161         * @return true if valid, false otherwise
162         */
163        protected boolean hasOnlySourceOrTargetTransactionLines(EndowmentTransactionLinesDocument endowmentTransactionLinesDocument) {
164            boolean isValid = true;
165    
166            boolean hasSourceTransLines = endowmentTransactionLinesDocument.getSourceTransactionLines() != null && endowmentTransactionLinesDocument.getSourceTransactionLines().size() > 0;
167            boolean hasTargetTransLines = endowmentTransactionLinesDocument.getTargetTransactionLines() != null && endowmentTransactionLinesDocument.getTargetTransactionLines().size() > 0;
168    
169            if (hasSourceTransLines && hasTargetTransLines) {
170                isValid = false;
171                putFieldError(EndowConstants.TRANSACTION_LINE_ERRORS, EndowKeyConstants.EndowmentTransactionDocumentConstants.ERROR_UNIT_SHARE_ADJUSTMENT_ADD_ONLY_SOURCE_OR_TARGET_TRAN_LINES);
172            }
173            return isValid;
174        }
175    
176        /**
177         * Validates that the user can only enter to or from transaction lines not both.
178         * 
179         * @param endowmentTransactionLinesDocument
180         * @param transLine
181         * @param index
182         * @return true if valid, false otherwise
183         */
184        protected boolean canOnlyAddSourceOrTargetTransactionLines(EndowmentTransactionLinesDocument endowmentTransactionLinesDocument, EndowmentTransactionLine transLine, int index) {
185            boolean isValid = true;
186    
187            boolean isSource = transLine instanceof EndowmentSourceTransactionLine;
188    
189            // the user can only enter to or from transaction lines not both
190            if (isSource) {
191                if (endowmentTransactionLinesDocument.getTargetTransactionLines() != null && endowmentTransactionLinesDocument.getTargetTransactionLines().size() > 0) {
192                    isValid = false;
193                    putFieldError(getErrorPrefix(transLine, index), EndowKeyConstants.HoldingAdjustmentConstants.ERROR_HOLDING_ADJUSTMENT_ADD_ONLY_SOURCE_OR_TARGET_TRAN_LINES);
194                }
195            }
196            else {
197                if (endowmentTransactionLinesDocument.getSourceTransactionLines() != null && endowmentTransactionLinesDocument.getSourceTransactionLines().size() > 0) {
198                    isValid = false;
199                    putFieldError(getErrorPrefix(transLine, index), EndowKeyConstants.HoldingAdjustmentConstants.ERROR_HOLDING_ADJUSTMENT_ADD_ONLY_SOURCE_OR_TARGET_TRAN_LINES);
200                }
201            }
202    
203            return isValid;
204        }
205    
206        /**
207         * Checks that there are holding tax lots with positive units for the given kemid, security, registration code and IP indicator.
208         * 
209         * @param endowmentTransactionLinesDocument
210         * @param transLine
211         * @param index
212         * @return true if there are tax lots that meet the criteria, false otherwise
213         */
214        protected boolean validateKemidHasTaxLots(EndowmentTransactionLinesDocument endowmentTransactionLinesDocument, EndowmentTransactionLine transLine, int index) {
215            boolean isValid = true;
216    
217            HoldingAdjustmentDocument holdingAdjustmentDocument = (HoldingAdjustmentDocument) endowmentTransactionLinesDocument;
218            EndowmentTransactionSecurity endowmentTransactionSecurity = holdingAdjustmentDocument.getSourceTransactionSecurity();
219    
220            HoldingTaxLotService holdingTaxLotService = SpringContext.getBean(HoldingTaxLotService.class);
221            List<HoldingTaxLot> holdingTaxLots = holdingTaxLotService.getAllTaxLotsWithPositiveUnits(transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), transLine.getTransactionIPIndicatorCode());
222    
223            if (holdingTaxLots == null || holdingTaxLots.size() == 0) {
224                isValid = false;
225                putFieldError(getErrorPrefix(transLine, index) + EndowPropertyConstants.KEMID, EndowKeyConstants.HoldingAdjustmentConstants.ERROR_HOLDING_ADJUSTMENT_NO_TAX_LOTS_FOUND);
226            }
227    
228            return isValid;
229        }
230    
231        /**
232         * @see org.kuali.kfs.module.endow.document.validation.DeleteTaxLotLineRule#processDeleteTaxLotLineRules(org.kuali.kfs.module.endow.document.EndowmentTaxLotLinesDocument,
233         *      org.kuali.kfs.module.endow.businessobject.EndowmentTransactionTaxLotLine,
234         *      org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine, java.lang.Number, java.lang.Number)
235         */
236        public boolean processDeleteTaxLotLineRules(EndowmentTaxLotLinesDocument endowmentTaxLotLinesDocument, EndowmentTransactionTaxLotLine endowmentTransactionTaxLotLine, EndowmentTransactionLine endowmentTransactionLine, Number transLineIndex, Number taxLotLineIndex) {
237            boolean isValid = true;
238    
239            if (endowmentTransactionLine.getTaxLotLines() != null && endowmentTransactionLine.getTaxLotLines().size() <= 1) {
240                isValid = false;
241                putFieldError(getErrorPrefix(endowmentTransactionLine, (Integer) transLineIndex) + EndowPropertyConstants.KEMID, EndowKeyConstants.HoldingAdjustmentConstants.ERROR_HOLDING__ADJUSTMENT_TRANS_LINE_MUST_HAVE_AT_LEAST_ONE_TAX_LOT);
242            }
243    
244            return isValid;
245        }
246    }