diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/industrialinjury/vo/UploadFilesVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/industrialinjury/vo/UploadFilesVO.java new file mode 100644 index 00000000..374d7293 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/industrialinjury/vo/UploadFilesVO.java @@ -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 urls; +} diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java new file mode 100644 index 00000000..3d22c139 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/StaffSalaryController.java @@ -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 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 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 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 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> getListByStaffId(@RequestParam("staffId") Long staffId) { + List staffSalary = staffSalaryService.getListByStaffId(staffId); + List 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> getStaffSalaryPage(@Valid StaffSalaryPageReqVO pageReqVO) { + PageResult 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 list = staffSalaryService.getStaffSalaryPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "厂区员工工资.xls", "数据", StaffSalaryRespVO.class, + list); + } +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalaryPageReqVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalaryPageReqVO.java new file mode 100644 index 00000000..519baab8 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalaryPageReqVO.java @@ -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; +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalaryRespVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalaryRespVO.java new file mode 100644 index 00000000..e303bd5c --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalaryRespVO.java @@ -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 deductionItems; + + @Schema(description = "复核状态 | 0未复核 1已复核") + private Integer status; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "借支金额") + private BigDecimal loanAmount; +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalarySaveReqVO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalarySaveReqVO.java new file mode 100644 index 00000000..b089ef91 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/controller/admin/staffsalary/vo/StaffSalarySaveReqVO.java @@ -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 deductionItems; + + @Schema(description = "复核状态 | 0未复核 1已复核", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "0") + private Integer status; + +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staffsalary/StaffSalaryDO.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staffsalary/StaffSalaryDO.java new file mode 100644 index 00000000..6b0d1811 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/dataobject/staffsalary/StaffSalaryDO.java @@ -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 deductionItems; + /** + * 复核状态 | 0未复核 1已复核 + */ + private Integer status; + +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java new file mode 100644 index 00000000..adec9565 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/dal/mysql/staffsalary/StaffSalaryMapper.java @@ -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 { + + default PageResult selectSalaryPage(StaffSalaryPageReqVO reqVO) { + + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .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); + } +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/framework/job/staffSalary/StaffSalaryJob.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/framework/job/staffSalary/StaffSalaryJob.java new file mode 100644 index 00000000..62885ae2 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/framework/job/staffSalary/StaffSalaryJob.java @@ -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 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 recordDOS = staffAttendanceRecordService.getRecordListGroupByStaffId(month); + + // 获取厂区对应的考勤类型 + Map typeMap = recordDOS.stream() + .collect(Collectors.groupingBy(StaffAttendanceRecordDO::getFactoryId)) + .entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().get(0).getType() + )); + + // 获取厂区得员工信息 + List staffDOS = staffService.getListByFactoryIds(typeMap.keySet()); + Map staffMap = convertMap(staffDOS, StaffDO::getId); + + // 获取 用户map key为工厂编号 value 为 用户id集合 + Map> facrtoryMap = staffDOS.stream() + .collect(Collectors.groupingBy( + StaffDO::getFactoryId, // key + Collectors.mapping(StaffDO::getId, Collectors.toList()) // value + )); + + // 重新组合 考勤类型对应用户得map集合 + Map> 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> recordMap = new HashMap<>(); + for (Map.Entry> entry : resultMap.entrySet()) { + + Integer type = entry.getKey(); + List staffIds = entry.getValue(); + + LocalDate[] date; + if (type == 1) { + date = firstType; + }else if (type == 2) { + date = secondType; + } else { + date = new LocalDate[2]; + } + + Predicate filter = item -> + staffIds.contains(item.getStaffId()) + && !item.getPunchTime().isAfter(date[1]) + && !item.getPunchTime().isBefore(date[0]); + + // 过滤数据 + Map> typeOne = recordDOS.stream() + .filter(filter) + .collect(Collectors.groupingBy(StaffAttendanceRecordDO::getStaffId)); + + recordMap.putAll(typeOne); + } + + // 计算工资 + List salaryDOS = new ArrayList<>(); + for (Map.Entry> entry : recordMap.entrySet()) { + Long staffId = entry.getKey(); + List 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; + } +} diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java new file mode 100644 index 00000000..b122440b --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryService.java @@ -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 getStaffSalaryPage(StaffSalaryPageReqVO pageReqVO); + + /** + * 更新工资状态 + * @param updateReqVO 更新信息 + */ + void updateStatus(StaffSalarySaveReqVO updateReqVO); + + /** + * 获取指定员工工资列表 + * @param staffId 员工id + * @return 工资列表 + */ + List getListByStaffId(Long staffId); +} \ No newline at end of file diff --git a/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java new file mode 100644 index 00000000..7cfd0778 --- /dev/null +++ b/zn-module-smartfactory/zn-module-smartfactory-biz/src/main/java/cn/iocoder/yudao/module/smartfactory/service/staffsalary/StaffSalaryServiceImpl.java @@ -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 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 getListByStaffId(Long staffId) { + + return staffSalaryMapper.selectList(new LambdaQueryWrapperX() + .eq(StaffSalaryDO::getStaffId, staffId) + .eq(StaffSalaryDO::getStatus, 1)); + } +} \ No newline at end of file