三表一册数据来源
This commit is contained in:
parent
78b58fa7d6
commit
b0a89422bb
|
|
@ -0,0 +1,25 @@
|
|||
package com.bonus.job.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class MapBeanVo {
|
||||
|
||||
private String key;
|
||||
|
||||
private String value;
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
public MapBeanVo(String key, String value){
|
||||
this.value = value;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.bonus.job.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ThreeTableOneRosterPo {
|
||||
private Integer proId;
|
||||
private String attMonth;
|
||||
private Integer subId;
|
||||
private String subName;
|
||||
private Integer teamId;
|
||||
private String teamName;
|
||||
private Integer workerId;
|
||||
private String name;
|
||||
private String sex;
|
||||
private Integer postId;
|
||||
private String postName;
|
||||
private String idNumber;
|
||||
private String address;
|
||||
private String phone;
|
||||
private String proName;
|
||||
//1.花名册
|
||||
private String firstEinTime;
|
||||
private String lastExitTime;
|
||||
//2.农民工实名制工资信息报审表
|
||||
private String bankName;
|
||||
private String bankCardCode;
|
||||
private String bankIdentifierCode;
|
||||
private Integer contractId;
|
||||
private Double priceWage;
|
||||
private String payment;
|
||||
private String payDay;
|
||||
private String remark;
|
||||
|
||||
//3.考勤明细表
|
||||
private String einDay;
|
||||
private String attDay;
|
||||
private String isRepair;
|
||||
private String attendanceDay;
|
||||
private Integer checkDay;
|
||||
private Integer repairNum;
|
||||
private Integer attendanceNum;
|
||||
//4.工资明细表
|
||||
private Double payMoney;
|
||||
private Double deductMoney;
|
||||
private Double actualMoney;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.bonus.job.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class WorkerAttDayVo {
|
||||
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
private String day;
|
||||
/**
|
||||
* 是否在场
|
||||
*/
|
||||
private String isEin;
|
||||
/**
|
||||
* 是否打卡
|
||||
*/
|
||||
private String isAtt;
|
||||
/**
|
||||
* 是否为补卡
|
||||
*/
|
||||
private String isRepair;
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
package com.bonus.job.mapper;
|
||||
|
||||
import com.bonus.job.domain.BmWorkerBlackJob;
|
||||
import com.bonus.job.domain.MapBeanVo;
|
||||
import com.bonus.job.domain.PmWorkerJob;
|
||||
import com.bonus.job.domain.ThreeTableOneRosterPo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -33,4 +36,45 @@ public interface WorkerJobMapper {
|
|||
int insertWorkerBlack(List<BmWorkerBlackJob> list);
|
||||
|
||||
void updateWorkerEinDayRecordBlackStatus(List<BmWorkerBlackJob> list);
|
||||
|
||||
/**
|
||||
* 查询所有有人在场的工程
|
||||
* @param lastMonth
|
||||
* @return
|
||||
*/
|
||||
List<MapBeanVo> getAllPro(String lastMonth);
|
||||
|
||||
/**
|
||||
* 人员花名册
|
||||
* @param attMonth
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
* @param proId
|
||||
* @return
|
||||
*/
|
||||
List<ThreeTableOneRosterPo> getWorkerRosterData(@Param("attMonth") String attMonth, @Param("startTime") String startTime, @Param("endTime") String endTime, @Param("proId") Integer proId);
|
||||
|
||||
/**
|
||||
* 农民工实名制工资信息报审表
|
||||
* @param attMonth
|
||||
* @param proId
|
||||
* @return
|
||||
*/
|
||||
List<ThreeTableOneRosterPo> getWorkerApplyData(@Param("attMonth") String attMonth, @Param("proId") Integer proId);
|
||||
|
||||
/**
|
||||
* 农民工实名制工资信息考勤表
|
||||
* @param attMonth
|
||||
* @param proId
|
||||
* @return
|
||||
*/
|
||||
List<ThreeTableOneRosterPo> getWorkerAttData(@Param("attMonth") String attMonth, @Param("proId") Integer proId);
|
||||
|
||||
/**
|
||||
* 农民工实名制工资信息支付表
|
||||
* @param attMonth
|
||||
* @param proId
|
||||
* @return
|
||||
*/
|
||||
List<ThreeTableOneRosterPo> getWorkerPayData(@Param("attMonth") String attMonth, @Param("proId") Integer proId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,239 @@
|
|||
package com.bonus.job.task;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.bonus.job.domain.MapBeanVo;
|
||||
import com.bonus.job.domain.ThreeTableOneRosterPo;
|
||||
import com.bonus.job.domain.WorkerAttDayVo;
|
||||
import com.bonus.job.mapper.WorkerJobMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.time.YearMonth;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 三表一册定时任务调度
|
||||
*
|
||||
* @author bonus
|
||||
*/
|
||||
@Component("threeTableOneRosterTask")
|
||||
public class ThreeTableOneRosterTask {
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
@Resource
|
||||
private WorkerJobMapper mapper;
|
||||
|
||||
/**
|
||||
* 三表一册生成
|
||||
* 每月1号生成上月数据
|
||||
*/
|
||||
public void createThreeTableOneRosterData(){
|
||||
try{
|
||||
// 获取当前年月
|
||||
YearMonth current = YearMonth.now();
|
||||
// 获取上一个月
|
||||
YearMonth lastMonth = current.minusMonths(1);
|
||||
// 本月第一天
|
||||
LocalDate firstDayOfThisMonth = YearMonth.now().atDay(1);
|
||||
// 上个月第一天:先得到本月第一天,再减一个月
|
||||
LocalDate firstDayOfLastMonth = YearMonth.now().minusMonths(1).atDay(1);
|
||||
|
||||
String startTime = firstDayOfLastMonth.format(FORMATTER)+" 00:00:00";
|
||||
String endTime = firstDayOfThisMonth.format(FORMATTER)+" 00:00:00";
|
||||
|
||||
//查询所有有人在场的工程
|
||||
List<MapBeanVo> listPro = mapper.getAllPro(lastMonth.toString());
|
||||
listPro.forEach(mapBeanVo -> {
|
||||
//每个工程去循环生成
|
||||
//1.花名册
|
||||
List<ThreeTableOneRosterPo> listRoster = mapper.getWorkerRosterData(lastMonth.toString(),startTime,endTime,mapBeanVo.getId());
|
||||
//2.农民工实名制工资信息报审表
|
||||
List<ThreeTableOneRosterPo> listApply = mapper.getWorkerApplyData(lastMonth.toString(),mapBeanVo.getId());
|
||||
//3.考勤明细表
|
||||
List<ThreeTableOneRosterPo> listAtt = mapper.getWorkerAttData(lastMonth.toString(),mapBeanVo.getId());
|
||||
List<ThreeTableOneRosterPo> listAttDeal = dealAttData(listAtt,lastMonth);
|
||||
//4.农民工资支付表
|
||||
// 数据串联生成工资支付数据
|
||||
// 通过workerId,proId将listApply、listAttDeal数据填充到listRoster
|
||||
// 先将listApply按workerId和proId分组
|
||||
Map<String, ThreeTableOneRosterPo> applyMap = listApply.stream()
|
||||
.collect(Collectors.toMap(
|
||||
item -> item.getWorkerId() + "_" + item.getProId(),
|
||||
item -> item,
|
||||
(existing, replacement) -> existing
|
||||
));
|
||||
|
||||
// 将listAttDeal按workerId和proId分组
|
||||
Map<String, ThreeTableOneRosterPo> attDealMap = listAttDeal.stream()
|
||||
.collect(Collectors.toMap(
|
||||
item -> item.getWorkerId() + "_" + item.getProId(),
|
||||
item -> item,
|
||||
(existing, replacement) -> existing
|
||||
));
|
||||
|
||||
// 遍历listRoster,填充数据
|
||||
listRoster.forEach(roster -> {
|
||||
String key = roster.getWorkerId() + "_" + roster.getProId();
|
||||
// 从listApply中查找匹配的数据
|
||||
ThreeTableOneRosterPo applyData = applyMap.get(key);
|
||||
if (applyData != null) {
|
||||
// 填充apply相关字段
|
||||
roster.setBankName(applyData.getBankName());
|
||||
roster.setBankCardCode(applyData.getBankCardCode());
|
||||
roster.setBankIdentifierCode(applyData.getBankIdentifierCode());
|
||||
roster.setContractId(applyData.getContractId());
|
||||
roster.setPriceWage(applyData.getPriceWage());
|
||||
roster.setPayment(applyData.getPayment());
|
||||
}
|
||||
|
||||
// 从listAttDeal中查找匹配的数据
|
||||
ThreeTableOneRosterPo attDealData = attDealMap.get(key);
|
||||
if (attDealData != null) {
|
||||
// 填充attDeal相关字段
|
||||
roster.setAttendanceDay(attDealData.getAttendanceDay());
|
||||
roster.setAttendanceNum(attDealData.getAttendanceNum());
|
||||
roster.setRepairNum(attDealData.getRepairNum());
|
||||
roster.setCheckDay(attDealData.getCheckDay());
|
||||
// 根据实际需要填充其他字段
|
||||
}
|
||||
// 计算工资,使用精度计算,如果有null返回0
|
||||
double calculatePayMoney = Optional.ofNullable(roster.getPriceWage()).orElse(0.0) *
|
||||
Optional.ofNullable(roster.getAttendanceNum()).orElse(0);
|
||||
roster.setPayMoney(calculatePayMoney);
|
||||
roster.setDeductMoney(0.0);
|
||||
roster.setActualMoney(calculatePayMoney);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
//1.花名册
|
||||
|
||||
}catch (Exception e){
|
||||
logger.error("人员入场更新表失败,{}",e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<ThreeTableOneRosterPo> dealAttData(List<ThreeTableOneRosterPo> listAtt, YearMonth lastMonth) {
|
||||
// 按照 workerId 分组
|
||||
Map<Integer, List<ThreeTableOneRosterPo>> groupedByWorkerId = listAtt.stream()
|
||||
.collect(Collectors.groupingBy(ThreeTableOneRosterPo::getWorkerId));
|
||||
// 获取上个月的所有日期
|
||||
List<MapBeanVo> daysOfMonth = generateDaysOfMonth(lastMonth);
|
||||
// 处理每个员工的考勤数据
|
||||
// 处理每个员工的考勤数据
|
||||
// 获取第一条数据作为基础数据
|
||||
// 处理考勤日数据
|
||||
// 将处理后的考勤日数据设置到基础数据中
|
||||
return groupedByWorkerId.entrySet().stream()
|
||||
.map(entry -> {
|
||||
Integer workerId = entry.getKey();
|
||||
List<ThreeTableOneRosterPo> workerAttendance = entry.getValue();
|
||||
// 获取第一条数据作为基础数据
|
||||
ThreeTableOneRosterPo baseData = workerAttendance.get(0);
|
||||
// 处理考勤日数据
|
||||
List<WorkerAttDayVo> attendanceDays = processWorkerAttendance(workerId, workerAttendance, daysOfMonth);
|
||||
//计算出勤天数
|
||||
int attNum = 0;
|
||||
int repairNum = 0;
|
||||
for (WorkerAttDayVo attendanceDay : attendanceDays) {
|
||||
if("1".equals(attendanceDay.getIsAtt())){
|
||||
attNum++;
|
||||
if("1".equals(attendanceDay.getIsRepair())){
|
||||
repairNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
baseData.setAttendanceNum(attNum);
|
||||
baseData.setRepairNum(repairNum);
|
||||
baseData.setCheckDay(attNum-repairNum);
|
||||
JSONArray o = (JSONArray)JSON.toJSON(attendanceDays);
|
||||
// 将处理后的考勤日数据设置到基础数据中
|
||||
baseData.setAttendanceDay(JSON.toJSONString(o));
|
||||
return baseData;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成指定年月的所有日期列表
|
||||
* @param yearMonth 指定的年月
|
||||
* @return 日期列表,包含 yyyy-MM-dd 和 dd 两个字段的 MapBeanVo
|
||||
*/
|
||||
private List<MapBeanVo> generateDaysOfMonth(YearMonth yearMonth) {
|
||||
List<MapBeanVo> days = new ArrayList<>();
|
||||
LocalDate firstDay = yearMonth.atDay(1);
|
||||
LocalDate lastDay = yearMonth.atEndOfMonth();
|
||||
LocalDate currentDate = firstDay;
|
||||
while (!currentDate.isAfter(lastDay)) {
|
||||
MapBeanVo dayInfo = new MapBeanVo();
|
||||
dayInfo.setValue(currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||
dayInfo.setKey(String.format("%02d", currentDate.getDayOfMonth()));
|
||||
days.add(dayInfo);
|
||||
currentDate = currentDate.plusDays(1);
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个员工的考勤数据
|
||||
* @param workerId 员工ID
|
||||
* @param attendanceRecords 该员工的考勤记录
|
||||
* @param daysOfMonth 月份中的所有日期
|
||||
* @return 处理后的考勤数据列表
|
||||
*/
|
||||
private List<WorkerAttDayVo> processWorkerAttendance(Integer workerId,
|
||||
List<ThreeTableOneRosterPo> attendanceRecords, List<MapBeanVo> daysOfMonth) {
|
||||
List<WorkerAttDayVo> result = new ArrayList<>();
|
||||
// 将该员工的考勤记录按日期分组,便于快速查找
|
||||
// 将该员工的考勤记录按日期分组,便于快速查找
|
||||
Map<String, ThreeTableOneRosterPo> einByDate = attendanceRecords.stream()
|
||||
.collect(Collectors.toMap(
|
||||
ThreeTableOneRosterPo::getEinDay,
|
||||
record -> record,
|
||||
(existing, replacement) -> existing));
|
||||
// 遍历月份中的每一天
|
||||
for (MapBeanVo dayInfo : daysOfMonth) {
|
||||
String dateStr = dayInfo.getValue();
|
||||
String dayStr = dayInfo.getKey();
|
||||
WorkerAttDayVo dayRecord = new WorkerAttDayVo();
|
||||
dayRecord.setDay(dayStr);
|
||||
// 查找该日期是否有考勤记录
|
||||
ThreeTableOneRosterPo einForDate = einByDate.get(dateStr);
|
||||
if (einForDate != null) {
|
||||
// 存在考勤记录
|
||||
dayRecord.setIsEin("1"); // 在场
|
||||
// 检查是否有打卡记录
|
||||
if (einForDate.getAttDay() != null) {
|
||||
dayRecord.setIsAtt("1"); // 打卡
|
||||
}
|
||||
// 检查是否有补卡记录
|
||||
if ("1".equals(einForDate.getIsRepair())) {
|
||||
dayRecord.setIsRepair("1"); // 补卡
|
||||
}
|
||||
} else {
|
||||
// 无考勤记录
|
||||
dayRecord.setIsEin("0"); // 不在场
|
||||
dayRecord.setIsAtt("0"); // 未打卡
|
||||
dayRecord.setIsRepair("0"); // 未补卡
|
||||
}
|
||||
result.add(dayRecord);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -94,4 +94,145 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
#{item.id}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<select id="getAllPro" resultType="com.bonus.job.domain.MapBeanVo">
|
||||
SELECT
|
||||
distinct
|
||||
pro_id as id
|
||||
FROM
|
||||
bm_worker_ein_day_record
|
||||
where att_month = #{lastMonth}
|
||||
order by pro_id
|
||||
</select>
|
||||
|
||||
<select id="getWorkerRosterData" resultType="com.bonus.job.domain.ThreeTableOneRosterPo">
|
||||
SELECT
|
||||
d.pro_id,
|
||||
d.pro_name,
|
||||
d.att_month,
|
||||
d.sub_id,
|
||||
d.sub_name,
|
||||
d.team_id,
|
||||
d.team_name,
|
||||
d.worker_id,
|
||||
pw.`name`,
|
||||
pw.sex,
|
||||
d.post_id,
|
||||
d.post_name,
|
||||
d.id_number,
|
||||
pw.address,
|
||||
pw.phone,
|
||||
'remark' as remark,
|
||||
-- 正确的最早入场时间:所有与8月相关的入场中最早的
|
||||
MIN(p.ein_time) AS first_ein_time,
|
||||
-- 获取最后一次“相关入场”的出场时间(即使为 null)
|
||||
(
|
||||
SELECT p2.exit_time
|
||||
FROM bm_worker_ein_pro_record p2
|
||||
WHERE p2.worker_id = d.worker_id
|
||||
AND p2.pro_id = d.pro_id
|
||||
AND (
|
||||
-- 情况1:入场在8月内
|
||||
(p2.ein_time >= #{startTime} AND p2.ein_time < #{endTime})
|
||||
OR
|
||||
-- 情况2:入场在8月前,但8月仍在场
|
||||
(p2.ein_time < #{startTime} AND p2.exit_time >= #{startTime})
|
||||
)
|
||||
ORDER BY p2.ein_time DESC
|
||||
LIMIT 1
|
||||
) AS last_exit_time
|
||||
FROM
|
||||
bm_worker_ein_day_record d
|
||||
LEFT JOIN pm_worker pw ON pw.id = d.worker_id
|
||||
LEFT JOIN
|
||||
bm_worker_ein_pro_record p
|
||||
ON d.worker_id = p.worker_id
|
||||
AND d.pro_id = p.pro_id
|
||||
AND (
|
||||
-- 同样条件:只关联与8月出勤相关的出入记录
|
||||
(p.ein_time >= #{startTime} AND p.ein_time < #{endTime})
|
||||
OR
|
||||
(p.ein_time < #{startTime} AND p.exit_time >= #{startTime})
|
||||
)
|
||||
WHERE
|
||||
d.pro_id = #{proId}
|
||||
AND d.att_month = #{attMonth}
|
||||
GROUP BY
|
||||
d.worker_id;
|
||||
</select>
|
||||
|
||||
<select id="getWorkerApplyData" resultType="com.bonus.job.domain.ThreeTableOneRosterPo">
|
||||
SELECT
|
||||
d.pro_id,
|
||||
d.att_month,
|
||||
d.sub_id,
|
||||
d.sub_name,
|
||||
d.team_id,
|
||||
d.team_name,
|
||||
d.worker_id,
|
||||
pw.`name`,
|
||||
d.id_number,
|
||||
bwwc.bank_name,
|
||||
bwwc.bank_card_code,
|
||||
bwwc.bank_identifier_code,
|
||||
MAX(d.contract_id) AS contract_id,
|
||||
bwc.day_rate as price_wage,
|
||||
'按月支付' AS payment,
|
||||
'每月20日前' AS pay_day,
|
||||
'备注' AS remark,
|
||||
pw.phone
|
||||
FROM
|
||||
bm_worker_ein_day_record d
|
||||
LEFT JOIN pm_worker pw ON pw.id = d.worker_id
|
||||
LEFT JOIN bm_worker_wage_card bwwc ON bwwc.worker_id = pw.id
|
||||
LEFT JOIN bm_worker_contract bwc ON (
|
||||
bwc.id = (
|
||||
SELECT
|
||||
MAX(d2.contract_id)
|
||||
FROM
|
||||
bm_worker_ein_day_record d2
|
||||
WHERE
|
||||
d2.worker_id = d.worker_id
|
||||
AND d2.pro_id = #{proId}
|
||||
AND d2.att_month = #{attMonth}
|
||||
AND d2.contract_id IS NOT NULL
|
||||
)
|
||||
)
|
||||
WHERE
|
||||
d.pro_id = #{proId}
|
||||
AND d.att_month = #{attMonth}
|
||||
GROUP BY
|
||||
d.worker_id;
|
||||
</select>
|
||||
|
||||
<select id="getWorkerAttData" resultType="com.bonus.job.domain.ThreeTableOneRosterPo">
|
||||
|
||||
SELECT
|
||||
d.pro_id,
|
||||
d.pro_name,
|
||||
d.att_month,
|
||||
d.sub_id,
|
||||
d.sub_name,
|
||||
d.team_id,
|
||||
d.team_name,
|
||||
d.post_id,
|
||||
d.post_name,
|
||||
d.worker_id,
|
||||
pw.`name`,
|
||||
d.id_number,
|
||||
d.ein_day,
|
||||
bap.att_day,
|
||||
bap.is_repair
|
||||
FROM
|
||||
bm_worker_ein_day_record d
|
||||
LEFT JOIN pm_worker pw ON pw.id = d.worker_id
|
||||
LEFT JOIN bm_att_person bap ON bap.att_day = d.ein_day and bap.pro_id = d.pro_id and bap.worker_id = d.worker_id
|
||||
WHERE
|
||||
d.pro_id = #{proId}
|
||||
AND d.att_month = #{attMonth}
|
||||
|
||||
</select>
|
||||
|
||||
<select id="getWorkerPayData" resultType="com.bonus.job.domain.ThreeTableOneRosterPo">
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
|||
Loading…
Reference in New Issue