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.batch.service.impl;
017    
018    import java.math.BigDecimal;
019    import java.util.Collection;
020    
021    import org.kuali.kfs.module.endow.EndowParameterKeyConstants;
022    import org.kuali.kfs.module.endow.batch.AvailableCashUpdateStep;
023    import org.kuali.kfs.module.endow.batch.service.AvailableCashUpdateService;
024    import org.kuali.kfs.module.endow.batch.service.KEMIDCurrentAvailableBalanceService;
025    import org.kuali.kfs.module.endow.businessobject.KEMID;
026    import org.kuali.kfs.module.endow.businessobject.KEMIDCurrentAvailableBalance;
027    import org.kuali.kfs.module.endow.businessobject.KemidCurrentCash;
028    import org.kuali.kfs.module.endow.document.service.HoldingTaxLotService;
029    import org.kuali.kfs.module.endow.document.service.KEMIDService;
030    import org.kuali.kfs.module.endow.document.service.KemidCurrentCashService;
031    import org.kuali.rice.kns.service.ParameterService;
032    import org.kuali.rice.kns.util.Guid;
033    import org.kuali.rice.kns.util.ObjectUtils;
034    import org.springframework.transaction.annotation.Transactional;
035    
036    /**
037     * This class implements the AvailableCashUpdateService batch job.
038     */
039    @Transactional
040    public class AvailableCashUpdateServiceImpl implements AvailableCashUpdateService {
041        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AvailableCashUpdateServiceImpl.class);
042        
043        protected ParameterService parameterService;
044        protected KemidCurrentCashService kemidCurrentCashService;
045        protected HoldingTaxLotService holdingTaxLotService;
046        protected KEMIDService kEMIDService;
047        protected KEMIDCurrentAvailableBalanceService kEMIDCurrentAvailableBalanceService;
048        /**
049         * Constructs a AvailableCashUpdateServiceImpl instance
050         */
051        public AvailableCashUpdateServiceImpl() {
052            
053        }
054    
055        /**
056         * This process will generate records at the end of each processing cycle to summarize the 
057         * available spendable funds for every KEMID that is not closed.  
058         */
059        public boolean summarizeAvailableSpendableFunds() {
060            boolean success = true;
061            
062            if (systemParametersForSummarizeAvailableSpendableFundsJobExist()) {
063                //Step 1: remove all the records from END_AVAIL_CSH_T table
064                kEMIDCurrentAvailableBalanceService.clearAllAvailableCash();
065               
066                //Step 2: Retrieve all KEMID records where CLOSED_IND set to N
067                Collection<KEMID> kemIdRecords = kEMIDService.getAllKemIdWithClosedIndicatorNo();
068                //process the records in the collection
069                for (KEMID kemIdRecord : kemIdRecords) {
070                    KEMIDCurrentAvailableBalance kEMIDCurrentAvailableBalance = new KEMIDCurrentAvailableBalance();
071                    String kemId = kemIdRecord.getKemid();
072                    kEMIDCurrentAvailableBalance.setKemid(kemId);
073                    LOG.info("Calculate sum for available income cash and available principal cash for the kemid: " + kemId);                        
074                    kEMIDCurrentAvailableBalance.setAvailableIncomeCash(getAvailableIncomeCash(kemId));
075                    kEMIDCurrentAvailableBalance.setAvailablePrincipalCash(getAvailablePrincipalCash(kemId, kemIdRecord.getPrincipalRestrictionCode()));
076                    kEMIDCurrentAvailableBalance.setAvailableTotalCash(kEMIDCurrentAvailableBalance.getAvailableIncomeCash().add(kEMIDCurrentAvailableBalance.getAvailablePrincipalCash()));
077                    kEMIDCurrentAvailableBalance.setObjectId(new Guid().toString());
078                    kEMIDCurrentAvailableBalance.setVersionNumber(1L);
079                    kEMIDCurrentAvailableBalanceService.InsertAvailableCash(kEMIDCurrentAvailableBalance);
080                }
081            }
082            
083            LOG.info("Processed all KEMID records.  Summarized available spendable funds."); 
084            
085            return success;
086        }
087        
088        /**
089         * This method checks if the System parameters have been set up for this batch job.
090         * @result return true if the system parameters exist, else false
091         */
092        protected boolean systemParametersForSummarizeAvailableSpendableFundsJobExist() {
093            LOG.info("systemParametersForSummarizeAvailableSpendableFundsJobExist() started.");
094            
095            boolean systemParameterExists = true;
096            
097            // check to make sure the system parameter has been setup...
098            if (!getParameterService().parameterExists(AvailableCashUpdateStep.class, EndowParameterKeyConstants.AvailableCashUpdateConstants.AVAILABLE_CASH_PERCENT)) {
099              LOG.warn("AVAILABLE_CASH_PERCENT System parameter does not exist in the parameters list.  The job can not continue without this parameter");
100              return false;
101            }
102            
103            return systemParameterExists;
104        }
105    
106        /**
107         * Method to calculate sum of available cash Income Cash
108         * 1.   END_CRNT_CSH_T: CRNT_INC_CSH for the KEMID
109         * 2.  The Market Value of the KEMID END_HLDG_TAX_LOT_T records with a CLS_CD_TYP of 
110         * Cash Equivalents (C), and with the HLDG_IP_IND equal to I.
111         * 3.  The Market Value of the KEMID END_HLDG_TAX_LOT_T records with a CLS_CD_TYP of 
112         * Pooled Investment (P) and with the HLDG_IP_IND equal to I times the value in the 
113         * Available Cash Percent institutional parameter (accounts for only a percentage of the market 
114         * value allowing for pricing changes).
115         * @param kemId
116         * @return availableIncomeCash
117         */
118        protected BigDecimal getAvailableIncomeCash(String kemId) {
119            BigDecimal availableIncomeCash = BigDecimal.ZERO;
120            
121            KemidCurrentCash kemidCurrentCash = kemidCurrentCashService.getByPrimaryKey(kemId);
122            if (ObjectUtils.isNotNull(kemidCurrentCash)) {
123                availableIncomeCash = availableIncomeCash.add(kemidCurrentCash.getCurrentIncomeCash().bigDecimalValue());
124            }
125            
126            //get market value of the KEMID with class code type = C and IP indicator = I
127            availableIncomeCash = availableIncomeCash.add(holdingTaxLotService.getMarketValueForCashEquivalentsForAvailableIncomeCash(kemId));
128            
129            //get market value of the KEMID with class code type = P and IP indicator = I        
130            availableIncomeCash = availableIncomeCash.add(holdingTaxLotService.getMarketValueForPooledInvestmentForAvailableIncomeCash(kemId));        
131    
132            return availableIncomeCash;
133        }
134        
135        /**
136         * If the END_KEMID_T record has a TYP_PRIN_RESTR CD where END_TYP_RESTR_CD_T:  PERM is 
137         * equal to Y (Yes), the principal is Permanently Restricted and AVAIL_PRIN_CSH is zero (0.00).
138         * Otherwise Principal Available Cash is the sum of all of the following :
139         * END_CRNT_CSH: CRNT_PRIN_CSH
140         * The Market Value of the END_HLDG_TAX_LOT_T records with a CLS_CD_TYP of Cash Equivalents (C) 
141         * and with the HLDG_IP_IND equal to P.
142         * The Market Value of the KEMID END_HLDG_TAX_LOT_T records with a CLS_CD_TYP of 
143         * Pooled Investment (P) and with the HLDG_IP_IND equal to P times the value in the 
144         * Available Cash Percent institutional parameter (accounts for only a percentage of 
145         * the market value allowing for pricing changes)
146         *
147         * @param kemId, typeRestrictionCode
148         * @return availableIncomeCash
149         */
150        protected BigDecimal getAvailablePrincipalCash(String kemId, String typePrincipalRestrictedCode) {
151            BigDecimal availablePrincipalCash = BigDecimal.ZERO;
152            
153            if (kEMIDService.isTrueEndowment(kemId)) {
154                return availablePrincipalCash;
155            }
156            
157            KemidCurrentCash kemidCurrentCash = kemidCurrentCashService.getByPrimaryKey(kemId);
158            
159            if (ObjectUtils.isNotNull(kemidCurrentCash)) {
160                availablePrincipalCash = availablePrincipalCash.add(kemidCurrentCash.getCurrentPrincipalCash().bigDecimalValue());
161            }
162            
163            //get market value of the KEMID with class code type = C and IP indicator = P
164            availablePrincipalCash = availablePrincipalCash.add(holdingTaxLotService.getMarketValueForCashEquivalentsForAvailablePrincipalCash(kemId));
165            
166            //get market value of the KEMID with class code type = P and IP indicator = P        
167            availablePrincipalCash = availablePrincipalCash.add(holdingTaxLotService.getMarketValueForPooledInvestmentForAvailablePrincipalCash(kemId));        
168    
169            return availablePrincipalCash;
170        }    
171        
172        /**
173         * Gets the parameterService attribute.
174         * 
175         * @return Returns the parameterService.
176         */    
177        protected ParameterService getParameterService() {
178            return parameterService;
179        }
180    
181        /**
182         * Sets the parameterService attribute value.
183         * 
184         * @param parameterService The parameterService to set.
185         */    
186        public void setParameterService(ParameterService parameterService) {
187            this.parameterService = parameterService;
188        }
189    
190        /**
191         * gets the kemidCurrentCashService
192         * 
193         * @param kemidCurrentCashService The kemidCurrentCashService to get.
194         */
195        protected KemidCurrentCashService getKemidCurrentCashOpenRecordsService() {
196            return kemidCurrentCashService;
197        }
198    
199        /**
200         * Sets the kemidCurrentCashService
201         * 
202         * @param kemidCurrentCashService The kemidCurrentCashService to set.
203         */
204        public void setKemidCurrentCashService(KemidCurrentCashService kemidCurrentCashService) {
205            this.kemidCurrentCashService = kemidCurrentCashService;
206        }
207    
208        /**
209         * gets the holdingTaxLotService
210         * 
211         * @param holdingTaxLotService The holdingTaxLotService to get.
212         */    
213        protected HoldingTaxLotService getHoldingTaxLotService() {
214            return holdingTaxLotService;
215        }
216    
217        /**
218         * Sets the holdingTaxLotService
219         * 
220         * @param holdingTaxLotService The holdingTaxLotService to set.
221         */
222        public void setHoldingTaxLotService(HoldingTaxLotService holdingTaxLotService) {
223            this.holdingTaxLotService = holdingTaxLotService;
224        }
225        
226        /**
227         * gets the kEMIDService
228         * 
229         * @param kEMIDService The kEMIDService to get.
230         */    
231        protected KEMIDService getkEMIDService() {
232            return kEMIDService;
233        }
234    
235        /**
236         * gets the kEMIDService
237         * 
238         * @param kEMIDService The kEMIDService to get.
239         */    
240        public void setkEMIDService(KEMIDService kEMIDService) {
241            this.kEMIDService = kEMIDService;
242        }
243    
244        /**
245         * Gets the kEMIDCurrentAvailableBalanceService attribute. 
246         * @return Returns the kEMIDCurrentAvailableBalanceService.
247         */
248        protected KEMIDCurrentAvailableBalanceService getkEMIDCurrentAvailableBalanceService() {
249            return kEMIDCurrentAvailableBalanceService;
250        }
251    
252        /**
253         * Sets the kEMIDCurrentAvailableBalanceService attribute value.
254         * @param kEMIDCurrentAvailableBalanceService The kEMIDCurrentAvailableBalanceService to set.
255         */
256        public void setkEMIDCurrentAvailableBalanceService(KEMIDCurrentAvailableBalanceService kEMIDCurrentAvailableBalanceService) {
257            this.kEMIDCurrentAvailableBalanceService = kEMIDCurrentAvailableBalanceService;
258        }
259    }