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.bc.document.dataaccess.impl;
017    
018    import java.util.ArrayList;
019    
020    import org.kuali.kfs.module.bc.BCConstants;
021    import org.kuali.kfs.module.bc.batch.dataaccess.impl.SQLForStep;
022    import org.kuali.kfs.module.bc.document.dataaccess.BudgetConstructionSalaryStatisticsReportDao;
023    import org.kuali.rice.kns.service.PersistenceService;
024    import org.kuali.rice.kns.util.Guid;
025    
026    /**
027     * buiilds reporting source tables for the salary statistics report
028     */
029    
030    public class BudgetConstructionSalaryStatisticsReportDaoJdbc extends BudgetConstructionDaoJdbcBase implements BudgetConstructionSalaryStatisticsReportDao {
031        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BudgetConstructionSalaryStatisticsReportDaoJdbc.class);
032    
033        private static ArrayList<SQLForStep> updateReportsSalaryStatisticsTable = new ArrayList<SQLForStep>(12);
034        
035        private PersistenceService persistenceService;
036    
037        public BudgetConstructionSalaryStatisticsReportDaoJdbc() {
038    
039            ArrayList<Integer> insertionPoints = new ArrayList<Integer>(10);
040            
041            // builds and updates SalaryStatisticsReports
042    
043            /* get no leave bcaf, bcsf and posn info first */
044            StringBuilder sqlText = new StringBuilder(2500);
045            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT01_MT \n");
046            sqlText.append("(SESID, EMPLID, POSITION_NBR, SAL_AMT, SAL_PCT, SAL_MTHS, POS_CSF_AMT, POS_CSF_TM_PCT, SAL_PMTHS) \n");
047            sqlText.append("SELECT ?, bcaf.emplid, bcaf.position_nbr, bcaf.appt_rqst_amt, bcaf.appt_rqst_tm_pct, \n");
048            sqlText.append(" bcaf.appt_fnd_mo, bcsf.pos_csf_amt, bcsf.pos_csf_tm_pct, posn.iu_pay_months \n");
049            sqlText.append("FROM (LD_PNDBC_APPTFND_T bcaf LEFT OUTER JOIN  LD_BCN_CSF_TRCKR_T bcsf ON \n");
050            sqlText.append(" ((bcaf.univ_fiscal_yr = bcsf.univ_fiscal_yr) AND \n");
051            sqlText.append(" (bcaf.fin_coa_cd = bcsf.fin_coa_cd) AND \n");
052            sqlText.append(" (bcaf.account_nbr = bcsf.account_nbr) AND \n");
053            sqlText.append(" (bcaf.sub_acct_nbr = bcsf.sub_acct_nbr) AND \n");
054            sqlText.append(" (bcaf.fin_object_cd = bcsf.fin_object_cd) AND \n");
055            sqlText.append(" (bcaf.fin_sub_obj_cd = bcsf.fin_sub_obj_cd) AND \n");
056            sqlText.append(" (bcaf.position_nbr = bcsf.position_nbr) AND \n");
057            sqlText.append("(bcaf.emplid = bcsf.emplid))), LD_BCN_POS_T posn, LD_BCN_CTRL_LIST_T ctrl, LD_BCN_OBJ_PICK_T pick \n");
058            sqlText.append("WHERE ctrl.person_unvl_id = ? \n");
059            sqlText.append("AND bcaf.univ_fiscal_yr = ctrl.univ_fiscal_yr \n");
060            sqlText.append("AND bcaf.fin_coa_cd = ctrl.fin_coa_cd \n");
061            sqlText.append("AND bcaf.account_nbr = ctrl.account_nbr \n");
062            sqlText.append("AND bcaf.sub_acct_nbr = ctrl.sub_acct_nbr \n");
063            sqlText.append("AND bcaf.emplid <> 'VACANT' \n");
064            sqlText.append("AND bcaf.appt_fnd_dur_cd = '");
065            // default budget construction leave code
066            insertionPoints.add(sqlText.length());
067            sqlText.append("' \n");
068            sqlText.append("AND bcaf.fin_object_cd = pick.fin_object_cd \n");
069            sqlText.append("AND pick.person_unvl_id = ctrl.person_unvl_id \n");
070            sqlText.append("AND pick.select_flag > 0 \n");
071            sqlText.append("AND bcaf.univ_fiscal_yr = posn.univ_fiscal_yr \n");
072            sqlText.append("AND bcaf.position_nbr = posn.position_nbr \n");
073    
074            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText,insertionPoints));
075            sqlText.delete(0, sqlText.length());
076            insertionPoints.clear();
077    
078            /* get leave flagged bcaf, bcsf and posn info first */
079            /* uses leave related info from bcaf, etc */
080    
081            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT01_MT \n");
082            sqlText.append("(SESID, EMPLID, POSITION_NBR, SAL_AMT, SAL_PCT, SAL_MTHS, POS_CSF_AMT, POS_CSF_TM_PCT, SAL_PMTHS) \n");
083            sqlText.append("SELECT ?, bcaf.emplid, bcaf.position_nbr, bcaf.appt_rqst_csf_amt, bcaf.appt_rqcsf_tm_pct, posn.iu_norm_work_months, \n");
084            sqlText.append(" bcsf.pos_csf_amt, bcsf.pos_csf_tm_pct, posn.iu_pay_months \n");
085            sqlText.append("FROM (LD_PNDBC_APPTFND_T bcaf LEFT OUTER JOIN  LD_BCN_CSF_TRCKR_T bcsf ON \n");
086            sqlText.append(" ((bcaf.univ_fiscal_yr = bcsf.univ_fiscal_yr) AND \n");
087            sqlText.append(" (bcaf.fin_coa_cd = bcsf.fin_coa_cd) AND \n");
088            sqlText.append(" (bcaf.account_nbr = bcsf.account_nbr) AND \n");
089            sqlText.append(" (bcaf.sub_acct_nbr = bcsf.sub_acct_nbr) AND \n");
090            sqlText.append(" (bcaf.fin_object_cd = bcsf.fin_object_cd) AND \n");
091            sqlText.append(" (bcaf.fin_sub_obj_cd = bcsf.fin_sub_obj_cd) AND \n");
092            sqlText.append(" (bcaf.position_nbr = bcsf.position_nbr) AND \n");
093            sqlText.append(" (bcaf.emplid = bcsf.emplid))), LD_BCN_POS_T posn, LD_BCN_CTRL_LIST_T ctrl, LD_BCN_OBJ_PICK_T pick \n");
094            sqlText.append("WHERE ctrl.person_unvl_id = ? \n");
095            sqlText.append(" AND bcaf.univ_fiscal_yr = ctrl.univ_fiscal_yr \n");
096            sqlText.append(" AND bcaf.fin_coa_cd = ctrl.fin_coa_cd \n");
097            sqlText.append(" AND bcaf.account_nbr = ctrl.account_nbr \n");
098            sqlText.append(" AND bcaf.sub_acct_nbr = ctrl.sub_acct_nbr \n");
099            sqlText.append(" AND bcaf.emplid <> 'VACANT' \n");
100            sqlText.append(" AND bcaf.appt_fnd_dur_cd <> '");
101            // default budget construction leave code
102            insertionPoints.add(sqlText.length());
103            sqlText.append("' \n");
104            sqlText.append(" AND bcaf.fin_object_cd = pick.fin_object_cd \n");
105            sqlText.append(" AND pick.person_unvl_id = ctrl.person_unvl_id \n");
106            sqlText.append(" AND pick.select_flag > 0 \n");
107            sqlText.append(" AND bcaf.univ_fiscal_yr = posn.univ_fiscal_yr \n");
108            sqlText.append(" AND bcaf.position_nbr = posn.position_nbr \n");
109    
110            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText,insertionPoints));
111            sqlText.delete(0, sqlText.length());
112            insertionPoints.clear();
113            
114    
115            /* take the request appointment attributes (months, position months) from the record with the largest salary (arbitrarily use the smallest position number to break ties) */
116            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT02_MT \n");
117            sqlText.append("(SESID, EMPLID, SAL_MTHS, SAL_PMTHS) \n");
118            sqlText.append("SELECT DISTINCT ?, sd.emplid, sd.sal_mths, sd.sal_pmths \n");
119            sqlText.append("FROM LD_BCN_BUILD_SALTOT01_MT sd \n");
120            sqlText.append("WHERE sesid = ? \n");
121            sqlText.append(" AND sd.sal_amt <> 0 \n");
122            sqlText.append(" AND sd.sal_amt = \n");
123            sqlText.append("  (SELECT max(sd2.sal_amt) \n");
124            sqlText.append("  FROM LD_BCN_BUILD_SALTOT01_MT sd2 \n");
125            sqlText.append("  WHERE sd2.sesid = sd.sesid \n");
126            sqlText.append("  AND sd2.emplid = sd.emplid) \n");
127            sqlText.append(" AND sd.position_nbr = \n");
128            sqlText.append("  (SELECT min(sd3.position_nbr) \n");
129            sqlText.append("  FROM LD_BCN_BUILD_SALTOT01_MT sd3 \n");
130            sqlText.append("  WHERE sd3.sesid = sd.sesid \n");
131            sqlText.append("  AND sd3.emplid = sd.emplid \n");
132            sqlText.append("  AND sd3.sal_amt = sd.sal_amt) \n");
133    
134            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
135            sqlText.delete(0, sqlText.length());
136    
137            /* take the previous year's appointment attributes (work months, pay months) from the record with the largest previous year's salary (arbitrarily use the smallest position number to break ties)  */
138            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT03_MT (SESID, EMPLID, CSF_MTHS, CSF_PMTHS) \n");
139            sqlText.append("SELECT DISTINCT ?, sd.emplid, p.iu_norm_work_months, p.iu_pay_months \n");
140            sqlText.append("FROM LD_BCN_BUILD_SALTOT01_MT sd, LD_BCN_POS_T p \n");
141            sqlText.append("WHERE sesid = ? \n");
142            sqlText.append(" AND sd.pos_csf_amt <> 0 \n");
143            sqlText.append(" AND sd.pos_csf_amt = \n");
144            sqlText.append("  (SELECT max(sd2.pos_csf_amt) \n");
145            sqlText.append("  FROM LD_BCN_BUILD_SALTOT01_MT sd2 \n");
146            sqlText.append("  WHERE sd2.sesid = sd.sesid \n");
147            sqlText.append("   AND sd2.emplid = sd.emplid) \n");
148            sqlText.append(" AND sd.position_nbr = \n");
149            sqlText.append("  (SELECT min(sd3.position_nbr) \n");
150            sqlText.append("  FROM LD_BCN_BUILD_SALTOT01_MT sd3 \n");
151            sqlText.append("  WHERE sd3.sesid = sd.sesid \n");
152            sqlText.append("   AND sd3.emplid = sd.emplid \n");
153            sqlText.append("   AND sd3.pos_csf_amt = sd.pos_csf_amt) \n");
154            sqlText.append(" AND p.univ_fiscal_yr = ? \n");
155            sqlText.append(" AND p.position_nbr = sd.position_nbr \n");
156                
157            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
158            sqlText.delete(0, sqlText.length());
159                  
160            /* merge the request and base attributes into a single table and compute sums for salary and percent time */
161            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT04_MT \n");
162            sqlText.append("(SESID, EMPLID, POS_CSF_AMT, RES_CSF_AMT, POS_CSF_TM_PCT, SAL_AMT, \n");
163            sqlText.append(" SAL_PCT, SAL_FTE, SAL_MTHS, SAL_PMTHS, CSF_MTHS, CSF_PMTHS) \n");
164            sqlText.append("SELECT ?, sm.emplid, SUM(COALESCE(sd.pos_csf_amt,0)), 0, SUM(COALESCE(sd.pos_csf_tm_pct,0)), SUM(COALESCE(sd.sal_amt,0)), \n");
165            sqlText.append(" SUM(COALESCE(sd.sal_pct,0)), 0, sm.sal_mths, sm.sal_pmths, COALESCE(cm.csf_mths,0), COALESCE(cm.csf_pmths,0) \n");
166            sqlText.append("FROM (LD_BCN_BUILD_SALTOT02_MT sm  LEFT OUTER JOIN LD_BCN_BUILD_SALTOT03_MT cm \n");
167            sqlText.append(" ON ((sm.sesid = cm.sesid) AND (sm.emplid = cm.emplid))), LD_BCN_BUILD_SALTOT01_MT sd \n");
168            sqlText.append("WHERE sm.sesid = ? \n");
169            sqlText.append(" AND sd.sesid = sm.sesid \n");
170            sqlText.append(" AND sd.emplid = sm.emplid \n");
171            sqlText.append("GROUP BY sm.emplid, sm.sal_mths, sm.sal_pmths, cm.csf_mths, cm.csf_pmths \n");
172            
173            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
174            sqlText.delete(0, sqlText.length());
175    
176            /* restate the prior year (CSF) amount so it is comparable to the request (adjust for a change in months appointment, for example) */
177            sqlText.append("UPDATE LD_BCN_BUILD_SALTOT04_MT \n");
178            sqlText.append("SET res_csf_amt = ROUND(COALESCE(((pos_csf_amt * sal_pct * sal_mths * csf_pmths) / \n");
179            sqlText.append(" (pos_csf_tm_pct * csf_mths * sal_pmths)), 0.00),0) \n");
180            sqlText.append("WHERE sesid = ? AND pos_csf_tm_pct <> 0 AND csf_mths <> 0 AND sal_pmths <> 0 \n");
181    
182            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
183            sqlText.delete(0, sqlText.length());
184    
185            /* restate the prior year (CSF) amount by adjusting for a change in FTE from base to request */
186            sqlText.append("UPDATE LD_BCN_BUILD_SALTOT04_MT \n");
187            sqlText.append("SET res_csf_amt = ROUND(COALESCE(((res_csf_amt * sal_pmths) / csf_pmths), 0.00),0) \n");
188            sqlText.append("WHERE sesid = ? AND sal_pmths <> csf_pmths AND csf_pmths <> 0 \n");
189            
190            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
191            sqlText.delete(0, sqlText.length());
192            
193            /* calculate the request fte for each person */
194            sqlText.append("UPDATE LD_BCN_BUILD_SALTOT04_MT \n");
195            sqlText.append("SET sal_fte = COALESCE((((sal_pct * sal_mths) / sal_pmths) / 100.0), 0.0) \n");
196            sqlText.append("WHERE sesid = ? AND sal_pmths <> 0 \n");
197            
198            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
199            sqlText.delete(0, sqlText.length());
200            
201            /* create copy of detail rows by organization for continuing people */
202            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT05_MT \n");
203            sqlText.append("(SESID, ORG_FIN_COA_CD, ORG_CD, EMPLID, POS_CSF_AMT, APPT_RQST_AMT, APPT_RQST_FTE_QTY, INIT_RQST_AMT, INIT_RQST_FTE) \n");
204            sqlText.append("SELECT DISTINCT ?, ctrl.sel_org_fin_coa, ctrl.sel_org_cd, ssni.emplid, ssni.res_csf_amt, ssni.sal_amt, ssni.sal_fte, 0, 0 \n");
205            sqlText.append("FROM LD_BCN_CTRL_LIST_T ctrl, LD_PNDBC_APPTFND_T bcaf, LD_BCN_OBJ_PICK_T pick, LD_BCN_BUILD_SALTOT04_MT ssni \n");
206            sqlText.append("WHERE ssni.res_csf_amt <> 0 \n");
207            sqlText.append(" AND ctrl.person_unvl_id = ? \n");
208            sqlText.append(" AND bcaf.univ_fiscal_yr = ctrl.univ_fiscal_yr \n");
209            sqlText.append(" AND bcaf.fin_coa_cd = ctrl.fin_coa_cd \n");
210            sqlText.append(" AND bcaf.account_nbr = ctrl.account_nbr \n");
211            sqlText.append(" AND bcaf.sub_acct_nbr = ctrl.sub_acct_nbr \n");
212            sqlText.append(" AND bcaf.emplid = ssni.emplid \n");
213            sqlText.append(" AND ssni.sesid = ? \n");
214            sqlText.append(" AND bcaf.fin_object_cd = pick.fin_object_cd \n");
215            sqlText.append(" AND pick.person_unvl_id = ctrl.person_unvl_id \n");
216            sqlText.append(" AND pick.select_flag > 0 \n");
217    
218            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
219            sqlText.delete(0, sqlText.length());
220            
221            /* create copy of detail rows by organization for new people */
222            sqlText.append("INSERT INTO LD_BCN_BUILD_SALTOT05_MT \n");
223            sqlText.append("(SESID, ORG_FIN_COA_CD, ORG_CD, EMPLID, POS_CSF_AMT, APPT_RQST_AMT, APPT_RQST_FTE_QTY, INIT_RQST_AMT, INIT_RQST_FTE) \n");
224            sqlText.append("SELECT DISTINCT ?, ctrl.sel_org_fin_coa, ctrl.sel_org_cd, ssni.emplid, ssni.res_csf_amt, 0, 0, ssni.sal_amt, ssni.sal_fte \n");
225            sqlText.append("FROM LD_BCN_CTRL_LIST_T ctrl, LD_PNDBC_APPTFND_T bcaf, LD_BCN_OBJ_PICK_T pick, LD_BCN_BUILD_SALTOT04_MT ssni  \n");
226            sqlText.append("WHERE ssni.res_csf_amt = 0 \n");
227            sqlText.append(" AND ctrl.person_unvl_id = ? \n");
228            sqlText.append(" AND bcaf.univ_fiscal_yr = ctrl.univ_fiscal_yr \n");
229            sqlText.append(" AND bcaf.fin_coa_cd = ctrl.fin_coa_cd \n");
230            sqlText.append(" AND bcaf.account_nbr = ctrl.account_nbr \n");
231            sqlText.append(" AND bcaf.sub_acct_nbr = ctrl.sub_acct_nbr \n");
232            sqlText.append(" AND bcaf.emplid = ssni.emplid \n");
233            sqlText.append(" AND ssni.sesid = ? \n");
234            sqlText.append(" AND bcaf.fin_object_cd = pick.fin_object_cd \n");
235            sqlText.append(" AND pick.person_unvl_id = ctrl.person_unvl_id \n");
236            sqlText.append(" AND pick.select_flag > 0 \n");
237            
238            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
239            sqlText.delete(0, sqlText.length());
240            
241            /* sum the detailed (request amounts and FTE, adjusted base amounts and FTE) and insert into the report table */
242            sqlText.append("INSERT INTO LD_BCN_SLRY_TOT_T \n");
243            sqlText.append("(PERSON_UNVL_ID, ORG_FIN_COA_CD, ORG_CD, POS_CSF_AMT, APPT_RQST_AMT, APPT_RQST_FTE_QTY, INIT_RQST_AMT, INIT_RQST_FTE_QTY) \n");
244            sqlText.append("SELECT ?, org_fin_coa_cd, org_cd, ROUND(SUM(pos_csf_amt),0), SUM(appt_rqst_amt), SUM(appt_rqst_fte_qty), SUM(init_rqst_amt), SUM(init_rqst_fte) \n");
245            sqlText.append("FROM  LD_BCN_BUILD_SALTOT05_MT \n");
246            sqlText.append("WHERE sesid = ? \n");
247            sqlText.append("GROUP BY org_fin_coa_cd, org_cd \n");
248            
249            updateReportsSalaryStatisticsTable.add(new SQLForStep(sqlText));
250            sqlText.delete(0, sqlText.length());
251        
252        }
253    
254        public void cleanReportsSalaryStatisticsTable(String principalName) {
255            clearTempTableByUnvlId("LD_BCN_SLRY_TOT_T", "PERSON_UNVL_ID", principalName);
256            /**
257             * this is necessary to clear any rows for the tables we have just updated from the OJB cache.  otherwise, subsequent calls to OJB will fetch the old, unupdated cached rows.
258             */
259            persistenceService.clearCache();
260        }
261        
262        protected void cleanWorkTables(String idForSession)
263        {
264            clearTempTableBySesId("LD_BCN_BUILD_SALTOT01_MT","SESID",idForSession);
265            clearTempTableBySesId("LD_BCN_BUILD_SALTOT02_MT","SESID",idForSession);
266            clearTempTableBySesId("LD_BCN_BUILD_SALTOT03_MT","SESID",idForSession);
267            clearTempTableBySesId("LD_BCN_BUILD_SALTOT04_MT","SESID",idForSession);
268            clearTempTableBySesId("LD_BCN_BUILD_SALTOT05_MT","SESID",idForSession);
269        }
270    
271        public void updateReportsSalaryStatisticsTable(String principalName, Integer previousFiscalYear) {
272    
273            // get a unique session ID
274            String idForSession = (new Guid()).toString();
275            
276            // build the leave string to be inserted into some of the SQL below
277            ArrayList<String> leaveCodeToInsert = new ArrayList<String>(1);
278            leaveCodeToInsert.add(BCConstants.AppointmentFundingDurationCodes.NONE.durationCode);
279            
280            // remove any previous reporting rows geneterated by this user
281            cleanReportsSalaryStatisticsTable(principalName);
282            
283            // get appointment funding information for people with no leave
284            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(0).getSQL(leaveCodeToInsert), idForSession, principalName);
285            // get appointment funding information for people with a leave requested
286            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(1).getSQL(leaveCodeToInsert), idForSession, principalName);
287            // take the request appointment attributes for each individual from the request row with the largest request amount
288            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(2).getSQL(), idForSession, idForSession);
289            // take the previous year's appointment attributes for each individual from the previous year's (base) row with the largest amount
290            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(3).getSQL(), idForSession, idForSession, previousFiscalYear);
291            // merge the request and base (previous year's) appointment attributes into a single table and sum the corresponding amounts and percent time
292            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(4).getSQL(), idForSession, idForSession);
293            // adjust the base (prior year) amounts to match the attributes of the request (months of appointment, percent time, etc.)
294            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(5).getSQL(), idForSession);
295            // adjust the base (prior year) amounts for any change in FTE in the request
296            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(6).getSQL(), idForSession);
297            // calculate the request FTE for each person
298            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(7).getSQL(), idForSession);
299            // fetch the detail rows by organization for continuing people (both base and request)
300            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(8).getSQL(), idForSession, principalName, idForSession);
301            // fetch the dtail rows by organization for new people (zero out the base)
302            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(9).getSQL(), idForSession, principalName, idForSession);
303            // sum the salary and FTE from the detail to get the statistics
304            getSimpleJdbcTemplate().update(updateReportsSalaryStatisticsTable.get(10).getSQL(), principalName, idForSession);
305            
306            // clean out the working tables used in this session
307            cleanWorkTables(idForSession);
308            /**
309             * this is necessary to clear any rows for the tables we have just updated from the OJB cache.  otherwise, subsequent calls to OJB will fetch the old, unupdated cached rows.
310             */
311            persistenceService.clearCache();
312        }
313        
314        public void setPersistenceService(PersistenceService persistenceService)
315        {
316            this.persistenceService = persistenceService;
317        }
318    
319    }
320