文章目录
- 一、考勤时间表设计
- 1、表设计
- 二、缓存考勤时间
- 1、mapper.xml
- 2、常量封装类
- 三、封装检测当天是否可以签到
- 1、为什么要检测是否可以签到?
- 2、怎么判断当天是工作日还是节假日?
- 3、封装持久层代码
- 1)查询特殊休息日
- 2)查询特殊工作日
- 3)查询当天是否已经签到
- 4、封装业务层代码
- 5、封装检测当天是否可以签到(Web层)
一、考勤时间表设计
在 sys_config 数据表中保存了系统的常量配置信息,其中就包括了考勤部分的常量信息。例如每天上班考勤从几点开始,截止到几点。下班考勤从几点开始,几点结束。
因为这些常量信息跟考勤模块息息相关,所以我们要编写Java代码,在SpringBoot项目启动的时
候,就去数据库读取这些常量信息,然后缓存成Java对象,全局都可以使用,当然季节性考勤时间会有变动,所以预留对应的接口修改数据库中时间同时刷新缓存中的时间。
1、表设计
DROP TABLE IF EXISTS `sys_config`;
CREATE TABLE `sys_config` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`param_key` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '参数名',
`param_value` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数值',
`status` tinyint(1) UNSIGNED NOT NULL COMMENT '状态',
`remark` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `unq_param_key`(`param_key`) USING BTREE,
INDEX `idx_status`(`status`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_config
-- ----------------------------
INSERT INTO `sys_config` VALUES (1, 'attendance_start_time', '06:00', 1, '上班考勤开始时间');
INSERT INTO `sys_config` VALUES (2, 'attendance_time', '08:30', 1, '上班时间');
INSERT INTO `sys_config` VALUES (3, 'attendance_end_time', '09:30', 1, '上班考勤截止时间');
INSERT INTO `sys_config` VALUES (4, 'closing_start_time', '16:30', 1, '下班考勤开始时间');
INSERT INTO `sys_config` VALUES (5, 'closing_time', '17:30', 1, '下班时间');
INSERT INTO `sys_config` VALUES (6, 'closing_end_time', '23:59', 1, '下班考勤截止时间');
二、缓存考勤时间
1、mapper.xml
<select id="selectAllParam" resultMap="BaseResultMap">
SELECT param_key, param_value FROM sys_config WHERE status = 1;
</select>
@Mapper
public interface SysConfigDao {
List<SysConfig> selectAllParam();
}
2、常量封装类
@Data
@Component
public class SystemConstants {
public String attendanceStartTime;
public String attendanceTime;
public String attendanceEndTime;
public String closingStartTime;
public String closingTime;
public String closingEndTime;
}
在 EmosWxApiApplication.java 文件中创建 init() 方法,读取常量数据并缓存
package com.buba.wechatmini;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
@SpringBootApplication
@Slf4j
public class WeChatMiNiApplication {
@Autowired
private SystemConstants selectAllParam;
@Autowired
private SysConfigDao sysConfigDao;
public static void main(String[] args) {
SpringApplication.run(WeChatMiNiApplication.class, args);
}
@PostConstruct
public void init() {
List<SysConfig> list = sysConfigDao.selectAllParam();
list.forEach(one -> {
String key = one.getParamKey();
key = StrUtil.toCamelCase(key);
String value = one.getParamValue();
try {
Field field = selectAllParam.getClass().getDeclaredField(key);
field.set(selectAllParam, value);
} catch (Exception e) {
log.error("执行异常", e);
}
});
}
}
三、封装检测当天是否可以签到
1、为什么要检测是否可以签到?
上面通过封装SystemConstants 系统常量信息,从而得知考勤是分为起止时间的。在考勤开始之前,
用户是不能考勤签到的。同理,在当天考勤结束之后,用户也是不能考勤签到的。甚至节假日也
不能考勤,只有正常的工作日才能考勤签到。
2、怎么判断当天是工作日还是节假日?
在数据库中有 tb_workday 和 tb_holidays 两张数据表,记录着哪天是工作日,哪天是休息日。系统默认周一至周五为工作日,周六周日为休息日。但是这两张表不是把所有的工作日和休息日都记录下来,只是记录比特殊的工作日或者休息日。比如说今年的中秋节赶上了礼拜四,于是就把周五和周六设置成休息日,跟中秋节连成三连休,然后周日正常上班。这种特殊情况我们就要记录下来。在tb_workday 记录周日是工作日,在 tb_holidays 表中记录周五那天是休息日。这样系统在中秋三连休期间不会执行考勤签到。
DROP TABLE IF EXISTS `tb_workday`;
CREATE TABLE `tb_workday` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`date` DATE NULL DEFAULT NULL COMMENT '日期',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `unq_date`(`date`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
DROP TABLE IF EXISTS `tb_holidays`;
CREATE TABLE `tb_holidays` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`date` DATE NOT NULL COMMENT '日期',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `unq_date`(`date`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '节假日表' ROW_FORMAT = DYNAMIC;
3、封装持久层代码
1)查询特殊休息日
在 TbHolidaysDao.xml 文件中,添加查询语句
<select id="searchTodayIsHolidays" resultType="Integer">
SELECT id FROM tb_holidays WHERE date=CURRENT_DATE LIMIT 1;
</select>
在 TbHolidaysDao.java 文件中,添加抽象方法
@Mapper
public interface TbHolidaysDao {
Integer searchTodayIsHolidays();
}
2)查询特殊工作日
在 TbWorkdayDao.xml 文件中,添加查询语句
<select id="searchTodayIsWorkday" resultType="Integer">
SELECT id FROM tb_workday WHERE date=CURRENT_DATE LIMIT 1;
</select>
在 TbWorkdayDao.java 文件中,添加抽象方法
@Mapper
public interface TbWorkdayDao {
Integer searchTodayIsWorkday();
}
3)查询当天是否已经签到
tb_checkin 表结构如下,系统不仅要记录考勤的人员、时间,还要记录考勤人的地理坐标。
DROP TABLE IF EXISTS `tb_checkin`;
CREATE TABLE `tb_checkin` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` int(10) UNSIGNED NOT NULL COMMENT '用户ID',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '签到地址',
`country` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '国家',
`province` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '省份',
`city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '城市',
`district` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '区划',
`status` tinyint(3) UNSIGNED NOT NULL COMMENT '考勤结果',
`risk` int(255) UNSIGNED NULL DEFAULT 0 COMMENT '风险等级',
`date` date NOT NULL COMMENT '签到日期',
`create_time` datetime(0) NOT NULL COMMENT '签到时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `unq_user_id`(`user_id`, `date`) USING BTREE,
INDEX `idx_date`(`date`) USING BTREE,
INDEX `idx_status`(`status`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 33 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '签到表' ROW_FORMAT = DYNAMIC;
在 TbCheckinDao.xml 文件中,添加查询语句
<select id="haveCheckin" parameterType="HashMap" resultType="Integer">
SELECT id
FROM tb_checkin
WHERE user_id = #{userId} AND date = CURRENT_DATE
AND create_time BETWEEN #{start} AND #{end}
LIMIT 1;
</select>
在 TbCheckinDao.java 文件中,添加抽象方法
@Mapper
public interface TbCheckinDao {
Integer haveCheckin(HashMap param);
}
4、封装业务层代码
检测是否可以考勤
@Service
@Scope("prototype")
@Slf4j
public class CheckinService {
@Autowired
private SystemConstants systemConstants;
@Autowired
private TbHolidaysDao holidaysDao;
@Autowired
private TbWorkdayDao workdayDao;
@Autowired
private TbCheckinDao checkinDao;
public String validCanCheckIn(int userId, String date) {
boolean bool_1 = holidaysDao.searchTodayIsHolidays() != null ? true : false;
boolean bool_2 = workdayDao.searchTodayIsWorkday() != null ? true : false;
String type = "工作日";
if (DateUtil.date().isWeekend()) {
type = "节假日";
}
if (bool_1) {
type = "节假日";
} else if (bool_2) {
type = "工作日";
}
if (type.equals("节假日")) {
return "节假日不需要考勤";
} else {
DateTime now = DateUtil.date();
String start = DateUtil.today() + " " + systemConstants.attendanceStartTime;
String end = DateUtil.today() + " " + systemConstants.attendanceEndTime;
DateTime attendanceStart = DateUtil.parse(start);
DateTime attendanceEnd = DateUtil.parse(end);
if (now.isBefore(attendanceStart)) {
return "没有到上班考勤开始时间";
} else if (now.isAfter(attendanceEnd)) {
return "超过了上班考勤结束时间";
} else {
HashMap map = new HashMap();
map.put("userId", userId);
map.put("date", date);
map.put("start", start);
map.put("end", end);
boolean bool = checkinDao.haveCheckin(map) != null ? true : false;
return bool ? "今日已经考勤,不用重复考勤" : "可以考勤";
}
}
}
}
5、封装检测当天是否可以签到(Web层)
/**
* @author qlx
*/
@RequestMapping("/checkin")
@RestController
@Api("签到模块Web接口")
@Slf4j
public class CheckinController {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private CheckinService checkinService;
@GetMapping("/validCanCheckIn")
@ApiOperation("查看用户今天是否可以签到")
public Result validCanCheckIn(@RequestHeader("token") String token) {
int userId = jwtUtil.getUserId(token);
String result = checkinService.validCanCheckIn(userId, DateUtil.today());
return Result.ok(result);
}
}