双机架轧辊管理工作绩效粒度分割到每一个辊
This commit is contained in:
@@ -7,8 +7,8 @@ import com.klp.common.core.domain.PageQuery;
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.klp.common.enums.BusinessType;
|
||||
import java.util.Map;
|
||||
import com.klp.mes.roll.domain.bo.MesRollChangeBo;
|
||||
import com.klp.mes.roll.domain.vo.MesRollChangeVo;
|
||||
import com.klp.mes.roll.service.IMesRollChangeService;
|
||||
@@ -47,12 +47,12 @@ public class MesRollChangeController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定机架当前轧辊的实时工作长度(m)
|
||||
* GET /mes/rollChange/workLength?standNo=1%23
|
||||
* 查询各机架各辊位实时工作绩效(工作长度/卷数/重量)
|
||||
* GET /mes/rollChange/performance
|
||||
*/
|
||||
@GetMapping("/workLength")
|
||||
public R<BigDecimal> workLength(@RequestParam String standNo) {
|
||||
return R.ok(iMesRollChangeService.queryRealtimeWorkLength(standNo));
|
||||
@GetMapping("/performance")
|
||||
public R<Map<String, Map<String, Object>>> performance() {
|
||||
return R.ok(iMesRollChangeService.queryRollPerformance());
|
||||
}
|
||||
|
||||
/** 详情 */
|
||||
|
||||
@@ -54,4 +54,10 @@ public class MesRollChangeVo {
|
||||
|
||||
/** 本次换辊方案的累计工作长度(m),由 WMS 卷料数据计算得出 */
|
||||
private BigDecimal workLength;
|
||||
|
||||
/** 本次换辊方案内处理的卷数 */
|
||||
private Integer coilCount;
|
||||
|
||||
/** 本次换辊方案内处理的净重合计(单位与 wms_material_coil.net_weight 一致) */
|
||||
private BigDecimal totalWeight;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import com.klp.mes.roll.domain.MesRollChange;
|
||||
import com.klp.mes.roll.domain.vo.MesRollChangeVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 换辊记录 Mapper
|
||||
@@ -17,14 +17,30 @@ public interface MesRollChangeMapper extends BaseMapperPlus<MesRollChangeMapper,
|
||||
MesRollChangeVo selectLatestByStand(@Param("standNo") String standNo);
|
||||
|
||||
/**
|
||||
* 查询同机架下一次换辊时间(用于确定本次换辊的服务结束时刻)
|
||||
* 按辊位查询该位置最新一次有记录的换辊(支持部分换辊)
|
||||
* posType: upperWr / lowerWr / upperBr / lowerBr
|
||||
*/
|
||||
MesRollChangeVo selectLatestByStandAndPosition(@Param("standNo") String standNo,
|
||||
@Param("posType") String posType);
|
||||
|
||||
/**
|
||||
* 组合查询机架各辊位当前实际在机状态(每个位置独立取最新非空记录)
|
||||
* 返回 map,key 同 MesRollChangeVo 字段名(camelCase)
|
||||
*/
|
||||
Map<String, Object> selectCurrentStateByStand(@Param("standNo") String standNo);
|
||||
|
||||
/**
|
||||
* 查询同机架下一次换辊时间(任意辊位有换辊即触发)
|
||||
* 返回 null 表示该辊仍在机
|
||||
*/
|
||||
Date selectNextChangeTime(@Param("standNo") String standNo, @Param("changeTime") Date changeTime);
|
||||
|
||||
/**
|
||||
* 统计指定时间区间内的卷料实测长度之和(mm→调用方除以1000转m)
|
||||
* 统计指定时间区间内的卷料生产统计:
|
||||
* coilCount — 卷数(DISTINCT coil_id)
|
||||
* totalLength — 实测长度之和(mm,调用方/1000 转 m)
|
||||
* totalWeight — 净重之和(原始单位)
|
||||
* endTime 为 null 时统计到当前时刻
|
||||
*/
|
||||
BigDecimal selectWorkLength(@Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
Map<String, Object> selectCoilStats(@Param("startTime") Date startTime, @Param("endTime") Date endTime);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.mes.roll.domain.bo.MesRollChangeBo;
|
||||
import com.klp.mes.roll.domain.vo.MesRollChangeVo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 换辊记录 Service 接口
|
||||
@@ -28,8 +28,9 @@ public interface IMesRollChangeService {
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 查询指定机架当前在机轧辊的实时工作长度(m)
|
||||
* 从最近一次换辊时间到现在,统计 WMS 卷料实测长度之和
|
||||
* 查询各机架各辊位的实时工作绩效(工作长度/卷数/重量)
|
||||
* 返回结构: { posType -> { standNo -> { rollNo, workLength, coilCount, totalWeight } } }
|
||||
* posType: upperBr / upperWr / lowerWr / lowerBr
|
||||
*/
|
||||
BigDecimal queryRealtimeWorkLength(String standNo);
|
||||
Map<String, Map<String, Object>> queryRollPerformance();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ import java.math.RoundingMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 换辊记录 Service 实现
|
||||
@@ -43,33 +45,115 @@ public class MesRollChangeServiceImpl implements IMesRollChangeService {
|
||||
|
||||
@Override
|
||||
public MesRollChangeVo queryCurrentByStand(String standNo) {
|
||||
return baseMapper.selectLatestByStand(standNo);
|
||||
// 组合各辊位最新状态,转换为 VO
|
||||
Map<String, Object> state = baseMapper.selectCurrentStateByStand(standNo);
|
||||
if (state == null) return null;
|
||||
MesRollChangeVo vo = new MesRollChangeVo();
|
||||
vo.setStandNo(standNo);
|
||||
vo.setUpperWrNo(str(state.get("upperWrNo")));
|
||||
vo.setUpperWrDia(decimal(state.get("upperWrDia")));
|
||||
vo.setLowerWrNo(str(state.get("lowerWrNo")));
|
||||
vo.setLowerWrDia(decimal(state.get("lowerWrDia")));
|
||||
vo.setUpperBrNo(str(state.get("upperBrNo")));
|
||||
vo.setUpperBrDia(decimal(state.get("upperBrDia")));
|
||||
vo.setLowerBrNo(str(state.get("lowerBrNo")));
|
||||
vo.setLowerBrDia(decimal(state.get("lowerBrDia")));
|
||||
if (state.get("changeTime") instanceof Date) {
|
||||
vo.setChangeTime((Date) state.get("changeTime"));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo<MesRollChangeVo> queryPageList(MesRollChangeBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<MesRollChange> lqw = buildQueryWrapper(bo);
|
||||
Page<MesRollChangeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
// 为每条换辊记录计算工作长度(上辊时间 → 下辊时间,下辊时间为 null 时统计到 NOW())
|
||||
// 为每条换辊记录计算:工作长度、卷数、重量
|
||||
for (MesRollChangeVo vo : result.getRecords()) {
|
||||
Date endTime = baseMapper.selectNextChangeTime(vo.getStandNo(), vo.getChangeTime());
|
||||
BigDecimal lengthMm = baseMapper.selectWorkLength(vo.getChangeTime(), endTime);
|
||||
// mm 转 m,保留 2 位小数
|
||||
vo.setWorkLength(lengthMm == null ? BigDecimal.ZERO
|
||||
: lengthMm.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP));
|
||||
Map<String, Object> stats = baseMapper.selectCoilStats(vo.getChangeTime(), endTime);
|
||||
fillStatsToVo(vo, stats);
|
||||
}
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
private static final List<String> POS_TYPES = Arrays.asList("upperBr", "upperWr", "lowerWr", "lowerBr");
|
||||
private static final List<String> STANDS = Arrays.asList("1#", "2#");
|
||||
|
||||
@Override
|
||||
public BigDecimal queryRealtimeWorkLength(String standNo) {
|
||||
MesRollChangeVo latest = baseMapper.selectLatestByStand(standNo);
|
||||
if (latest == null || latest.getChangeTime() == null) {
|
||||
return BigDecimal.ZERO;
|
||||
public Map<String, Map<String, Object>> queryRollPerformance() {
|
||||
Map<String, Map<String, Object>> result = new HashMap<>(4);
|
||||
for (String posType : POS_TYPES) {
|
||||
Map<String, Object> byStand = new HashMap<>(2);
|
||||
for (String standNo : STANDS) {
|
||||
MesRollChangeVo rec = baseMapper.selectLatestByStandAndPosition(standNo, posType);
|
||||
Map<String, Object> cell = new HashMap<>(6);
|
||||
if (rec != null) {
|
||||
cell.put("rollNo", getRollNoByPos(rec, posType));
|
||||
cell.put("onlineTime", rec.getChangeTime());
|
||||
Map<String, Object> stats = baseMapper.selectCoilStats(rec.getChangeTime(), null);
|
||||
MesRollChangeVo tmp = new MesRollChangeVo();
|
||||
fillStatsToVo(tmp, stats);
|
||||
cell.put("workLength", tmp.getWorkLength());
|
||||
cell.put("coilCount", tmp.getCoilCount());
|
||||
cell.put("totalWeight", tmp.getTotalWeight());
|
||||
}
|
||||
byStand.put(standNo, cell);
|
||||
}
|
||||
result.put(posType, byStand);
|
||||
}
|
||||
BigDecimal lengthMm = baseMapper.selectWorkLength(latest.getChangeTime(), null);
|
||||
return lengthMm == null ? BigDecimal.ZERO
|
||||
: lengthMm.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 若该辊位要换新辊,则把当前在机的旧辊下线 */
|
||||
private void offlineIfReplaced(String standNo, String posType, String newRollNo) {
|
||||
if (StringUtils.isBlank(newRollNo)) return;
|
||||
MesRollChangeVo cur = baseMapper.selectLatestByStandAndPosition(standNo, posType);
|
||||
if (cur != null) {
|
||||
String oldRollNo = getRollNoByPos(cur, posType);
|
||||
if (StringUtils.isNotBlank(oldRollNo)) {
|
||||
rollInfoMapper.updateStatusByRollNoIfStatus(oldRollNo, "Offline", "Online");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 从 VO 按辊位取辊号 */
|
||||
private String getRollNoByPos(MesRollChangeVo vo, String posType) {
|
||||
switch (posType) {
|
||||
case "upperWr": return vo.getUpperWrNo();
|
||||
case "lowerWr": return vo.getLowerWrNo();
|
||||
case "upperBr": return vo.getUpperBrNo();
|
||||
case "lowerBr": return vo.getLowerBrNo();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 类型安全的 String 转换 */
|
||||
private static String str(Object o) { return o == null ? null : o.toString(); }
|
||||
private static BigDecimal decimal(Object o) {
|
||||
if (o == null) return null;
|
||||
return o instanceof BigDecimal ? (BigDecimal) o : new BigDecimal(o.toString());
|
||||
}
|
||||
|
||||
/** 将 selectCoilStats 返回的 Map 解析并设置到 VO */
|
||||
private void fillStatsToVo(MesRollChangeVo vo, Map<String, Object> stats) {
|
||||
if (stats == null) {
|
||||
vo.setWorkLength(BigDecimal.ZERO);
|
||||
vo.setCoilCount(0);
|
||||
vo.setTotalWeight(BigDecimal.ZERO);
|
||||
return;
|
||||
}
|
||||
// totalLength (mm → m)
|
||||
BigDecimal lengthMm = stats.get("totalLength") instanceof Number
|
||||
? new BigDecimal(stats.get("totalLength").toString()) : BigDecimal.ZERO;
|
||||
vo.setWorkLength(lengthMm.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP));
|
||||
// coilCount
|
||||
Number cnt = (Number) stats.getOrDefault("coilCount", 0);
|
||||
vo.setCoilCount(cnt.intValue());
|
||||
// totalWeight(保留 2 位小数)
|
||||
BigDecimal weight = stats.get("totalWeight") instanceof Number
|
||||
? new BigDecimal(stats.get("totalWeight").toString()) : BigDecimal.ZERO;
|
||||
vo.setTotalWeight(weight.setScale(2, RoundingMode.HALF_UP));
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<MesRollChange> buildQueryWrapper(MesRollChangeBo bo) {
|
||||
@@ -99,26 +183,18 @@ public class MesRollChangeServiceImpl implements IMesRollChangeService {
|
||||
if (StringUtils.isBlank(add.getChangeType())) {
|
||||
add.setChangeType("三级换辊");
|
||||
}
|
||||
// 换辊前:将上一批在机轧辊状态改为 Offline
|
||||
MesRollChangeVo prev = baseMapper.selectLatestByStand(add.getStandNo());
|
||||
if (prev != null) {
|
||||
for (String rollNo : Arrays.asList(
|
||||
prev.getUpperWrNo(), prev.getLowerWrNo(),
|
||||
prev.getUpperBrNo(), prev.getLowerBrNo())) {
|
||||
if (StringUtils.isNotBlank(rollNo)) {
|
||||
rollInfoMapper.updateStatusByRollNo(rollNo, "Offline");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 按辊位独立换辊:只下线被替换的那个位置的旧辊
|
||||
offlineIfReplaced(add.getStandNo(), "upperWr", add.getUpperWrNo());
|
||||
offlineIfReplaced(add.getStandNo(), "lowerWr", add.getLowerWrNo());
|
||||
offlineIfReplaced(add.getStandNo(), "upperBr", add.getUpperBrNo());
|
||||
offlineIfReplaced(add.getStandNo(), "lowerBr", add.getLowerBrNo());
|
||||
|
||||
baseMapper.insert(add);
|
||||
|
||||
// 将本次换上的 4 支辊状态同步为 Online
|
||||
List<String> rollNos = Arrays.asList(
|
||||
add.getUpperWrNo(), add.getLowerWrNo(),
|
||||
add.getUpperBrNo(), add.getLowerBrNo()
|
||||
);
|
||||
for (String rollNo : rollNos) {
|
||||
// 将本次有记录的辊状态同步为 Online
|
||||
for (String rollNo : Arrays.asList(
|
||||
add.getUpperWrNo(), add.getLowerWrNo(),
|
||||
add.getUpperBrNo(), add.getLowerBrNo())) {
|
||||
if (StringUtils.isNotBlank(rollNo)) {
|
||||
rollInfoMapper.updateStatusByRollNo(rollNo, "Online");
|
||||
}
|
||||
|
||||
@@ -121,17 +121,26 @@ public class MesRollInfoServiceImpl implements IMesRollInfoService {
|
||||
|
||||
@Override
|
||||
public void syncStatusFromChange() {
|
||||
// 从每个机架最新换辊记录中取出在机辊号,更新为 Online
|
||||
// 按辊位独立取最新在机辊,确保各位置状态正确
|
||||
for (String standNo : Arrays.asList("1#", "2#")) {
|
||||
MesRollChangeVo latest = rollChangeMapper.selectLatestByStand(standNo);
|
||||
if (latest == null) continue;
|
||||
for (String rollNo : Arrays.asList(
|
||||
latest.getUpperWrNo(), latest.getLowerWrNo(),
|
||||
latest.getUpperBrNo(), latest.getLowerBrNo())) {
|
||||
for (String posType : Arrays.asList("upperWr", "lowerWr", "upperBr", "lowerBr")) {
|
||||
MesRollChangeVo rec = rollChangeMapper.selectLatestByStandAndPosition(standNo, posType);
|
||||
if (rec == null) continue;
|
||||
String rollNo = getRollNoByPos(rec, posType);
|
||||
if (StringUtils.isNotBlank(rollNo)) {
|
||||
baseMapper.updateStatusByRollNo(rollNo, "Online");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getRollNoByPos(MesRollChangeVo vo, String posType) {
|
||||
switch (posType) {
|
||||
case "upperWr": return vo.getUpperWrNo();
|
||||
case "lowerWr": return vo.getLowerWrNo();
|
||||
case "upperBr": return vo.getUpperBrNo();
|
||||
case "lowerBr": return vo.getLowerBrNo();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,37 @@
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 按辊位查最新非空换辊记录(支持部分换辊) -->
|
||||
<select id="selectLatestByStandAndPosition" resultType="com.klp.mes.roll.domain.vo.MesRollChangeVo">
|
||||
SELECT change_id, change_no, change_time, stand_no, operator,
|
||||
upper_wr_no, upper_wr_dia, lower_wr_no, lower_wr_dia,
|
||||
upper_br_no, upper_br_dia, lower_br_no, lower_br_dia
|
||||
FROM mes_roll_change
|
||||
WHERE del_flag = 0 AND stand_no = #{standNo}
|
||||
<choose>
|
||||
<when test="posType == 'upperWr'">AND upper_wr_no IS NOT NULL AND upper_wr_no != ''</when>
|
||||
<when test="posType == 'lowerWr'">AND lower_wr_no IS NOT NULL AND lower_wr_no != ''</when>
|
||||
<when test="posType == 'upperBr'">AND upper_br_no IS NOT NULL AND upper_br_no != ''</when>
|
||||
<when test="posType == 'lowerBr'">AND lower_br_no IS NOT NULL AND lower_br_no != ''</when>
|
||||
</choose>
|
||||
ORDER BY change_time DESC, change_id DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 组合查询各辊位当前实际在机状态(每个位置独立取最新非空记录) -->
|
||||
<select id="selectCurrentStateByStand" resultType="map">
|
||||
SELECT
|
||||
(SELECT upper_wr_no FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND upper_wr_no IS NOT NULL AND upper_wr_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS upperWrNo,
|
||||
(SELECT upper_wr_dia FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND upper_wr_no IS NOT NULL AND upper_wr_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS upperWrDia,
|
||||
(SELECT lower_wr_no FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND lower_wr_no IS NOT NULL AND lower_wr_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS lowerWrNo,
|
||||
(SELECT lower_wr_dia FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND lower_wr_no IS NOT NULL AND lower_wr_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS lowerWrDia,
|
||||
(SELECT upper_br_no FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND upper_br_no IS NOT NULL AND upper_br_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS upperBrNo,
|
||||
(SELECT upper_br_dia FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND upper_br_no IS NOT NULL AND upper_br_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS upperBrDia,
|
||||
(SELECT lower_br_no FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND lower_br_no IS NOT NULL AND lower_br_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS lowerBrNo,
|
||||
(SELECT lower_br_dia FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0 AND lower_br_no IS NOT NULL AND lower_br_no != '' ORDER BY change_time DESC, change_id DESC LIMIT 1) AS lowerBrDia,
|
||||
(SELECT MAX(change_time) FROM mes_roll_change WHERE stand_no = #{standNo} AND del_flag = 0) AS changeTime
|
||||
</select>
|
||||
|
||||
<!-- 查询同机架在本次换辊之后最近一次换辊的时间 -->
|
||||
<select id="selectNextChangeTime" resultType="java.util.Date">
|
||||
SELECT MIN(change_time)
|
||||
@@ -25,16 +56,20 @@
|
||||
</select>
|
||||
|
||||
<!--
|
||||
统计 [startTime, endTime) 时间段内,
|
||||
符合条件的 wms_coil_pending_action 记录关联的卷料实测长度之和(mm)。
|
||||
统计 [startTime, endTime) 时间段内,符合条件的卷料生产三项汇总:
|
||||
coilCount — 卷数(COUNT DISTINCT coil_id)
|
||||
totalLength — 实测长度之和(mm)
|
||||
totalWeight — 净重之和(net_weight 原始单位)
|
||||
endTime 为 null 时取 NOW() 作为上界。
|
||||
processed_coil_ids 存储逗号分隔的 material_id 列表,使用 FIND_IN_SET 关联。
|
||||
-->
|
||||
<select id="selectWorkLength" resultType="java.math.BigDecimal">
|
||||
SELECT IFNULL(SUM(mc.actual_length), 0)
|
||||
<select id="selectCoilStats" resultType="map">
|
||||
SELECT
|
||||
COUNT(DISTINCT mc.coil_id) AS coilCount,
|
||||
IFNULL(SUM(mc.actual_length), 0) AS totalLength,
|
||||
IFNULL(SUM(mc.net_weight), 0) AS totalWeight
|
||||
FROM wms_coil_pending_action cpa
|
||||
INNER JOIN wms_material_coil mc
|
||||
ON FIND_IN_SET(mc.coil_id, cpa.processed_coil_ids) > 0
|
||||
ON FIND_IN_SET(mc.coil_id, cpa.processed_coil_ids) > 0
|
||||
WHERE cpa.del_flag = 0
|
||||
AND cpa.action_status = 2
|
||||
AND cpa.action_type IN (205, 504, 524)
|
||||
|
||||
Reference in New Issue
Block a user