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 java.math.BigDecimal;
19 import java.sql.Date;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.LinkedHashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.hr.time.accrual.AccrualCategory;
28 import org.kuali.hr.time.accrual.TimeOffAccrual;
29 import org.kuali.hr.time.accrual.dao.TimeOffAccrualDao;
30 import org.kuali.hr.time.earncode.EarnCode;
31 import org.kuali.hr.time.service.base.TkServiceLocator;
32 import org.kuali.hr.time.timeblock.TimeBlock;
33 import org.kuali.hr.time.timesheet.TimesheetDocument;
34 import org.kuali.hr.time.util.TkConstants;
35
36 public class TimeOffAccrualServiceImpl implements TimeOffAccrualService {
37
38 public static final String ACCRUAL_CATEGORY_KEY = "accrualCategory";
39 public static final String ACCRUAL_NAME_KEY = "accrualName";
40 public static final String YEARLY_CARRYOVER_KEY = "yearlyCarryover";
41 public static final String HOURS_ACCRUED_KEY = "hoursAccrued";
42 public static final String HOURS_TAKEN_KEY = "hoursTaken";
43 public static final String HOURS_ADJUST_KEY = "hoursAdjust";
44 public static final String TOTAL_HOURS_KEY = "totalHours";
45 public static final String EFF_DATE_KEY = "effdt";
46
47 private TimeOffAccrualDao timeOffAccrualDao;
48
49 public void setTimeOffAccrualDao(TimeOffAccrualDao timeOffAccrualDao) {
50 this.timeOffAccrualDao = timeOffAccrualDao;
51 }
52
53 @Override
54 public List<TimeOffAccrual> getTimeOffAccruals(String principalId, Date asOfDate) {
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 public List<String> validateAccrualHoursLimit(TimesheetDocument timesheetDocument) {
92 String pId = "";
93 if (timesheetDocument != null) {
94 pId = timesheetDocument.getPrincipalId();
95 }
96
97 return validateAccrualHoursLimit(pId, timesheetDocument.getTimeBlocks(), timesheetDocument.getAsOfDate());
98
99 }
100
101 public List<String> validateAccrualHoursLimit(String pId, List<TimeBlock> tbList, Date asOfDate) {
102 List<String> warningMessages = new ArrayList<String>();
103
104 List<Map<String, Object>> calcList = this.getTimeOffAccrualsCalc(pId, asOfDate);
105
106 if (tbList.isEmpty()) {
107 return warningMessages;
108 }
109 List<String> accruals = new ArrayList<String>();
110 for (Map<String, Object> aMap : calcList) {
111 accruals.add((String) aMap.get(ACCRUAL_CATEGORY_KEY));
112 }
113 for (Map<String, Object> aMap : calcList) {
114 String accrualCategory = (String) aMap.get(ACCRUAL_NAME_KEY);
115 List<TimeBlock> warningTbs = new ArrayList<TimeBlock>();
116 BigDecimal totalForAccrCate = this.totalForAccrCate(accrualCategory, tbList, warningTbs);
117
118 if(totalForAccrCate.compareTo(BigDecimal.ZERO)==0){
119 continue;
120 }
121 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)));
122
123 if (totalForAccrCate.compareTo(balanceHrs) == 1) {
124 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/>";
125 for(TimeBlock tb : warningTbs) {
126 msg += "Earn code: " + tb.getEarnCode()+ " Hours: " + tb.getHours().toString() + " on Date " + (tb.getBeginTimeDisplay() != null ? tb.getBeginTimeDisplay().toString(TkConstants.DT_BASIC_DATE_FORMAT) : "") + "<br/>";
127 }
128 warningMessages.add(msg);
129
130 }
131 }
132 return warningMessages;
133 }
134 public List<String> validateAccrualHoursLimitByEarnCode(TimesheetDocument timesheetDocument, String earnCode) {
135 List<String> warningMessages = new ArrayList<String>();
136 String pId = "";
137 if (timesheetDocument != null) {
138 pId = timesheetDocument.getPrincipalId();
139 }
140 List<Map<String, Object>> calcList = this.getTimeOffAccrualsCalc(pId, timesheetDocument.getAsOfDate());
141
142 List<TimeBlock> tbList = timesheetDocument.getTimeBlocks();
143 if (tbList.isEmpty()) {
144 return warningMessages;
145 }
146 List<String> accruals = new ArrayList<String>();
147 for (Map<String, Object> aMap : calcList) {
148 accruals.add((String) aMap.get(ACCRUAL_CATEGORY_KEY));
149 }
150
151 List<AccrualCategory> accrualCategories = TkServiceLocator.getAccrualCategoryService().getActiveAccrualCategories(timesheetDocument.getAsOfDate());
152
153 for(AccrualCategory accrualCategory : accrualCategories){
154 if(!accruals.contains(accrualCategory.getAccrualCategory()) && !StringUtils.equals(TkConstants.HOLIDAY_EARN_CODE, accrualCategory.getAccrualCategory())){
155 Map<String, Object> accrualData = new LinkedHashMap<String, Object>();
156 accrualData.put(ACCRUAL_CATEGORY_KEY, accrualCategory.getAccrualCategory());
157 accrualData.put(YEARLY_CARRYOVER_KEY, new BigDecimal(0.00));
158 accrualData.put(HOURS_ACCRUED_KEY, new BigDecimal(0.00));
159 accrualData.put(HOURS_TAKEN_KEY, new BigDecimal(0.00));
160 accrualData.put(HOURS_ADJUST_KEY, new BigDecimal(0.00));
161 calcList.add(accrualData);
162 }
163 }
164 for (Map<String, Object> aMap : calcList) {
165 String accrualCategory = (String) aMap.get(ACCRUAL_CATEGORY_KEY);
166 List<TimeBlock> warningTbs = new ArrayList<TimeBlock>();
167 BigDecimal totalForAccrCate = this.totalForAccrCate(accrualCategory, tbList, warningTbs);
168 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)));
169
170 if (totalForAccrCate.compareTo(balanceHrs) == 1) {
171 if (accrualCategory.equals(earnCode)) {
172 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: ";
173 for(TimeBlock tb : warningTbs) {
174 msg += "Earn code: " + tb.getEarnCode()+ " Hours: " + tb.getHours().toString() + " on Date " + (tb.getBeginTimeDisplay() != null ? tb.getBeginTimeDisplay().toString(TkConstants.DT_BASIC_DATE_FORMAT) : "") + " ";
175 }
176
177 warningMessages.add(msg);
178 }
179
180 }
181 }
182 return warningMessages;
183 }
184
185 public BigDecimal totalForAccrCate(String accrualCategory, List<TimeBlock> tbList, List<TimeBlock> warningTbs) {
186 BigDecimal total = BigDecimal.ZERO;
187 for (TimeBlock tb : tbList) {
188 String earnCode = tb.getEarnCode();
189 Date asOfDate = new java.sql.Date(tb.getBeginTimestamp().getTime());
190 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
191 String accrCate = "";
192 if (ec != null) {
193 accrCate = ec.getAccrualCategory();
194 if (accrCate != null) {
195 if (accrCate.equals(accrualCategory)) {
196 total = total.add(tb.getHours());
197 warningTbs.add(tb);
198 }
199 }
200 }
201 }
202 return total;
203 }
204
205 @Override
206 public TimeOffAccrual getTimeOffAccrual(Long laTimeOffAccrualId) {
207 return timeOffAccrualDao.getTimeOffAccrual(laTimeOffAccrualId);
208 }
209
210 @Override
211 public int getTimeOffAccrualCount(String accrualCategory, Date effectiveDate, String principalId, String lmAccrualId) {
212 return timeOffAccrualDao.getTimeOffAccrualCount(accrualCategory, effectiveDate, principalId, lmAccrualId);
213 }
214
215 @Override
216 public List<TimeOffAccrual> getTimeOffAccruals(String principalId, String accrualCategory){
217 return timeOffAccrualDao.getTimeOffAccruals(principalId, accrualCategory);
218 }
219 }