Blame view

service-user/src/main/java/com/java110/user/cmd/property/QueryAttendanceReminderCmd.java 9.98 KB
d92aa15f   王彪总   fix(config): 更新配置...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  package com.java110.user.cmd.property;
  
  import com.alibaba.fastjson.JSONArray;
  import com.alibaba.fastjson.JSONObject;
  import com.java110.core.annotation.Java110Cmd;
  import com.java110.core.context.ICmdDataFlowContext;
  import com.java110.core.event.cmd.Cmd;
  import com.java110.core.event.cmd.CmdEvent;
  import com.java110.user.dao.property.IAttendanceReminderV1ServiceDao;
  import com.java110.utils.exception.CmdException;
  import com.java110.utils.util.Assert;
  import com.java110.vo.ResultVo;
  import org.springframework.beans.factory.annotation.Autowired;
  
  import java.text.SimpleDateFormat;
  import java.util.*;
  
  @Java110Cmd(serviceCode = "property.queryAttendanceReminder")
  public class QueryAttendanceReminderCmd extends Cmd {
  
      @Autowired
      private IAttendanceReminderV1ServiceDao attendanceReminderV1ServiceDao;
  
      @Override
      public void validate(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) {
          Assert.hasKeyAndValue(reqJson, "userId", "未包含用户ID");
      }
  
      @Override
      public void doCmd(CmdEvent event, ICmdDataFlowContext context, JSONObject reqJson) {
          String userId = reqJson.getString("userId");
          String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
          Calendar cal = Calendar.getInstance();
          int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
          int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
          // Calendar.SUNDAY=1, MONDAY=2, ..., but schedule_classes_day uses week_flag differently
          // week_flag: 1=周一, 2=周二, ..., 7=周日
          int weekFlag = dayOfWeek == Calendar.SUNDAY ? 7 : dayOfWeek - 1;
  
          JSONArray overdueShifts = new JSONArray();
          boolean hasReminder = false;
  
          // 1. Query staff's schedule assignments
          Map<String, Object> staffParams = new HashMap<>();
          staffParams.put("staffId", userId);
          List<Map> staffSchedules = attendanceReminderV1ServiceDao.queryStaffSchedules(staffParams);
  
          if (staffSchedules == null || staffSchedules.isEmpty()) {
              // No schedule assigned → default to "always working", check if clocked in today
              checkDefaultReminder(userId, today, overdueShifts);
              if (!overdueShifts.isEmpty()) hasReminder = true;
              JSONObject result = new JSONObject();
              result.put("hasReminder", hasReminder);
              result.put("overdueShifts", overdueShifts);
              context.setResponseEntity(ResultVo.createResponseEntity(result));
              return;
          }
  
          // 2. For each schedule, determine today's work times
          for (Map staffSchedule : staffSchedules) {
              String scheduleId = (String) staffSchedule.get("scheduleId");
  
              // Query schedule definition
              Map<String, Object> schedParams = new HashMap<>();
              schedParams.put("scheduleId", scheduleId);
              List<Map> schedules = attendanceReminderV1ServiceDao.queryScheduleById(schedParams);
              if (schedules == null || schedules.isEmpty()) continue;
              Map schedule = schedules.get(0);
  
              String scheduleType = (String) schedule.get("scheduleType");
              if (!"1001".equals(schedule.get("state"))) continue; // not started
  
              List<Map> dayEntries = null;
  
              if ("1001".equals(scheduleType)) {
                  // Day-based schedule
                  int scheduleCycle = Integer.parseInt(safeString(schedule.get("scheduleCycle")));
                  String computeTimeStr = safeString(schedule.get("computeTime"));
                  try {
                      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                      Date computeDate = sdf.parse(computeTimeStr);
                      long daysBetween = (cal.getTimeInMillis() - computeDate.getTime()) / (24 * 3600 * 1000);
                      int dayInCycle = (int) ((daysBetween % scheduleCycle) + 1);
  
                      Map<String, Object> dayParams = new HashMap<>();
                      dayParams.put("scheduleId", scheduleId);
                      dayParams.put("day", String.valueOf(dayInCycle));
                      dayEntries = attendanceReminderV1ServiceDao.queryScheduleDay(dayParams);
                  } catch (Exception e) {
                      continue;
                  }
              } else if ("2002".equals(scheduleType)) {
                  // Week-based schedule
                  Map<String, Object> dayParams = new HashMap<>();
                  dayParams.put("scheduleId", scheduleId);
                  dayParams.put("day", String.valueOf(weekFlag));
                  dayParams.put("weekFlag", String.valueOf(weekFlag));
                  dayEntries = attendanceReminderV1ServiceDao.queryScheduleDay(dayParams);
              } else if ("3003".equals(scheduleType)) {
                  // Month-based schedule
                  Map<String, Object> dayParams = new HashMap<>();
                  dayParams.put("scheduleId", scheduleId);
                  dayParams.put("day", String.valueOf(dayOfMonth));
                  dayEntries = attendanceReminderV1ServiceDao.queryScheduleDay(dayParams);
              }
  
              if (dayEntries == null || dayEntries.isEmpty()) continue;
  
              for (Map dayEntry : dayEntries) {
                  String workday = (String) dayEntry.get("workday");
                  if ("2002".equals(workday)) continue; // rest day
  
                  String dayId = (String) dayEntry.get("dayId");
                  Map<String, Object> timeParams = new HashMap<>();
                  timeParams.put("dayId", dayId);
                  List<Map> times = attendanceReminderV1ServiceDao.queryScheduleTimes(timeParams);
  
                  if (times == null || times.isEmpty()) continue;
  
                  // 3. Check if clocked in today
                  Map<String, Object> punchParams = new HashMap<>();
                  punchParams.put("userId", userId);
                  punchParams.put("punchType", "ON");
                  Map todayPunch = attendanceReminderV1ServiceDao.queryTodayPunch(punchParams);
  
                  for (Map time : times) {
                      String startTime = (String) time.get("startTime");
                      String endTime = (String) time.get("endTime");
  
                      String fullStartTime = today + " " + startTime + ":00";
                      try {
                          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                          Date startDt = sdf.parse(fullStartTime);
                          Date now = new Date();
  
                          long diffMinutes = (now.getTime() - startDt.getTime()) / (60 * 1000);
                          // Within 5 minutes after start time, or after
                          if (diffMinutes >= 0 && diffMinutes <= 120) {
                              boolean clockedIn = todayPunch != null;
                              if (!clockedIn) {
                                  hasReminder = true;
                                  JSONObject shift = new JSONObject();
                                  shift.put("startTime", startTime);
                                  shift.put("endTime", endTime);
                                  shift.put("fullStartTime", fullStartTime);
                                  shift.put("scheduleName", staffSchedule.getOrDefault("scheduleName", ""));
                                  shift.put("overdueMinutes", diffMinutes);
                                  overdueShifts.add(shift);
                              }
                          }
                      } catch (Exception ignored) {
                      }
                  }
              }
          }
  
          // Fallback: if no overdue shifts found from schedule, but staff has schedule and no clockin,
          // use default time window to check
          if (!hasReminder && overdueShifts.isEmpty()) {
              Map<String, Object> punchParams = new HashMap<>();
              punchParams.put("userId", userId);
              punchParams.put("punchType", "ON");
              Map todayPunch = attendanceReminderV1ServiceDao.queryTodayPunch(punchParams);
              if (todayPunch == null) {
                  checkDefaultReminder(userId, today, overdueShifts);
                  if (!overdueShifts.isEmpty()) hasReminder = true;
              }
          }
  
          JSONObject result = new JSONObject();
          result.put("hasReminder", hasReminder);
          result.put("overdueShifts", overdueShifts);
          context.setResponseEntity(ResultVo.createResponseEntity(result));
      }
  
      /**
       * Default reminder check: when no schedule, assume staff should be working.
       * Checks if current time is past 8:00 AM and no clock-in today.
       */
      private void checkDefaultReminder(String userId, String today, JSONArray overdueShifts) {
          try {
              // Default work window: 08:00 - 18:00
              String defaultStart = today + " 08:00:00";
              String defaultEnd = today + " 18:00:00";
              SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
              Date startDt = sdf.parse(defaultStart);
              Date endDt = sdf.parse(defaultEnd);
              Date now = new Date();
  
              // Only remind between 8:00 and 18:00, and at least 5 min past start
              if (now.after(startDt) && now.before(endDt)) {
                  long diffMinutes = (now.getTime() - startDt.getTime()) / (60 * 1000);
                  if (diffMinutes >= 0 && diffMinutes <= 600) { // within 10 hours
                      JSONObject shift = new JSONObject();
                      shift.put("startTime", "08:00");
                      shift.put("endTime", "18:00");
                      shift.put("fullStartTime", defaultStart);
                      shift.put("scheduleName", "默认班次");
                      shift.put("overdueMinutes", diffMinutes);
                      overdueShifts.add(shift);
                  }
              }
          } catch (Exception ignored) {
          }
      }
  
      private String safeString(Object obj) {
          if (obj == null) return "";
          if (obj instanceof String) return (String) obj;
          if (obj instanceof java.sql.Timestamp) {
              return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.sql.Timestamp) obj);
          }
          return obj.toString();
      }
  }