更新,工序计划

This commit is contained in:
tzy 2026-04-14 19:33:22 +08:00
parent 2da37daa29
commit 4c39bbab96
10 changed files with 154 additions and 33 deletions

View File

@ -73,7 +73,7 @@ public class SfcOperationPlanningMainController extends BaseController {
}
@SaIgnore
@Log(title = "工序作业人员更新", businessType = BusinessType.UPDATE)
@Log(title = "工序作业人员/设备更新", businessType = BusinessType.UPDATE)
@PutMapping("/updateOperators")
public R<Void> updateOperators(@Validated @RequestBody OperationPlanningUpdateOperatorsReq req) {
return toAjax(iSfcOperationPlanningMainService.updateOperators(req));

View File

@ -118,4 +118,10 @@ public class SfcOperationPlanningDetail extends BaseEntity {
*/
private String operDescription;
/**
* 设备
*/
private String equipment;
}

View File

@ -182,4 +182,10 @@ public class OperationPlanningDTO {
@JsonProperty("FPlanFinishTime")
private String fPlanFinishTime;
/**
* 设备
*/
@JsonProperty("F_HBYT_SB")
private String fHbytSbFName;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
/**

View File

@ -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;
/*
入库仓库
*/

View File

@ -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());

View File

@ -164,7 +164,7 @@ public class updatePcessPlanConver {
for (Model model : numDTO) {
MainModel mainModel = new MainModel();
List<String> needUpDateFields = Arrays.asList(
"FEntity", "FSubEntity", "F_HBYT_ZYRY"
"FEntity", "FSubEntity", "F_HBYT_ZYRY","F_HBYT_SB"
);
mainModel.setNeedUpDateFields(needUpDateFields);
mainModel.setDeleteEntry(false);

View File

@ -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<Long, OperationPlanningUpdateOperatorItem> 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<Long> entityEntryIds = new ArrayList<>(updateMap.keySet());
List<Long> k3DetailIds = new ArrayList<>(updateMap.keySet());
List<SfcOperationPlanningDetail> details = detailMapper.selectList(Wrappers.<SfcOperationPlanningDetail>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<Model> models = new ArrayList<>();
Model model = new Model();
model.setFID(fid.intValue());
Map<Long, FEntity> 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<OperationPlanResultDTO> 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<SfcOperationPlanningMain> lqw = buildQueryWrapper(bo);
// 过滤生产令号包含暂停的记录
lqw.notLike(SfcOperationPlanningMain::getHbytSclh, "暂停");
// 2. 分页查询主表数据
// 3. 如果不是管理员且有所属工段且部门名称是指定的具体工段之一则只查询明细表中包含该工段的订单主表 ID
boolean isSpecificWorkCenter = false;
if (!isAdmin && StringUtils.isNotBlank(currentUserWorkCenter)) {
List<String> 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<SfcOperationPlanningMain> page = baseMapper.selectPage(pageQuery.build(), lqw);
List<SfcOperationPlanningMain> mainList = page.getRecords();
@ -381,19 +423,19 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin
return TableDataInfo.build(new ArrayList<>());
}
// 3. 提取当前页所有主表的 ID
// 5. 提取当前页所有主表的 ID
List<Long> mainIds = mainList.stream().map(SfcOperationPlanningMain::getId).collect(Collectors.toList());
// 4. 根据主表 ID 批量查询子表数据并按工序号升序排序
// 6. 根据主表 ID 批量查询子表数据并按工序号升序排序 (这里查询所有的明细用于计算外层的总进度)
List<SfcOperationPlanningDetail> detailList = detailMapper.selectList(Wrappers.<SfcOperationPlanningDetail>lambdaQuery()
.in(SfcOperationPlanningDetail::getMainId, mainIds)
.orderByAsc(SfcOperationPlanningDetail::getOperNumber));
// 5. 按主表 ID 对子表数据进行分组
// 7. 按主表 ID 对子表数据进行分组
Map<Long, List<SfcOperationPlanningDetail>> detailMap = detailList.stream()
.collect(Collectors.groupingBy(SfcOperationPlanningDetail::getMainId));
// 6. 组装返回给前端的层级结构
// 8. 组装返回给前端的层级结构
List<OperationPlanResultDTO> resultList = new ArrayList<>();
for (SfcOperationPlanningMain main : mainList) {
OperationPlanResultDTO resultDTO = new OperationPlanResultDTO();
@ -413,8 +455,30 @@ public class SfcOperationPlanningMainServiceImpl implements ISfcOperationPlannin
// 组装关联的子表数据
List<ProcessDetailDTO> processList = new ArrayList<>();
List<SfcOperationPlanningDetail> 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);