feat(smartfactory): 添加员工工资计算功能

- 新增工资计算相关接口和实现
- 添加考勤记录审核功能
- 优化员工信息获取方法
-调整工业事故相关模型和接口
This commit is contained in:
furongxin 2025-03-31 10:10:51 +08:00
parent 870b9df2b7
commit 3bcd04cac8
22 changed files with 421 additions and 65 deletions

View File

@ -28,4 +28,9 @@ public interface StaffApi {
@Operation(summary = "获得员工信息") @Operation(summary = "获得员工信息")
@Parameter(name = "staffIds", description = "员工编号数组", required = true, example = "1,2,3") @Parameter(name = "staffIds", description = "员工编号数组", required = true, example = "1,2,3")
CommonResult<List<StaffDTO>> getStaffList(@RequestParam("staffIds") Collection<Long> staffId); CommonResult<List<StaffDTO>> getStaffList(@RequestParam("staffIds") Collection<Long> staffId);
@GetMapping(PREFIX + "/getByUserId")
@Operation(summary = "根据系统用户编号获得员工信息")
@Parameter(name = "userId", description = "系统用户编号", required = true, example = "1")
CommonResult<StaffDTO> getStaffByUserId(@RequestParam("userId") Long userId);
} }

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.smartfactory.api.staff.dto.StaffDTO; import cn.iocoder.yudao.module.smartfactory.api.staff.dto.StaffDTO;
import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService; import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -30,4 +31,9 @@ public class StaffApiImpl implements StaffApi {
public CommonResult<List<StaffDTO>> getStaffList(Collection<Long> staffId) { public CommonResult<List<StaffDTO>> getStaffList(Collection<Long> staffId) {
return success(BeanUtils.toBean(staffService.getList(staffId), StaffDTO.class)); return success(BeanUtils.toBean(staffService.getList(staffId), StaffDTO.class));
} }
@Override
public CommonResult<StaffDTO> getStaffByUserId(Long userId) {
return success(BeanUtils.toBean(staffService.getStaffByUserId(userId), StaffDTO.class));
}
} }

View File

@ -128,6 +128,18 @@ public class StaffAttendanceRecordController {
return success(staffAttendanceRecordService.getType(factoryId, month)); return success(staffAttendanceRecordService.getType(factoryId, month));
} }
@GetMapping("/isReview")
@Operation(summary = "获得厂区员工考勤记录审核状态")
@Parameter(name = "factoryId", description = "工厂编号", required = true, example = "1024")
@Parameter(name = "month", description = "考勤月份", required = true, example = "2025-11")
@PreAuthorize("@ss.hasPermission('smartfactory:staff-attendance-record:query')")
public CommonResult<Integer> getIsReview(@RequestParam("factoryId") Long factoryId,
@RequestParam("month") String month) {
// 获取考勤审核状态
return success(staffAttendanceRecordService.getIsReview(factoryId, month));
}
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "获得厂区员工考勤记录列表") @Operation(summary = "获得厂区员工考勤记录列表")
@PreAuthorize("@ss.hasPermission('smartfactory:staff-attendance-record:query')") @PreAuthorize("@ss.hasPermission('smartfactory:staff-attendance-record:query')")
@ -137,8 +149,37 @@ public class StaffAttendanceRecordController {
// 查询该厂区员工在 其他厂区得考勤记录 // 查询该厂区员工在 其他厂区得考勤记录
List<StaffAttendanceRecordDO> otherRecordDOS = staffAttendanceRecordService.getOtherRecord(reqVO); List<StaffAttendanceRecordDO> otherRecordDOS = staffAttendanceRecordService.getOtherRecord(reqVO);
// 获取工厂员工列表
List<StaffDO> staffDOS = staffService.getListByFactory(reqVO.getFactoryId(), true);
Map<Long, StaffDO> staffMap = convertMap(staffDOS, StaffDO::getId);
if (CollUtil.isNotEmpty(recordDOS)) { if (CollUtil.isNotEmpty(recordDOS)) {
return success(convertRecord(reqVO, recordDOS, otherRecordDOS)); List<StaffAttendanceRecordRespVO> recordRespVO = convertRecord(reqVO, recordDOS, otherRecordDOS);
// 筛选掉已经存在的员工
List<Long> staffIds = staffDOS.stream()
.map(StaffDO::getId)
.filter(id -> !convertList(recordDOS, StaffAttendanceRecordDO::getStaffId).contains(id))
.collect(Collectors.toList());
// 获取其他员工的考勤记录 打卡状态设置为null
List<AttendanceRecordVO> otherRecords = recordRespVO.get(0).getRecords().stream()
.map(record -> BeanUtils.toBean(record, AttendanceRecordVO.class)
.setStatus(null))
.collect(Collectors.toList());
List<StaffAttendanceRecordRespVO> otherRespVO = staffIds.stream()
.map(id -> new StaffAttendanceRecordRespVO()
.setStaffId(id)
.setFactoryId(reqVO.getFactoryId())
.setMonth(reqVO.getMonth())
.setType(reqVO.getType())
.setStaffName(staffMap.get(id).getNickName())
.setWorkTypeId(staffMap.get(id).getWorkTypeId())
.setRecords(otherRecords))
.collect(Collectors.toList());
recordRespVO.addAll(otherRespVO);
return success(recordRespVO);
}else { }else {
// 判断是否 新增考勤情况 // 判断是否 新增考勤情况
if (reqVO.getFactoryId() != null && reqVO.getMonth() != null && reqVO.getType() != null) { if (reqVO.getFactoryId() != null && reqVO.getMonth() != null && reqVO.getType() != null) {
@ -156,8 +197,6 @@ public class StaffAttendanceRecordController {
.setWorkTypeId(staffDO.getWorkTypeId()); .setWorkTypeId(staffDO.getWorkTypeId());
return success(Collections.singletonList(respVO)); return success(Collections.singletonList(respVO));
}else { }else {
// 获取工厂员工列表
List<StaffDO> staffDOS = staffService.getListByFactory(reqVO.getFactoryId(), true);
List<StaffAttendanceRecordRespVO> respVO = staffDOS.stream() List<StaffAttendanceRecordRespVO> respVO = staffDOS.stream()
.map(staffDO -> new StaffAttendanceRecordRespVO() .map(staffDO -> new StaffAttendanceRecordRespVO()
.setStaffId(staffDO.getId()) .setStaffId(staffDO.getId())
@ -310,4 +349,16 @@ public class StaffAttendanceRecordController {
ExcelUtils.write(response, "厂区员工考勤记录.xls", "数据", StaffAttendanceRecordRespVO.class, ExcelUtils.write(response, "厂区员工考勤记录.xls", "数据", StaffAttendanceRecordRespVO.class,
convertRecord(reqVO, recordDOS, null)); convertRecord(reqVO, recordDOS, null));
} }
@PutMapping("/review")
@Operation(summary = "考勤记录审核")
@Parameter(name = "factoryId", description = "工厂编号", required = true, example = "1024")
@Parameter(name = "month", description = "考勤月份", required = true, example = "2025-11")
@PreAuthorize("@ss.hasPermission('smartfactory:staff-attendance-record:review')")
public CommonResult<Boolean> reviewAttendanceRecord(@RequestParam("factoryId") Long factoryId,
@RequestParam("month") String month) {
staffAttendanceRecordService.updateReview(factoryId, month);
return success(true);
}
} }

View File

@ -38,6 +38,9 @@ public class StaffAttendanceRecordRespVO {
@Schema(description = "其他打卡记录") @Schema(description = "其他打卡记录")
private List<StaffAttendanceRecordRespVO> childRecords; private List<StaffAttendanceRecordRespVO> childRecords;
@Schema(description = "是否已审核")
private Integer isReview;
public StaffAttendanceRecordRespVO(Long staffId, Long factoryId, Integer type, String month) { public StaffAttendanceRecordRespVO(Long staffId, Long factoryId, Integer type, String month) {
this.staffId = staffId; this.staffId = staffId;
this.factoryId = factoryId; this.factoryId = factoryId;

View File

@ -96,6 +96,8 @@ public class IndustrialInjuryController {
result.getList().forEach(vo -> { result.getList().forEach(vo -> {
vo.setStaffName(userMap.get(vo.getStaffId()) != null ? userMap.get(vo.getStaffId()).getNickName() : null); vo.setStaffName(userMap.get(vo.getStaffId()) != null ? userMap.get(vo.getStaffId()).getNickName() : null);
vo.setFactoryName(factoryMap.get(vo.getFactoryId()) != null ? factoryMap.get(vo.getFactoryId()).getName() : null); vo.setFactoryName(factoryMap.get(vo.getFactoryId()) != null ? factoryMap.get(vo.getFactoryId()).getName() : null);
// 设置理赔总金额
vo.setClaimTotalAmount(vo.getClaimAmount().add(vo.getAgreementClaimAmount()));
}); });
} }

View File

@ -12,10 +12,16 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data @Data
public class AdvancePaymentItem { public class AdvancePaymentItem {
@Schema(description = "垫资方 | 1公司 2工厂")
private Integer payer;
@Schema(description = "金额") @Schema(description = "金额")
private BigDecimal amount; private BigDecimal amount;
@Schema(description = "时间") @Schema(description = "时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private String time; private String time;
@Schema(description = "备注")
private String notes;
} }

View File

@ -12,8 +12,8 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data @Data
public class ClaimAmountItem { public class ClaimAmountItem {
@Schema(description = "理赔") @Schema(description = "理赔类型")
private String payee; private Integer payee;
@Schema(description = "金额") @Schema(description = "金额")
private BigDecimal amount; private BigDecimal amount;
@ -21,4 +21,7 @@ public class ClaimAmountItem {
@Schema(description = "理赔时间") @Schema(description = "理赔时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private String time; private String time;
@Schema(description = "备注")
private String notes;
} }

View File

@ -48,10 +48,6 @@ public class IndustrialInjuryRespVO {
@Schema(description = "医药垫资明细") @Schema(description = "医药垫资明细")
private List<AdvancePaymentItem> advancePaymentItems; private List<AdvancePaymentItem> advancePaymentItems;
@Schema(description = "垫资方 | 1公司 2工厂")
@ExcelProperty("垫资方 | 1公司 2工厂")
private Integer payer;
@Schema(description = "理赔金额") @Schema(description = "理赔金额")
@ExcelProperty("理赔金额") @ExcelProperty("理赔金额")
private BigDecimal claimAmount; private BigDecimal claimAmount;
@ -59,10 +55,33 @@ public class IndustrialInjuryRespVO {
@Schema(description = "理赔明细") @Schema(description = "理赔明细")
private List<ClaimAmountItem> claimAmountItems; private List<ClaimAmountItem> claimAmountItems;
@Schema(description = "状态 | 1处理中 2已完成", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "协议理赔金额")
@ExcelProperty("状态 | 1处理中 2已完成") private BigDecimal agreementClaimAmount;
@Schema(description = "协议理赔明细")
private List<ClaimAmountItem> agreementClaimItems;
@Schema(description = "理赔总金额")
private BigDecimal claimTotalAmount;
@Schema(description = "备注")
private String notes;
@Schema(description = "状态 | 1处理中 2已完成")
private Integer status; private Integer status;
@Schema(description = "是否上传发票 |0否 1是")
private Integer isUploadInvoice;
@Schema(description = "是否保险理赔|0否 1是")
private Integer isInsuranceClaims;
@Schema(description = "是否协议理赔|0否 1是")
private Integer isAgreementClaims;
@Schema(description = "发票文件信息")
private List<UploadFilesVO> invoiceFileItems;
@Schema(description = "附件信息") @Schema(description = "附件信息")
@ExcelProperty("附件信息") @ExcelProperty("附件信息")
private List<UploadFilesVO> fileItems; private List<UploadFilesVO> fileItems;
@ -70,5 +89,4 @@ public class IndustrialInjuryRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@ -34,18 +34,36 @@ public class IndustrialInjurySaveReqVO {
@Schema(description = "医药垫资明细") @Schema(description = "医药垫资明细")
private List<AdvancePaymentItem> advancePaymentItems; private List<AdvancePaymentItem> advancePaymentItems;
@Schema(description = "垫资方 | 1公司 2工厂")
private Integer payer;
@Schema(description = "理赔金额") @Schema(description = "理赔金额")
private BigDecimal claimAmount; private BigDecimal claimAmount;
@Schema(description = "理赔明细") @Schema(description = "理赔明细")
private List<ClaimAmountItem> claimAmountItems; private List<ClaimAmountItem> claimAmountItems;
@Schema(description = "协议理赔金额")
private BigDecimal agreementClaimAmount;
@Schema(description = "协议理赔明细")
private List<ClaimAmountItem> agreementClaimItems;
@Schema(description = "备注")
private String notes;
@Schema(description = "状态 | 1处理中 2已完成") @Schema(description = "状态 | 1处理中 2已完成")
private Integer status; private Integer status;
@Schema(description = "是否上传发票 |0否 1是")
private Integer isUploadInvoice;
@Schema(description = "是否保险理赔|0否 1是")
private Integer isInsuranceClaims;
@Schema(description = "是否协议理赔|0否 1是")
private Integer isAgreementClaims;
@Schema(description = "发票文件信息")
private List<UploadFilesVO> invoiceFileItems;
@Schema(description = "附件信息") @Schema(description = "附件信息")
private List<UploadFilesVO> fileItems; private List<UploadFilesVO> fileItems;

View File

@ -41,12 +41,6 @@ public class StaffSalaryController {
@Resource @Resource
private StaffSalaryService staffSalaryService; private StaffSalaryService staffSalaryService;
@Resource
private StaffService staffService;
@Resource
private FactoryInfoService factoryInfoService;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建员工工资") @Operation(summary = "创建员工工资")
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:create')") @PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:create')")
@ -89,29 +83,6 @@ public class StaffSalaryController {
return success(BeanUtils.toBean(staffSalary, StaffSalaryRespVO.class)); return success(BeanUtils.toBean(staffSalary, StaffSalaryRespVO.class));
} }
@GetMapping("/get-list")
@Operation(summary = "获得指定员工工资列表")
@Parameter(name = "staffId", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:query')")
public CommonResult<List<StaffSalaryRespVO>> getListByStaffId(@RequestParam("staffId") Long staffId) {
List<StaffSalaryDO> staffSalary = staffSalaryService.getListByStaffId(staffId);
List<StaffSalaryRespVO> respVOS = BeanUtils.toBean(staffSalary, StaffSalaryRespVO.class);
// 获取员工信息
StaffDO staffDO = staffService.getStaff(staffId);
// 获取工厂信息
FactoryInfoDO factoryInfoDO = factoryInfoService.getFactoryInfo(staffDO.getFactoryId());
// 移除归还金额为0的记录
respVOS.removeIf(vo -> vo.getRealAmount().compareTo(BigDecimal.ZERO) == 0);
respVOS.forEach(vo -> {
vo.setStaffName(staffDO.getNickName());
vo.setFactoryName(factoryInfoDO.getName());
});
return success(respVOS);
}
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得厂区员工工资分页") @Operation(summary = "获得厂区员工工资分页")
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:query')") @PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:query')")

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 厂区员工考勤审核表 DO
*
* @author 符溶馨
*/
@TableName("sf_attendance_review")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SfAttendanceReviewDO extends BaseDO {
/**
* 主键id
*/
@TableId
private Long id;
/**
* 工厂id
*/
private Long factoryId;
/**
* 考勤月份
*/
private String month;
/**
* 审核状态 | 0未审核 1已审核
*/
private Integer status;
}

View File

@ -60,10 +60,6 @@ public class IndustrialInjuryDO extends BaseDO {
*/ */
@TableField(typeHandler = JacksonTypeHandler.class) @TableField(typeHandler = JacksonTypeHandler.class)
private List<AdvancePaymentItem> advancePaymentItems; private List<AdvancePaymentItem> advancePaymentItems;
/**
* 垫资方 | 1公司 2工厂
*/
private Integer payer;
/** /**
* 理赔金额 * 理赔金额
*/ */
@ -73,10 +69,40 @@ public class IndustrialInjuryDO extends BaseDO {
*/ */
@TableField(typeHandler = JacksonTypeHandler.class) @TableField(typeHandler = JacksonTypeHandler.class)
private List<ClaimAmountItem> claimAmountItems; private List<ClaimAmountItem> claimAmountItems;
/**
* 协议理赔金额
*/
private BigDecimal agreementClaimAmount;
/**
* 协议理赔明细
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<ClaimAmountItem> agreementClaimItems;
/** /**
* 状态 | 1处理中 2已完成 * 状态 | 1处理中 2已完成
*/ */
private Integer status; private Integer status;
/**
* 是否上传发票 | 0否 1是
*/
private Integer isUploadInvoice;
/**
* 是否保险理赔 | 0否 1是
*/
private Integer isInsuranceClaims;
/**
* 是否协议理赔 | 0否 1是
*/
private Integer isAgreementClaims;
/**
* 备注
*/
private String notes;
/**
* 发票附件信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<UploadFilesVO> invoiceFileItems;
/** /**
* 附件信息 * 附件信息
*/ */

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.smartfactory.dal.mysql.attendance;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance.SfAttendanceReviewDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 厂区员工考勤审核 Mapper
*
* @author 符溶馨
*/
@Mapper
public interface SfAttendanceReviewMapper extends BaseMapperX<SfAttendanceReviewDO> {
}

View File

@ -20,7 +20,6 @@ public interface IndustrialInjuryMapper extends BaseMapperX<IndustrialInjuryDO>
.eqIfPresent(IndustrialInjuryDO::getStaffId, reqVO.getStaffId()) .eqIfPresent(IndustrialInjuryDO::getStaffId, reqVO.getStaffId())
.eqIfPresent(IndustrialInjuryDO::getFactoryId, reqVO.getFactoryId()) .eqIfPresent(IndustrialInjuryDO::getFactoryId, reqVO.getFactoryId())
.betweenIfPresent(IndustrialInjuryDO::getHappenTime, reqVO.getHappenTime()) .betweenIfPresent(IndustrialInjuryDO::getHappenTime, reqVO.getHappenTime())
.eqIfPresent(IndustrialInjuryDO::getPayer, reqVO.getPayer())
.eqIfPresent(IndustrialInjuryDO::getStatus, reqVO.getStatus()) .eqIfPresent(IndustrialInjuryDO::getStatus, reqVO.getStatus())
.orderByDesc(IndustrialInjuryDO::getId)); .orderByDesc(IndustrialInjuryDO::getId));
} }

View File

@ -78,4 +78,6 @@ public interface StaffMapper extends BaseMapperX<StaffDO> {
return selectJoinPage(pageReqVO, StaffSalaryRespVO.class, query); return selectJoinPage(pageReqVO, StaffSalaryRespVO.class, query);
} }
StaffDO selectStaffByUserId(@Param("userId") Long userId);
} }

View File

@ -73,4 +73,19 @@ public interface StaffAttendanceRecordService {
* @return 勤记录列表 * @return 勤记录列表
*/ */
List<StaffAttendanceRecordDO> getRecordListGroupByStaffId(String month); List<StaffAttendanceRecordDO> getRecordListGroupByStaffId(String month);
/**
* 考勤记录审核
* @param factoryId 工厂编号
* @param month 考勤月份
*/
void updateReview(Long factoryId, String month);
/**
* 获取考勤记录是否已审核
* @param factoryId 工厂编号
* @param month 考勤月份
* @return 是否已审核
*/
Integer getIsReview(Long factoryId, String month);
} }

View File

@ -5,8 +5,13 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.smartfactory.controller.admin.attendance.vo.StaffAttendanceRecordReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.attendance.vo.StaffAttendanceRecordReqVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.attendance.vo.StaffAttendanceRecordSaveReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.attendance.vo.StaffAttendanceRecordSaveReqVO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance.SfAttendanceReviewDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance.StaffAttendanceRecordDO; import cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance.StaffAttendanceRecordDO;
import cn.iocoder.yudao.module.smartfactory.dal.mysql.attendance.SfAttendanceReviewMapper;
import cn.iocoder.yudao.module.smartfactory.dal.mysql.attendance.StaffAttendanceRecordMapper; import cn.iocoder.yudao.module.smartfactory.dal.mysql.attendance.StaffAttendanceRecordMapper;
import cn.iocoder.yudao.module.smartfactory.framework.job.staffSalary.StaffSalaryJob;
import cn.iocoder.yudao.module.smartfactory.service.staffsalary.StaffSalaryService;
import org.springframework.data.redis.connection.stream.ObjectRecord;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -32,6 +37,12 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe
@Resource @Resource
private StaffAttendanceRecordMapper staffAttendanceRecordMapper; private StaffAttendanceRecordMapper staffAttendanceRecordMapper;
@Resource
private StaffSalaryService staffSalaryService;
@Resource
private SfAttendanceReviewMapper attendanceReviewMapper;
@Override @Override
public void createStaffAttendanceRecord(List<StaffAttendanceRecordSaveReqVO> createReqVO) { public void createStaffAttendanceRecord(List<StaffAttendanceRecordSaveReqVO> createReqVO) {
@ -164,4 +175,27 @@ public class StaffAttendanceRecordServiceImpl implements StaffAttendanceRecordSe
.eq(StaffAttendanceRecordDO::getStatus, 1) .eq(StaffAttendanceRecordDO::getStatus, 1)
.eq(StaffAttendanceRecordDO::getMonth, month)); .eq(StaffAttendanceRecordDO::getMonth, month));
} }
@Override
public void updateReview(Long factoryId, String month) {
attendanceReviewMapper.insert(new SfAttendanceReviewDO()
.setFactoryId(factoryId)
.setMonth(month)
.setStatus(1));
List<StaffAttendanceRecordDO> createDo = staffAttendanceRecordMapper.selectList(new LambdaQueryWrapperX<StaffAttendanceRecordDO>()
.eq(StaffAttendanceRecordDO::getFactoryId, factoryId)
.eq(StaffAttendanceRecordDO::getMonth, month));
// 审核考勤记录后 自动计算员工薪资
staffSalaryService.calculateSalary(createDo);
}
@Override
public Integer getIsReview(Long factoryId, String month) {
SfAttendanceReviewDO attendanceReviewDO = attendanceReviewMapper.selectOne(new LambdaQueryWrapperX<SfAttendanceReviewDO>()
.eq(SfAttendanceReviewDO::getFactoryId, factoryId)
.eq(SfAttendanceReviewDO::getMonth, month));
return attendanceReviewDO != null ? attendanceReviewDO.getStatus() : 0;
}
} }

View File

@ -67,14 +67,12 @@ public interface StaffService {
/** /**
* 获取人员数量 * 获取人员数量
*
* @return * @return
*/ */
Integer getCount(); Integer getCount();
/** /**
* 查询工厂员工信息 * 查询工厂员工信息
*
* @param factoryId 工厂编号 * @param factoryId 工厂编号
* @return * @return
*/ */
@ -82,8 +80,7 @@ public interface StaffService {
/** /**
* 导入员工 * 导入员工
* * @param list 导入数据集合
* @param list 导入数据集合
* @param updateSupport 是否可更新 * @param updateSupport 是否可更新
* @return 导入结果 * @return 导入结果
*/ */
@ -93,7 +90,7 @@ public interface StaffService {
* 获取指定厂区得员工列表 * 获取指定厂区得员工列表
* *
* @param factoryId 工厂编号 * @param factoryId 工厂编号
* @param isIn 是否获取该厂区员工 * @param isIn 是否获取该厂区员工
* @return 员工列表 * @return 员工列表
*/ */
List<StaffDO> getListByFactory(Long factoryId, Boolean isIn); List<StaffDO> getListByFactory(Long factoryId, Boolean isIn);
@ -108,7 +105,6 @@ public interface StaffService {
/** /**
* 获取员工信息列表 * 获取员工信息列表
*
* @param staffIds 员工编号集合 * @param staffIds 员工编号集合
* @return 员工信息列表 * @return 员工信息列表
*/ */
@ -125,8 +121,15 @@ public interface StaffService {
/** /**
* *
* @param userId *
* @return * @return
*/ */
Long getTheFactoryOfTheCurrentlyLoggedInUser(); Long getTheFactoryOfTheCurrentlyLoggedInUser();
/**
* 根据系统用户编号获取员工信息
* @param userId 系统用户编号
* @return 员工信息
*/
StaffDO getStaffByUserId(Long userId);
} }

View File

@ -58,6 +58,10 @@ public class StaffServiceImpl implements StaffService {
@Override @Override
public Long createStaff(StaffSaveReqVO createReqVO) { public Long createStaff(StaffSaveReqVO createReqVO) {
// 身份证号是否已经存在
validateUserForCreate(null, null, null, createReqVO.getIdCard());
// 插入 // 插入
StaffDO staff = BeanUtils.toBean(createReqVO, StaffDO.class); StaffDO staff = BeanUtils.toBean(createReqVO, StaffDO.class);
staffMapper.insert(staff); staffMapper.insert(staff);
@ -70,6 +74,10 @@ public class StaffServiceImpl implements StaffService {
if (staffMapper.selectById(updateReqVO.getId()) == null) { if (staffMapper.selectById(updateReqVO.getId()) == null) {
throw exception(STAFF_NOT_EXISTS); throw exception(STAFF_NOT_EXISTS);
} }
// 身份证号是否已经存在
validateUserForCreate(null, null, null, updateReqVO.getIdCard());
// 更新 // 更新
StaffDO updateObj = BeanUtils.toBean(updateReqVO, StaffDO.class); StaffDO updateObj = BeanUtils.toBean(updateReqVO, StaffDO.class);
staffMapper.updateById(updateObj); staffMapper.updateById(updateObj);
@ -274,4 +282,10 @@ public class StaffServiceImpl implements StaffService {
} }
return dto.getFactoryId(); return dto.getFactoryId();
} }
@Override
public StaffDO getStaffByUserId(Long userId) {
return staffMapper.selectStaffByUserId(userId);
}
} }

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance.StaffAttendanceRecordDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO; import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO;
import javax.validation.Valid; import javax.validation.Valid;
@ -60,9 +61,8 @@ public interface StaffSalaryService {
void updateStatus(StaffSalarySaveReqVO updateReqVO); void updateStatus(StaffSalarySaveReqVO updateReqVO);
/** /**
* 获取指定员工工资列表 * 工资计算
* @param staffId 员工id * @param vo 考勤信息
* @return 工资列表
*/ */
List<StaffSalaryDO> getListByStaffId(Long staffId); void calculateSalary(List<StaffAttendanceRecordDO> vo);
} }

View File

@ -1,14 +1,21 @@
package cn.iocoder.yudao.module.smartfactory.service.staffsalary; package cn.iocoder.yudao.module.smartfactory.service.staffsalary;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.jackson.core.databind.LocalDateTimeDeserializer;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.api.oa.BpmOALoanApi;
import cn.iocoder.yudao.module.bpm.api.oa.vo.loan.BpmOALoanSumDTO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryPageReqVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalaryRespVO;
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO; import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.attendance.StaffAttendanceRecordDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staff.StaffDO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO; import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO;
import cn.iocoder.yudao.module.smartfactory.dal.mysql.staff.StaffMapper; import cn.iocoder.yudao.module.smartfactory.dal.mysql.staff.StaffMapper;
import cn.iocoder.yudao.module.smartfactory.dal.mysql.staffsalary.StaffSalaryMapper; import cn.iocoder.yudao.module.smartfactory.dal.mysql.staffsalary.StaffSalaryMapper;
import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService;
import cn.iocoder.yudao.module.system.api.loan.LoanApi; import cn.iocoder.yudao.module.system.api.loan.LoanApi;
import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO; import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -17,9 +24,16 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_EXISTS; import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_EXISTS;
import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_NOT_EXISTS; import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_NOT_EXISTS;
@ -41,6 +55,12 @@ public class StaffSalaryServiceImpl implements StaffSalaryService {
@Resource @Resource
private LoanApi loanApi; private LoanApi loanApi;
@Resource
private BpmOALoanApi bpmOALoanApi;
@Resource
private StaffService staffService;
@Override @Override
public Long createStaffSalary(StaffSalarySaveReqVO createReqVO) { public Long createStaffSalary(StaffSalarySaveReqVO createReqVO) {
@ -113,6 +133,7 @@ public class StaffSalaryServiceImpl implements StaffSalaryService {
// 更新借支管理中 人员的归还金额 // 更新借支管理中 人员的归还金额
LoanDTO updateDO = new LoanDTO() LoanDTO updateDO = new LoanDTO()
.setUserId(staffSalaryDO.getStaffId()) .setUserId(staffSalaryDO.getStaffId())
.setLoanType(1)
.setAmount(BigDecimal.ZERO) .setAmount(BigDecimal.ZERO)
.setReturnAmount(staffSalaryDO.getReturnAmount()); .setReturnAmount(staffSalaryDO.getReturnAmount());
loanApi.createLoan(updateDO); loanApi.createLoan(updateDO);
@ -120,10 +141,99 @@ public class StaffSalaryServiceImpl implements StaffSalaryService {
} }
@Override @Override
public List<StaffSalaryDO> getListByStaffId(Long staffId) { public void calculateSalary(List<StaffAttendanceRecordDO> vo) {
return staffSalaryMapper.selectList(new LambdaQueryWrapperX<StaffSalaryDO>() // 获取厂区考勤类型
.eq(StaffSalaryDO::getStaffId, staffId) Integer type = vo.get(0).getType();
.eq(StaffSalaryDO::getStatus, 1)); // 获取厂区考勤月份
String month = vo.get(0).getMonth();
// 获取当前考勤月份得第一天
LocalDate firstDayOfMonth = LocalDate.parse(month + "-01", DateTimeFormatter.ISO_LOCAL_DATE);
LocalDate[] date = new LocalDate[2];
if (type == 1) {
date = new LocalDate[]{
firstDayOfMonth.minusMonths(1).withDayOfMonth(26),
firstDayOfMonth.withDayOfMonth(25)
};
}else if (type == 2) {
date = new LocalDate[]{
firstDayOfMonth,
firstDayOfMonth.withDayOfMonth(firstDayOfMonth.lengthOfMonth())
};
}
Map<Long, List<StaffAttendanceRecordDO>> recordMap = vo.stream()
.collect(Collectors.groupingBy(StaffAttendanceRecordDO::getStaffId));
// 获取厂区得员工信息
List<StaffDO> staffDOS = staffService.getList(convertSet(vo, StaffAttendanceRecordDO::getStaffId));
Map<Long, StaffDO> staffMap = convertMap(staffDOS, StaffDO::getId);
// 获取员工借支记录
List<BpmOALoanSumDTO> loanDOS = bpmOALoanApi.getListByStaffId(recordMap.keySet(), month).getCheckedData();
Map<Long, BigDecimal> loanMap = loanDOS.stream()
.collect(Collectors.toMap(
BpmOALoanSumDTO::getSfUserId,
BpmOALoanSumDTO::getTotalAmount,
BigDecimal::add
));
// 获取员工剩余的 工资借支金额
List<LoanDTO> sysLoanDOS = loanApi.getListByMonth(recordMap.keySet(), month).getCheckedData();
Map<Long, BigDecimal> sysLoanMap = new HashMap<>();
if (CollUtil.isNotEmpty(sysLoanDOS)) {
sysLoanMap = sysLoanDOS.stream()
.collect(Collectors.toMap(LoanDTO::getUserId, LoanDTO::getRemainingAmount));
}
List<StaffSalaryDO> salaryDOS = new ArrayList<>();
for (Map.Entry<Long, List<StaffAttendanceRecordDO>> entry : recordMap.entrySet()) {
Long staffId = entry.getKey();
// 获取该员工的上班考勤记录
List<StaffAttendanceRecordDO> items = entry.getValue().stream()
.filter(item -> item.getStatus() == 1)
.collect(Collectors.toList());
// 创建薪资DO
StaffSalaryDO salaryDO = new StaffSalaryDO()
.setStaffId(staffId)
.setMonth(month)
.setAttendanceDays(items.size())
.setFactoryId(entry.getValue().get(0).getFactoryId())
.setReturnAmount(loanMap.getOrDefault(staffId, BigDecimal.ZERO)
.add(sysLoanMap.getOrDefault(staffId, BigDecimal.ZERO)));
// 计算当月的工作天数
long days = ChronoUnit.DAYS.between(date[0], date[1]);
int workDays = (int) days + 1;
// 计算应发工资
if (staffMap.get(staffId).getSalary() != null) { // 没有录入基本薪资时不做计算
if (salaryDO.getAttendanceDays() == workDays) {
// 设置应发工资
salaryDO.setPayableAmount(staffMap.get(staffId).getSalary());
// 设置实发工资
salaryDO.setRealAmount(staffMap.get(staffId).getSalary());
} else {
BigDecimal payableAmount = staffMap.get(staffId).getSalary().divide(BigDecimal.valueOf(workDays), RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(salaryDO.getAttendanceDays()));
// 设置应发工资
salaryDO.setPayableAmount(payableAmount);
// 设置实发工资
salaryDO.setRealAmount(payableAmount);
}
}
// 插入集合
salaryDOS.add(salaryDO);
}
// 插入工资记录
staffSalaryMapper.insertBatch(salaryDOS);
} }
} }

View File

@ -51,4 +51,21 @@
</if> </if>
</where> </where>
</select> </select>
<select id="selectStaffByUserId" resultType="cn.iocoder.yudao.module.smartfactory.dal.dataobject.staff.StaffDO">
SELECT
a.*
FROM sf_staff a
JOIN system_users u ON
u.id = #{userId}
AND u.idcard = a.id_card
AND u.deleted = 0
-- JOIN system_dept d ON
-- d.id = u.dept_id
-- AND d.factory_id = a.factory_id
-- AND d.deleted = 0
WHERE
a.status = 1
and a.deleted = 0
</select>
</mapper> </mapper>