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 org.kuali.kfs.module.bc.document.dataaccess.OrganizationSalarySettingSearchDao;
019    import org.kuali.rice.kns.util.Guid;
020    
021    /**
022     * This class...
023     * 
024     */
025    public class OrganizationSalarySettingSearchDaoJdbc extends BudgetConstructionDaoJdbcBase implements OrganizationSalarySettingSearchDao {
026    
027        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OrganizationSalarySettingSearchDaoJdbc.class);
028    
029        private static final int MAXLEVEL = 50;
030        private static String[] buildIntendedIncumbentSelectTemplates = new String[1];
031        private static String[] initSelectedPositionOrgsTemplates = new String[1];
032        private static String[] populateSelectedPositionOrgsSubTreeTemplates = new String[1];
033        private static String[] populatePositionSelectForSubTreeTemplates = new String[7];
034        
035        public OrganizationSalarySettingSearchDaoJdbc() {
036            
037            StringBuilder sqlText = new StringBuilder(500);
038    
039            // This uses the GROUP BY clause to force a distinct set so as to not trip over the unique constraint on the target table.
040            // For some reason the constraint is violated without the use of GROUP BY in Oracle
041            sqlText.append("INSERT INTO LD_BCN_INCUMBENT_SEL_T \n");
042            sqlText.append(" (PERSON_UNVL_ID, EMPLID, FIN_OBJECT_CD, PERSON_NM) \n");
043            sqlText.append("SELECT DISTINCT pull.person_unvl_id, bcaf.emplid, bcaf.fin_object_cd, iinc.person_nm \n");
044            sqlText.append("FROM LD_BCN_PULLUP_T pull, LD_BCN_ACCT_ORG_HIER_T hier, LD_PNDBC_APPTFND_T bcaf, LD_BCN_INTINCBNT_T iinc \n");
045            sqlText.append("WHERE pull.pull_flag > 0 \n");
046            sqlText.append("  AND pull.person_unvl_id = ? \n");
047            sqlText.append("  AND hier.univ_fiscal_yr = ? \n");
048            sqlText.append("  AND hier.org_fin_coa_cd = pull.fin_coa_cd \n");
049            sqlText.append("  AND hier.org_cd = pull.org_cd \n");
050            sqlText.append("  AND bcaf.univ_fiscal_yr = hier.univ_fiscal_yr \n");
051            sqlText.append("  AND bcaf.fin_coa_cd = hier.fin_coa_cd \n");
052            sqlText.append("  AND bcaf.account_nbr = hier.account_nbr \n");
053            sqlText.append("  AND bcaf.emplid NOT IN ('VACANT') \n");
054            sqlText.append("  AND iinc.emplid = bcaf.emplid \n");
055            sqlText.append("GROUP BY pull.person_unvl_id, bcaf.emplid, bcaf.fin_object_cd, iinc.person_nm");
056            buildIntendedIncumbentSelectTemplates[0] = sqlText.toString();
057            sqlText.delete(0, sqlText.length());
058            
059            sqlText.append("INSERT INTO LD_BCN_BUILD_POS_SEL01_MT \n");
060            sqlText.append(" (SESID, FIN_COA_CD, ORG_CD, ORG_LEVEL_CD) \n");
061            sqlText.append("SELECT ?, p.fin_coa_cd, p.org_cd,  ? \n");
062            sqlText.append("FROM LD_BCN_PULLUP_T p \n");
063            sqlText.append("WHERE p.pull_flag > 0 \n");
064            sqlText.append("  AND p.person_unvl_id = ?");
065            initSelectedPositionOrgsTemplates[0] = sqlText.toString();
066            sqlText.delete(0, sqlText.length());
067            
068            sqlText.append("INSERT INTO LD_BCN_BUILD_POS_SEL01_MT \n");
069            sqlText.append(" (SESID, FIN_COA_CD, ORG_CD, ORG_LEVEL_CD) \n");
070            sqlText.append("SELECT ?, r.fin_coa_cd, r.org_cd, ? \n");
071            sqlText.append("FROM LD_BCN_ORG_RPTS_T r, LD_BCN_BUILD_POS_SEL01_MT a \n");
072            sqlText.append("WHERE a.sesid = ? \n");
073            sqlText.append("  AND a.org_level_cd = ? \n");
074            sqlText.append("  AND a.fin_coa_cd = r.rpts_to_fin_coa_cd \n");
075            sqlText.append("  AND a.org_cd = r.rpts_to_org_cd \n");
076            sqlText.append("  AND not (r.fin_coa_cd = r.rpts_to_fin_coa_cd and r.org_cd = r.rpts_to_org_cd)");
077            populateSelectedPositionOrgsSubTreeTemplates[0] = sqlText.toString();
078            sqlText.delete(0, sqlText.length());
079    
080            // insert actives that are funded with person or vacant
081            sqlText.append("INSERT INTO LD_BCN_POS_SEL_T \n");
082            sqlText.append(" (PERSON_UNVL_ID, POSITION_NBR, UNIV_FISCAL_YR, EMPLID,  \n");
083            sqlText.append("  IU_POSITION_TYPE, POS_DEPTID, SETID_SALARY , SAL_ADMIN_PLAN, GRADE, POS_DESCR, PERSON_NM) \n");
084            sqlText.append("SELECT DISTINCT ?, p.position_nbr,p.univ_fiscal_yr, af.emplid, p.iu_position_type, \n");
085            sqlText.append("    p.pos_deptid, p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr, i.person_nm \n");
086            sqlText.append("FROM LD_BCN_BUILD_POS_SEL01_MT o, LD_BCN_POS_T p, \n");
087            sqlText.append("     LD_PNDBC_APPTFND_T af LEFT OUTER JOIN LD_BCN_INTINCBNT_T i ON (af.emplid=i.emplid) \n");
088            sqlText.append("WHERE o.sesid = ? \n");
089            sqlText.append("  AND p.pos_deptid = CONCAT(o.fin_coa_cd, CONCAT('-', o.org_cd)) \n");
090            sqlText.append("  AND p.univ_fiscal_yr = ? \n");
091            sqlText.append("  AND p.pos_eff_status <> 'I' \n");
092            sqlText.append("  AND p.univ_fiscal_yr = af.univ_fiscal_yr \n");
093            sqlText.append("  AND p.position_nbr = af.position_nbr \n");
094            sqlText.append("GROUP BY p.position_nbr, p.univ_fiscal_yr, af.emplid,p.iu_position_type, p.pos_deptid, \n");
095            sqlText.append("         p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr, i.person_nm");  
096            populatePositionSelectForSubTreeTemplates[0] = sqlText.toString();
097            sqlText.delete(0, sqlText.length());
098    
099            // add actives that are unfunded
100            sqlText.append("INSERT INTO LD_BCN_POS_SEL_T \n");
101            sqlText.append(" (PERSON_UNVL_ID, POSITION_NBR, UNIV_FISCAL_YR, EMPLID,  \n");
102            sqlText.append("  IU_POSITION_TYPE, POS_DEPTID, SETID_SALARY , SAL_ADMIN_PLAN, GRADE, POS_DESCR) \n");
103            sqlText.append("SELECT DISTINCT ?, p.position_nbr, p.univ_fiscal_yr, 'NOTFUNDED', p.iu_position_type, \n");
104            sqlText.append("    p.pos_deptid, p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr \n");
105            sqlText.append("FROM LD_BCN_BUILD_POS_SEL01_MT o, LD_BCN_POS_T p \n");
106            sqlText.append("WHERE o.sesid = ? \n");
107            sqlText.append("  AND p.pos_deptid = CONCAT(o.fin_coa_cd, CONCAT('-', o.org_cd)) \n");
108            sqlText.append("  AND p.univ_fiscal_yr = ? \n");
109            sqlText.append("  AND p.pos_eff_status <> 'I' \n");
110            sqlText.append("  AND NOT EXISTS \n");
111            sqlText.append("      (SELECT * \n");
112            sqlText.append("       FROM LD_BCN_POS_SEL_T ps \n");
113            sqlText.append("       WHERE ps.person_unvl_id = ? \n");
114            sqlText.append("         AND ps.position_nbr = p.position_nbr \n");
115            sqlText.append("         AND ps.univ_fiscal_yr = p.univ_fiscal_yr) \n");
116            sqlText.append("GROUP BY p.position_nbr, p.univ_fiscal_yr, p.iu_position_type, p.pos_deptid, \n");
117            sqlText.append("         p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr");
118            populatePositionSelectForSubTreeTemplates[1] = sqlText.toString();
119            sqlText.delete(0, sqlText.length());
120    
121            // insert inactives that are funded due to timing problem
122            sqlText.append("INSERT INTO LD_BCN_POS_SEL_T \n");
123            sqlText.append(" (PERSON_UNVL_ID, POSITION_NBR, UNIV_FISCAL_YR, EMPLID,  \n");
124            sqlText.append("  IU_POSITION_TYPE, POS_DEPTID, SETID_SALARY , SAL_ADMIN_PLAN, GRADE, POS_DESCR, PERSON_NM) \n");
125            sqlText.append("SELECT DISTINCT ?, p.position_nbr, p.univ_fiscal_yr, af.emplid, p.iu_position_type, \n");
126            sqlText.append("    p.pos_deptid, p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr, 'INACTIVE POS.' \n");
127            sqlText.append("FROM LD_BCN_BUILD_POS_SEL01_MT o, LD_BCN_POS_T p, \n");
128            sqlText.append("     LD_PNDBC_APPTFND_T af LEFT OUTER JOIN LD_BCN_INTINCBNT_T i ON (af.emplid=i.emplid) \n");
129            sqlText.append("WHERE o.sesid = ? \n");
130            sqlText.append("  AND p.pos_deptid = CONCAT(o.fin_coa_cd, CONCAT('-', o.org_cd)) \n");
131            sqlText.append("  AND p.univ_fiscal_yr = ? \n");
132            sqlText.append("  AND p.pos_eff_status = 'I' \n");
133            sqlText.append("  AND p.univ_fiscal_yr = af.univ_fiscal_yr \n");
134            sqlText.append("  AND p.position_nbr = af.position_nbr \n");
135            sqlText.append("GROUP BY p.position_nbr, p.univ_fiscal_yr, af.emplid,p.iu_position_type, p.pos_deptid, \n");
136            sqlText.append("         p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr");  
137            populatePositionSelectForSubTreeTemplates[2] = sqlText.toString();
138            sqlText.delete(0, sqlText.length());
139    
140            // insert inactives that are unfunded
141            sqlText.append("INSERT INTO LD_BCN_POS_SEL_T \n");
142            sqlText.append(" (PERSON_UNVL_ID, POSITION_NBR, UNIV_FISCAL_YR, EMPLID,  \n");
143            sqlText.append(" IU_POSITION_TYPE, POS_DEPTID, SETID_SALARY , SAL_ADMIN_PLAN, GRADE, POS_DESCR, PERSON_NM) \n");
144            sqlText.append("SELECT DISTINCT ?, p.position_nbr, p.univ_fiscal_yr, 'NOTFUNDED', p.iu_position_type, \n");
145            sqlText.append("    p.pos_deptid, p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr, 'INACTIVE POS.' \n");
146            sqlText.append("FROM LD_BCN_BUILD_POS_SEL01_MT o, LD_BCN_POS_T p \n");
147            sqlText.append("WHERE o.sesid = ? \n");
148            sqlText.append("  AND p.pos_deptid = CONCAT(o.fin_coa_cd, CONCAT('-', o.org_cd)) \n");
149            sqlText.append("  AND p.univ_fiscal_yr = ? \n");
150            sqlText.append("  AND p.pos_eff_status = 'I' \n");
151            sqlText.append("  AND NOT EXISTS \n");
152            sqlText.append("      (SELECT * \n");
153            sqlText.append("       FROM LD_BCN_POS_SEL_T ps \n");
154            sqlText.append("       WHERE ps.person_unvl_id = ? \n");
155            sqlText.append("         AND ps.position_nbr = p.position_nbr \n");
156            sqlText.append("         AND ps.univ_fiscal_yr = p.univ_fiscal_yr) \n");
157            sqlText.append("GROUP BY p.position_nbr, p.univ_fiscal_yr, p.iu_position_type, p.pos_deptid, \n");
158            sqlText.append("         p.setid_salary, p.pos_sal_plan_dflt, p.pos_grade_dflt, p.pos_descr");
159            populatePositionSelectForSubTreeTemplates[3] = sqlText.toString();
160            sqlText.delete(0, sqlText.length());
161    
162            // set name field for vacants
163            sqlText.append("UPDATE LD_BCN_POS_SEL_T p \n");
164            sqlText.append("SET person_nm = 'VACANT' \n");
165            sqlText.append("WHERE p.person_unvl_id = ? \n");
166            sqlText.append("  AND p.emplid = 'VACANT' \n");
167            sqlText.append("  AND p.person_nm IS NULL");
168            populatePositionSelectForSubTreeTemplates[4] = sqlText.toString();
169            sqlText.delete(0, sqlText.length());
170    
171            // reset name field for positions that only have deleted funding associated
172            // note that this overwrites any actual names except for Inactives
173            sqlText.append("UPDATE LD_BCN_POS_SEL_T p \n");
174            sqlText.append("SET person_nm = 'NOT FUNDED' \n");
175            sqlText.append("WHERE p.person_unvl_id = ? \n");
176            sqlText.append("  AND p.person_nm <> 'INACTIVE POS.' \n");
177            sqlText.append("  AND NOT EXISTS \n");
178            sqlText.append("    (SELECT * \n");
179            sqlText.append("    FROM LD_PNDBC_APPTFND_T af \n");
180            sqlText.append("    WHERE af.univ_fiscal_yr = p.univ_fiscal_yr \n");
181            sqlText.append("      AND af.position_nbr = p.position_nbr \n");
182            sqlText.append("      AND af.appt_fnd_dlt_cd = 'N')");
183            populatePositionSelectForSubTreeTemplates[5] = sqlText.toString();
184            sqlText.delete(0, sqlText.length());
185    
186            // anything leftover is not funded
187            sqlText.append("UPDATE LD_BCN_POS_SEL_T p \n");
188            sqlText.append("SET person_nm = 'NOT FUNDED' \n");
189            sqlText.append("WHERE p.person_unvl_id = ? \n");
190            sqlText.append("    AND p.person_nm IS NULL \n");
191            populatePositionSelectForSubTreeTemplates[6] = sqlText.toString();
192            
193        }
194        
195        /**
196         * @see org.kuali.kfs.module.bc.document.dataaccess.OrganizationSalarySettingSearchDao#buildIntendedIncumbentSelect(java.lang.String,
197         *      java.lang.Integer)
198         */
199        public void buildIntendedIncumbentSelect(String principalName, Integer universityFiscalYear) {
200    
201            LOG.debug("buildIntendedIncumbentSelect() started");
202            
203            getSimpleJdbcTemplate().update(buildIntendedIncumbentSelectTemplates[0], principalName, universityFiscalYear);
204        }
205    
206        /**
207         * @see org.kuali.kfs.module.bc.document.dataaccess.OrganizationSalarySettingSearchDao#cleanIntendedIncumbentSelect(java.lang.String)
208         */
209        public void cleanIntendedIncumbentSelect(String principalName) {
210    
211            clearTempTableByUnvlId("LD_BCN_INCUMBENT_SEL_T", "PERSON_UNVL_ID", principalName);
212        }
213    
214        /**
215         * @see org.kuali.kfs.module.bc.document.dataaccess.OrganizationSalarySettingSearchDao#buildPositionSelect(java.lang.String, java.lang.Integer)
216         */
217        public void buildPositionSelect(String principalName, Integer universityFiscalYear) {
218    
219            LOG.debug("buildPositionSelect() started");
220    
221            String sessionId = new Guid().toString();
222            initSelectedPositionOrgs(sessionId, principalName);
223    
224            populatePositionSelectForSubTree(sessionId, principalName, universityFiscalYear);
225    
226            clearTempTableBySesId("LD_BCN_BUILD_POS_SEL01_MT", "SESID", sessionId);
227        }
228    
229        protected void initSelectedPositionOrgs(String sessionId, String principalName) {
230    
231            int currentLevel = 0;
232    
233            int rowsAffected = getSimpleJdbcTemplate().update(initSelectedPositionOrgsTemplates[0], sessionId, currentLevel, principalName);
234    
235            if (rowsAffected > 0) {
236                populateSelectedPositionOrgsSubTree(currentLevel, sessionId);
237            }
238        }
239    
240        protected void populateSelectedPositionOrgsSubTree(int previousLevel, String sessionId) {
241    
242            if (previousLevel <= MAXLEVEL) {
243                int currentLevel = previousLevel + 1;
244    
245                int rowsAffected = getSimpleJdbcTemplate().update(populateSelectedPositionOrgsSubTreeTemplates[0], sessionId, currentLevel, sessionId, previousLevel);
246    
247                if (rowsAffected > 0) {
248                    populateSelectedPositionOrgsSubTree(currentLevel, sessionId);
249                }
250            }
251            else {
252                // overrun problem
253                LOG.warn(String.format("\nWarning: One or more selected organizations have reporting organizations more than maxlevel of %d deep.", MAXLEVEL));
254            }
255        }
256    
257        protected void populatePositionSelectForSubTree(String sessionId, String principalName, Integer universityFiscalYear) {
258    
259            // insert actives that are funded with person or vacant
260            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[0], principalName, sessionId, universityFiscalYear);
261    
262            // add actives that are unfunded
263            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[1], principalName, sessionId, universityFiscalYear, principalName);
264    
265            // insert inactives that are funded due to timing problem
266            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[2], principalName, sessionId, universityFiscalYear);
267    
268            // insert inactives that are unfunded
269            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[3], principalName, sessionId, universityFiscalYear, principalName);
270    
271            // set name field for vacants
272            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[4], principalName);
273    
274            // reset name field for positions that only have deleted funding associated
275            // note that this overwrites any actual names except for Inactives
276            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[5], principalName);
277    
278            // anything leftover is not funded
279            getSimpleJdbcTemplate().update(populatePositionSelectForSubTreeTemplates[6], principalName);
280    
281        }
282    
283        /**
284         * @see org.kuali.kfs.module.bc.document.dataaccess.OrganizationSalarySettingSearchDao#cleanPositionSelect(java.lang.String)
285         */
286        public void cleanPositionSelect(String principalName) {
287    
288            clearTempTableByUnvlId("LD_BCN_POS_SEL_T", "PERSON_UNVL_ID", principalName);
289        }
290    
291    }
292