Commit dd34cfdce4c6af1c977971261104b6a86b5a2348
1 parent
3ed86517
feat(mes): 新增 IPQC 过程检验模块,对接缺陷记录与检验结果
- 新增 IPQC 过程检验单全套后端:DO、Mapper、VO、Service、Controller - MesQcIpqcService 新增 validateIpqcExists、recalculateDefectStats 方法 - MesQcIpqcLineService 新增 validateIpqcLineExists、recalculateLineDefectStats 方法 - MesQcDefectRecordServiceImpl 扩展 IPQC 分支(校验 + 缺陷统计重算) - MesQcIndicatorResultServiceImpl 扩展 IPQC 分支(获取 itemId) - MesQcTemplateService 新增 getTemplateByItemIdAndType 方法,支持按产品+类型自动匹配模板 - IPQC 删除时级联清理缺陷记录 - 新增错误码 1_040_604_xxx 系列
Showing
19 changed files
with
1648 additions
and
3 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc; | ||
| 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.qc.ipqc.vo.MesQcIpqcPageReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcRespVO; | ||
| 12 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; | ||
| 13 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; | ||
| 14 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; | ||
| 15 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; | ||
| 16 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; | ||
| 17 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; | ||
| 18 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; | ||
| 19 | +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; | ||
| 20 | +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; | ||
| 21 | +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; | ||
| 22 | +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; | ||
| 23 | +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; | ||
| 24 | +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; | ||
| 25 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 26 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 27 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 28 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 29 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 30 | +import jakarta.annotation.Resource; | ||
| 31 | +import jakarta.servlet.http.HttpServletResponse; | ||
| 32 | +import jakarta.validation.Valid; | ||
| 33 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 34 | +import org.springframework.validation.annotation.Validated; | ||
| 35 | +import org.springframework.web.bind.annotation.*; | ||
| 36 | + | ||
| 37 | +import java.io.IOException; | ||
| 38 | +import java.util.ArrayList; | ||
| 39 | +import java.util.Collections; | ||
| 40 | +import java.util.List; | ||
| 41 | +import java.util.Map; | ||
| 42 | + | ||
| 43 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; | ||
| 44 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 45 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 46 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 47 | + | ||
| 48 | +@Tag(name = "管理后台 - MES 过程检验单(IPQC)") | ||
| 49 | +@RestController | ||
| 50 | +@RequestMapping("/mes/qc/ipqc") | ||
| 51 | +@Validated | ||
| 52 | +public class MesQcIpqcController { | ||
| 53 | + | ||
| 54 | + @Resource | ||
| 55 | + private MesQcIpqcService ipqcService; | ||
| 56 | + @Resource | ||
| 57 | + private MesProWorkOrderService workOrderService; | ||
| 58 | + @Resource | ||
| 59 | + private MesMdWorkstationService workstationService; | ||
| 60 | + @Resource | ||
| 61 | + private MesProProcessService processService; | ||
| 62 | + @Resource | ||
| 63 | + private MesMdItemService itemService; | ||
| 64 | + @Resource | ||
| 65 | + private MesMdUnitMeasureService unitMeasureService; | ||
| 66 | + | ||
| 67 | + @Resource | ||
| 68 | + private AdminUserApi adminUserApi; | ||
| 69 | + | ||
| 70 | + @PostMapping("/create") | ||
| 71 | + @Operation(summary = "创建过程检验单") | ||
| 72 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:create')") | ||
| 73 | + public CommonResult<Long> createIpqc(@Valid @RequestBody MesQcIpqcSaveReqVO createReqVO) { | ||
| 74 | + return success(ipqcService.createIpqc(createReqVO)); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @PutMapping("/update") | ||
| 78 | + @Operation(summary = "更新过程检验单") | ||
| 79 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:update')") | ||
| 80 | + public CommonResult<Boolean> updateIpqc(@Valid @RequestBody MesQcIpqcSaveReqVO updateReqVO) { | ||
| 81 | + ipqcService.updateIpqc(updateReqVO); | ||
| 82 | + return success(true); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @PutMapping("/complete") | ||
| 86 | + @Operation(summary = "完成过程检验单") | ||
| 87 | + @Parameter(name = "id", description = "编号", required = true) | ||
| 88 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:update')") | ||
| 89 | + public CommonResult<Boolean> completeIpqc(@RequestParam("id") Long id) { | ||
| 90 | + ipqcService.completeIpqc(id); | ||
| 91 | + return success(true); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @DeleteMapping("/delete") | ||
| 95 | + @Operation(summary = "删除过程检验单") | ||
| 96 | + @Parameter(name = "id", description = "编号", required = true) | ||
| 97 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:delete')") | ||
| 98 | + public CommonResult<Boolean> deleteIpqc(@RequestParam("id") Long id) { | ||
| 99 | + ipqcService.deleteIpqc(id); | ||
| 100 | + return success(true); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + @GetMapping("/get") | ||
| 104 | + @Operation(summary = "获得过程检验单") | ||
| 105 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||
| 106 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") | ||
| 107 | + public CommonResult<MesQcIpqcRespVO> getIpqc(@RequestParam("id") Long id) { | ||
| 108 | + MesQcIpqcDO ipqc = ipqcService.getIpqc(id); | ||
| 109 | + return success(buildIpqcRespVOList(Collections.singletonList(ipqc)).get(0)); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + @GetMapping("/page") | ||
| 113 | + @Operation(summary = "获得过程检验单分页") | ||
| 114 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") | ||
| 115 | + public CommonResult<PageResult<MesQcIpqcRespVO>> getIpqcPage(@Valid MesQcIpqcPageReqVO pageReqVO) { | ||
| 116 | + PageResult<MesQcIpqcDO> pageResult = ipqcService.getIpqcPage(pageReqVO); | ||
| 117 | + return success(new PageResult<>(buildIpqcRespVOList(pageResult.getList()), pageResult.getTotal())); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + @GetMapping("/export-excel") | ||
| 121 | + @Operation(summary = "导出过程检验单 Excel") | ||
| 122 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:export')") | ||
| 123 | + @ApiAccessLog(operateType = EXPORT) | ||
| 124 | + public void exportIpqcExcel(@Valid MesQcIpqcPageReqVO pageReqVO, | ||
| 125 | + HttpServletResponse response) throws IOException { | ||
| 126 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | ||
| 127 | + List<MesQcIpqcDO> list = ipqcService.getIpqcPage(pageReqVO).getList(); | ||
| 128 | + List<MesQcIpqcRespVO> voList = buildIpqcRespVOList(list); | ||
| 129 | + ExcelUtils.write(response, "过程检验单.xls", "数据", MesQcIpqcRespVO.class, voList); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + // ==================== 拼接 VO ==================== | ||
| 133 | + | ||
| 134 | + private List<MesQcIpqcRespVO> buildIpqcRespVOList(List<MesQcIpqcDO> list) { | ||
| 135 | + if (CollUtil.isEmpty(list)) { | ||
| 136 | + return Collections.emptyList(); | ||
| 137 | + } | ||
| 138 | + // 批量查询工单 | ||
| 139 | + Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap( | ||
| 140 | + convertSet(list, MesQcIpqcDO::getWorkOrderId)); | ||
| 141 | + // 批量查询工位 | ||
| 142 | + Map<Long, MesMdWorkstationDO> workstationMap = workstationService.getWorkstationMap( | ||
| 143 | + convertSet(list, MesQcIpqcDO::getWorkstationId)); | ||
| 144 | + // 批量查询工序 | ||
| 145 | + Map<Long, MesProProcessDO> processMap = processService.getProcessMap( | ||
| 146 | + convertSet(list, MesQcIpqcDO::getProcessId)); | ||
| 147 | + // 批量查询物料 | ||
| 148 | + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap( | ||
| 149 | + convertSet(list, MesQcIpqcDO::getItemId)); | ||
| 150 | + // 批量查询计量单位( | ||
| 151 | + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap( | ||
| 152 | + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); | ||
| 153 | + // 批量查询检测人员 | ||
| 154 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 155 | + convertSet(list, MesQcIpqcDO::getInspectorUserId)); | ||
| 156 | + // 拼装 VO | ||
| 157 | + return BeanUtils.toBean(list, MesQcIpqcRespVO.class, vo -> { | ||
| 158 | + findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> vo | ||
| 159 | + .setWorkOrderCode(workOrder.getCode()).setWorkOrderName(workOrder.getName())); | ||
| 160 | + findAndThen(workstationMap, vo.getWorkstationId(), | ||
| 161 | + ws -> vo.setWorkstationName(ws.getName())); | ||
| 162 | + findAndThen(processMap, vo.getProcessId(), | ||
| 163 | + process -> vo.setProcessName(process.getName())); | ||
| 164 | + findAndThen(itemMap, vo.getItemId(), item -> { | ||
| 165 | + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); | ||
| 166 | + findAndThen(unitMeasureMap, item.getUnitMeasureId(), | ||
| 167 | + unit -> vo.setUnitName(unit.getName())); | ||
| 168 | + }); | ||
| 169 | + findAndThen(userMap, vo.getInspectorUserId(), | ||
| 170 | + user -> vo.setInspectorNickname(user.getNickname())); | ||
| 171 | + }); | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcLineController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLineRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; | ||
| 10 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; | ||
| 11 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; | ||
| 12 | +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; | ||
| 13 | +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; | ||
| 14 | +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; | ||
| 15 | +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcLineService; | ||
| 16 | +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService; | ||
| 17 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 18 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 19 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 20 | +import jakarta.annotation.Resource; | ||
| 21 | +import jakarta.validation.Valid; | ||
| 22 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 23 | +import org.springframework.validation.annotation.Validated; | ||
| 24 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 27 | +import org.springframework.web.bind.annotation.RestController; | ||
| 28 | + | ||
| 29 | +import java.util.Collections; | ||
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Map; | ||
| 32 | + | ||
| 33 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 36 | + | ||
| 37 | +@Tag(name = "管理后台 - MES 过程检验单行") | ||
| 38 | +@RestController | ||
| 39 | +@RequestMapping("/mes/qc/ipqc/line") | ||
| 40 | +@Validated | ||
| 41 | +public class MesQcIpqcLineController { | ||
| 42 | + | ||
| 43 | + @Resource | ||
| 44 | + private MesQcIpqcLineService ipqcLineService; | ||
| 45 | + @Resource | ||
| 46 | + private MesQcIndicatorService indicatorService; | ||
| 47 | + @Resource | ||
| 48 | + private MesMdUnitMeasureService unitMeasureService; | ||
| 49 | + @Resource | ||
| 50 | + private MesTmToolService toolService; | ||
| 51 | + | ||
| 52 | + @GetMapping("/get") | ||
| 53 | + @Operation(summary = "获得过程检验单行") | ||
| 54 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||
| 55 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") | ||
| 56 | + public CommonResult<MesQcIpqcLineRespVO> getIpqcLine(@RequestParam("id") Long id) { | ||
| 57 | + MesQcIpqcLineDO line = ipqcLineService.getIpqcLine(id); | ||
| 58 | + return success(buildLineRespVOList(Collections.singletonList(line)).get(0)); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + @GetMapping("/page") | ||
| 62 | + @Operation(summary = "获得过程检验单行分页") | ||
| 63 | + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") | ||
| 64 | + public CommonResult<PageResult<MesQcIpqcLineRespVO>> getIpqcLinePage(@Valid MesQcIpqcLinePageReqVO pageReqVO) { | ||
| 65 | + PageResult<MesQcIpqcLineDO> pageResult = ipqcLineService.getIpqcLinePage(pageReqVO); | ||
| 66 | + return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal())); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + // ==================== 拼接 VO ==================== | ||
| 70 | + | ||
| 71 | + private List<MesQcIpqcLineRespVO> buildLineRespVOList(List<MesQcIpqcLineDO> list) { | ||
| 72 | + if (CollUtil.isEmpty(list)) { | ||
| 73 | + return Collections.emptyList(); | ||
| 74 | + } | ||
| 75 | + // 批量查询检测指标 | ||
| 76 | + Map<Long, MesQcIndicatorDO> indicatorMap = indicatorService.getIndicatorMap( | ||
| 77 | + convertSet(list, MesQcIpqcLineDO::getIndicatorId)); | ||
| 78 | + // 批量查询计量单位 | ||
| 79 | + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap( | ||
| 80 | + convertSet(list, MesQcIpqcLineDO::getUnitMeasureId)); | ||
| 81 | + // 拼装 VO | ||
| 82 | + return BeanUtils.toBean(list, MesQcIpqcLineRespVO.class, vo -> { | ||
| 83 | + findAndThen(indicatorMap, vo.getIndicatorId(), indicator -> | ||
| 84 | + vo.setIndicatorCode(indicator.getCode()).setIndicatorName(indicator.getName()) | ||
| 85 | + .setIndicatorType(indicator.getType())); | ||
| 86 | + findAndThen(unitMeasureMap, vo.getUnitMeasureId(), | ||
| 87 | + unit -> vo.setUnitMeasureName(unit.getName())); | ||
| 88 | + // 逐个查询工具名称(工具数量通常较少) | ||
| 89 | + if (vo.getToolId() != null) { | ||
| 90 | + MesTmToolDO tool = toolService.getTool(vo.getToolId()); | ||
| 91 | + if (tool != null) { | ||
| 92 | + vo.setToolName(tool.getName()); | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + }); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.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 MesQcIpqcPageReqVO extends PageParam { | ||
| 19 | + | ||
| 20 | + @Schema(description = "检验单编号", example = "IPQC2025") | ||
| 21 | + private String code; | ||
| 22 | + | ||
| 23 | + @Schema(description = "IPQC 检验类型", example = "IPQC") | ||
| 24 | + private String type; | ||
| 25 | + | ||
| 26 | + @Schema(description = "生产工单 ID", example = "10") | ||
| 27 | + private Long workOrderId; | ||
| 28 | + | ||
| 29 | + @Schema(description = "工位 ID", example = "30") | ||
| 30 | + private Long workstationId; | ||
| 31 | + | ||
| 32 | + @Schema(description = "产品物料 ID", example = "50") | ||
| 33 | + private Long itemId; | ||
| 34 | + | ||
| 35 | + @Schema(description = "检测结果", example = "1") | ||
| 36 | + private Integer checkResult; | ||
| 37 | + | ||
| 38 | + @Schema(description = "状态", example = "0") | ||
| 39 | + private Integer status; | ||
| 40 | + | ||
| 41 | + @Schema(description = "检测人员用户 ID", example = "1") | ||
| 42 | + private Long inspectorUserId; | ||
| 43 | + | ||
| 44 | + @Schema(description = "检测日期") | ||
| 45 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 46 | + private LocalDateTime[] inspectDate; | ||
| 47 | + | ||
| 48 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo; | ||
| 2 | + | ||
| 3 | +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; | ||
| 4 | +import cn.idev.excel.annotation.ExcelProperty; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +import java.math.BigDecimal; | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - MES 过程检验单 Response VO") | ||
| 12 | +@Data | ||
| 13 | +@ExcelIgnoreUnannotated | ||
| 14 | +public class MesQcIpqcRespVO { | ||
| 15 | + | ||
| 16 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + @ExcelProperty("编号") | ||
| 18 | + private Long id; | ||
| 19 | + | ||
| 20 | + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPQC20250101001") | ||
| 21 | + @ExcelProperty("检验单编号") | ||
| 22 | + private String code; | ||
| 23 | + | ||
| 24 | + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX工单过程检验") | ||
| 25 | + @ExcelProperty("检验单名称") | ||
| 26 | + private String name; | ||
| 27 | + | ||
| 28 | + @Schema(description = "IPQC 检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPQC") | ||
| 29 | + @ExcelProperty("检验类型") | ||
| 30 | + private String type; | ||
| 31 | + | ||
| 32 | + @Schema(description = "检验模板 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 33 | + private Long templateId; | ||
| 34 | + | ||
| 35 | + // ========== 来源单据 ========== | ||
| 36 | + | ||
| 37 | + @Schema(description = "来源单据 ID", example = "200") | ||
| 38 | + private Long sourceDocId; | ||
| 39 | + | ||
| 40 | + @Schema(description = "来源单据类型", example = "FEEDBACK") | ||
| 41 | + private String sourceDocType; | ||
| 42 | + | ||
| 43 | + @Schema(description = "来源单据编号", example = "FB20250101001") | ||
| 44 | + private String sourceDocCode; | ||
| 45 | + | ||
| 46 | + @Schema(description = "来源单据行 ID", example = "300") | ||
| 47 | + private Long sourceLineId; | ||
| 48 | + | ||
| 49 | + // ========== 生产关联 ========== | ||
| 50 | + | ||
| 51 | + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 52 | + private Long workOrderId; | ||
| 53 | + | ||
| 54 | + @Schema(description = "工单编号", example = "WO20250101001") | ||
| 55 | + @ExcelProperty("工单编号") | ||
| 56 | + private String workOrderCode; | ||
| 57 | + | ||
| 58 | + @Schema(description = "工单名称", example = "生产工单A") | ||
| 59 | + private String workOrderName; | ||
| 60 | + | ||
| 61 | + @Schema(description = "生产任务 ID", example = "20") | ||
| 62 | + private Long taskId; | ||
| 63 | + | ||
| 64 | + @Schema(description = "工位 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") | ||
| 65 | + private Long workstationId; | ||
| 66 | + | ||
| 67 | + @Schema(description = "工位名称", example = "工位A") | ||
| 68 | + @ExcelProperty("工位名称") | ||
| 69 | + private String workstationName; | ||
| 70 | + | ||
| 71 | + @Schema(description = "工序 ID", example = "40") | ||
| 72 | + private Long processId; | ||
| 73 | + | ||
| 74 | + @Schema(description = "工序名称", example = "组装") | ||
| 75 | + @ExcelProperty("工序名称") | ||
| 76 | + private String processName; | ||
| 77 | + | ||
| 78 | + // ========== 物料 ========== | ||
| 79 | + | ||
| 80 | + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") | ||
| 81 | + private Long itemId; | ||
| 82 | + | ||
| 83 | + @Schema(description = "产品物料编码", example = "ITEM001") | ||
| 84 | + @ExcelProperty("产品物料编码") | ||
| 85 | + private String itemCode; | ||
| 86 | + | ||
| 87 | + @Schema(description = "产品物料名称", example = "物料A") | ||
| 88 | + @ExcelProperty("产品物料名称") | ||
| 89 | + private String itemName; | ||
| 90 | + | ||
| 91 | + @Schema(description = "规格型号", example = "100mm*50mm") | ||
| 92 | + private String itemSpecification; | ||
| 93 | + | ||
| 94 | + @Schema(description = "单位名称", example = "个") | ||
| 95 | + private String unitName; | ||
| 96 | + | ||
| 97 | + // ========== 数量 ========== | ||
| 98 | + | ||
| 99 | + @Schema(description = "检测数量", example = "100") | ||
| 100 | + @ExcelProperty("检测数量") | ||
| 101 | + private BigDecimal checkQuantity; | ||
| 102 | + | ||
| 103 | + @Schema(description = "合格品数量", example = "95") | ||
| 104 | + @ExcelProperty("合格品数量") | ||
| 105 | + private BigDecimal qualifiedQuantity; | ||
| 106 | + | ||
| 107 | + @Schema(description = "不合格品数量", example = "5") | ||
| 108 | + @ExcelProperty("不合格品数量") | ||
| 109 | + private BigDecimal unqualifiedQuantity; | ||
| 110 | + | ||
| 111 | + @Schema(description = "工废数量", example = "2") | ||
| 112 | + @ExcelProperty("工废数量") | ||
| 113 | + private BigDecimal laborScrapQuantity; | ||
| 114 | + | ||
| 115 | + @Schema(description = "料废数量", example = "2") | ||
| 116 | + @ExcelProperty("料废数量") | ||
| 117 | + private BigDecimal materialScrapQuantity; | ||
| 118 | + | ||
| 119 | + @Schema(description = "其他废品数量", example = "1") | ||
| 120 | + @ExcelProperty("其他废品数量") | ||
| 121 | + private BigDecimal otherScrapQuantity; | ||
| 122 | + | ||
| 123 | + // ========== 缺陷统计 ========== | ||
| 124 | + | ||
| 125 | + @Schema(description = "致命缺陷率(%)", example = "0.00") | ||
| 126 | + private BigDecimal criticalRate; | ||
| 127 | + | ||
| 128 | + @Schema(description = "严重缺陷率(%)", example = "0.00") | ||
| 129 | + private BigDecimal majorRate; | ||
| 130 | + | ||
| 131 | + @Schema(description = "轻微缺陷率(%)", example = "10.00") | ||
| 132 | + private BigDecimal minorRate; | ||
| 133 | + | ||
| 134 | + @Schema(description = "致命缺陷数量", example = "0") | ||
| 135 | + private Integer criticalQuantity; | ||
| 136 | + | ||
| 137 | + @Schema(description = "严重缺陷数量", example = "0") | ||
| 138 | + private Integer majorQuantity; | ||
| 139 | + | ||
| 140 | + @Schema(description = "轻微缺陷数量", example = "1") | ||
| 141 | + private Integer minorQuantity; | ||
| 142 | + | ||
| 143 | + // ========== 检验 ========== | ||
| 144 | + | ||
| 145 | + @Schema(description = "检测结果", example = "1") | ||
| 146 | + @ExcelProperty("检测结果") | ||
| 147 | + private Integer checkResult; | ||
| 148 | + | ||
| 149 | + @Schema(description = "检测日期") | ||
| 150 | + @ExcelProperty("检测日期") | ||
| 151 | + private LocalDateTime inspectDate; | ||
| 152 | + | ||
| 153 | + @Schema(description = "检测人员用户 ID", example = "1") | ||
| 154 | + private Long inspectorUserId; | ||
| 155 | + | ||
| 156 | + @Schema(description = "检测人员昵称", example = "张三") | ||
| 157 | + @ExcelProperty("检测人员") | ||
| 158 | + private String inspectorNickname; | ||
| 159 | + | ||
| 160 | + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 161 | + @ExcelProperty("状态") | ||
| 162 | + private Integer status; | ||
| 163 | + | ||
| 164 | + @Schema(description = "备注", example = "备注") | ||
| 165 | + @ExcelProperty("备注") | ||
| 166 | + private String remark; | ||
| 167 | + | ||
| 168 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 169 | + @ExcelProperty("创建时间") | ||
| 170 | + private LocalDateTime createTime; | ||
| 171 | + | ||
| 172 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotEmpty; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +import java.math.BigDecimal; | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - MES 过程检验单新增/修改 Request VO") | ||
| 12 | +@Data | ||
| 13 | +public class MesQcIpqcSaveReqVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "编号", example = "1024") | ||
| 16 | + private Long id; | ||
| 17 | + | ||
| 18 | + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPQC20250101001") | ||
| 19 | + @NotEmpty(message = "检验单编号不能为空") | ||
| 20 | + private String code; | ||
| 21 | + | ||
| 22 | + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX工单过程检验") | ||
| 23 | + @NotEmpty(message = "检验单名称不能为空") | ||
| 24 | + private String name; | ||
| 25 | + | ||
| 26 | + @Schema(description = "IPQC 检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPQC") | ||
| 27 | + @NotEmpty(message = "检验类型不能为空") | ||
| 28 | + private String type; | ||
| 29 | + | ||
| 30 | + @Schema(description = "检验模板 ID", example = "100") | ||
| 31 | + private Long templateId; | ||
| 32 | + | ||
| 33 | + // ========== 来源单据 ========== | ||
| 34 | + | ||
| 35 | + @Schema(description = "来源单据 ID", example = "200") | ||
| 36 | + private Long sourceDocId; | ||
| 37 | + | ||
| 38 | + @Schema(description = "来源单据类型", example = "FEEDBACK") | ||
| 39 | + private String sourceDocType; | ||
| 40 | + | ||
| 41 | + @Schema(description = "来源单据编号", example = "FB20250101001") | ||
| 42 | + private String sourceDocCode; | ||
| 43 | + | ||
| 44 | + @Schema(description = "来源单据行 ID", example = "300") | ||
| 45 | + private Long sourceLineId; | ||
| 46 | + | ||
| 47 | + // ========== 生产关联 ========== | ||
| 48 | + | ||
| 49 | + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 50 | + @NotNull(message = "生产工单不能为空") | ||
| 51 | + private Long workOrderId; | ||
| 52 | + | ||
| 53 | + @Schema(description = "生产任务 ID", example = "20") | ||
| 54 | + private Long taskId; | ||
| 55 | + | ||
| 56 | + @Schema(description = "工位 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") | ||
| 57 | + @NotNull(message = "工位不能为空") | ||
| 58 | + private Long workstationId; | ||
| 59 | + | ||
| 60 | + @Schema(description = "工序 ID", example = "40") | ||
| 61 | + private Long processId; | ||
| 62 | + | ||
| 63 | + // ========== 物料 ========== | ||
| 64 | + | ||
| 65 | + @Schema(description = "产品物料 ID", example = "50") | ||
| 66 | + private Long itemId; | ||
| 67 | + | ||
| 68 | + // ========== 数量 ========== | ||
| 69 | + | ||
| 70 | + @Schema(description = "检测数量", example = "100") | ||
| 71 | + private BigDecimal checkQuantity; | ||
| 72 | + | ||
| 73 | + @Schema(description = "合格品数量", example = "95") | ||
| 74 | + private BigDecimal qualifiedQuantity; | ||
| 75 | + | ||
| 76 | + @Schema(description = "不合格品数量", example = "5") | ||
| 77 | + private BigDecimal unqualifiedQuantity; | ||
| 78 | + | ||
| 79 | + @Schema(description = "工废数量", example = "2") | ||
| 80 | + private BigDecimal laborScrapQuantity; | ||
| 81 | + | ||
| 82 | + @Schema(description = "料废数量", example = "2") | ||
| 83 | + private BigDecimal materialScrapQuantity; | ||
| 84 | + | ||
| 85 | + @Schema(description = "其他废品数量", example = "1") | ||
| 86 | + private BigDecimal otherScrapQuantity; | ||
| 87 | + | ||
| 88 | + // ========== 检验 ========== | ||
| 89 | + | ||
| 90 | + @Schema(description = "检测结果", example = "1") | ||
| 91 | + private Integer checkResult; | ||
| 92 | + | ||
| 93 | + @Schema(description = "检测日期") | ||
| 94 | + private LocalDateTime inspectDate; | ||
| 95 | + | ||
| 96 | + @Schema(description = "检测人员用户 ID", example = "1") | ||
| 97 | + private Long inspectorUserId; | ||
| 98 | + | ||
| 99 | + @Schema(description = "备注", example = "备注") | ||
| 100 | + private String remark; | ||
| 101 | + | ||
| 102 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLinePageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.ToString; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - MES 过程检验单行分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +@ToString(callSuper = true) | ||
| 14 | +public class MesQcIpqcLinePageReqVO extends PageParam { | ||
| 15 | + | ||
| 16 | + @Schema(description = "过程检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 17 | + @NotNull(message = "过程检验单 ID 不能为空") | ||
| 18 | + private Long ipqcId; | ||
| 19 | + | ||
| 20 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.experimental.Accessors; | ||
| 6 | + | ||
| 7 | +import java.math.BigDecimal; | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - MES 过程检验单行 Response VO") | ||
| 11 | +@Data | ||
| 12 | +@Accessors(chain = true) | ||
| 13 | +public class MesQcIpqcLineRespVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + private Long id; | ||
| 17 | + | ||
| 18 | + @Schema(description = "过程检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 19 | + private Long ipqcId; | ||
| 20 | + | ||
| 21 | + @Schema(description = "检测指标 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 22 | + private Long indicatorId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "检测指标编码", example = "IND001") | ||
| 25 | + private String indicatorCode; | ||
| 26 | + | ||
| 27 | + @Schema(description = "检测指标名称", example = "外观") | ||
| 28 | + private String indicatorName; | ||
| 29 | + | ||
| 30 | + @Schema(description = "检测指标类型", example = "QUANTITATIVE") | ||
| 31 | + private String indicatorType; | ||
| 32 | + | ||
| 33 | + @Schema(description = "检测工具 ID", example = "5") | ||
| 34 | + private Long toolId; | ||
| 35 | + | ||
| 36 | + @Schema(description = "检测工具名称", example = "卡尺") | ||
| 37 | + private String toolName; | ||
| 38 | + | ||
| 39 | + @Schema(description = "检测方法", example = "目测") | ||
| 40 | + private String checkMethod; | ||
| 41 | + | ||
| 42 | + @Schema(description = "标准值", example = "10.5000") | ||
| 43 | + private BigDecimal standardValue; | ||
| 44 | + | ||
| 45 | + @Schema(description = "计量单位 ID", example = "3") | ||
| 46 | + private Long unitMeasureId; | ||
| 47 | + | ||
| 48 | + @Schema(description = "计量单位名称", example = "毫米") | ||
| 49 | + private String unitMeasureName; | ||
| 50 | + | ||
| 51 | + @Schema(description = "误差上限", example = "11.0000") | ||
| 52 | + private BigDecimal maxThreshold; | ||
| 53 | + | ||
| 54 | + @Schema(description = "误差下限", example = "10.0000") | ||
| 55 | + private BigDecimal minThreshold; | ||
| 56 | + | ||
| 57 | + @Schema(description = "致命缺陷数量", example = "0") | ||
| 58 | + private Integer criticalQuantity; | ||
| 59 | + | ||
| 60 | + @Schema(description = "严重缺陷数量", example = "0") | ||
| 61 | + private Integer majorQuantity; | ||
| 62 | + | ||
| 63 | + @Schema(description = "轻微缺陷数量", example = "1") | ||
| 64 | + private Integer minorQuantity; | ||
| 65 | + | ||
| 66 | + @Schema(description = "备注", example = "备注") | ||
| 67 | + private String remark; | ||
| 68 | + | ||
| 69 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 70 | + private LocalDateTime createTime; | ||
| 71 | + | ||
| 72 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; | ||
| 5 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; | ||
| 6 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; | ||
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; | ||
| 8 | +import com.baomidou.mybatisplus.annotation.KeySequence; | ||
| 9 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 10 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 11 | +import lombok.*; | ||
| 12 | + | ||
| 13 | +import java.math.BigDecimal; | ||
| 14 | +import java.time.LocalDateTime; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * MES 过程检验单(IPQC, In-Process Quality Control) DO | ||
| 18 | + * | ||
| 19 | + * @author 芋道源码 | ||
| 20 | + */ | ||
| 21 | +@TableName("mes_qc_ipqc") | ||
| 22 | +@KeySequence("mes_qc_ipqc_seq") | ||
| 23 | +@Data | ||
| 24 | +@EqualsAndHashCode(callSuper = true) | ||
| 25 | +@ToString(callSuper = true) | ||
| 26 | +@Builder | ||
| 27 | +@NoArgsConstructor | ||
| 28 | +@AllArgsConstructor | ||
| 29 | +public class MesQcIpqcDO extends BaseDO { | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 编号 | ||
| 33 | + */ | ||
| 34 | + @TableId | ||
| 35 | + private Long id; | ||
| 36 | + /** | ||
| 37 | + * 检验单编号 | ||
| 38 | + */ | ||
| 39 | + private String code; | ||
| 40 | + /** | ||
| 41 | + * 检验单名称 | ||
| 42 | + */ | ||
| 43 | + private String name; | ||
| 44 | + // TODO @AI:搞成 int 类型; | ||
| 45 | + /** | ||
| 46 | + * IPQC 检验类型 | ||
| 47 | + * | ||
| 48 | + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_IPQC_TYPE} | ||
| 49 | + */ | ||
| 50 | + private String type; | ||
| 51 | + /** | ||
| 52 | + * 检验模板 ID | ||
| 53 | + * | ||
| 54 | + * 关联 {@link MesQcTemplateDO#getId()} | ||
| 55 | + */ | ||
| 56 | + private Long templateId; | ||
| 57 | + | ||
| 58 | + // ========== 来源单据(TODO @芋艿:PRO/WM 模块联动后接入) ========== | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 来源单据 ID | ||
| 62 | + */ | ||
| 63 | + private Long sourceDocId; | ||
| 64 | + /** | ||
| 65 | + * 来源单据类型 | ||
| 66 | + */ | ||
| 67 | + private String sourceDocType; | ||
| 68 | + /** | ||
| 69 | + * 来源单据编号 | ||
| 70 | + */ | ||
| 71 | + private String sourceDocCode; | ||
| 72 | + /** | ||
| 73 | + * 来源单据行 ID | ||
| 74 | + */ | ||
| 75 | + private Long sourceLineId; | ||
| 76 | + | ||
| 77 | + // ========== 生产关联 ========== | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 生产工单 ID | ||
| 81 | + * | ||
| 82 | + * 关联 {@link MesProWorkOrderDO#getId()} | ||
| 83 | + */ | ||
| 84 | + private Long workOrderId; | ||
| 85 | + /** | ||
| 86 | + * 生产任务 ID | ||
| 87 | + * | ||
| 88 | + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO#getId()} | ||
| 89 | + */ | ||
| 90 | + private Long taskId; | ||
| 91 | + /** | ||
| 92 | + * 工位 ID | ||
| 93 | + * | ||
| 94 | + * 关联 {@link MesMdWorkstationDO#getId()} | ||
| 95 | + */ | ||
| 96 | + private Long workstationId; | ||
| 97 | + /** | ||
| 98 | + * 工序 ID | ||
| 99 | + * | ||
| 100 | + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO#getId()} | ||
| 101 | + */ | ||
| 102 | + private Long processId; | ||
| 103 | + | ||
| 104 | + // ========== 物料 ========== | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 产品物料 ID | ||
| 108 | + * | ||
| 109 | + * 关联 {@link MesMdItemDO#getId()} | ||
| 110 | + */ | ||
| 111 | + private Long itemId; | ||
| 112 | + | ||
| 113 | + // ========== 数量 ========== | ||
| 114 | + | ||
| 115 | + /** | ||
| 116 | + * 检测数量 | ||
| 117 | + */ | ||
| 118 | + private BigDecimal checkQuantity; | ||
| 119 | + /** | ||
| 120 | + * 合格品数量 | ||
| 121 | + */ | ||
| 122 | + private BigDecimal qualifiedQuantity; | ||
| 123 | + /** | ||
| 124 | + * 不合格品数量 | ||
| 125 | + */ | ||
| 126 | + private BigDecimal unqualifiedQuantity; | ||
| 127 | + /** | ||
| 128 | + * 工废数量 | ||
| 129 | + */ | ||
| 130 | + private BigDecimal laborScrapQuantity; | ||
| 131 | + /** | ||
| 132 | + * 料废数量 | ||
| 133 | + */ | ||
| 134 | + private BigDecimal materialScrapQuantity; | ||
| 135 | + /** | ||
| 136 | + * 其他废品数量 | ||
| 137 | + */ | ||
| 138 | + private BigDecimal otherScrapQuantity; | ||
| 139 | + | ||
| 140 | + // ========== 缺陷统计 ========== | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * 致命缺陷率(%) | ||
| 144 | + */ | ||
| 145 | + private BigDecimal criticalRate; | ||
| 146 | + /** | ||
| 147 | + * 严重缺陷率(%) | ||
| 148 | + */ | ||
| 149 | + private BigDecimal majorRate; | ||
| 150 | + /** | ||
| 151 | + * 轻微缺陷率(%) | ||
| 152 | + */ | ||
| 153 | + private BigDecimal minorRate; | ||
| 154 | + /** | ||
| 155 | + * 致命缺陷数量 | ||
| 156 | + */ | ||
| 157 | + private Integer criticalQuantity; | ||
| 158 | + /** | ||
| 159 | + * 严重缺陷数量 | ||
| 160 | + */ | ||
| 161 | + private Integer majorQuantity; | ||
| 162 | + /** | ||
| 163 | + * 轻微缺陷数量 | ||
| 164 | + */ | ||
| 165 | + private Integer minorQuantity; | ||
| 166 | + | ||
| 167 | + // ========== 检验 ========== | ||
| 168 | + | ||
| 169 | + /** | ||
| 170 | + * 检测结果 | ||
| 171 | + * | ||
| 172 | + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} | ||
| 173 | + */ | ||
| 174 | + private Integer checkResult; | ||
| 175 | + /** | ||
| 176 | + * 检测日期 | ||
| 177 | + */ | ||
| 178 | + private LocalDateTime inspectDate; | ||
| 179 | + /** | ||
| 180 | + * 检测人员用户 ID | ||
| 181 | + * | ||
| 182 | + * 关联 AdminUserDO 的 id | ||
| 183 | + */ | ||
| 184 | + private Long inspectorUserId; | ||
| 185 | + /** | ||
| 186 | + * 状态 | ||
| 187 | + * | ||
| 188 | + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum} | ||
| 189 | + */ | ||
| 190 | + private Integer status; | ||
| 191 | + /** | ||
| 192 | + * 备注 | ||
| 193 | + */ | ||
| 194 | + private String remark; | ||
| 195 | + | ||
| 196 | + // ========== 预留字段 ========== | ||
| 197 | + | ||
| 198 | + /** | ||
| 199 | + * 预留字段 1 | ||
| 200 | + */ | ||
| 201 | + private String attribute1; | ||
| 202 | + /** | ||
| 203 | + * 预留字段 2 | ||
| 204 | + */ | ||
| 205 | + private String attribute2; | ||
| 206 | + /** | ||
| 207 | + * 预留字段 3 | ||
| 208 | + */ | ||
| 209 | + private Integer attribute3; | ||
| 210 | + /** | ||
| 211 | + * 预留字段 4 | ||
| 212 | + */ | ||
| 213 | + private Integer attribute4; | ||
| 214 | + | ||
| 215 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcLineDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; | ||
| 5 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; | ||
| 6 | +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; | ||
| 7 | +import com.baomidou.mybatisplus.annotation.KeySequence; | ||
| 8 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 9 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 10 | +import lombok.*; | ||
| 11 | + | ||
| 12 | +import java.math.BigDecimal; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * MES 过程检验单行 DO | ||
| 16 | + * | ||
| 17 | + * @author 芋道源码 | ||
| 18 | + */ | ||
| 19 | +@TableName("mes_qc_ipqc_line") | ||
| 20 | +@KeySequence("mes_qc_ipqc_line_seq") | ||
| 21 | +@Data | ||
| 22 | +@EqualsAndHashCode(callSuper = true) | ||
| 23 | +@ToString(callSuper = true) | ||
| 24 | +@Builder | ||
| 25 | +@NoArgsConstructor | ||
| 26 | +@AllArgsConstructor | ||
| 27 | +public class MesQcIpqcLineDO extends BaseDO { | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 编号 | ||
| 31 | + */ | ||
| 32 | + @TableId | ||
| 33 | + private Long id; | ||
| 34 | + /** | ||
| 35 | + * 过程检验单 ID | ||
| 36 | + * | ||
| 37 | + * 关联 {@link MesQcIpqcDO#getId()} | ||
| 38 | + */ | ||
| 39 | + private Long ipqcId; | ||
| 40 | + /** | ||
| 41 | + * 检测指标 ID | ||
| 42 | + * | ||
| 43 | + * 关联 {@link MesQcIndicatorDO#getId()} | ||
| 44 | + */ | ||
| 45 | + private Long indicatorId; | ||
| 46 | + /** | ||
| 47 | + * 检测工具 ID | ||
| 48 | + * | ||
| 49 | + * 关联 {@link MesTmToolDO#getId()} | ||
| 50 | + */ | ||
| 51 | + private Long toolId; | ||
| 52 | + /** | ||
| 53 | + * 检测方法 | ||
| 54 | + */ | ||
| 55 | + private String checkMethod; | ||
| 56 | + /** | ||
| 57 | + * 标准值 | ||
| 58 | + */ | ||
| 59 | + private BigDecimal standardValue; | ||
| 60 | + /** | ||
| 61 | + * 计量单位 ID | ||
| 62 | + * | ||
| 63 | + * 关联 {@link MesMdUnitMeasureDO#getId()} | ||
| 64 | + */ | ||
| 65 | + private Long unitMeasureId; | ||
| 66 | + /** | ||
| 67 | + * 误差上限 | ||
| 68 | + */ | ||
| 69 | + private BigDecimal maxThreshold; | ||
| 70 | + /** | ||
| 71 | + * 误差下限 | ||
| 72 | + */ | ||
| 73 | + private BigDecimal minThreshold; | ||
| 74 | + /** | ||
| 75 | + * 致命缺陷数量 | ||
| 76 | + */ | ||
| 77 | + private Integer criticalQuantity; | ||
| 78 | + /** | ||
| 79 | + * 严重缺陷数量 | ||
| 80 | + */ | ||
| 81 | + private Integer majorQuantity; | ||
| 82 | + /** | ||
| 83 | + * 轻微缺陷数量 | ||
| 84 | + */ | ||
| 85 | + private Integer minorQuantity; | ||
| 86 | + /** | ||
| 87 | + * 备注 | ||
| 88 | + */ | ||
| 89 | + private String remark; | ||
| 90 | + | ||
| 91 | + // ========== 预留字段 ========== | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * 预留字段 1 | ||
| 95 | + */ | ||
| 96 | + private String attribute1; | ||
| 97 | + /** | ||
| 98 | + * 预留字段 2 | ||
| 99 | + */ | ||
| 100 | + private String attribute2; | ||
| 101 | + /** | ||
| 102 | + * 预留字段 3 | ||
| 103 | + */ | ||
| 104 | + private Integer attribute3; | ||
| 105 | + /** | ||
| 106 | + * 预留字段 4 | ||
| 107 | + */ | ||
| 108 | + private Integer attribute4; | ||
| 109 | + | ||
| 110 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc; | ||
| 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.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; | ||
| 8 | +import org.apache.ibatis.annotations.Mapper; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * MES 过程检验单行 Mapper | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 17 | +@Mapper | ||
| 18 | +public interface MesQcIpqcLineMapper extends BaseMapperX<MesQcIpqcLineDO> { | ||
| 19 | + | ||
| 20 | + default PageResult<MesQcIpqcLineDO> selectPage(MesQcIpqcLinePageReqVO reqVO) { | ||
| 21 | + return selectPage(reqVO, new LambdaQueryWrapperX<MesQcIpqcLineDO>() | ||
| 22 | + .eqIfPresent(MesQcIpqcLineDO::getIpqcId, reqVO.getIpqcId()) | ||
| 23 | + .orderByAsc(MesQcIpqcLineDO::getId)); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + default List<MesQcIpqcLineDO> selectListByIpqcId(Long ipqcId) { | ||
| 27 | + return selectList(MesQcIpqcLineDO::getIpqcId, ipqcId); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + default void deleteByIpqcId(Long ipqcId) { | ||
| 31 | + delete(new LambdaQueryWrapperX<MesQcIpqcLineDO>() | ||
| 32 | + .eq(MesQcIpqcLineDO::getIpqcId, ipqcId)); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc; | ||
| 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.qc.ipqc.vo.MesQcIpqcPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; | ||
| 8 | +import org.apache.ibatis.annotations.Mapper; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * MES 过程检验单(IPQC) Mapper | ||
| 12 | + * | ||
| 13 | + * @author 芋道源码 | ||
| 14 | + */ | ||
| 15 | +@Mapper | ||
| 16 | +public interface MesQcIpqcMapper extends BaseMapperX<MesQcIpqcDO> { | ||
| 17 | + | ||
| 18 | + default PageResult<MesQcIpqcDO> selectPage(MesQcIpqcPageReqVO reqVO) { | ||
| 19 | + return selectPage(reqVO, new LambdaQueryWrapperX<MesQcIpqcDO>() | ||
| 20 | + .likeIfPresent(MesQcIpqcDO::getCode, reqVO.getCode()) | ||
| 21 | + .eqIfPresent(MesQcIpqcDO::getType, reqVO.getType()) | ||
| 22 | + .eqIfPresent(MesQcIpqcDO::getWorkOrderId, reqVO.getWorkOrderId()) | ||
| 23 | + .eqIfPresent(MesQcIpqcDO::getWorkstationId, reqVO.getWorkstationId()) | ||
| 24 | + .eqIfPresent(MesQcIpqcDO::getItemId, reqVO.getItemId()) | ||
| 25 | + .eqIfPresent(MesQcIpqcDO::getCheckResult, reqVO.getCheckResult()) | ||
| 26 | + .eqIfPresent(MesQcIpqcDO::getStatus, reqVO.getStatus()) | ||
| 27 | + .betweenIfPresent(MesQcIpqcDO::getInspectDate, reqVO.getInspectDate()) | ||
| 28 | + .eqIfPresent(MesQcIpqcDO::getInspectorUserId, reqVO.getInspectorUserId()) | ||
| 29 | + .orderByDesc(MesQcIpqcDO::getId)); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + default MesQcIpqcDO selectByCode(String code) { | ||
| 33 | + return selectOne(MesQcIpqcDO::getCode, code); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
| @@ -270,6 +270,24 @@ public interface ErrorCodeConstants { | @@ -270,6 +270,24 @@ public interface ErrorCodeConstants { | ||
| 270 | // ========== MES 质量管理-检验结果(1-040-606-000) ========== | 270 | // ========== MES 质量管理-检验结果(1-040-606-000) ========== |
| 271 | ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在"); | 271 | ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在"); |
| 272 | 272 | ||
| 273 | + // ========== MES 质量管理-出货检验(1-040-607-000) ========== | ||
| 274 | + ErrorCode QC_OQC_NOT_EXISTS = new ErrorCode(1_040_607_000, "出货检验单不存在"); | ||
| 275 | + ErrorCode QC_OQC_CODE_DUPLICATE = new ErrorCode(1_040_607_001, "出货检验单编号已存在"); | ||
| 276 | + ErrorCode QC_OQC_NOT_PREPARE = new ErrorCode(1_040_607_002, "只有草稿状态的检验单才可操作"); | ||
| 277 | + ErrorCode QC_OQC_QUANTITY_MISMATCH = new ErrorCode(1_040_607_004, "合格品与不合格品数量之和须等于检测数量"); | ||
| 278 | + ErrorCode QC_OQC_NO_TEMPLATE = new ErrorCode(1_040_607_005, "当前产品未配置 OQC 检测模板"); | ||
| 279 | + // ========== MES 质量管理-出货检验行(1-040-607-100) ========== | ||
| 280 | + ErrorCode QC_OQC_LINE_NOT_EXISTS = new ErrorCode(1_040_607_100, "出货检验行不存在"); | ||
| 281 | + | ||
| 282 | + // ========== MES 质量管理-退货检验 RQC(1-040-608-000) ========== | ||
| 283 | + ErrorCode QC_RQC_NOT_EXISTS = new ErrorCode(1_040_608_000, "退货检验单不存在"); | ||
| 284 | + ErrorCode QC_RQC_CODE_DUPLICATE = new ErrorCode(1_040_608_001, "退货检验单编号已存在"); | ||
| 285 | + ErrorCode QC_RQC_NOT_PREPARE = new ErrorCode(1_040_608_002, "只有草稿状态的检验单才可操作"); | ||
| 286 | + ErrorCode QC_RQC_QUANTITY_MISMATCH = new ErrorCode(1_040_608_004, "合格品与不合格品数量之和须等于检测数量"); | ||
| 287 | + ErrorCode QC_RQC_NO_TEMPLATE = new ErrorCode(1_040_608_005, "当前产品未配置 RQC 检测模板"); | ||
| 288 | + // ========== MES 质量管理-退货检验行(1-040-608-100) ========== | ||
| 289 | + ErrorCode QC_RQC_LINE_NOT_EXISTS = new ErrorCode(1_040_608_100, "退货检验行不存在"); | ||
| 290 | + | ||
| 273 | // ========== MES 仓库管理-仓库(1-040-700-000) ========== | 291 | // ========== MES 仓库管理-仓库(1-040-700-000) ========== |
| 274 | ErrorCode WM_WAREHOUSE_NOT_EXISTS = new ErrorCode(1_040_700_000, "仓库不存在"); | 292 | ErrorCode WM_WAREHOUSE_NOT_EXISTS = new ErrorCode(1_040_700_000, "仓库不存在"); |
| 275 | ErrorCode WM_WAREHOUSE_CODE_DUPLICATE = new ErrorCode(1_040_700_001, "仓库编码已存在"); | 293 | ErrorCode WM_WAREHOUSE_CODE_DUPLICATE = new ErrorCode(1_040_700_001, "仓库编码已存在"); |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcOqcStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.enums.qc; | ||
| 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 MesQcOqcStatusEnum implements ArrayValuable<Integer> { | ||
| 17 | + | ||
| 18 | + PREPARE(0, "草稿"), | ||
| 19 | + FINISHED(1, "已完成"); | ||
| 20 | + | ||
| 21 | + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcOqcStatusEnum::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/process/MesProProcessService.java
| @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcess | @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcess | ||
| 6 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; | 6 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; |
| 7 | 7 | ||
| 8 | import jakarta.validation.Valid; | 8 | import jakarta.validation.Valid; |
| 9 | + | ||
| 10 | +import java.util.Collection; | ||
| 9 | import java.util.List; | 11 | import java.util.List; |
| 10 | import java.util.Map; | 12 | import java.util.Map; |
| 11 | 13 | ||
| @@ -54,7 +56,7 @@ public interface MesProProcessService { | @@ -54,7 +56,7 @@ public interface MesProProcessService { | ||
| 54 | * @param ids 编号列表 | 56 | * @param ids 编号列表 |
| 55 | * @return 生产工序列表 | 57 | * @return 生产工序列表 |
| 56 | */ | 58 | */ |
| 57 | - List<MesProProcessDO> getProcessList(List<Long> ids); | 59 | + List<MesProProcessDO> getProcessList(Collection<Long> ids); |
| 58 | 60 | ||
| 59 | /** | 61 | /** |
| 60 | * 获得生产工序分页 | 62 | * 获得生产工序分页 |
| @@ -85,7 +87,7 @@ public interface MesProProcessService { | @@ -85,7 +87,7 @@ public interface MesProProcessService { | ||
| 85 | * @param ids 编号列表 | 87 | * @param ids 编号列表 |
| 86 | * @return 工序 Map | 88 | * @return 工序 Map |
| 87 | */ | 89 | */ |
| 88 | - default Map<Long, MesProProcessDO> getProcessMap(List<Long> ids) { | 90 | + default Map<Long, MesProProcessDO> getProcessMap(Collection<Long> ids) { |
| 89 | return convertMap(getProcessList(ids), MesProProcessDO::getId); | 91 | return convertMap(getProcessList(ids), MesProProcessDO::getId); |
| 90 | } | 92 | } |
| 91 | 93 |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java
| @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; | @@ -13,6 +13,7 @@ import org.springframework.stereotype.Service; | ||
| 13 | import org.springframework.transaction.annotation.Transactional; | 13 | import org.springframework.transaction.annotation.Transactional; |
| 14 | import org.springframework.validation.annotation.Validated; | 14 | import org.springframework.validation.annotation.Validated; |
| 15 | 15 | ||
| 16 | +import java.util.Collection; | ||
| 16 | import java.util.Collections; | 17 | import java.util.Collections; |
| 17 | import java.util.List; | 18 | import java.util.List; |
| 18 | 19 | ||
| @@ -119,7 +120,7 @@ public class MesProProcessServiceImpl implements MesProProcessService { | @@ -119,7 +120,7 @@ public class MesProProcessServiceImpl implements MesProProcessService { | ||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | @Override | 122 | @Override |
| 122 | - public List<MesProProcessDO> getProcessList(List<Long> ids) { | 123 | + public List<MesProProcessDO> getProcessList(Collection<Long> ids) { |
| 123 | if (CollUtil.isEmpty(ids)) { | 124 | if (CollUtil.isEmpty(ids)) { |
| 124 | return Collections.emptyList(); | 125 | return Collections.emptyList(); |
| 125 | } | 126 | } |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.service.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; | ||
| 6 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; | ||
| 7 | + | ||
| 8 | +import java.util.List; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * MES 过程检验单行 Service 接口 | ||
| 12 | + * | ||
| 13 | + * @author 芋道源码 | ||
| 14 | + */ | ||
| 15 | +public interface MesQcIpqcLineService { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 获得过程检验行 | ||
| 19 | + * | ||
| 20 | + * @param id 编号 | ||
| 21 | + * @return 过程检验行 | ||
| 22 | + */ | ||
| 23 | + MesQcIpqcLineDO getIpqcLine(Long id); | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 获得过程检验行分页 | ||
| 27 | + * | ||
| 28 | + * @param pageReqVO 分页查询 | ||
| 29 | + * @return 过程检验行分页 | ||
| 30 | + */ | ||
| 31 | + PageResult<MesQcIpqcLineDO> getIpqcLinePage(MesQcIpqcLinePageReqVO pageReqVO); | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 根据过程检验单 ID 查询所有行 | ||
| 35 | + * | ||
| 36 | + * @param ipqcId 过程检验单 ID | ||
| 37 | + * @return 行列表 | ||
| 38 | + */ | ||
| 39 | + List<MesQcIpqcLineDO> selectListByIpqcId(Long ipqcId); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 从模板指标自动生成检验行 | ||
| 43 | + * | ||
| 44 | + * @param ipqcId 过程检验单 ID | ||
| 45 | + * @param templateId 模板 ID | ||
| 46 | + */ | ||
| 47 | + void createLinesFromTemplate(Long ipqcId, Long templateId); | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 根据过程检验单 ID 级联删除所有行 | ||
| 51 | + * | ||
| 52 | + * @param ipqcId 过程检验单 ID | ||
| 53 | + */ | ||
| 54 | + void deleteByIpqcId(Long ipqcId); | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 校验过程检验行存在 | ||
| 58 | + * | ||
| 59 | + * @param id 编号 | ||
| 60 | + * @return 过程检验行 | ||
| 61 | + */ | ||
| 62 | + MesQcIpqcLineDO validateIpqcLineExists(Long id); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 根据缺陷记录重新计算行级缺陷统计 | ||
| 66 | + * | ||
| 67 | + * @param ipqcId 过程检验单 ID | ||
| 68 | + * @param records 缺陷记录列表 | ||
| 69 | + */ | ||
| 70 | + void recalculateLineDefectStats(Long ipqcId, List<MesQcDefectRecordDO> records); | ||
| 71 | + | ||
| 72 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.service.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.util.ObjUtil; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; | ||
| 8 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; | ||
| 9 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; | ||
| 10 | +import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcLineMapper; | ||
| 11 | +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; | ||
| 12 | +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; | ||
| 13 | +import jakarta.annotation.Resource; | ||
| 14 | +import org.springframework.stereotype.Service; | ||
| 15 | +import org.springframework.validation.annotation.Validated; | ||
| 16 | + | ||
| 17 | +import java.util.ArrayList; | ||
| 18 | +import java.util.List; | ||
| 19 | +import java.util.Objects; | ||
| 20 | + | ||
| 21 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 22 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 23 | +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * MES 过程检验单行 Service 实现类 | ||
| 27 | + * | ||
| 28 | + * @author 芋道源码 | ||
| 29 | + */ | ||
| 30 | +@Service | ||
| 31 | +@Validated | ||
| 32 | +public class MesQcIpqcLineServiceImpl implements MesQcIpqcLineService { | ||
| 33 | + | ||
| 34 | + @Resource | ||
| 35 | + private MesQcIpqcLineMapper ipqcLineMapper; | ||
| 36 | + @Resource | ||
| 37 | + private MesQcTemplateIndicatorMapper templateIndicatorMapper; | ||
| 38 | + | ||
| 39 | + @Override | ||
| 40 | + public MesQcIpqcLineDO getIpqcLine(Long id) { | ||
| 41 | + return ipqcLineMapper.selectById(id); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + @Override | ||
| 45 | + public PageResult<MesQcIpqcLineDO> getIpqcLinePage(MesQcIpqcLinePageReqVO pageReqVO) { | ||
| 46 | + return ipqcLineMapper.selectPage(pageReqVO); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + @Override | ||
| 50 | + public List<MesQcIpqcLineDO> selectListByIpqcId(Long ipqcId) { | ||
| 51 | + return ipqcLineMapper.selectListByIpqcId(ipqcId); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + @Override | ||
| 55 | + public void createLinesFromTemplate(Long ipqcId, Long templateId) { | ||
| 56 | + List<MesQcTemplateIndicatorDO> indicators = templateIndicatorMapper.selectListByTemplateId(templateId); | ||
| 57 | + List<MesQcIpqcLineDO> lines = convertList(indicators, indicator -> new MesQcIpqcLineDO() | ||
| 58 | + .setIpqcId(ipqcId).setIndicatorId(indicator.getIndicatorId()) | ||
| 59 | + .setToolId(null) // TODO @芋艿:模板指标暂无 toolId,后续可扩展 | ||
| 60 | + .setCheckMethod(indicator.getCheckMethod()) | ||
| 61 | + .setStandardValue(indicator.getStandardValue()).setUnitMeasureId(indicator.getUnitMeasureId()) | ||
| 62 | + .setMaxThreshold(indicator.getThresholdMax()).setMinThreshold(indicator.getThresholdMin()) | ||
| 63 | + .setCriticalQuantity(0).setMajorQuantity(0).setMinorQuantity(0)); | ||
| 64 | + ipqcLineMapper.insertBatch(lines); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @Override | ||
| 68 | + public void deleteByIpqcId(Long ipqcId) { | ||
| 69 | + ipqcLineMapper.deleteByIpqcId(ipqcId); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @Override | ||
| 73 | + public MesQcIpqcLineDO validateIpqcLineExists(Long id) { | ||
| 74 | + MesQcIpqcLineDO line = ipqcLineMapper.selectById(id); | ||
| 75 | + if (line == null) { | ||
| 76 | + throw exception(QC_IPQC_LINE_NOT_EXISTS); | ||
| 77 | + } | ||
| 78 | + return line; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void recalculateLineDefectStats(Long ipqcId, List<MesQcDefectRecordDO> records) { | ||
| 83 | + List<MesQcIpqcLineDO> lines = ipqcLineMapper.selectListByIpqcId(ipqcId); | ||
| 84 | + if (CollUtil.isEmpty(lines)) { | ||
| 85 | + return; | ||
| 86 | + } | ||
| 87 | + List<MesQcIpqcLineDO> updateLines = new ArrayList<>(lines.size()); | ||
| 88 | + for (MesQcIpqcLineDO line : lines) { | ||
| 89 | + int critical = 0, major = 0, minor = 0; | ||
| 90 | + for (MesQcDefectRecordDO record : records) { | ||
| 91 | + if (ObjUtil.notEqual(record.getLineId(), line.getId())) { | ||
| 92 | + continue; | ||
| 93 | + } | ||
| 94 | + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); | ||
| 95 | + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { | ||
| 96 | + critical += quantity; | ||
| 97 | + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { | ||
| 98 | + major += quantity; | ||
| 99 | + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { | ||
| 100 | + minor += quantity; | ||
| 101 | + } else { | ||
| 102 | + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + updateLines.add(new MesQcIpqcLineDO().setId(line.getId()) | ||
| 106 | + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor)); | ||
| 107 | + } | ||
| 108 | + for (MesQcIpqcLineDO updateLine : updateLines) { | ||
| 109 | + ipqcLineMapper.updateById(updateLine); | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.service.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; | ||
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; | ||
| 8 | +import jakarta.validation.Valid; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * MES 过程检验单(IPQC) Service 接口 | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 17 | +public interface MesQcIpqcService { | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 创建过程检验单 | ||
| 21 | + * | ||
| 22 | + * @param createReqVO 创建信息 | ||
| 23 | + * @return 编号 | ||
| 24 | + */ | ||
| 25 | + Long createIpqc(@Valid MesQcIpqcSaveReqVO createReqVO); | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 更新过程检验单 | ||
| 29 | + * | ||
| 30 | + * @param updateReqVO 更新信息 | ||
| 31 | + */ | ||
| 32 | + void updateIpqc(@Valid MesQcIpqcSaveReqVO updateReqVO); | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 完成过程检验单 | ||
| 36 | + * | ||
| 37 | + * @param id 编号 | ||
| 38 | + */ | ||
| 39 | + void completeIpqc(Long id); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 删除过程检验单 | ||
| 43 | + * | ||
| 44 | + * @param id 编号 | ||
| 45 | + */ | ||
| 46 | + void deleteIpqc(Long id); | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 获得过程检验单 | ||
| 50 | + * | ||
| 51 | + * @param id 编号 | ||
| 52 | + * @return 过程检验单 | ||
| 53 | + */ | ||
| 54 | + MesQcIpqcDO getIpqc(Long id); | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 获得过程检验单分页 | ||
| 58 | + * | ||
| 59 | + * @param pageReqVO 分页查询 | ||
| 60 | + * @return 过程检验单分页 | ||
| 61 | + */ | ||
| 62 | + PageResult<MesQcIpqcDO> getIpqcPage(MesQcIpqcPageReqVO pageReqVO); | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * 校验过程检验单存在 | ||
| 66 | + * | ||
| 67 | + * @param id 编号 | ||
| 68 | + * @return 过程检验单 | ||
| 69 | + */ | ||
| 70 | + MesQcIpqcDO validateIpqcExists(Long id); | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 根据缺陷记录重新计算主表的缺陷统计(含行级下沉) | ||
| 74 | + * | ||
| 75 | + * @param ipqcId 过程检验单 ID | ||
| 76 | + * @param records 缺陷记录列表 | ||
| 77 | + */ | ||
| 78 | + void recalculateDefectStats(Long ipqcId, List<MesQcDefectRecordDO> records); | ||
| 79 | + | ||
| 80 | +} |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.service.qc.ipqc; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ObjUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; | ||
| 9 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; | ||
| 10 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; | ||
| 11 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; | ||
| 12 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; | ||
| 13 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; | ||
| 14 | +import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper; | ||
| 15 | +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; | ||
| 16 | +import cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum; | ||
| 17 | +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; | ||
| 18 | +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; | ||
| 19 | +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; | ||
| 20 | +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; | ||
| 21 | +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateService; | ||
| 22 | +import jakarta.annotation.Resource; | ||
| 23 | +import org.springframework.context.annotation.Lazy; | ||
| 24 | +import org.springframework.stereotype.Service; | ||
| 25 | +import org.springframework.transaction.annotation.Transactional; | ||
| 26 | +import org.springframework.validation.annotation.Validated; | ||
| 27 | + | ||
| 28 | +import java.math.BigDecimal; | ||
| 29 | +import java.math.RoundingMode; | ||
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Objects; | ||
| 32 | + | ||
| 33 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 34 | +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; | ||
| 35 | + | ||
| 36 | +/** | ||
| 37 | + * MES 过程检验单(IPQC) Service 实现类 | ||
| 38 | + * | ||
| 39 | + * @author 芋道源码 | ||
| 40 | + */ | ||
| 41 | +@Service | ||
| 42 | +@Validated | ||
| 43 | +public class MesQcIpqcServiceImpl implements MesQcIpqcService { | ||
| 44 | + | ||
| 45 | + @Resource | ||
| 46 | + private MesQcIpqcMapper ipqcMapper; | ||
| 47 | + | ||
| 48 | + @Resource | ||
| 49 | + private MesQcTemplateService templateService; | ||
| 50 | + @Resource | ||
| 51 | + private MesQcIpqcLineService ipqcLineService; | ||
| 52 | + @Resource | ||
| 53 | + @Lazy | ||
| 54 | + private MesProWorkOrderService workOrderService; | ||
| 55 | + @Resource | ||
| 56 | + @Lazy | ||
| 57 | + private MesMdWorkstationService workstationService; | ||
| 58 | + @Resource | ||
| 59 | + @Lazy | ||
| 60 | + private MesQcDefectRecordService defectRecordService; | ||
| 61 | + | ||
| 62 | + @Override | ||
| 63 | + @Transactional(rollbackFor = Exception.class) | ||
| 64 | + public Long createIpqc(MesQcIpqcSaveReqVO createReqVO) { | ||
| 65 | + // 1.1 校验编号唯一 | ||
| 66 | + validateIpqcCodeUnique(null, createReqVO.getCode()); | ||
| 67 | + | ||
| 68 | + // 1.2 从工单获取产品物料 ID | ||
| 69 | + // TODO @AI:需要校验 workOrderService 存在; | ||
| 70 | +// TODO createReqVO 里的 itemId 字段去掉;直接去下面的实体去 set; | ||
| 71 | + MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(createReqVO.getWorkOrderId()); | ||
| 72 | + if (workOrder != null) { | ||
| 73 | + createReqVO.setItemId(workOrder.getProductId()); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + // 1.3 从工位获取工序 ID | ||
| 77 | + // TODO @AI:需要校验 workstationService 存在; | ||
| 78 | + // TODO @AI:processId 不存储,去读取好了; | ||
| 79 | + MesMdWorkstationDO workstation = workstationService.getWorkstation(createReqVO.getWorkstationId()); | ||
| 80 | + if (workstation != null && workstation.getProcessId() != null) { | ||
| 81 | + createReqVO.setProcessId(workstation.getProcessId()); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + // 1.4 根据产品 + 检验类型自动匹配模板 | ||
| 85 | + // TODO @AI:直接调用 templateService 的校验方法; | ||
| 86 | + MesQcTemplateDO template = templateService.getTemplateByItemIdAndType( | ||
| 87 | + createReqVO.getItemId(), MesQcTypeEnum.IPQC.getType()); | ||
| 88 | + if (template == null) { | ||
| 89 | + throw exception(QC_IPQC_NO_TEMPLATE); | ||
| 90 | + } | ||
| 91 | + createReqVO.setTemplateId(template.getId()); | ||
| 92 | + | ||
| 93 | + // 1.5 从模板的产品关联中获取检测参数 | ||
| 94 | + MesQcTemplateItemDO templateItem = templateService.getTemplateItemByTemplateIdAndItemId( | ||
| 95 | + template.getId(), createReqVO.getItemId()); | ||
| 96 | + // 模板产品关联可能为空(模板关联了其他产品但也可手动选择),此处不强制 | ||
| 97 | + | ||
| 98 | + // 2. 插入主表 | ||
| 99 | + MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class); | ||
| 100 | + ipqc.setStatus(MesQcIqcStatusEnum.PREPARE.getType()); | ||
| 101 | + ipqcMapper.insert(ipqc); | ||
| 102 | + | ||
| 103 | + // 3. 从模板指标自动生成检验行 | ||
| 104 | + ipqcLineService.createLinesFromTemplate(ipqc.getId(), template.getId()); | ||
| 105 | + return ipqc.getId(); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + @Override | ||
| 109 | + public void updateIpqc(MesQcIpqcSaveReqVO updateReqVO) { | ||
| 110 | + // 1.1 校验存在 + 草稿状态 | ||
| 111 | + validateIpqcStatusPrepare(updateReqVO.getId()); | ||
| 112 | + // 1.2 校验编号唯一 | ||
| 113 | + validateIpqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); | ||
| 114 | + | ||
| 115 | + // 2. 更新 | ||
| 116 | + MesQcIpqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIpqcDO.class); | ||
| 117 | + ipqcMapper.updateById(updateObj); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + @Override | ||
| 121 | + public void completeIpqc(Long id) { | ||
| 122 | + // 1.1 校验存在 + 草稿状态 | ||
| 123 | + MesQcIpqcDO ipqc = validateIpqcStatusPrepare(id); | ||
| 124 | + // 1.2 校验合格品 + 不合格品 = 检测数量 | ||
| 125 | + if (ipqc.getCheckQuantity() != null && ipqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { | ||
| 126 | + BigDecimal qualified = ipqc.getQualifiedQuantity() != null ? ipqc.getQualifiedQuantity() : BigDecimal.ZERO; | ||
| 127 | + BigDecimal unqualified = ipqc.getUnqualifiedQuantity() != null ? ipqc.getUnqualifiedQuantity() : BigDecimal.ZERO; | ||
| 128 | + if (qualified.add(unqualified).compareTo(ipqc.getCheckQuantity()) != 0) { | ||
| 129 | + throw exception(QC_IPQC_QUANTITY_MISMATCH); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + // 2. 更新状态为已完成 | ||
| 134 | + MesQcIpqcDO updateObj = new MesQcIpqcDO(); | ||
| 135 | + updateObj.setId(id); | ||
| 136 | + updateObj.setStatus(MesQcIqcStatusEnum.FINISHED.getType()); | ||
| 137 | + ipqcMapper.updateById(updateObj); | ||
| 138 | + | ||
| 139 | + // TODO @芋艿:IPQC 完成时的 PRO/WM 联动(报工反馈更新、产品产出单拆分),待 WM 模块迁移后对接 | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + @Override | ||
| 143 | + @Transactional(rollbackFor = Exception.class) | ||
| 144 | + public void deleteIpqc(Long id) { | ||
| 145 | + // 1. 校验存在 + 草稿状态 | ||
| 146 | + validateIpqcStatusPrepare(id); | ||
| 147 | + | ||
| 148 | + // 2.1 删除主表 | ||
| 149 | + ipqcMapper.deleteById(id); | ||
| 150 | + // 2.2 级联删除行 | ||
| 151 | + ipqcLineService.deleteByIpqcId(id); | ||
| 152 | + // 2.3 级联删除缺陷记录 | ||
| 153 | + defectRecordService.deleteByQcTypeAndQcId(MesQcTypeEnum.IPQC.getType(), id); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + @Override | ||
| 157 | + public MesQcIpqcDO validateIpqcExists(Long id) { | ||
| 158 | + MesQcIpqcDO ipqc = ipqcMapper.selectById(id); | ||
| 159 | + if (ipqc == null) { | ||
| 160 | + throw exception(QC_IPQC_NOT_EXISTS); | ||
| 161 | + } | ||
| 162 | + return ipqc; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + /** | ||
| 166 | + * 校验过程检验单存在且为草稿状态 | ||
| 167 | + * | ||
| 168 | + * @param id 过程检验单 ID | ||
| 169 | + * @return 过程检验单 | ||
| 170 | + */ | ||
| 171 | + private MesQcIpqcDO validateIpqcStatusPrepare(Long id) { | ||
| 172 | + MesQcIpqcDO ipqc = validateIpqcExists(id); | ||
| 173 | + if (ObjUtil.notEqual(ipqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) { | ||
| 174 | + throw exception(QC_IPQC_NOT_PREPARE); | ||
| 175 | + } | ||
| 176 | + return ipqc; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + private void validateIpqcCodeUnique(Long id, String code) { | ||
| 180 | + MesQcIpqcDO ipqc = ipqcMapper.selectByCode(code); | ||
| 181 | + if (ipqc == null) { | ||
| 182 | + return; | ||
| 183 | + } | ||
| 184 | + if (ObjUtil.notEqual(ipqc.getId(), id)) { | ||
| 185 | + throw exception(QC_IPQC_CODE_DUPLICATE); | ||
| 186 | + } | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + @Override | ||
| 190 | + public MesQcIpqcDO getIpqc(Long id) { | ||
| 191 | + return ipqcMapper.selectById(id); | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + @Override | ||
| 195 | + public PageResult<MesQcIpqcDO> getIpqcPage(MesQcIpqcPageReqVO pageReqVO) { | ||
| 196 | + return ipqcMapper.selectPage(pageReqVO); | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + @Override | ||
| 200 | + public void recalculateDefectStats(Long ipqcId, List<MesQcDefectRecordDO> records) { | ||
| 201 | + // 1. 行级缺陷统计 | ||
| 202 | + ipqcLineService.recalculateLineDefectStats(ipqcId, records); | ||
| 203 | + | ||
| 204 | + // 2.1 汇总主表的缺陷数量 | ||
| 205 | + int totalCritical = 0, totalMajor = 0, totalMinor = 0; | ||
| 206 | + for (MesQcDefectRecordDO record : records) { | ||
| 207 | + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); | ||
| 208 | + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { | ||
| 209 | + totalCritical += quantity; | ||
| 210 | + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { | ||
| 211 | + totalMajor += quantity; | ||
| 212 | + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { | ||
| 213 | + totalMinor += quantity; | ||
| 214 | + } else { | ||
| 215 | + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | + // 2.2 计算缺陷率(IPQC 的 checkQuantity 是 BigDecimal) | ||
| 219 | + MesQcIpqcDO ipqc = validateIpqcExists(ipqcId); | ||
| 220 | + BigDecimal criticalRate = BigDecimal.ZERO; | ||
| 221 | + BigDecimal majorRate = BigDecimal.ZERO; | ||
| 222 | + BigDecimal minorRate = BigDecimal.ZERO; | ||
| 223 | + if (ipqc.getCheckQuantity() != null && ipqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { | ||
| 224 | + BigDecimal checkQty = ipqc.getCheckQuantity(); | ||
| 225 | + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) | ||
| 226 | + .divide(checkQty, 2, RoundingMode.HALF_UP); | ||
| 227 | + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) | ||
| 228 | + .divide(checkQty, 2, RoundingMode.HALF_UP); | ||
| 229 | + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100)) | ||
| 230 | + .divide(checkQty, 2, RoundingMode.HALF_UP); | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + // 3. 更新主表 | ||
| 234 | + MesQcIpqcDO updateIpqc = new MesQcIpqcDO().setId(ipqcId) | ||
| 235 | + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor) | ||
| 236 | + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate); | ||
| 237 | + ipqcMapper.updateById(updateIpqc); | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | +} |