diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/controller/SfcOperationPlanningMainController.java b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SfcOperationPlanningMainController.java index 77610f5..2b17766 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/controller/SfcOperationPlanningMainController.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/controller/SfcOperationPlanningMainController.java @@ -73,7 +73,7 @@ public class SfcOperationPlanningMainController extends BaseController { } @SaIgnore - @Log(title = "工序作业人员更新", businessType = BusinessType.UPDATE) + @Log(title = "工序作业人员/设备更新", businessType = BusinessType.UPDATE) @PutMapping("/updateOperators") public R updateOperators(@Validated @RequestBody OperationPlanningUpdateOperatorsReq req) { return toAjax(iSfcOperationPlanningMainService.updateOperators(req)); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SfcOperationPlanningDetail.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SfcOperationPlanningDetail.java index 4cb9f2f..d0392aa 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SfcOperationPlanningDetail.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SfcOperationPlanningDetail.java @@ -118,4 +118,10 @@ public class SfcOperationPlanningDetail extends BaseEntity { */ private String operDescription; + /** + * 设备 + */ + private String equipment; + + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningDTO.java index dc58d26..be2414b 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningDTO.java @@ -182,4 +182,10 @@ public class OperationPlanningDTO { @JsonProperty("FPlanFinishTime") private String fPlanFinishTime; + + /** + * 设备 + */ + @JsonProperty("F_HBYT_SB") + private String fHbytSbFName; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorItem.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorItem.java index dfca735..2ee88bc 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorItem.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorItem.java @@ -2,14 +2,26 @@ package com.ruoyi.system.domain.dto; import lombok.Data; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data public class OperationPlanningUpdateOperatorItem { - @NotNull + private Long fid; + private Long entityEntryId; + + private Long k3DetailId; + private Integer operNo; + private String operator; + private String processName; + + /** + * 设备 + */ + private String equipment; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorsReq.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorsReq.java index b88756a..1f4c2f4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorsReq.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/OperationPlanningUpdateOperatorsReq.java @@ -3,7 +3,9 @@ package com.ruoyi.system.domain.dto; import lombok.Data; import javax.validation.Valid; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.util.List; @Data diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessDetailDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessDetailDTO.java index 5cadc96..d7597e0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessDetailDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/dto/ProcessDetailDTO.java @@ -4,44 +4,44 @@ import lombok.Data; @Data public class ProcessDetailDTO { - + /** * 工序号 */ private Integer operNo; - + /** * 作业/工序名称 */ private String processName; - + /** * 工作中心 */ private String workCenter; - + /** * 计划/工序数量 */ private Double planQty; - + /** * 转入数量 */ private Double inQty; private Double progress; - + /** * 合格数量 */ private Double okQty; - + /** * 废品数量 */ private Double ngQty; - + /** * 状态 */ @@ -102,6 +102,12 @@ public class ProcessDetailDTO { */ private String operDescription; + /** + * 设备 + */ + private String equipment; + + private Long k3DetailId; /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/jdmain/rouplan/FSubEntity.java b/ruoyi-system/src/main/java/com/ruoyi/system/jdmain/rouplan/FSubEntity.java index 0ea7196..395f5f3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/jdmain/rouplan/FSubEntity.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/jdmain/rouplan/FSubEntity.java @@ -21,6 +21,10 @@ public class FSubEntity { @JsonProperty("F_HBYT_ZYRY") private String F_HBYT_ZYRY; + + @JsonProperty("F_HBYT_SB") + private String F_HBYT_SB; + /* 入库仓库 */ diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java index a2c6258..67ef168 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/JdUtil.java @@ -3674,7 +3674,7 @@ public class JdUtil { "FID,FENTITY_FEntryID,FSubEntity_FDetailID,F_HBYT_SCLH,FMONumber,FProductId.FNumber,FProductName,FProSpecification,FBillNo,FOperNumber," + "FOperQty,FQualifiedQty,FTransOutQty,FUnqualifiedQty,FWastageQty,FTransInQty,FDepartmentId.FName,FWorkCenterId.FName," + "FProcessId.FName,F_HBYT_ZYRY,FOperStatus,FSeqPlanStartTime,FSeqPlanFinishTime,FOperPlanStartTime,FOperPlanFinishTime," + - "FOptCtrlCodeId.FName,FKeyOper,FActivity1Name,FOperDescription,FPlanStartTime,FPlanFinishTime"); + "FOptCtrlCodeId.FName,FKeyOper,FActivity1Name,FOperDescription,FPlanStartTime,FPlanFinishTime,F_HBYT_SB"); // 创建过滤条件 JsonArray filterString = new JsonArray(); JsonObject filterObject = new JsonObject(); @@ -3688,7 +3688,7 @@ public class JdUtil { JsonObject filterObject1 = new JsonObject(); filterObject1.addProperty("FieldName", "FPlanFinishTime"); filterObject1.addProperty("Compare", "39"); - filterObject1.addProperty("Value", "2026-04-12 00:00:00"); + filterObject1.addProperty("Value", "2026-04-15 00:00:00"); filterObject1.addProperty("Left", ""); filterObject1.addProperty("Right", ""); filterObject1.addProperty("Logic", 0); @@ -3842,6 +3842,7 @@ public class JdUtil { detail.setKeyOper(item.getFKeyOper()); detail.setActivity1Name(item.getFActivity1Name()); detail.setOperDescription(item.getFOperDescription()); + detail.setEquipment(item.getFHbytSbFName()); detail.setK3DetailId(item.getFSubEntityFDetailId()); detail.setEntityEntryId(item.getFEntityFEntryId()); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java b/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java index 0128765..ba33230 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/runner/updatePcessPlanConver.java @@ -164,7 +164,7 @@ public class updatePcessPlanConver { for (Model model : numDTO) { MainModel mainModel = new MainModel(); List needUpDateFields = Arrays.asList( - "FEntity", "FSubEntity", "F_HBYT_ZYRY" + "FEntity", "FSubEntity", "F_HBYT_ZYRY","F_HBYT_SB" ); mainModel.setNeedUpDateFields(needUpDateFields); mainModel.setDeleteEntry(false); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SfcOperationPlanningMainServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SfcOperationPlanningMainServiceImpl.java index 1507255..cdb1d97 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SfcOperationPlanningMainServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SfcOperationPlanningMainServiceImpl.java @@ -2,11 +2,13 @@ package com.ruoyi.system.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.domain.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.common.helper.LoginHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -157,6 +159,8 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin detailEntity.setKeyOper(detailDTO.getKeyOper()); detailEntity.setActivityName(detailDTO.getActivity1Name()); detailEntity.setOperDescription(detailDTO.getOperDescription()); + detailEntity.setEquipment(detailDTO.getEquipment()); + detailEntity.setK3DetailId(detailDTO.getK3DetailId()); if (detailEntity.getId() == null) { detailMapper.insert(detailEntity); @@ -197,12 +201,12 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin Long fid = main.getFid(); Map updateMap = req.getUpdates().stream() - .collect(Collectors.toMap(OperationPlanningUpdateOperatorItem::getEntityEntryId, item -> item, (a, b) -> b, LinkedHashMap::new)); + .collect(Collectors.toMap(OperationPlanningUpdateOperatorItem::getK3DetailId, item -> item, (a, b) -> b, LinkedHashMap::new)); - List entityEntryIds = new ArrayList<>(updateMap.keySet()); + List k3DetailIds = new ArrayList<>(updateMap.keySet()); List details = detailMapper.selectList(Wrappers.lambdaQuery() .eq(SfcOperationPlanningDetail::getFid, fid) - .in(SfcOperationPlanningDetail::getEntityEntryId, entityEntryIds)); + .in(SfcOperationPlanningDetail::getK3DetailId, k3DetailIds)); if (details == null || details.isEmpty()) { throw new ServiceException("未找到可更新的工序行"); @@ -213,8 +217,13 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin } List models = new ArrayList<>(); + Model model = new Model(); + model.setFID(fid.intValue()); + + Map entityMap = new LinkedHashMap<>(); + for (SfcOperationPlanningDetail detail : details) { - OperationPlanningUpdateOperatorItem item = updateMap.get(detail.getEntityEntryId()); + OperationPlanningUpdateOperatorItem item = updateMap.get(detail.getK3DetailId()); if (item == null) { continue; } @@ -241,19 +250,25 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin subEntity.setFDetailID(detail.getK3DetailId().intValue()); subEntity.setF_HBYT_ZYRY(operator); - FEntity entity = new FEntity(); - entity.setFEntryID(detail.getEntityEntryId().intValue()); - entity.getFSubEntity().add(subEntity); + if (StringUtils.isNotBlank(item.getEquipment())) { + subEntity.setF_HBYT_SB(item.getEquipment()); + } - Model model = new Model(); - model.setFID(fid.intValue()); - model.getFEntity().add(entity); - models.add(model); + Long entryId = detail.getEntityEntryId(); + FEntity entity = entityMap.computeIfAbsent(entryId, k -> { + FEntity e = new FEntity(); + e.setFEntryID(entryId.intValue()); + return e; + }); + entity.getFSubEntity().add(subEntity); } - if (models.isEmpty()) { + model.getFEntity().addAll(entityMap.values()); + + if (model.getFEntity().isEmpty()) { throw new ServiceException("未找到可更新的工序行"); } + models.add(model); RepoRet repoRet = updatePcessPlanConver.updatePcessOperator(models); if (repoRet == null || repoRet.getResult() == null || repoRet.getResult().getResponseStatus() == null || !repoRet.getResult().getResponseStatus().isIsSuccess()) { @@ -261,7 +276,7 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin } for (SfcOperationPlanningDetail detail : details) { - OperationPlanningUpdateOperatorItem item = updateMap.get(detail.getEntityEntryId()); + OperationPlanningUpdateOperatorItem item = updateMap.get(detail.getK3DetailId()); if (item == null) { continue; } @@ -273,6 +288,7 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin } } detail.setOperator(operator); + detail.setEquipment(item.getEquipment()); // 同步更新设备字段 detailMapper.updateById(detail); } return true; @@ -368,12 +384,38 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin */ @Override public TableDataInfo queryCascadePageList(SfcOperationPlanningMainBo bo, PageQuery pageQuery) { - // 1. 构建主表查询条件 + // 1. 获取当前登录用户信息与工段 + boolean isAdmin = false; + String currentUserWorkCenter = ""; + try { + LoginUser loginUser = LoginHelper.getLoginUser(); + if (loginUser != null && loginUser.getDeptName() != null) { + isAdmin = com.ruoyi.common.helper.LoginHelper.isAdmin(); + if (loginUser.getDeptName() != null) { + currentUserWorkCenter = loginUser.getDeptName(); + } + } + } catch (Exception e) { + log.warn("获取当前登录用户失败,可能未登录或在定时任务中执行"); + } + + // 2. 构建主表查询条件 LambdaQueryWrapper lqw = buildQueryWrapper(bo); // 过滤生产令号包含“暂停”的记录 lqw.notLike(SfcOperationPlanningMain::getHbytSclh, "暂停"); - // 2. 分页查询主表数据 + // 3. 如果不是管理员,且有所属工段,且部门名称是指定的具体工段之一,则只查询明细表中包含该工段的订单主表 ID + boolean isSpecificWorkCenter = false; + if (!isAdmin && StringUtils.isNotBlank(currentUserWorkCenter)) { + List targetWorkCenters = java.util.Arrays.asList("机一工段", "装二工段", "装一工段", "铆焊工段", "机二工段", "委外中心"); + if (targetWorkCenters.contains(currentUserWorkCenter)) { + isSpecificWorkCenter = true; + lqw.inSql(SfcOperationPlanningMain::getId, + "SELECT main_id FROM sfc_operation_planning_detail WHERE work_center_name = '" + currentUserWorkCenter + "'"); + } + } + + // 4. 分页查询主表数据 Page page = baseMapper.selectPage(pageQuery.build(), lqw); List mainList = page.getRecords(); @@ -381,19 +423,19 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin return TableDataInfo.build(new ArrayList<>()); } - // 3. 提取当前页所有主表的 ID + // 5. 提取当前页所有主表的 ID List mainIds = mainList.stream().map(SfcOperationPlanningMain::getId).collect(Collectors.toList()); - // 4. 根据主表 ID 批量查询子表数据,并按工序号升序排序 + // 6. 根据主表 ID 批量查询子表数据,并按工序号升序排序 (这里查询所有的明细用于计算外层的总进度) List detailList = detailMapper.selectList(Wrappers.lambdaQuery() .in(SfcOperationPlanningDetail::getMainId, mainIds) .orderByAsc(SfcOperationPlanningDetail::getOperNumber)); - // 5. 按主表 ID 对子表数据进行分组 + // 7. 按主表 ID 对子表数据进行分组 Map> detailMap = detailList.stream() .collect(Collectors.groupingBy(SfcOperationPlanningDetail::getMainId)); - // 6. 组装返回给前端的层级结构 + // 8. 组装返回给前端的层级结构 List resultList = new ArrayList<>(); for (SfcOperationPlanningMain main : mainList) { OperationPlanResultDTO resultDTO = new OperationPlanResultDTO(); @@ -413,8 +455,30 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin // 组装关联的子表数据 List processList = new ArrayList<>(); List relatedDetails = detailMap.get(main.getId()); + + double totalPlanQty = 0.0; + double totalOkQty = 0.0; + int finishedCount = 0; + String mainWorkCenter = ""; + if (relatedDetails != null) { + // 计算该单据所有工段的总进度数据 + mainWorkCenter = relatedDetails.get(0).getWorkCenterName(); for (SfcOperationPlanningDetail detail : relatedDetails) { + if (detail.getOperQty() != null) totalPlanQty += detail.getOperQty().doubleValue(); + if (detail.getQualifiedQty() != null) totalOkQty += detail.getQualifiedQty().doubleValue(); + if ("4".equals(detail.getOperStatus())) { + finishedCount++; + } + } + + // 构建明细列表,并在构建时进行权限过滤(只有指定的几个工段用户才只能看到自己的数据,其他非管理员都能看所有) + for (SfcOperationPlanningDetail detail : relatedDetails) { + // 权限过滤:如果当前用户属于这几个特定的工段,则只显示自己工段的明细 + if (isSpecificWorkCenter && !currentUserWorkCenter.equals(detail.getWorkCenterName())) { + continue; + } + ProcessDetailDTO detailDTO = new ProcessDetailDTO(); detailDTO.setOperNo(detail.getOperNumber() != null ? detail.getOperNumber().intValue() : null); detailDTO.setProcessName(detail.getProcessName()); @@ -430,7 +494,7 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin if (detailDTO.getPlanQty() != null && detailDTO.getInQty() != null && detailDTO.getPlanQty() > 0) { BigDecimal progress = BigDecimal.valueOf(detailDTO.getInQty()) .multiply(BigDecimal.valueOf(100)) - .divide(BigDecimal.valueOf(detailDTO.getPlanQty()), 2, RoundingMode.HALF_UP); + .divide(BigDecimal.valueOf(detailDTO.getPlanQty()), 1, RoundingMode.HALF_UP); if (progress.compareTo(BigDecimal.ZERO) < 0) { progress = BigDecimal.ZERO; } else if (progress.compareTo(BigDecimal.valueOf(100)) > 0) { @@ -475,11 +539,31 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin detailDTO.setKeyOper(detail.getKeyOper()); detailDTO.setActivity1Name(detail.getActivityName()); detailDTO.setOperDescription(detail.getOperDescription()); + detailDTO.setEquipment(detail.getEquipment()); detailDTO.setK3DetailId(detail.getK3DetailId()); detailDTO.setEntityEntryId(detail.getEntityEntryId()); processList.add(detailDTO); } + + resultDTO.setWorkCenter(mainWorkCenter); + resultDTO.setOverallPlanQty(totalPlanQty); + resultDTO.setOverallOkQty(totalOkQty); + + double progress = 0.0; + if (totalPlanQty > 0) { + progress = (totalOkQty / totalPlanQty) * 100; + } + resultDTO.setOverallProgress(Math.min(100.0, Math.max(0.0, progress))); + + // 计算总体状态 + if (relatedDetails.isEmpty() || (finishedCount == 0 && totalOkQty == 0)) { + resultDTO.setOverallStatus("未开工"); + } else if (finishedCount == relatedDetails.size()) { + resultDTO.setOverallStatus("已完工"); + } else { + resultDTO.setOverallStatus("生产中"); + } } resultDTO.setProcessList(processList); resultList.add(resultDTO);