feat(smartfactory): 新增厂区员工工资管理功能
- 添加员工工资相关接口和页面 - 实现员工工资计算和发放逻辑 - 集成考勤数据,支持不同考勤类型的工资计算 - 添加工资记录查询、更新和导出功能
This commit is contained in:
parent
58d31795ac
commit
9a85af033e
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.controller.admin.industrialinjury.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 文件上传 Response VO")
|
||||
@Data
|
||||
public class UploadFilesVO {
|
||||
|
||||
@Schema(description = "文件类型名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件地址列表")
|
||||
private List<UploadUserFile> urls;
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
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.StaffSalarySaveReqVO;
|
||||
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factoryinfo.FactoryInfoDO;
|
||||
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.service.factoryinfo.FactoryInfoService;
|
||||
import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService;
|
||||
import cn.iocoder.yudao.module.smartfactory.service.staffsalary.StaffSalaryService;
|
||||
import cn.iocoder.yudao.module.system.api.loan.LoanApi;
|
||||
import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - 厂区员工工资")
|
||||
@RestController
|
||||
@RequestMapping("/smartfactory/staff-salary")
|
||||
@Validated
|
||||
public class StaffSalaryController {
|
||||
|
||||
@Resource
|
||||
private StaffSalaryService staffSalaryService;
|
||||
|
||||
@Resource
|
||||
private StaffService staffService;
|
||||
|
||||
@Resource
|
||||
private FactoryInfoService factoryInfoService;
|
||||
|
||||
@Resource
|
||||
private LoanApi loanApi;
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新厂区员工工资")
|
||||
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:update')")
|
||||
public CommonResult<Boolean> updateStaffSalary(@Valid @RequestBody StaffSalarySaveReqVO updateReqVO) {
|
||||
staffSalaryService.updateStaffSalary(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "更新厂区员工工资状态")
|
||||
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:update')")
|
||||
public CommonResult<Boolean> updateStatus(@RequestBody StaffSalarySaveReqVO updateReqVO) {
|
||||
staffSalaryService.updateStatus(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除厂区员工工资")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:delete')")
|
||||
public CommonResult<Boolean> deleteStaffSalary(@RequestParam("id") Long id) {
|
||||
staffSalaryService.deleteStaffSalary(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得厂区员工工资")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:query')")
|
||||
public CommonResult<StaffSalaryRespVO> getStaffSalary(@RequestParam("id") Long id) {
|
||||
StaffSalaryDO staffSalary = staffSalaryService.getStaffSalary(id);
|
||||
StaffSalaryRespVO respVO = BeanUtils.toBean(staffSalary, StaffSalaryRespVO.class);
|
||||
if (respVO != null) {
|
||||
|
||||
// 获取员工借支信息
|
||||
LoanDTO loanDTO = loanApi.getByUserId(staffSalary.getStaffId()).getCheckedData();
|
||||
// 设置员工借支余额
|
||||
respVO.setLoanAmount(loanDTO.getRemainingAmount());
|
||||
}
|
||||
return success(respVO);
|
||||
}
|
||||
|
||||
@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")
|
||||
@Operation(summary = "获得厂区员工工资分页")
|
||||
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:query')")
|
||||
public CommonResult<PageResult<StaffSalaryRespVO>> getStaffSalaryPage(@Valid StaffSalaryPageReqVO pageReqVO) {
|
||||
PageResult<StaffSalaryRespVO> pageResult = staffSalaryService.getStaffSalaryPage(pageReqVO);
|
||||
return success(pageResult);
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出厂区员工工资 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('smartfactory:staff-salary:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportStaffSalaryExcel(@Valid StaffSalaryPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<StaffSalaryRespVO> list = staffSalaryService.getStaffSalaryPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "厂区员工工资.xls", "数据", StaffSalaryRespVO.class,
|
||||
list);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 厂区员工工资分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class StaffSalaryPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "用户编号", example = "146")
|
||||
private Long staffId;
|
||||
|
||||
@Schema(description = "工厂编号", example = "146")
|
||||
private Long factoryId;
|
||||
|
||||
@Schema(description = "工资月份 | YYYY-MM")
|
||||
private String month;
|
||||
|
||||
@Schema(description = "工种", example = "6971")
|
||||
private Integer workTypeId;
|
||||
|
||||
@Schema(description = "复核状态 | 0未复核 1已复核", example = "0")
|
||||
private Integer status;
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 厂区员工工资 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class StaffSalaryRespVO {
|
||||
|
||||
@Schema(description = "主键id")
|
||||
@ExcelProperty("序号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户编号")
|
||||
private Long staffId;
|
||||
|
||||
@Schema(description = "用户姓名")
|
||||
@ExcelProperty("用户姓名")
|
||||
private String staffName;
|
||||
|
||||
@Schema(description = "工种")
|
||||
private Integer workTypeId;
|
||||
|
||||
@Schema(description = "所属工厂编号")
|
||||
private Long factoryId;
|
||||
|
||||
@Schema(description = "所属工厂名称")
|
||||
@ExcelProperty("所属工厂")
|
||||
private String factoryName;
|
||||
|
||||
@Schema(description = "工资月份 | YYYY-MM")
|
||||
@ExcelProperty("工资月份")
|
||||
private String month;
|
||||
|
||||
@Schema(description = "基础工资")
|
||||
@ExcelProperty("基础工资")
|
||||
private BigDecimal salary;
|
||||
|
||||
@Schema(description = "考勤天数")
|
||||
@ExcelProperty("考勤天数")
|
||||
private Integer attendanceDays;
|
||||
|
||||
@Schema(description = "应发工资")
|
||||
@ExcelProperty("应发工资")
|
||||
private BigDecimal payableAmount;
|
||||
|
||||
@Schema(description = "归还金额")
|
||||
@ExcelProperty("归还金额")
|
||||
private BigDecimal returnAmount;
|
||||
|
||||
@Schema(description = "扣款金额")
|
||||
@ExcelProperty("扣款金额")
|
||||
private BigDecimal deductionAmount;
|
||||
|
||||
@Schema(description = "实发工资")
|
||||
@ExcelProperty("实发工资")
|
||||
private BigDecimal realAmount;
|
||||
|
||||
@Schema(description = "扣款明细")
|
||||
private List<DeductionItemsVO> deductionItems;
|
||||
|
||||
@Schema(description = "复核状态 | 0未复核 1已复核")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "借支金额")
|
||||
private BigDecimal loanAmount;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 厂区员工工资新增/修改 Request VO")
|
||||
@Data
|
||||
public class StaffSalarySaveReqVO {
|
||||
|
||||
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "146")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long staffId;
|
||||
|
||||
@Schema(description = "所属工厂编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "146")
|
||||
@NotNull(message = "所属工厂不能为空")
|
||||
private Long factoryId;
|
||||
|
||||
@Schema(description = "工资月份 | YYYY-MM", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "月份不能为空")
|
||||
private String month;
|
||||
|
||||
@Schema(description = "考勤天数")
|
||||
private Integer attendanceDays;
|
||||
|
||||
@Schema(description = "应发工资")
|
||||
private BigDecimal payableAmount;
|
||||
|
||||
@Schema(description = "归还金额")
|
||||
private BigDecimal returnAmount;
|
||||
|
||||
@Schema(description = "扣款金额")
|
||||
private BigDecimal deductionAmount;
|
||||
|
||||
@Schema(description = "实发工资", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "实发工资不能为空")
|
||||
private BigDecimal realAmount;
|
||||
|
||||
@Schema(description = "扣款明细")
|
||||
private List<DeductionItemsVO> deductionItems;
|
||||
|
||||
@Schema(description = "复核状态 | 0未复核 1已复核", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "0")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.DeductionItemsVO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 厂区员工工资 DO
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@TableName(value = "sf_staff_salary", autoResultMap = true)
|
||||
@KeySequence("sf_staff_salary_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class StaffSalaryDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long staffId;
|
||||
/**
|
||||
* 所属工厂编号
|
||||
*/
|
||||
private Long factoryId;
|
||||
/**
|
||||
* 工资月份 | YYYY-MM
|
||||
*/
|
||||
private String month;
|
||||
/**
|
||||
* 考勤天数
|
||||
*/
|
||||
private Integer attendanceDays;
|
||||
/**
|
||||
* 应发工资
|
||||
*/
|
||||
private BigDecimal payableAmount;
|
||||
/**
|
||||
* 归还金额
|
||||
*/
|
||||
private BigDecimal returnAmount;
|
||||
/**
|
||||
* 扣款金额
|
||||
*/
|
||||
private BigDecimal deductionAmount;
|
||||
/**
|
||||
* 实发工资
|
||||
*/
|
||||
private BigDecimal realAmount;
|
||||
/**
|
||||
* 扣款明细
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<DeductionItemsVO> deductionItems;
|
||||
/**
|
||||
* 复核状态 | 0未复核 1已复核
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.dal.mysql.staffsalary;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
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.dal.dataobject.factoryinfo.FactoryInfoDO;
|
||||
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staff.StaffDO;
|
||||
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 厂区员工工资 Mapper
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@Mapper
|
||||
public interface StaffSalaryMapper extends BaseMapperX<StaffSalaryDO> {
|
||||
|
||||
default PageResult<StaffSalaryRespVO> selectSalaryPage(StaffSalaryPageReqVO reqVO) {
|
||||
|
||||
MPJLambdaWrapperX<StaffSalaryDO> query = new MPJLambdaWrapperX<StaffSalaryDO>()
|
||||
.selectAll(StaffSalaryDO.class)
|
||||
.selectAs(StaffDO::getNickName, StaffSalaryRespVO::getStaffName)
|
||||
.selectAs(StaffDO::getWorkTypeId, StaffSalaryRespVO::getWorkTypeId)
|
||||
.selectAs(FactoryInfoDO::getName, StaffSalaryRespVO::getFactoryName)
|
||||
.selectAs(StaffDO::getSalary, StaffSalaryRespVO::getSalary);
|
||||
|
||||
query.leftJoin(StaffDO.class, "staff", StaffDO::getId, StaffSalaryDO::getStaffId);
|
||||
query.leftJoin(FactoryInfoDO.class, FactoryInfoDO::getId, StaffSalaryDO::getFactoryId);
|
||||
query.eqIfPresent(StaffSalaryDO::getStaffId, reqVO.getStaffId());
|
||||
query.eqIfPresent(StaffSalaryDO::getMonth, reqVO.getMonth());
|
||||
query.eqIfPresent(StaffSalaryDO::getFactoryId, reqVO.getFactoryId());
|
||||
query.eqIfPresent(StaffSalaryDO::getStatus, reqVO.getStatus());
|
||||
query.apply(Objects.nonNull(reqVO.getWorkTypeId()), "staff.work_type_id = {0} ", reqVO.getWorkTypeId());
|
||||
|
||||
return selectJoinPage(reqVO, StaffSalaryRespVO.class, query);
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.framework.job.staffSalary;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
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.mysql.staffsalary.StaffSalaryMapper;
|
||||
import cn.iocoder.yudao.module.smartfactory.service.attendance.StaffAttendanceRecordService;
|
||||
import cn.iocoder.yudao.module.smartfactory.service.staff.StaffService;
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 工厂员工 月工资计算 定时任务
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StaffSalaryJob {
|
||||
|
||||
@Resource
|
||||
private StaffAttendanceRecordService staffAttendanceRecordService;
|
||||
|
||||
@Resource
|
||||
private StaffService staffService;
|
||||
|
||||
@Resource
|
||||
private StaffSalaryMapper staffSalaryMapper;
|
||||
|
||||
@XxlJob("staffSalaryJob")
|
||||
@TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意
|
||||
public ReturnT<String> execute() throws Exception {
|
||||
|
||||
// 获取当前日期 上个月得第一天
|
||||
LocalDate firstDayOfMonth = LocalDate.now().minusMonths(1).withDayOfMonth(1);
|
||||
// 获取当前日期 上个月得月份
|
||||
String month = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM"));
|
||||
// 获取两种考勤类型得 日期区间
|
||||
// 类型一 上月26日 - 本月25日
|
||||
LocalDate[] firstType = new LocalDate[]{
|
||||
firstDayOfMonth.minusMonths(1).withDayOfMonth(26),
|
||||
firstDayOfMonth.withDayOfMonth(25)
|
||||
};
|
||||
// 类型二 本月初 - 本月底
|
||||
LocalDate[] secondType = new LocalDate[]{
|
||||
firstDayOfMonth,
|
||||
firstDayOfMonth.withDayOfMonth(firstDayOfMonth.lengthOfMonth())
|
||||
};
|
||||
|
||||
// 获取考勤记录
|
||||
List<StaffAttendanceRecordDO> recordDOS = staffAttendanceRecordService.getRecordListGroupByStaffId(month);
|
||||
|
||||
// 获取厂区对应的考勤类型
|
||||
Map<Long, Integer> typeMap = recordDOS.stream()
|
||||
.collect(Collectors.groupingBy(StaffAttendanceRecordDO::getFactoryId))
|
||||
.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().get(0).getType()
|
||||
));
|
||||
|
||||
// 获取厂区得员工信息
|
||||
List<StaffDO> staffDOS = staffService.getListByFactoryIds(typeMap.keySet());
|
||||
Map<Long, StaffDO> staffMap = convertMap(staffDOS, StaffDO::getId);
|
||||
|
||||
// 获取 用户map key为工厂编号 value 为 用户id集合
|
||||
Map<Long, List<Long>> facrtoryMap = staffDOS.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
StaffDO::getFactoryId, // key
|
||||
Collectors.mapping(StaffDO::getId, Collectors.toList()) // value
|
||||
));
|
||||
|
||||
// 重新组合 考勤类型对应用户得map集合
|
||||
Map<Integer, List<Long>> resultMap = typeMap.entrySet().stream()
|
||||
.filter(entry -> facrtoryMap.containsKey(entry.getKey())) // 只保留 key 相同的项
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getValue, // typeMap 中的 value 作为新 map 的 key
|
||||
entry -> facrtoryMap.get(entry.getKey()) // staffDOS 中的 value 作为新 map 的 value
|
||||
));
|
||||
|
||||
// 遍历 resultMap
|
||||
Map<Long, List<StaffAttendanceRecordDO>> recordMap = new HashMap<>();
|
||||
for (Map.Entry<Integer, List<Long>> entry : resultMap.entrySet()) {
|
||||
|
||||
Integer type = entry.getKey();
|
||||
List<Long> staffIds = entry.getValue();
|
||||
|
||||
LocalDate[] date;
|
||||
if (type == 1) {
|
||||
date = firstType;
|
||||
}else if (type == 2) {
|
||||
date = secondType;
|
||||
} else {
|
||||
date = new LocalDate[2];
|
||||
}
|
||||
|
||||
Predicate<StaffAttendanceRecordDO> filter = item ->
|
||||
staffIds.contains(item.getStaffId())
|
||||
&& !item.getPunchTime().isAfter(date[1])
|
||||
&& !item.getPunchTime().isBefore(date[0]);
|
||||
|
||||
// 过滤数据
|
||||
Map<Long, List<StaffAttendanceRecordDO>> typeOne = recordDOS.stream()
|
||||
.filter(filter)
|
||||
.collect(Collectors.groupingBy(StaffAttendanceRecordDO::getStaffId));
|
||||
|
||||
recordMap.putAll(typeOne);
|
||||
}
|
||||
|
||||
// 计算工资
|
||||
List<StaffSalaryDO> salaryDOS = new ArrayList<>();
|
||||
for (Map.Entry<Long, List<StaffAttendanceRecordDO>> entry : recordMap.entrySet()) {
|
||||
Long staffId = entry.getKey();
|
||||
List<StaffAttendanceRecordDO> items = entry.getValue();
|
||||
|
||||
// 创建薪资DO
|
||||
StaffSalaryDO salaryDO = new StaffSalaryDO()
|
||||
.setStaffId(staffId)
|
||||
.setMonth(month)
|
||||
.setAttendanceDays(items.size())
|
||||
.setFactoryId(staffMap.get(staffId).getFactoryId());
|
||||
|
||||
// 计算当月的工作天数
|
||||
int type = typeMap.get(staffMap.get(staffId).getFactoryId());
|
||||
int workDays = 0;
|
||||
if (type == 1) {
|
||||
long days = ChronoUnit.DAYS.between(firstType[0],
|
||||
firstDayOfMonth.minusMonths(1).withDayOfMonth(firstDayOfMonth.minusMonths(1).lengthOfMonth()));
|
||||
|
||||
workDays = (int) days + 25;
|
||||
} else if (type == 2) {
|
||||
long days = ChronoUnit.DAYS.between(secondType[0], secondType[1]);
|
||||
|
||||
workDays = (int) days;
|
||||
}
|
||||
|
||||
// 计算应发工资
|
||||
if (staffMap.get(staffId).getSalary() != null) { // 没有录入基本薪资时,不做计算
|
||||
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);
|
||||
|
||||
// 返回执行成功
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.service.staffsalary;
|
||||
|
||||
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.StaffSalaryRespVO;
|
||||
import cn.iocoder.yudao.module.smartfactory.controller.admin.staffsalary.vo.StaffSalarySaveReqVO;
|
||||
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 厂区员工工资 Service 接口
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
public interface StaffSalaryService {
|
||||
|
||||
/**
|
||||
* 更新厂区员工工资
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateStaffSalary(@Valid StaffSalarySaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除厂区员工工资
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStaffSalary(Long id);
|
||||
|
||||
/**
|
||||
* 获得厂区员工工资
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 厂区员工工资
|
||||
*/
|
||||
StaffSalaryDO getStaffSalary(Long id);
|
||||
|
||||
/**
|
||||
* 获得厂区员工工资分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 厂区员工工资分页
|
||||
*/
|
||||
PageResult<StaffSalaryRespVO> getStaffSalaryPage(StaffSalaryPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 更新工资状态
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateStatus(StaffSalarySaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 获取指定员工工资列表
|
||||
* @param staffId 员工id
|
||||
* @return 工资列表
|
||||
*/
|
||||
List<StaffSalaryDO> getListByStaffId(Long staffId);
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package cn.iocoder.yudao.module.smartfactory.service.staffsalary;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
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.StaffSalarySaveReqVO;
|
||||
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.staffsalary.StaffSalaryDO;
|
||||
import cn.iocoder.yudao.module.smartfactory.dal.mysql.staffsalary.StaffSalaryMapper;
|
||||
import cn.iocoder.yudao.module.system.api.loan.LoanApi;
|
||||
import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.STAFF_SALARY_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* 厂区员工工资 Service 实现类
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class StaffSalaryServiceImpl implements StaffSalaryService {
|
||||
|
||||
@Resource
|
||||
private StaffSalaryMapper staffSalaryMapper;
|
||||
|
||||
@Resource
|
||||
private LoanApi loanApi;
|
||||
|
||||
@Override
|
||||
public void updateStaffSalary(StaffSalarySaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateStaffSalaryExists(updateReqVO.getId());
|
||||
// 更新
|
||||
StaffSalaryDO updateObj = BeanUtils.toBean(updateReqVO, StaffSalaryDO.class);
|
||||
staffSalaryMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStaffSalary(Long id) {
|
||||
// 校验存在
|
||||
validateStaffSalaryExists(id);
|
||||
// 删除
|
||||
staffSalaryMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private StaffSalaryDO validateStaffSalaryExists(Long id) {
|
||||
StaffSalaryDO staffSalaryDO = staffSalaryMapper.selectById(id);
|
||||
if (staffSalaryDO == null) {
|
||||
throw exception(STAFF_SALARY_NOT_EXISTS);
|
||||
}
|
||||
return staffSalaryDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaffSalaryDO getStaffSalary(Long id) {
|
||||
return staffSalaryMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<StaffSalaryRespVO> getStaffSalaryPage(StaffSalaryPageReqVO pageReqVO) {
|
||||
return staffSalaryMapper.selectSalaryPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(StaffSalarySaveReqVO updateReqVO) {
|
||||
|
||||
// 校验存在
|
||||
StaffSalaryDO staffSalaryDO = validateStaffSalaryExists(updateReqVO.getId());
|
||||
// 更新
|
||||
StaffSalaryDO updateObj = BeanUtils.toBean(updateReqVO, StaffSalaryDO.class);
|
||||
staffSalaryMapper.updateById(updateObj);
|
||||
|
||||
// 判断是否有归还借支金额
|
||||
if (staffSalaryDO.getReturnAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 更新借支管理中 人员的归还金额
|
||||
LoanDTO updateDO = new LoanDTO()
|
||||
.setUserId(staffSalaryDO.getStaffId())
|
||||
.setAmount(BigDecimal.ZERO)
|
||||
.setReturnAmount(staffSalaryDO.getReturnAmount());
|
||||
loanApi.createLoan(updateDO);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StaffSalaryDO> getListByStaffId(Long staffId) {
|
||||
|
||||
return staffSalaryMapper.selectList(new LambdaQueryWrapperX<StaffSalaryDO>()
|
||||
.eq(StaffSalaryDO::getStaffId, staffId)
|
||||
.eq(StaffSalaryDO::getStatus, 1));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user