1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.accrual.service;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.kuali.hr.time.accrual.AccrualCategory;
21 import org.kuali.hr.time.accrual.TimeOffAccrual;
22 import org.kuali.hr.time.accrual.dao.TimeOffAccrualDao;
23 import org.kuali.hr.time.earncode.EarnCode;
24 import org.kuali.hr.time.service.base.TkServiceLocator;
25 import org.kuali.hr.time.timeblock.TimeBlock;
26 import org.kuali.hr.time.timesheet.TimesheetDocument;
27 import org.kuali.hr.time.util.TKUtils;
28 import org.kuali.hr.time.util.TkConstants;
29
30 import java.math.BigDecimal;
31 import java.sql.Date;
32 import java.util.*;
33
34 public class TimeOffAccrualServiceImpl implements TimeOffAccrualService {
35
36 private static final Logger LOG = Logger.getLogger(TimeOffAccrualServiceImpl.class);
37 public static final String ACCRUAL_CATEGORY_KEY = "accrualCategory";
38 public static final String ACCRUAL_NAME_KEY = "accrualName";
39 public static final String YEARLY_CARRYOVER_KEY = "yearlyCarryover";
40 public static final String HOURS_ACCRUED_KEY = "hoursAccrued";
41 public static final String HOURS_TAKEN_KEY = "hoursTaken";
42 public static final String HOURS_ADJUST_KEY = "hoursAdjust";
43 public static final String TOTAL_HOURS_KEY = "totalHours";
44 public static final String EFF_DATE_KEY = "effdt";
45
46 private TimeOffAccrualDao timeOffAccrualDao;
47
48 public void setTimeOffAccrualDao(TimeOffAccrualDao timeOffAccrualDao) {
49 this.timeOffAccrualDao = timeOffAccrualDao;
50 }
51
52 @Override
53 public List<TimeOffAccrual> getTimeOffAccruals(String principalId, Date asOfDate) {
54 java.sql.Date currentDate = TKUtils.getTimelessDate(null);
55 return timeOffAccrualDao.getActiveTimeOffAccruals(principalId, asOfDate);
56 }
57
58 @Override
59 public List<Map<String, Object>> getTimeOffAccrualsCalc(String principalId, Date asOfDate) {
60
61 List<Map<String, Object>> timeOffAccrualsCalc = new ArrayList<Map<String, Object>>();
62 Map<String,String> accrualCatToDescr = new HashMap<String, String>();
63
64 for(TimeOffAccrual timeOffAccrual : getTimeOffAccruals(principalId, asOfDate)) {
65 String accrualCatDescr = accrualCatToDescr.get(timeOffAccrual.getAccrualCategory());
66
67 if(StringUtils.isBlank(accrualCatDescr)){
68 AccrualCategory accrualCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(timeOffAccrual.getAccrualCategory(), asOfDate);
69 if(accrualCat != null){
70 accrualCatDescr = accrualCat.getDescr();
71 accrualCatToDescr.put(accrualCat.getAccrualCategory(), accrualCatDescr);
72 }
73 }
74 Map<String, Object> output = new LinkedHashMap<String, Object>();
75 output.put(ACCRUAL_CATEGORY_KEY, accrualCatDescr + "("+timeOffAccrual.getAccrualCategory()+")");
76 output.put(ACCRUAL_NAME_KEY, timeOffAccrual.getAccrualCategory());
77 output.put(YEARLY_CARRYOVER_KEY, timeOffAccrual.getYearlyCarryover());
78 output.put(HOURS_ACCRUED_KEY, timeOffAccrual.getHoursAccrued());
79 output.put(HOURS_TAKEN_KEY, timeOffAccrual.getHoursTaken());
80 output.put(HOURS_ADJUST_KEY, timeOffAccrual.getHoursAdjust());
81 BigDecimal totalHours = timeOffAccrual.getYearlyCarryover().add(timeOffAccrual.getHoursAccrued().subtract(timeOffAccrual.getHoursTaken()).add(timeOffAccrual.getHoursAdjust()));
82 output.put(TOTAL_HOURS_KEY, totalHours);
83 output.put(EFF_DATE_KEY, timeOffAccrual.getEffectiveDate());
84
85 timeOffAccrualsCalc.add(output);
86 }
87
88 return timeOffAccrualsCalc;
89 }
90
91 @SuppressWarnings("unchecked")
92 public List<String> validateAccrualHoursLimit(TimesheetDocument timesheetDocument) {
93 String pId = "";
94 if (timesheetDocument != null) {
95 pId = timesheetDocument.getPrincipalId();
96 }
97
98 return validateAccrualHoursLimit(pId, timesheetDocument.getTimeBlocks(), timesheetDocument.getAsOfDate());
99
100 }
101
102 @SuppressWarnings("unchecked")
103 public List<String> validateAccrualHoursLimit(String pId, List<TimeBlock> tbList, Date asOfDate) {
104 List<String> warningMessages = new ArrayList<String>();
105
106 List<Map<String, Object>> calcList = this.getTimeOffAccrualsCalc(pId, asOfDate);
107
108 if (tbList.isEmpty()) {
109 return warningMessages;
110 }
111 List<String> accruals = new ArrayList<String>();
112 for (Map<String, Object> aMap : calcList) {
113 accruals.add((String) aMap.get(ACCRUAL_CATEGORY_KEY));
114 }
115 for (Map<String, Object> aMap : calcList) {
116 String accrualCategory = (String) aMap.get(ACCRUAL_NAME_KEY);
117 List<TimeBlock> warningTbs = new ArrayList<TimeBlock>();
118 BigDecimal totalForAccrCate = this.totalForAccrCate(accrualCategory, tbList, warningTbs);
119
120 if(totalForAccrCate.compareTo(BigDecimal.ZERO)==0){
121 continue;
122 }
123 BigDecimal balanceHrs = (((BigDecimal)aMap.get(YEARLY_CARRYOVER_KEY)).add((BigDecimal)aMap.get(HOURS_ACCRUED_KEY)).subtract((BigDecimal)aMap.get(HOURS_TAKEN_KEY)).add((BigDecimal)aMap.get(HOURS_ADJUST_KEY)));
124
125 if (totalForAccrCate.compareTo(balanceHrs) == 1) {
126 String msg = "Warning: Total hours entered (" + totalForAccrCate.toString() + ") for Accrual Category \"" + (String) aMap.get(ACCRUAL_CATEGORY_KEY) + "\" has exceeded balance (" + balanceHrs.toString() + "). Problem Time Blocks are:<br/>";
127 for(TimeBlock tb : warningTbs) {
128 msg += "Earn code: " + tb.getEarnCode()+ " Hours: " + tb.getHours().toString() + " on Date " + (tb.getBeginTimeDisplay() != null ? tb.getBeginTimeDisplay().toString(TkConstants.DT_BASIC_DATE_FORMAT) : "") + "<br/>";
129 }
130 warningMessages.add(msg);
131
132 }
133 }
134 return warningMessages;
135 }
136 public List<String> validateAccrualHoursLimitByEarnCode(TimesheetDocument timesheetDocument, String earnCode) {
137 List<String> warningMessages = new ArrayList<String>();
138 String pId = "";
139 if (timesheetDocument != null) {
140 pId = timesheetDocument.getPrincipalId();
141 }
142 List<Map<String, Object>> calcList = this.getTimeOffAccrualsCalc(pId, timesheetDocument.getAsOfDate());
143
144 List<TimeBlock> tbList = timesheetDocument.getTimeBlocks();
145 if (tbList.isEmpty()) {
146 return warningMessages;
147 }
148 List<String> accruals = new ArrayList<String>();
149 for (Map<String, Object> aMap : calcList) {
150 accruals.add((String) aMap.get(ACCRUAL_CATEGORY_KEY));
151 }
152
153 List<AccrualCategory> accrualCategories = TkServiceLocator.getAccrualCategoryService().getActiveAccrualCategories(timesheetDocument.getAsOfDate());
154
155 for(AccrualCategory accrualCategory : accrualCategories){
156 if(!accruals.contains(accrualCategory.getAccrualCategory()) && !StringUtils.equals(TkConstants.HOLIDAY_EARN_CODE, accrualCategory.getAccrualCategory())){
157 Map<String, Object> accrualData = new LinkedHashMap<String, Object>();
158 accrualData.put(ACCRUAL_CATEGORY_KEY, accrualCategory.getAccrualCategory());
159 accrualData.put(YEARLY_CARRYOVER_KEY, new BigDecimal(0.00));
160 accrualData.put(HOURS_ACCRUED_KEY, new BigDecimal(0.00));
161 accrualData.put(HOURS_TAKEN_KEY, new BigDecimal(0.00));
162 accrualData.put(HOURS_ADJUST_KEY, new BigDecimal(0.00));
163 calcList.add(accrualData);
164 }
165 }
166 for (Map<String, Object> aMap : calcList) {
167 String accrualCategory = (String) aMap.get(ACCRUAL_CATEGORY_KEY);
168 List<TimeBlock> warningTbs = new ArrayList<TimeBlock>();
169 BigDecimal totalForAccrCate = this.totalForAccrCate(accrualCategory, tbList, warningTbs);
170 BigDecimal balanceHrs = (((BigDecimal)aMap.get(YEARLY_CARRYOVER_KEY)).add((BigDecimal)aMap.get(HOURS_ACCRUED_KEY)).subtract((BigDecimal)aMap.get(HOURS_TAKEN_KEY)).add((BigDecimal)aMap.get(HOURS_ADJUST_KEY)));
171
172 if (totalForAccrCate.compareTo(balanceHrs) == 1) {
173 if (accrualCategory.equals(earnCode)) {
174 String msg = "Warning: Total hours entered (" + totalForAccrCate.toString() + ") for Accrual Category \"" + (String) aMap.get(ACCRUAL_CATEGORY_KEY) + "\" has exceeded balance (" + balanceHrs.toString() + "). Problem Time Blocks are: ";
175 for(TimeBlock tb : warningTbs) {
176 msg += "Earn code: " + tb.getEarnCode()+ " Hours: " + tb.getHours().toString() + " on Date " + (tb.getBeginTimeDisplay() != null ? tb.getBeginTimeDisplay().toString(TkConstants.DT_BASIC_DATE_FORMAT) : "") + " ";
177 }
178
179 warningMessages.add(msg);
180 }
181
182 }
183 }
184 return warningMessages;
185 }
186
187 public BigDecimal totalForAccrCate(String accrualCategory, List<TimeBlock> tbList, List<TimeBlock> warningTbs) {
188 BigDecimal total = BigDecimal.ZERO;
189 for (TimeBlock tb : tbList) {
190 String earnCode = tb.getEarnCode();
191 Date asOfDate = new java.sql.Date(tb.getBeginTimestamp().getTime());
192 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
193 String accrCate = "";
194 if (ec != null) {
195 accrCate = ec.getAccrualCategory();
196 if (accrCate != null) {
197 if (accrCate.equals(accrualCategory)) {
198 total = total.add(tb.getHours());
199 warningTbs.add(tb);
200 }
201 }
202 }
203 }
204 return total;
205 }
206
207 @Override
208 public TimeOffAccrual getTimeOffAccrual(Long laTimeOffAccrualId) {
209 return timeOffAccrualDao.getTimeOffAccrual(laTimeOffAccrualId);
210 }
211
212 @Override
213 public int getTimeOffAccrualCount(String accrualCategory, Date effectiveDate, String principalId, String lmAccrualId) {
214 return timeOffAccrualDao.getTimeOffAccrualCount(accrualCategory, effectiveDate, principalId, lmAccrualId);
215 }
216 }