Commit a883059d7be11c8cf0ef851cf6e0d1432a500073

Authored by YunaiV
1 parent 87227458

✨ feat(workrecord): 新增 MES 工作记录管理功能

实现工作记录的上下工记录流水,包括分页查询、导出 Excel、上线和下线操作。新增相关的请求和响应 VO,完善数据对象和服务接口,支持用户与工作站的绑定状态管理。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/MesProWorkrecordController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
  5 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  7 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  9 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO;
  11 +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogRespVO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
  13 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO;
  14 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO;
  15 +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
  16 +import cn.iocoder.yudao.module.mes.service.pro.workrecord.MesProWorkRecordService;
  17 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  18 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  19 +import io.swagger.v3.oas.annotations.Operation;
  20 +import io.swagger.v3.oas.annotations.Parameter;
  21 +import io.swagger.v3.oas.annotations.tags.Tag;
  22 +import jakarta.annotation.Resource;
  23 +import jakarta.servlet.http.HttpServletResponse;
  24 +import jakarta.validation.Valid;
  25 +import org.springframework.security.access.prepost.PreAuthorize;
  26 +import org.springframework.validation.annotation.Validated;
  27 +import org.springframework.web.bind.annotation.*;
  28 +
  29 +import java.io.IOException;
  30 +import java.util.Collections;
  31 +import java.util.List;
  32 +import java.util.Map;
  33 +
  34 +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
  35 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  36 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  37 +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
  38 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  39 +
  40 +@Tag(name = "管理后台 - MES 工作记录")
  41 +@RestController
  42 +@RequestMapping("/mes/pro/workrecord")
  43 +@Validated
  44 +public class MesProWorkRecordController {
  45 +
  46 + @Resource
  47 + private MesProWorkRecordService workRecordService;
  48 + @Resource
  49 + private MesMdWorkstationService workstationService;
  50 +
  51 + @Resource
  52 + private AdminUserApi adminUserApi;
  53 +
  54 + @GetMapping("/log/page")
  55 + @Operation(summary = "获得工作记录流水分页")
  56 + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:query')")
  57 + public CommonResult<PageResult<MesProWorkRecordLogRespVO>> getWorkRecordLogPage(
  58 + @Valid MesProWorkRecordLogPageReqVO pageReqVO) {
  59 + PageResult<MesProWorkRecordLogDO> pageResult = workRecordService.getWorkRecordLogPage(pageReqVO);
  60 + return success(new PageResult<>(buildWorkRecordLogRespVOList(pageResult.getList()), pageResult.getTotal()));
  61 + }
  62 +
  63 + @GetMapping("/log/get")
  64 + @Operation(summary = "获得工作记录流水")
  65 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  66 + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:query')")
  67 + public CommonResult<MesProWorkRecordLogRespVO> getWorkRecordLog(@RequestParam("id") Long id) {
  68 + MesProWorkRecordLogDO log = workRecordService.getWorkRecordLog(id);
  69 + return success(buildWorkRecordLogRespVO(log));
  70 + }
  71 +
  72 + @GetMapping("/log/export-excel")
  73 + @Operation(summary = "导出工作记录 Excel")
  74 + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:export')")
  75 + @ApiAccessLog(operateType = EXPORT)
  76 + public void exportWorkRecordLogExcel(@Valid MesProWorkRecordLogPageReqVO pageReqVO,
  77 + HttpServletResponse response) throws IOException {
  78 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  79 + List<MesProWorkRecordLogDO> list = workRecordService.getWorkRecordLogPage(pageReqVO).getList();
  80 + List<MesProWorkRecordLogRespVO> voList = buildWorkRecordLogRespVOList(list);
  81 + ExcelUtils.write(response, "工作记录.xls", "数据", MesProWorkRecordLogRespVO.class, voList);
  82 + }
  83 +
  84 + @PutMapping("/clock-in")
  85 + @Operation(summary = "上线(绑定工作站)")
  86 + @Parameter(name = "workstationId", description = "工作站编号", required = true)
  87 + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:clock')")
  88 + public CommonResult<Long> clockInWorkRecord(@RequestParam("workstationId") Long workstationId) {
  89 + return success(workRecordService.clockInWorkRecord(getLoginUserId(), workstationId));
  90 + }
  91 +
  92 + @PutMapping("/clock-out")
  93 + @Operation(summary = "下线(解绑工作站)")
  94 + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:clock')")
  95 + public CommonResult<Long> clockOutWorkRecord() {
  96 + return success(workRecordService.clockOutWorkRecord(getLoginUserId()));
  97 + }
  98 +
  99 + @GetMapping("/get-my")
  100 + @Operation(summary = "获取当前用户绑定的工作站状态")
  101 + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:query')")
  102 + public CommonResult<MesProWorkRecordLogRespVO> getMyWorkRecord() {
  103 + MesProWorkRecordDO record = workRecordService.getWorkRecord(getLoginUserId());
  104 + return success(buildWorkRecordRespVO(record));
  105 + }
  106 +
  107 + // ==================== 拼接 VO ====================
  108 +
  109 + private MesProWorkRecordLogRespVO buildWorkRecordLogRespVO(MesProWorkRecordLogDO log) {
  110 + if (log == null) {
  111 + return null;
  112 + }
  113 + return buildWorkRecordLogRespVOList(Collections.singletonList(log)).get(0);
  114 + }
  115 +
  116 + private List<MesProWorkRecordLogRespVO> buildWorkRecordLogRespVOList(List<MesProWorkRecordLogDO> list) {
  117 + if (CollUtil.isEmpty(list)) {
  118 + return Collections.emptyList();
  119 + }
  120 + // 1. 查询相关数据
  121 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  122 + convertSet(list, MesProWorkRecordLogDO::getUserId));
  123 + Map<Long, MesMdWorkstationDO> workstationMap = workstationService.getWorkstationMap(
  124 + convertSet(list, MesProWorkRecordLogDO::getWorkstationId));
  125 + // 2. 拼接 VO
  126 + return BeanUtils.toBean(list, MesProWorkRecordLogRespVO.class, vo -> {
  127 + findAndThen(userMap, vo.getUserId(), user ->
  128 + vo.setUserNickname(user.getNickname()));
  129 + findAndThen(workstationMap, vo.getWorkstationId(), ws ->
  130 + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName()));
  131 + });
  132 + }
  133 +
  134 + private MesProWorkRecordLogRespVO buildWorkRecordRespVO(MesProWorkRecordDO record) {
  135 + if (record == null) {
  136 + return null;
  137 + }
  138 + MesProWorkRecordLogRespVO vo = new MesProWorkRecordLogRespVO()
  139 + .setUserId(record.getUserId()).setWorkstationId(record.getWorkstationId())
  140 + .setCreateTime(record.getClockInTime()); // 前端显示为上工时间
  141 + // 拼接工作站信息
  142 + MesMdWorkstationDO ws = workstationService.getWorkstation(record.getWorkstationId());
  143 + if (ws != null) {
  144 + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName());
  145 + }
  146 + // 拼接用户信息
  147 + AdminUserRespDTO user = adminUserApi.getUser(record.getUserId());
  148 + if (user != null) {
  149 + vo.setUserNickname(user.getNickname());
  150 + }
  151 + return vo;
  152 + }
  153 +
  154 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@Schema(description = "管理后台 - MES 上下工记录流水分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class MesProWorkRecordLogPageReqVO extends PageParam {
  19 +
  20 + @Schema(description = "用户编号", example = "1")
  21 + private Long userId;
  22 +
  23 + @Schema(description = "工作站编号", example = "1")
  24 + private Long workstationId;
  25 +
  26 + @Schema(description = "操作类型(1=上工 2=下工)", example = "1")
  27 + private Integer type;
  28 +
  29 + @Schema(description = "创建时间")
  30 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  31 + private LocalDateTime[] createTime;
  32 +
  33 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  5 +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
  6 +import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
  7 +import cn.idev.excel.annotation.ExcelProperty;
  8 +import io.swagger.v3.oas.annotations.media.Schema;
  9 +import lombok.Data;
  10 +import lombok.experimental.Accessors;
  11 +
  12 +import java.time.LocalDateTime;
  13 +
  14 +@Schema(description = "管理后台 - MES 上下工记录流水 Response VO")
  15 +@Data
  16 +@Accessors(chain = true)
  17 +@ExcelIgnoreUnannotated
  18 +public class MesProWorkRecordLogRespVO {
  19 +
  20 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  21 + @ExcelProperty("编号")
  22 + private Long id;
  23 +
  24 + @Schema(description = "用户编号", example = "1")
  25 + private Long userId;
  26 +
  27 + @Schema(description = "用户昵称", example = "张三")
  28 + @ExcelProperty("用户昵称")
  29 + private String userNickname;
  30 +
  31 + @Schema(description = "工作站编号", example = "1")
  32 + private Long workstationId;
  33 +
  34 + @Schema(description = "工作站编码", example = "WS-001")
  35 + @ExcelProperty("工作站编码")
  36 + private String workstationCode;
  37 +
  38 + @Schema(description = "工作站名称", example = "注塑工作站")
  39 + @ExcelProperty("工作站名称")
  40 + private String workstationName;
  41 +
  42 + @Schema(description = "操作类型(1=上工 2=下工)", example = "1")
  43 + @ExcelProperty(value = "操作类型", converter = DictConvert.class)
  44 + @DictFormat(DictTypeConstants.MES_PRO_WORK_RECORD_TYPE)
  45 + private Integer type;
  46 +
  47 + @Schema(description = "备注", example = "备注")
  48 + @ExcelProperty("备注")
  49 + private String remark;
  50 +
  51 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  52 + @ExcelProperty("创建时间")
  53 + private LocalDateTime createTime;
  54 +
  55 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
  5 +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum;
  6 +import com.baomidou.mybatisplus.annotation.KeySequence;
  7 +import com.baomidou.mybatisplus.annotation.TableId;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import lombok.*;
  10 +
  11 +/**
  12 + * MES 上下工记录流水 DO
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@TableName("mes_pro_work_record_log")
  17 +@KeySequence("mes_pro_work_record_log_seq")
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class MesProWorkRecordLogDO extends BaseDO {
  25 +
  26 + /**
  27 + * 编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 + /**
  32 + * 用户编号
  33 + *
  34 + * 关联 AdminUserDO#getId()
  35 + */
  36 + private Long userId;
  37 + /**
  38 + * 工作站编号
  39 + *
  40 + * 关联 {@link MesMdWorkstationDO#getId()}
  41 + */
  42 + private Long workstationId;
  43 + /**
  44 + * 操作类型
  45 + *
  46 + * 枚举 {@link MesProWorkRecordTypeEnum}
  47 + */
  48 + private Integer type;
  49 + /**
  50 + * 备注
  51 + */
  52 + private String remark;
  53 +
  54 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkrecordDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +/**
  13 + * MES 用户工作站绑定关系(当前快照) DO
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@TableName("mes_pro_work_record")
  18 +@KeySequence("mes_pro_work_record_seq")
  19 +@Data
  20 +@EqualsAndHashCode(callSuper = true)
  21 +@ToString(callSuper = true)
  22 +@Builder
  23 +@NoArgsConstructor
  24 +@AllArgsConstructor
  25 +public class MesProWorkRecordDO extends BaseDO {
  26 +
  27 + /**
  28 + * 编号
  29 + */
  30 + @TableId
  31 + private Long id;
  32 + /**
  33 + * 用户编号
  34 + *
  35 + * 关联 AdminUserDO#getId()
  36 + */
  37 + private Long userId;
  38 + /**
  39 + * 工作站编号
  40 + *
  41 + * 关联 {@link MesMdWorkstationDO#getId()}
  42 + */
  43 + private Long workstationId;
  44 + /**
  45 + * 当前状态
  46 + *
  47 + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum}
  48 + */
  49 + private Integer type;
  50 + /**
  51 + * 上工时间
  52 + */
  53 + private LocalDateTime clockInTime;
  54 + /**
  55 + * 下工时间
  56 + */
  57 + private LocalDateTime clockOutTime;
  58 + /**
  59 + * 备注
  60 + */
  61 + private String remark;
  62 +
  63 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordLogMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +/**
  11 + * MES 上下工记录流水 Mapper
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Mapper
  16 +public interface MesProWorkRecordLogMapper extends BaseMapperX<MesProWorkRecordLogDO> {
  17 +
  18 + default PageResult<MesProWorkRecordLogDO> selectPage(MesProWorkRecordLogPageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<MesProWorkRecordLogDO>()
  20 + .eqIfPresent(MesProWorkRecordLogDO::getUserId, reqVO.getUserId())
  21 + .eqIfPresent(MesProWorkRecordLogDO::getWorkstationId, reqVO.getWorkstationId())
  22 + .eqIfPresent(MesProWorkRecordLogDO::getType, reqVO.getType())
  23 + .betweenIfPresent(MesProWorkRecordLogDO::getCreateTime, reqVO.getCreateTime())
  24 + .orderByDesc(MesProWorkRecordLogDO::getId));
  25 + }
  26 +
  27 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkrecordMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +/**
  9 + * MES 当前绑定状态(快照) Mapper
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Mapper
  14 +public interface MesProWorkRecordMapper extends BaseMapperX<MesProWorkRecordDO> {
  15 +
  16 + default MesProWorkRecordDO selectByUserId(Long userId) {
  17 + return selectOne(new LambdaQueryWrapperX<MesProWorkRecordDO>()
  18 + .eq(MesProWorkRecordDO::getUserId, userId));
  19 + }
  20 +
  21 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
... ... @@ -43,6 +43,7 @@ public interface DictTypeConstants {
43 43 String MES_DV_REPAIR_RESULT = "mes_dv_repair_result"; // MES 维修结果
44 44 String MES_PRO_ANDON_STATUS = "mes_pro_andon_status"; // MES 安灯处置状态
45 45 String MES_PRO_ANDON_LEVEL = "mes_pro_andon_level"; // MES 安灯级别
  46 + String MES_PRO_WORK_RECORD_TYPE = "mes_pro_work_record_type"; // MES 上下工状态类型
46 47 String MES_PRO_FEEDBACK_STATUS = "mes_pro_feedback_status"; // MES 生产报工状态
47 48 String MES_PRO_FEEDBACK_TYPE = "mes_pro_feedback_type"; // MES 生产报工类型
48 49 String MES_PRO_FEEDBACK_CHANNEL = "mes_pro_feedback_channel"; // MES 生产报工途径
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -281,6 +281,10 @@ public interface ErrorCodeConstants {
281 281 // ========== MES 生产管理-流转卡工序(1-040-507-100) ==========
282 282 ErrorCode PRO_CARD_PROCESS_NOT_EXISTS = new ErrorCode(1_040_507_100, "流转卡工序记录不存在");
283 283  
  284 + // ========== MES 生产管理-工作记录(1-040-508-000) ==========
  285 + ErrorCode WORK_RECORD_WORKSTATION_NOT_EXISTS = new ErrorCode(1_040_508_000, "工作站不存在");
  286 + ErrorCode WORK_RECORD_NOT_CLOCK_IN = new ErrorCode(1_040_508_001, "当前用户未上工,无法下工");
  287 +
284 288 // ========== MES 质量管理-质检方案(1-040-600-000) ==========
285 289 ErrorCode QC_TEMPLATE_NOT_EXISTS = new ErrorCode(1_040_600_000, "质检方案不存在");
286 290 ErrorCode QC_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_040_600_001, "质检方案编号已存在");
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkRecordTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.pro;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * MES 上下工操作类型枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum MesProWorkRecordTypeEnum implements ArrayValuable<Integer> {
  17 +
  18 + CLOCK_IN(1, "上工"),
  19 + CLOCK_OUT(2, "下工");
  20 +
  21 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkRecordTypeEnum::getType).toArray(Integer[]::new);
  22 +
  23 + /**
  24 + * 操作类型
  25 + */
  26 + private final Integer type;
  27 + /**
  28 + * 操作名
  29 + */
  30 + private final String name;
  31 +
  32 + @Override
  33 + public Integer[] array() {
  34 + return ARRAYS;
  35 + }
  36 +
  37 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkrecordService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.pro.workrecord;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO;
  7 +
  8 +/**
  9 + * MES 工作记录 Service 接口
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +public interface MesProWorkRecordService {
  14 +
  15 + /**
  16 + * 获得上下工记录流水分页
  17 + *
  18 + * @param pageReqVO 分页查询
  19 + * @return 上下工记录流水分页
  20 + */
  21 + PageResult<MesProWorkRecordLogDO> getWorkRecordLogPage(MesProWorkRecordLogPageReqVO pageReqVO);
  22 +
  23 + /**
  24 + * 获得上下工记录流水
  25 + *
  26 + * @param id 编号
  27 + * @return 上下工记录流水
  28 + */
  29 + MesProWorkRecordLogDO getWorkRecordLog(Long id);
  30 +
  31 + /**
  32 + * 上线(绑定工作站)
  33 + *
  34 + * @param userId 用户编号
  35 + * @param workstationId 工作站编号
  36 + * @return 记录编号
  37 + */
  38 + Long clockInWorkRecord(Long userId, Long workstationId);
  39 +
  40 + /**
  41 + * 下线(解绑工作站)
  42 + *
  43 + * @param userId 用户编号
  44 + * @return 记录编号
  45 + */
  46 + Long clockOutWorkRecord(Long userId);
  47 +
  48 + /**
  49 + * 获取指定用户当前的绑定状态
  50 + *
  51 + * @param userId 用户编号
  52 + * @return 绑定关系,如果未绑定则返回 null
  53 + */
  54 + MesProWorkRecordDO getWorkRecord(Long userId);
  55 +
  56 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkrecordServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.pro.workrecord;
  2 +
  3 +import cn.hutool.core.util.ObjUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO;
  8 +import cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord.MesProWorkRecordLogMapper;
  9 +import cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord.MesProWorkRecordMapper;
  10 +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum;
  11 +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
  12 +import jakarta.annotation.Resource;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.transaction.annotation.Transactional;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import java.time.LocalDateTime;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WORK_RECORD_NOT_CLOCK_IN;
  21 +
  22 +/**
  23 + * MES 工作记录 Service 实现类
  24 + *
  25 + * @author 芋道源码
  26 + */
  27 +@Service
  28 +@Validated
  29 +public class MesProWorkRecordServiceImpl implements MesProWorkRecordService {
  30 +
  31 + @Resource
  32 + private MesProWorkRecordLogMapper workRecordLogMapper;
  33 + @Resource
  34 + private MesProWorkRecordMapper workRecordMapper;
  35 + @Resource
  36 + private MesMdWorkstationService workstationService;
  37 +
  38 + @Override
  39 + public PageResult<MesProWorkRecordLogDO> getWorkRecordLogPage(MesProWorkRecordLogPageReqVO pageReqVO) {
  40 + return workRecordLogMapper.selectPage(pageReqVO);
  41 + }
  42 +
  43 + @Override
  44 + public MesProWorkRecordLogDO getWorkRecordLog(Long id) {
  45 + return workRecordLogMapper.selectById(id);
  46 + }
  47 +
  48 + @Override
  49 + @Transactional(rollbackFor = Exception.class)
  50 + public Long clockInWorkRecord(Long userId, Long workstationId) {
  51 + // 1. 校验工作站是否存在
  52 + workstationService.validateWorkstationExists(workstationId);
  53 +
  54 + // 2. 写入上线流水
  55 + MesProWorkRecordLogDO log = MesProWorkRecordLogDO.builder().userId(userId)
  56 + .workstationId(workstationId).type(MesProWorkRecordTypeEnum.CLOCK_IN.getType()).build();
  57 + workRecordLogMapper.insert(log);
  58 +
  59 + // 3. 更新用户工作站状态:如果没有记录,或先删除旧记录
  60 + MesProWorkRecordDO record = workRecordMapper.selectByUserId(userId);
  61 + if (record == null) {
  62 + record = MesProWorkRecordDO.builder().userId(userId).workstationId(workstationId)
  63 + .type(MesProWorkRecordTypeEnum.CLOCK_IN.getType()).clockInTime(LocalDateTime.now()).build();
  64 + workRecordMapper.insert(record);
  65 + } else {
  66 + workRecordMapper.updateById(new MesProWorkRecordDO().setId(record.getId())
  67 + .setWorkstationId(workstationId).setType(MesProWorkRecordTypeEnum.CLOCK_IN.getType())
  68 + .setClockInTime(LocalDateTime.now()));
  69 + }
  70 + return log.getId();
  71 + }
  72 +
  73 + @Override
  74 + @Transactional(rollbackFor = Exception.class)
  75 + public Long clockOutWorkRecord(Long userId) {
  76 + // 1. 校验是否有状态
  77 + MesProWorkRecordDO record = workRecordMapper.selectByUserId(userId);
  78 + if (record == null || ObjUtil.notEqual(MesProWorkRecordTypeEnum.CLOCK_IN.getType(), record.getType())) {
  79 + throw exception(WORK_RECORD_NOT_CLOCK_IN);
  80 + }
  81 +
  82 + // 2. 写入下线流水
  83 + MesProWorkRecordLogDO log = MesProWorkRecordLogDO.builder().userId(userId)
  84 + .workstationId(record.getWorkstationId()).type(MesProWorkRecordTypeEnum.CLOCK_OUT.getType())
  85 + .build();
  86 + workRecordLogMapper.insert(log);
  87 +
  88 + // 3. 更新用户状态
  89 + workRecordMapper.updateById(new MesProWorkRecordDO().setId(record.getId())
  90 + .setType(MesProWorkRecordTypeEnum.CLOCK_OUT.getType()).setClockOutTime(LocalDateTime.now()));
  91 + return log.getId();
  92 + }
  93 +
  94 + @Override
  95 + public MesProWorkRecordDO getWorkRecord(Long userId) {
  96 + return workRecordMapper.selectByUserId(userId);
  97 + }
  98 +
  99 +}
... ...