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.dataaccess.impl;
017    
018    import java.math.BigDecimal;
019    import java.sql.Date;
020    import java.sql.ResultSet;
021    import java.sql.SQLException;
022    import java.util.Calendar;
023    import java.util.Collection;
024    import java.util.GregorianCalendar;
025    import java.util.LinkedHashMap;
026    
027    import org.kuali.kfs.gl.Constant;
028    import org.kuali.kfs.gl.businessobject.TransientBalanceInquiryAttributes;
029    import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition;
030    import org.kuali.kfs.module.bc.businessobject.Position;
031    import org.kuali.kfs.module.bc.dataaccess.HumanResourcesPayrollDao;
032    import org.kuali.kfs.module.bc.document.dataaccess.impl.BudgetConstructionDaoJdbcBase;
033    import org.kuali.rice.kns.bo.PersistableBusinessObjectBase;
034    import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
035    
036    /**
037     * Implementation of <code>HumanResourcesPayrollDao</code> using JDBC to query PS_POSITION_DATA and then set other 
038     * <code>Position</code> fields to hard-coded IU values. This is for bootstrap only.
039     * 
040     * @see org.kuali.kfs.module.bc.dataaccess.HumanResourcesPayrollDao
041     */
042    public class HumanResourcesPayrollDaoJdbc extends BudgetConstructionDaoJdbcBase implements HumanResourcesPayrollDao {
043    
044        /**
045         * Gets the <code>Position</code> data by querying PS_POSITION_DATA then setting other fields using IU business rules. This is
046         * used in the bootstrap service implementation for an example.
047         * 
048         * @see org.kuali.kfs.module.bc.dataaccess.HumanResourcesPayrollDao#getPosition(java.lang.Integer, java.lang.String)
049         */
050        public Position getPosition(Integer universityFiscalYear, String positionNumber) {
051            PositionData positionData = getPositionDataForFiscalYear(universityFiscalYear, positionNumber);
052            
053            if (positionData == null) {
054                return null;
055            }
056    
057            Position position = new BudgetConstructionPosition();
058            position.setUniversityFiscalYear(universityFiscalYear);
059            position.setPositionNumber(positionNumber);
060    
061            populatePositionData(position, positionData);
062    
063            setDefaultObjectClass(position);
064    
065            return position;
066        }
067    
068        /**
069         * find positions with effective date before July 1 of fiscal year or on August 1 of fiscal year for academic tenure salary plan
070         * 
071         * @param universityFiscalYear
072         * @param positionNumber
073         * @return
074         */
075        protected PositionData getPositionDataForFiscalYear(Integer universityFiscalYear, String positionNumber) {
076            Collection<PositionData> positionData = getPositionData(positionNumber);
077            
078            if (positionData == null || positionData.isEmpty()) {
079                return null;
080            }
081    
082            // find positions with effective date before July 1 of fiscal year or on August 1 of fiscal year
083            // for academic tenure salary plan
084            Integer baseFiscalYear = universityFiscalYear - 1;
085    
086            GregorianCalendar calendarJuly1 = new GregorianCalendar(baseFiscalYear, Calendar.JULY, 1);
087            GregorianCalendar calendarAugust1 = new GregorianCalendar(universityFiscalYear, Calendar.AUGUST, 1);
088            Date julyFirst = new Date(calendarJuly1.getTimeInMillis());
089            Date augustFirst = new Date(calendarAugust1.getTimeInMillis());
090    
091            String academicTenureTrackSalaryPlan = new String("AC1");
092    
093            PositionData positionDataMaxEffectiveDate = null;
094            for (PositionData posData : positionData) {
095                Date positionEffectiveDate = posData.getEffectiveDate();
096                if ((positionEffectiveDate.compareTo(julyFirst) <= 0) || (academicTenureTrackSalaryPlan.equals(posData.getPositionSalaryPlanDefault()) && positionEffectiveDate.equals(augustFirst))) {
097                    // get position with max effective date for year
098                    if (positionDataMaxEffectiveDate == null || positionDataMaxEffectiveDate.getEffectiveDate().compareTo(positionEffectiveDate) < 0) {
099                        positionDataMaxEffectiveDate = posData;
100                    }
101                }
102            }
103    
104            return positionDataMaxEffectiveDate;
105        }
106    
107        /**
108         * Retrieves record for position key from PS_POSITION_DATA and returns populated <code>PositionData</code> business object.
109         */
110        public Collection<PositionData> getPositionData(String positionNumber) {
111            StringBuilder sqlBuilder = new StringBuilder();
112            sqlBuilder.append("SELECT POSITION_NBR, EFFDT, JOBCODE, POS_EFF_STATUS, DESCR, \n");
113            sqlBuilder.append("        DESCRSHORT, BUSINESS_UNIT, DEPTID, POSN_STATUS, STATUS_DT, \n");
114            sqlBuilder.append("        BUDGETED_POSN, STD_HRS_DEFAULT, STD_HRS_FREQUENCY, POS_REG_TEMP, \n");
115            sqlBuilder.append("        POS_FTE, POS_SAL_PLAN_DFLT, POS_GRADE_DFLT \n");
116            sqlBuilder.append(" FROM PS_POSITION_DATA \n");
117            sqlBuilder.append(" WHERE POSITION_NBR = ? \n");
118    
119            String sqlString = sqlBuilder.toString();
120    
121            ParameterizedRowMapper<PositionData> mapper = new ParameterizedRowMapper<PositionData>() {
122    
123                public PositionData mapRow(ResultSet rs, int rowNum) throws SQLException {
124                    PositionData positionData = new PositionData();
125                    positionData.setPositionNumber(rs.getString("POSITION_NBR"));
126                    positionData.setEffectiveDate(rs.getDate("EFFDT"));
127                    positionData.setJobCode(rs.getString("JOBCODE"));
128                    positionData.setPositionEffectiveStatus(rs.getString("POS_EFF_STATUS"));
129                    positionData.setDescription(rs.getString("DESCR"));
130                    positionData.setShortDescription(rs.getString("DESCRSHORT"));
131                    positionData.setBusinessUnit(rs.getString("BUSINESS_UNIT"));
132                    positionData.setDepartmentId(rs.getString("DEPTID"));
133                    positionData.setPositionStatus(rs.getString("POSN_STATUS"));
134                    positionData.setStatusDate(rs.getDate("STATUS_DT"));
135                    positionData.setBudgetedPosition(rs.getString("BUDGETED_POSN"));
136                    positionData.setStandardHoursDefault(rs.getBigDecimal("STD_HRS_DEFAULT"));
137                    positionData.setStandardHoursFrequency(rs.getString("STD_HRS_FREQUENCY"));
138                    positionData.setPositionRegularTemporary(rs.getString("POS_REG_TEMP"));
139                    positionData.setPositionFullTimeEquivalency(rs.getBigDecimal("POS_FTE"));
140                    positionData.setPositionSalaryPlanDefault(rs.getString("POS_SAL_PLAN_DFLT"));
141                    positionData.setPositionGradeDefault(rs.getString("POS_GRADE_DFLT"));
142    
143                    return positionData;
144                }
145            };
146    
147            return this.getSimpleJdbcTemplate().query(sqlString, mapper, positionNumber);
148        }
149    
150        /**
151         * Sets <code>Position</code> fields with data from <code>PositionData</code>
152         */
153        public void populatePositionData(Position position, PositionData positionData) {
154            position.setPositionEffectiveDate(positionData.getEffectiveDate());
155            position.setJobCode(positionData.getJobCode());
156            position.setPositionEffectiveStatus(positionData.getPositionEffectiveStatus());
157            position.setPositionDescription(positionData.getDescription());
158            position.setSetidDepartment(positionData.getBusinessUnit());
159            position.setPositionDepartmentIdentifier(positionData.getDepartmentId());
160            position.setPositionStatus(positionData.getPositionStatus());
161    
162            if ("Y".equalsIgnoreCase(positionData.getBudgetedPosition())) {
163                position.setBudgetedPosition(true);
164            }
165            else {
166                position.setBudgetedPosition(false);
167            }
168    
169            position.setPositionStandardHoursDefault(positionData.getStandardHoursDefault());
170            position.setPositionRegularTemporary(positionData.getPositionRegularTemporary());
171            position.setPositionFullTimeEquivalency(positionData.getPositionFullTimeEquivalency());
172            position.setPositionSalaryPlanDefault(positionData.getPositionSalaryPlanDefault());
173            position.setPositionGradeDefault(positionData.getPositionGradeDefault());
174        }
175    
176        /**
177         * Sets defaults based on salary plan.
178         * 
179         * @param position <code>Position</code> to update
180         */
181        public void setDefaultObjectClass(Position position) {
182            String salaryPlan = position.getPositionSalaryPlanDefault();
183    
184            if ("AC1".equals(salaryPlan)) {
185                position.setIuNormalWorkMonths(new Integer(10));
186                position.setIuPayMonths(new Integer(10));
187                position.setIuPositionType("AC");
188                position.setIuDefaultObjectCode("2000");
189            }
190    
191            else if ("PAO".equals(salaryPlan) || "PAU".equals(salaryPlan)) {
192                position.setIuNormalWorkMonths(new Integer(12));
193                position.setIuPayMonths(new Integer(12));
194                position.setIuPositionType("SM");
195                position.setIuDefaultObjectCode("2480");
196            }
197    
198            else if (salaryPlan.startsWith("P")) {
199                position.setIuNormalWorkMonths(new Integer(12));
200                position.setIuPayMonths(new Integer(12));
201                position.setIuPositionType("SM");
202                position.setIuDefaultObjectCode("2400");
203            }
204    
205            else {
206                position.setIuNormalWorkMonths(new Integer(12));
207                position.setIuPayMonths(new Integer(12));
208                position.setIuPositionType("SB");
209                position.setIuDefaultObjectCode("2500");
210                position.setPositionUnionCode("B1");
211            }
212        }
213        
214        protected class PositionData extends PersistableBusinessObjectBase {
215            private String positionNumber;
216            private String jobCode;
217            private Date effectiveDate;
218            private String positionEffectiveStatus;
219            private String description;
220            private String shortDescription;
221            private String businessUnit;
222            private String departmentId;
223            private String positionStatus;
224            private Date statusDate;
225            private String budgetedPosition;
226            private BigDecimal standardHoursDefault;
227            private String standardHoursFrequency;
228            private String positionRegularTemporary;
229            private BigDecimal positionFullTimeEquivalency;
230            private String positionSalaryPlanDefault;
231            private String positionGradeDefault;
232            private TransientBalanceInquiryAttributes dummyBusinessObject;
233    
234            /**
235             * Default constructor.
236             */
237            public PositionData() {
238                super();
239                this.dummyBusinessObject = new TransientBalanceInquiryAttributes();
240                this.dummyBusinessObject.setLinkButtonOption(Constant.LOOKUP_BUTTON_VALUE);
241            }
242    
243            /**
244             * Gets the positionNumber
245             * 
246             * @return Returns the positionNumber
247             */
248            public String getPositionNumber() {
249                return positionNumber;
250            }
251    
252            /**
253             * Sets the positionNumber
254             * 
255             * @param positionNumber The positionNumber to set.
256             */
257            public void setPositionNumber(String positionNumber) {
258                this.positionNumber = positionNumber;
259            }
260    
261            /**
262             * Gets the jobCode
263             * 
264             * @return Returns the jobCode
265             */
266            public String getJobCode() {
267                return jobCode;
268            }
269    
270            /**
271             * Sets the jobCode
272             * 
273             * @param jobCode The jobCode to set.
274             */
275            public void setJobCode(String jobCode) {
276                this.jobCode = jobCode;
277            }
278    
279            /**
280             * Gets the effectiveDate
281             * 
282             * @return Returns the effectiveDate
283             */
284            public Date getEffectiveDate() {
285                return effectiveDate;
286            }
287    
288            /**
289             * Sets the effectiveDate
290             * 
291             * @param effectiveDate The effectiveDate to set.
292             */
293            public void setEffectiveDate(Date effectiveDate) {
294                this.effectiveDate = effectiveDate;
295            }
296    
297            /**
298             * Gets the positionEffectiveStatus
299             * 
300             * @return Returns the positionEffectiveStatus
301             */
302            public String getPositionEffectiveStatus() {
303                return positionEffectiveStatus;
304            }
305    
306            /**
307             * Sets the positionEffectiveStatus
308             * 
309             * @param positionEffectiveStatus The positionEffectiveStatus to set.
310             */
311            public void setPositionEffectiveStatus(String positionEffectiveStatus) {
312                this.positionEffectiveStatus = positionEffectiveStatus;
313            }
314    
315            /**
316             * Gets the description
317             * 
318             * @return Returns the description
319             */
320            public String getDescription() {
321                return description;
322            }
323    
324            /**
325             * Sets the description
326             * 
327             * @param description The description to set.
328             */
329            public void setDescription(String description) {
330                this.description = description;
331            }
332    
333            /**
334             * Gets the shortDescription
335             * 
336             * @return Returns the shortDescription
337             */
338            public String getShortDescription() {
339                return shortDescription;
340            }
341    
342            /**
343             * Sets the shortDescription
344             * 
345             * @param shortDescription The shortDescription to set.
346             */
347            public void setShortDescription(String shortDescription) {
348                this.shortDescription = shortDescription;
349            }
350    
351            /**
352             * Gets the businessUnit
353             * 
354             * @return Returns the businessUnit
355             */
356            public String getBusinessUnit() {
357                return businessUnit;
358            }
359    
360            /**
361             * Sets the businessUnit
362             * 
363             * @param businessUnit The businessUnit to set.
364             */
365            public void setBusinessUnit(String businessUnit) {
366                this.businessUnit = businessUnit;
367            }
368    
369            /**
370             * Gets the departmentId
371             * 
372             * @return Returns the departmentId
373             */
374            public String getDepartmentId() {
375                return departmentId;
376            }
377    
378            /**
379             * Sets the departmentId
380             * 
381             * @param departmentId The departmentId to set.
382             */
383            public void setDepartmentId(String departmentId) {
384                this.departmentId = departmentId;
385            }
386    
387            /**
388             * Gets the positionStatus
389             * 
390             * @return Returns the positionStatus
391             */
392            public String getPositionStatus() {
393                return positionStatus;
394            }
395    
396            /**
397             * Sets the positionStatus
398             * 
399             * @param positionStatus The positionStatus to set.
400             */
401            public void setPositionStatus(String positionStatus) {
402                this.positionStatus = positionStatus;
403            }
404    
405            /**
406             * Gets the statusDate
407             * 
408             * @return Returns the statusDate
409             */
410            public Date getStatusDate() {
411                return statusDate;
412            }
413    
414            /**
415             * Sets the statusDate
416             * 
417             * @param statusDate The statusDate to set.
418             */
419            public void setStatusDate(Date statusDate) {
420                this.statusDate = statusDate;
421            }
422    
423            /**
424             * Gets the budgetedPosition
425             * 
426             * @return Returns the budgetedPosition
427             */
428            public String getBudgetedPosition() {
429                return budgetedPosition;
430            }
431    
432            /**
433             * Sets the budgetedPosition
434             * 
435             * @param budgetedPosition The budgetedPosition to set.
436             */
437            public void setBudgetedPosition(String budgetedPosition) {
438                this.budgetedPosition = budgetedPosition;
439            }
440    
441            /**
442             * Gets the standardHoursDefault
443             * 
444             * @return Returns the standardHoursDefault
445             */
446            public BigDecimal getStandardHoursDefault() {
447                return standardHoursDefault;
448            }
449    
450            /**
451             * Sets the standardHoursDefault
452             * 
453             * @param standardHoursDefault The standardHoursDefault to set.
454             */
455            public void setStandardHoursDefault(BigDecimal standardHoursDefault) {
456                this.standardHoursDefault = standardHoursDefault;
457            }
458    
459            /**
460             * Gets the standardHoursFrequency
461             * 
462             * @return Returns the standardHoursFrequency
463             */
464            public String getStandardHoursFrequency() {
465                return standardHoursFrequency;
466            }
467    
468            /**
469             * Sets the standardHoursFrequency
470             * 
471             * @param standardHoursFrequency The standardHoursFrequency to set.
472             */
473            public void setStandardHoursFrequency(String standardHoursFrequency) {
474                this.standardHoursFrequency = standardHoursFrequency;
475            }
476    
477            /**
478             * Gets the positionRegularTemporary
479             * 
480             * @return Returns the positionRegularTemporary
481             */
482            public String getPositionRegularTemporary() {
483                return positionRegularTemporary;
484            }
485    
486            /**
487             * Sets the positionRegularTemporary
488             * 
489             * @param positionRegularTemporary The positionRegularTemporary to set.
490             */
491            public void setPositionRegularTemporary(String positionRegularTemporary) {
492                this.positionRegularTemporary = positionRegularTemporary;
493            }
494    
495            /**
496             * Gets the positionFullTimeEquivalency
497             * 
498             * @return Returns the positionFullTimeEquivalency
499             */
500            public BigDecimal getPositionFullTimeEquivalency() {
501                return positionFullTimeEquivalency;
502            }
503    
504            /**
505             * Sets the positionFullTimeEquivalency
506             * 
507             * @param positionFullTimeEquivalency The positionFullTimeEquivalency to set.
508             */
509            public void setPositionFullTimeEquivalency(BigDecimal positionFullTimeEquivalency) {
510                this.positionFullTimeEquivalency = positionFullTimeEquivalency;
511            }
512    
513            /**
514             * Gets the positionSalaryPlanDefault
515             * 
516             * @return Returns the positionSalaryPlanDefault
517             */
518            public String getPositionSalaryPlanDefault() {
519                return positionSalaryPlanDefault;
520            }
521    
522            /**
523             * Sets the positionSalaryPlanDefault
524             * 
525             * @param positionSalaryPlanDefault The positionSalaryPlanDefault to set.
526             */
527            public void setPositionSalaryPlanDefault(String positionSalaryPlanDefault) {
528                this.positionSalaryPlanDefault = positionSalaryPlanDefault;
529            }
530    
531            /**
532             * Gets the positionGradeDefault
533             * 
534             * @return Returns the positionGradeDefault
535             */
536            public String getPositionGradeDefault() {
537                return positionGradeDefault;
538            }
539    
540            /**
541             * Sets the positionGradeDefault
542             * 
543             * @param positionGradeDefault The positionGradeDefault to set.
544             */
545            public void setPositionGradeDefault(String positionGradeDefault) {
546                this.positionGradeDefault = positionGradeDefault;
547            }
548    
549            /**
550             * construct the key list of the business object.
551             * 
552             * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper()
553             */
554            protected LinkedHashMap toStringMapper() {
555                LinkedHashMap m = new LinkedHashMap();
556                m.put("positionNumber", this.positionNumber);
557                if (this.effectiveDate != null) {
558                    m.put("effectiveDate", this.effectiveDate.toString());
559                }
560    
561                return m;
562            }
563    
564            /**
565             * Gets the dummyBusinessObject
566             * 
567             * @return Returns the dummyBusinessObject.
568             */
569            public TransientBalanceInquiryAttributes getDummyBusinessObject() {
570                return dummyBusinessObject;
571            }
572    
573            /**
574             * Sets the dummyBusinessObject
575             * 
576             * @param dummyBusinessObject The dummyBusinessObject to set.
577             */
578            public void setDummyBusinessObject(TransientBalanceInquiryAttributes dummyBusinessObject) {
579                this.dummyBusinessObject = dummyBusinessObject;
580            }
581        }
582    
583    }