feat(): 电文逻辑完善
This commit is contained in:
@@ -1,15 +1,10 @@
|
||||
package com.fizz.business.comm.OPC;
|
||||
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.AppMeasureMessage;
|
||||
import com.kangaroohy.milo.model.ReadWriteEntity;
|
||||
import com.kangaroohy.milo.service.MiloService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.fizz.business.constants;
|
||||
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
|
||||
import static com.fizz.business.constants.enums.DeviceEnum.DISC;
|
||||
import static com.fizz.business.constants.enums.DeviceEnum.INS;
|
||||
|
||||
public class CommonConstants {
|
||||
|
||||
@@ -50,7 +50,7 @@ public class CommonConstants {
|
||||
public static final String SEG_STRIP_LEN = "SEG_STRIP_LEN";
|
||||
|
||||
//卷取机前一个设备idx
|
||||
public static final DeviceEnum BEFORE_TR_IDX = DISC;
|
||||
public static final DeviceEnum BEFORE_TR_IDX = INS;
|
||||
|
||||
// 工艺规程点位代码
|
||||
public static final String SETUP_POINT_CODE = "SETUP_POINT_CODE";
|
||||
|
||||
@@ -5,57 +5,52 @@ import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
/**
|
||||
* 细粒度设备枚举(按你给出的17台设备)
|
||||
* position 为基准位置(单位:m),用于和 stripLocation 比较。
|
||||
* paramFields 列出该设备需要采样/缓存的字段名(与 AppMeasure*Message 中字段名对应)。
|
||||
*/
|
||||
public enum DeviceEnum {
|
||||
POR1(0, "1#开卷机"),
|
||||
POR2(1, "2#开卷机"),
|
||||
WELDER(2, "焊机"),
|
||||
BR1(3, "1#张力辊"),
|
||||
CEL(4, "入口活套"),
|
||||
BR2(5, "2#张力辊"),
|
||||
ALKALI(6, "碱洗"),
|
||||
DRYING(7, "热烘干"),
|
||||
BR4(8, "4#张力辊"),
|
||||
RTF(9, "加热炉"),
|
||||
SF1(10, "均热炉1"),
|
||||
EHF(11, "EHF"),
|
||||
SF2(12, "均热炉2"),
|
||||
CTF(13, "CTF"),
|
||||
SF3(14, "均热炉3"),
|
||||
RJC(15, "控冷段"),
|
||||
AJC(16, "快冷段"),
|
||||
BR5(17, "5#张力辊"),
|
||||
BR6(18, "6#张力辊"),
|
||||
CXL(19, "出口活套"),
|
||||
BR7(20, "7#张力辊"),
|
||||
BR8(21, "8#张力辊"),
|
||||
COAT(22, "涂机"),
|
||||
DISC(23, "圆盘剪"),
|
||||
TR1(24, "1#卷取机"),
|
||||
TR2(25, "2#卷取机");
|
||||
POR1(0, "1#开卷机", 0.0, Arrays.asList("tensionPorBr1", "stripSpeed")),
|
||||
POR2(1, "2#开卷机", 1.0, Arrays.asList("tensionPorBr2", "stripSpeed")),
|
||||
WELDER(2, "焊机", 5.0, Arrays.asList("weldStatus")),
|
||||
ENL1(3, "入口活套1", 10.0, Arrays.asList("celLength", "celCapacity", "tensionCel")),
|
||||
ENL2(4, "入口活套2", 12.0, Arrays.asList("celLength", "celCapacity", "tensionCel")),
|
||||
CLEAN(5, "清洗段", 20.0, Arrays.asList("cleaningVoltage", "cleaningCurrent", "alkaliConcentration", "alkaliTemperature")),
|
||||
FUR1(6, "退火炉-预热段", 30.0, Arrays.asList("phfExitStripTemp","potTemperature","gasConsumption")),
|
||||
FUR2(7, "退火炉-加热段", 40.0, Arrays.asList("rtfExitStripTemp","zincPotPower")),
|
||||
FUR3(8, "退火炉-冷却段", 50.0, Arrays.asList("jcsExitStripTemp","coolingTowerStripTemp")),
|
||||
FUR4(9, "退火炉-均衡段", 60.0, Arrays.asList("scsExitStripTemp")),
|
||||
TM(10, "光整机", 70.0, Arrays.asList("tensionBr5Tm", "stripSpeedTmExit")),
|
||||
TL(11, "拉矫机", 80.0, Arrays.asList("tlElongation", "tensionTlBr7")),
|
||||
COAT(12, "后处理段", 90.0, Arrays.asList(
|
||||
"avrCoatingWeightTop","stdCoatingWeightTop","maxCoatingWeightTop","minCoatingWeightTop",
|
||||
"avrCoatingWeightBottom","stdCoatingWeightBottom","maxCoatingWeightBottom","minCoatingWeightBottom",
|
||||
"airKnifePressure","airKnifeFlow","airKnifeGap","stripSpeedTmExit","tensionBr5Tm",
|
||||
"tensionTmBr6","tensionBr5Br6","tmMask","tmElongation","rollForceOperator","rollForceDrive",
|
||||
"motorTorque","bendingForce","antiCrimpingRollMesh","billyRollMesh",
|
||||
"tensionTlBr7","tensionBr6Br7","tlFlag","tlElongation","levelingUnit1Mesh","levelingUnit2Mesh",
|
||||
"antiCrossBowUnitMesh","tensionBr7Br8","stripSpeedAfp","stripTempAfp"
|
||||
)),
|
||||
CXL1(13, "出口活套1", 100.0, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
|
||||
CXL2(14, "出口活套2", 102.0, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
|
||||
INS(15, "检查站", 110.0, Arrays.asList("inspectionStatus")),
|
||||
TR(16, "卷取机", 120.0, Arrays.asList("coilLength", "speedExitSection", "tensionBr9Tr")),
|
||||
EXC(17, "卸卷小车", 999999.0, Collections.emptyList()),
|
||||
WEIGHT(18, "称重鞍座", 999999.0, Collections.emptyList());
|
||||
|
||||
|
||||
private final Integer idx;
|
||||
private final int idx;
|
||||
private final String desc;
|
||||
private static final Map<String, DeviceEnum> MAP = new HashMap<>();
|
||||
private final double basePosition;
|
||||
private final List<String> paramFields;
|
||||
|
||||
private static final Map<String, DeviceEnum> NAME_MAP = new HashMap<>();
|
||||
static {
|
||||
for (DeviceEnum e : DeviceEnum.values()) {
|
||||
MAP.put(e.getValue(), e);
|
||||
}
|
||||
for (DeviceEnum d : values()) NAME_MAP.put(d.name(), d);
|
||||
}
|
||||
|
||||
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
|
||||
public static DeviceEnum getByValue(String value) {
|
||||
return MAP.get(value);
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getValue() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
public static DeviceEnum fromName(String name) { return NAME_MAP.get(name); }
|
||||
}
|
||||
@@ -57,8 +57,7 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
|
||||
@Override
|
||||
public void operate(L1OperateMatForm form) {
|
||||
PRODUCING.syncPlanStatus(form.getPlanId());
|
||||
// 钢卷上线时, 缓存工艺规程
|
||||
// BeanFactory.getBean(RedisCacheManager.class).setCoilSetup(form.getPlanId());
|
||||
|
||||
WebSocketUtil.sendSignalMsg(form);
|
||||
}
|
||||
},
|
||||
@@ -66,8 +65,6 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
|
||||
@Override
|
||||
public void operate(L1OperateMatForm form) {
|
||||
PRODUCT.syncPlanStatus(form.getPlanId());
|
||||
// 删除工艺规程
|
||||
BeanFactory.getBean(RedisCacheManager.class).delCoilSetup(form.getEntryMatId());
|
||||
WebSocketUtil.sendSignalMsg(form);
|
||||
}
|
||||
},
|
||||
@@ -78,7 +75,7 @@ public enum L1OperateMatEnum implements IEnum<String>, IOperateMat<L1OperateMatF
|
||||
CrmPdiPlanService planClient = BeanFactory.getBean(CrmPdiPlanService.class);
|
||||
CrmPdiPlanVO plan = planClient.getByCoilIdAndOperId(form.getEntryMatId());
|
||||
Assert.notNull(plan, "计划[{}]不存在", plan.getId());
|
||||
|
||||
Assert.isTrue(status.contains(plan.getStatus()), "当前状态[{}]不支持甩尾", plan.getStatus());
|
||||
MatmapUtil.clearMatmap(form.getPorIdx());
|
||||
WebSocketUtil.sendSignalMsg(form);
|
||||
WebSocketUtil.sendMatmapMsg();
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
package com.fizz.business.constants.enums;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.annotation.IEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import com.fizz.business.domain.HalfReturn;
|
||||
import com.fizz.business.domain.Segment;
|
||||
import com.fizz.business.dto.CoilHeadDTO;
|
||||
import com.fizz.business.dto.ExitCoilInfoDTO;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.form.ChangePlanStatusForm;
|
||||
import com.fizz.business.form.WebOperateMatForm;
|
||||
import com.fizz.business.mapper.HalfReturnMapper;
|
||||
import com.fizz.business.mapper.SegmentMapper;
|
||||
import com.fizz.business.service.CrmPdiPlanService;
|
||||
import com.fizz.business.service.PdoExCoilService;
|
||||
import com.fizz.business.service.TrackService;
|
||||
@@ -24,14 +19,16 @@ import com.fizz.business.utils.ErrorDataException;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import com.fizz.business.utils.WebSocketUtil;
|
||||
import com.fizz.business.vo.CrmPdiPlanVO;
|
||||
import com.fizz.business.vo.PdiPlanVO;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 钢卷操作
|
||||
@@ -53,7 +50,6 @@ public enum WebOperateMatEnum implements IEnum<String>, IOperateMat<WebOperateMa
|
||||
if (MatmapUtil.already(porCoil)) {
|
||||
|
||||
ONLINE.syncPlanStatus(form.getPlanId());
|
||||
ONLINE.replaceVirtualPlan(form, porCoil);
|
||||
WebSocketUtil.sendSignalMsg(form, true);
|
||||
// 如果开卷机和焊机的钢卷相同,则将计划状态变更为生产中
|
||||
MatmapDTO welderCoil = MatmapUtil.getMatmap(DeviceEnum.WELDER.getIdx());
|
||||
@@ -250,52 +246,4 @@ public enum WebOperateMatEnum implements IEnum<String>, IOperateMat<WebOperateMa
|
||||
WebSocketUtil.sendMatmapMsg();
|
||||
}
|
||||
|
||||
private void replaceVirtualPlan(WebOperateMatForm form, MatmapDTO porCoil) {
|
||||
|
||||
// 更新matmap
|
||||
List<MatmapDTO> matmapList = MatmapUtil.getMatmapList();
|
||||
matmapList.forEach(matmap -> {
|
||||
if (Objects.equals(matmap.getMatId(), porCoil.getMatId())) {
|
||||
MatmapUtil.setMatmap(matmap.getPosIdx(), form.getEntryMatId(), form.getPlanId(), form.getPlanNo());
|
||||
}
|
||||
});
|
||||
RedisCacheManager redisCacheManager = BeanFactory.getBean(RedisCacheManager.class);
|
||||
// 更新headList
|
||||
List<CoilHeadDTO> headList = redisCacheManager.getHeadList();
|
||||
headList.forEach(head -> {
|
||||
if (Objects.equals(head.getMatId(), porCoil.getMatId())) {
|
||||
head.setMatId(form.getEntryMatId());
|
||||
head.setPlanNo(form.getPlanNo());
|
||||
head.setPlanId(form.getPlanId());
|
||||
head.setPorIdx(form.getPorIdx());
|
||||
}
|
||||
});
|
||||
redisCacheManager.setHeadList(headList);
|
||||
// 更新prevHead
|
||||
CoilHeadDTO prevHead = redisCacheManager.getPrevHead();
|
||||
if (Objects.nonNull(prevHead) && Objects.equals(prevHead.getMatId(), porCoil.getMatId())) {
|
||||
prevHead.setMatId(form.getEntryMatId());
|
||||
prevHead.setPlanNo(form.getPlanNo());
|
||||
prevHead.setPlanId(form.getPlanId());
|
||||
prevHead.setPorIdx(form.getPorIdx());
|
||||
redisCacheManager.setPrevHead(prevHead);
|
||||
}
|
||||
// 更新mergeHead
|
||||
CoilHeadDTO mergeHead = redisCacheManager.getMergeHead();
|
||||
if (Objects.nonNull(mergeHead) && Objects.equals(mergeHead.getMatId(), porCoil.getMatId())) {
|
||||
mergeHead.setMatId(form.getEntryMatId());
|
||||
mergeHead.setPlanNo(form.getPlanNo());
|
||||
mergeHead.setPlanId(form.getPlanId());
|
||||
prevHead.setPorIdx(form.getPorIdx());
|
||||
redisCacheManager.setMergeHead(mergeHead);
|
||||
}
|
||||
// 更新segment
|
||||
SegmentMapper segmentMapper = BeanFactory.getBean(SegmentMapper.class);
|
||||
LambdaUpdateWrapper<Segment> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(Segment::getEntryMatId, porCoil.getMatId());
|
||||
updateWrapper.eq(Segment::getPlanId, porCoil.getPlanId());
|
||||
updateWrapper.set(Segment::getEntryMatId, form.getEntryMatId());
|
||||
updateWrapper.set(Segment::getPlanId, form.getPlanId());
|
||||
segmentMapper.update(new Segment(), updateWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ public class CrmPdoExcoilController {
|
||||
@Resource
|
||||
private CrmPdoExcoilService crmPdoExcoilService;
|
||||
|
||||
@GetMapping("/get/{excoilid}/{operid}")
|
||||
@GetMapping("/get/{excoilid}")
|
||||
@Operation(summary ="查询实绩")
|
||||
public R<CrmPdoExcoil> getByExcoilIdAndOperId(@PathVariable String excoilid, @PathVariable Integer operid) {
|
||||
return R.ok(crmPdoExcoilService.getByExcoilIdAndOperId(excoilid, operid));
|
||||
public R<CrmPdoExcoil> getByExcoilId(@PathVariable String excoilid) {
|
||||
return R.ok(crmPdoExcoilService.getByExcoilId(excoilid));
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.fizz.business.controller;
|
||||
|
||||
|
||||
import com.fizz.business.service.CrmPdoExcoilService;
|
||||
import com.fizz.business.vo.ReportDetailVO;
|
||||
import com.fizz.business.vo.ReportSummaryVO;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/report")
|
||||
@Tag(name= "报表接口",description = "报表接口")
|
||||
@Anonymous
|
||||
public class ReportController {
|
||||
|
||||
@Resource
|
||||
private CrmPdoExcoilService crmPdoExcoilService;
|
||||
|
||||
@GetMapping("/summary")
|
||||
@Operation(summary = "生产实绩报表-汇总信息查询")
|
||||
public ReportSummaryVO getReportSummary(
|
||||
@RequestParam(required = false) String groupNo,
|
||||
@RequestParam(required = false) String shiftNo,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime
|
||||
) {
|
||||
return crmPdoExcoilService.getReportSummary(groupNo, shiftNo, startTime, endTime);
|
||||
}
|
||||
|
||||
@GetMapping("/details")
|
||||
@Operation(summary = "生产实绩报表-产出明细查询")
|
||||
public List<ReportDetailVO> getReportDetails(
|
||||
@RequestParam(required = false) String groupNo,
|
||||
@RequestParam(required = false) String shiftNo,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
|
||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime
|
||||
) {
|
||||
return crmPdoExcoilService.getReportDetails(groupNo, shiftNo, startTime, endTime);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public class AppMeasureEntryMessage extends OpcMessage {
|
||||
@Schema(description = "钢带位置 (m),0 表示头部在参考点 (Welder)")
|
||||
private BigDecimal stripLocation;
|
||||
|
||||
@Schema(description = "支付卷号,1 或 2")
|
||||
@Schema(description = "开卷机号,1 或 2")
|
||||
private Integer payOffReelNumber;
|
||||
|
||||
@Schema(description = "钢带张力 POR – BR1 (daN)")
|
||||
|
||||
@@ -21,13 +21,13 @@ public class AppMeasureExitMessage extends OpcMessage {
|
||||
@Schema(description = "钢带张力 BR8 – BR9 (daN)")
|
||||
private BigDecimal tensionBr8Br9;
|
||||
|
||||
@Schema(description = "入口活套位置(m)")
|
||||
@Schema(description = "出口活套位置(m)")
|
||||
private BigDecimal cxlLength;
|
||||
|
||||
@Schema(description = "入口活套百分比(m)")
|
||||
@Schema(description = "出口活套百分比(m)")
|
||||
private BigDecimal cxlCapacity;
|
||||
|
||||
@Schema(description = "入口活套张力(m)")
|
||||
@Schema(description = "出口活套张力(m)")
|
||||
private BigDecimal tensionCxl ;
|
||||
|
||||
@Schema(description = "涂油标志 (0=no, 1=yes)")
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package com.fizz.business.domain.msg;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class AppMeasureMessage extends OpcMessage {
|
||||
|
||||
AppMeasureEntryMessage appMeasureEntryMessage;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.fizz.business.domain.msg;
|
||||
|
||||
|
||||
import com.fizz.business.constants.enums.ExitCutTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -16,7 +17,7 @@ public class ExitCutMessage extends OpcMessage {
|
||||
private Integer counter;
|
||||
|
||||
@Schema(description = "剪切类型:0=split, 1=weldSeam, 2=stripBreak")
|
||||
private Integer cutType;
|
||||
private ExitCutTypeEnum cutType;
|
||||
|
||||
@Schema(description = "剪切时卷取长度 (m)")
|
||||
private BigDecimal cutLength;
|
||||
|
||||
@@ -14,8 +14,8 @@ public class ExitMovementMessage extends OpcMessage {
|
||||
private Integer counter;
|
||||
|
||||
@Schema(description = "Material Place Source")
|
||||
private Integer materialPlaceSource;
|
||||
private Integer exSrc;
|
||||
|
||||
@Schema(description = "Material Place Destination")
|
||||
private Integer materialPlaceDestination;
|
||||
private Integer exDesc;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public class ExitCoilInfoDTO implements Serializable {
|
||||
private double startPos;
|
||||
private double endPos;
|
||||
private double exitCutLength;
|
||||
private double outerDiameter;
|
||||
private String entryMatId;
|
||||
private String exitMatId;
|
||||
private boolean separateFlag;
|
||||
|
||||
@@ -1,17 +1,31 @@
|
||||
package com.fizz.business.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Data
|
||||
public class SegValue implements Serializable {
|
||||
private double max;
|
||||
private double min;
|
||||
private double avg;
|
||||
private double std;
|
||||
private BigDecimal max;
|
||||
private BigDecimal min;
|
||||
private BigDecimal avg;
|
||||
private BigDecimal std;
|
||||
private int cnt;
|
||||
private double sum;
|
||||
private BigDecimal sum;
|
||||
|
||||
public void add(BigDecimal value) {
|
||||
this.sum = this.sum.add(value);
|
||||
this.cnt++;
|
||||
}
|
||||
|
||||
public BigDecimal getAverage() {
|
||||
if (cnt == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return sum.divide(new BigDecimal(cnt), 2, BigDecimal.ROUND_HALF_UP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,57 @@
|
||||
package com.fizz.business.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Data
|
||||
public class SegmentDTO {
|
||||
@TableName("cpl_segment_total")
|
||||
public class SegmentDTO implements Serializable {
|
||||
|
||||
private boolean first;
|
||||
private Long planId;
|
||||
private String planNo;
|
||||
private String coilID;
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@TableField("en_coil_id")
|
||||
private String enCoilID;
|
||||
private String exCoilID;
|
||||
//MATID_Type matId;
|
||||
private int segNo;
|
||||
private double segLen;
|
||||
private double startPos;//位于带钢的起始位置
|
||||
private double endPos;
|
||||
private double headPos;//位于全线的位置
|
||||
private double tailPos;
|
||||
|
||||
@TableField("pickling_count")
|
||||
private Integer picklingCount;
|
||||
|
||||
@TableField("seg_no")
|
||||
private Integer segNo;
|
||||
|
||||
// 以下字段用于业务逻辑,不存入数据库
|
||||
@TableField(exist = false)
|
||||
private BigDecimal headPos;
|
||||
@TableField(exist = false)
|
||||
private BigDecimal tailPos;
|
||||
|
||||
// 以下字段存入数据库
|
||||
@TableField("start_pos")
|
||||
private BigDecimal startPos;
|
||||
@TableField("end_pos")
|
||||
private BigDecimal endPos;
|
||||
@TableField("seg_len")
|
||||
private BigDecimal segLen;
|
||||
@TableField("total_values_json")
|
||||
private String totalValuesJson;
|
||||
|
||||
// 以下 Map 用于业务逻辑,不存入数据库
|
||||
@TableField(exist = false)
|
||||
private Map<String, SegValue> totalValues = new ConcurrentHashMap<>();
|
||||
@TableField(exist = false)
|
||||
private Map<String, SegValue> L3values = new ConcurrentHashMap<>();
|
||||
|
||||
// 两个未使用的字段,可以根据需要保留或移除
|
||||
@TableField(exist = false)
|
||||
private int headPosNum;
|
||||
@TableField(exist = false)
|
||||
private int tailPosNum;
|
||||
private Map<String, SegValue> segValMap;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,30 @@ package com.fizz.business.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.CrmPdoExcoil;
|
||||
import com.fizz.business.vo.ReportDetailVO;
|
||||
import com.fizz.business.vo.ReportSummaryVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CrmPdoExcoilMapper extends BaseMapper<CrmPdoExcoil> {
|
||||
|
||||
|
||||
ReportSummaryVO getReportSummary(
|
||||
@Param("groupNo") String groupNo,
|
||||
@Param("shiftNo") String shiftNo,
|
||||
@Param("startTime") LocalDateTime startTime,
|
||||
@Param("endTime") LocalDateTime endTime
|
||||
);
|
||||
|
||||
List<ReportDetailVO> getReportDetails(
|
||||
@Param("groupNo") String groupNo,
|
||||
@Param("shiftNo") String shiftNo,
|
||||
@Param("startTime") LocalDateTime startTime,
|
||||
@Param("endTime") LocalDateTime endTime
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.fizz.business.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.fizz.business.domain.PdoStripvalue;
|
||||
import com.fizz.business.domain.Segment;
|
||||
import com.fizz.business.dto.SegmentDTO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@@ -15,7 +16,7 @@ import org.apache.ibatis.annotations.Param;
|
||||
* @since 2023-05-17
|
||||
*/
|
||||
@Mapper
|
||||
public interface SegmentMapper extends BaseMapper<Segment> {
|
||||
public interface SegmentMapper extends BaseMapper<SegmentDTO> {
|
||||
|
||||
PdoStripvalue getStripValue(@Param("entryMatId") String entryMatId, @Param("startPos") double startPos, @Param("endPos") double endPos);
|
||||
|
||||
|
||||
@@ -5,11 +5,15 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.fizz.business.domain.CrmPdoExcoil;
|
||||
import com.fizz.business.domain.PdoExcoil;
|
||||
import com.fizz.business.form.CrmPdoExcoilForm;
|
||||
import com.fizz.business.vo.ReportDetailVO;
|
||||
import com.fizz.business.vo.ReportSummaryVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public interface CrmPdoExcoilService extends IService<CrmPdoExcoil> {
|
||||
CrmPdoExcoil getByExcoilIdAndOperId(String excoilid, Integer operid);
|
||||
CrmPdoExcoil getByExcoilId(String excoilid);
|
||||
|
||||
boolean addCrmPdoExcoil(CrmPdoExcoil crmPdoExcoil);
|
||||
|
||||
@@ -20,5 +24,11 @@ public interface CrmPdoExcoilService extends IService<CrmPdoExcoil> {
|
||||
List<CrmPdoExcoil> listAll(CrmPdoExcoilForm form);
|
||||
|
||||
Long getNumber(String matId,String planId,Integer subNumber);
|
||||
|
||||
ReportSummaryVO getReportSummary(String groupNo, String shiftNo, LocalDateTime startTime, LocalDateTime endTime);
|
||||
|
||||
List<ReportDetailVO> getReportDetails(String groupNo, String shiftNo, LocalDateTime startTime, LocalDateTime endTime);
|
||||
|
||||
void updateExitCoilActualWeight(String exitMatId, BigDecimal weight);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.fizz.business.service.client;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fizz.business.constants.enums.LimitItemCode;
|
||||
import com.fizz.business.domain.DeviceDefine;
|
||||
import com.fizz.business.dto.PointConfigDTO;
|
||||
import com.fizz.business.mapper.DeviceDefineMapper;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* 本地缓存管理
|
||||
*
|
||||
* @author chenhao
|
||||
* @date 2023/05/15
|
||||
*/
|
||||
@Component
|
||||
public class LocalCacheManager {
|
||||
|
||||
private static DeviceDefineMapper deviceDefineMapper;
|
||||
|
||||
@Autowired
|
||||
public void setDeviceDefineMapper(DeviceDefineMapper deviceDefineMapper) {
|
||||
LocalCacheManager.deviceDefineMapper = deviceDefineMapper;
|
||||
}
|
||||
|
||||
public static LinkedHashMap<String, DeviceDefine> DEVICE_DEFINE_MAP = Maps.newLinkedHashMap();
|
||||
|
||||
@PostConstruct
|
||||
public static void init() {
|
||||
DEVICE_DEFINE_MAP = getDeviceDefine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static LinkedHashMap<String, DeviceDefine> getDeviceDefine() {
|
||||
List<DeviceDefine> list = deviceDefineMapper.selectList(new LambdaQueryWrapper<DeviceDefine>().orderByAsc(DeviceDefine::getPosIdx));
|
||||
return list.stream().collect(Collectors.toMap(DeviceDefine::getPositionNameEn, it -> it, (k1, k2) -> k1, LinkedHashMap::new));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -116,14 +116,14 @@ public class RedisCacheManager {
|
||||
if (segmentList.isEmpty()) {
|
||||
segmentRedisTemplate.opsForList().rightPush(COIL_SEG_LIST_KEY, segment);
|
||||
log.info("create new segment, coilId=[{}], segNo={}, startPos={}, endPos={}, segLen={}",
|
||||
segment.getCoilID(), segment.getSegNo(), segment.getStartPos(), segment.getEndPos(), segment.getSegLen());
|
||||
segment.getEnCoilID(), segment.getSegNo(), segment.getStartPos(), segment.getEndPos(), segment.getSegLen());
|
||||
} else {
|
||||
Map<String, String> exists = segmentList.stream().collect(Collectors.toMap(s -> s.getCoilID() + "-" + s.getSegNo() + "-" + s.getPlanId(), s -> s.getCoilID() + s.getSegNo() + s.getPlanId(), (k1, k2) -> k1));
|
||||
String key = segment.getCoilID() + "-" + segment.getSegNo() + "-" + segment.getPlanId();
|
||||
Map<String, String> exists = segmentList.stream().collect(Collectors.toMap(s -> s.getEnCoilID() + "-" + s.getSegNo(), s -> s.getEnCoilID() + s.getSegNo() , (k1, k2) -> k1));
|
||||
String key = segment.getEnCoilID() + "-" + segment.getSegNo() ;
|
||||
if (!exists.containsKey(key)) {
|
||||
segmentRedisTemplate.opsForList().rightPush(COIL_SEG_LIST_KEY, segment);
|
||||
log.info("create new segment, coilId=[{}], segNo={}, startPos={}, endPos={}, segLen={}",
|
||||
segment.getCoilID(), segment.getSegNo(), segment.getStartPos(), segment.getEndPos(), segment.getSegLen());
|
||||
segment.getEnCoilID(), segment.getSegNo(), segment.getStartPos(), segment.getEndPos(), segment.getSegLen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,45 @@
|
||||
package com.fizz.business.service.hanle;
|
||||
|
||||
import com.fizz.business.anno.OpcMessageHandlerType;
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.AppMeasureExitMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureMessage;
|
||||
import com.fizz.business.domain.msg.*;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import com.fizz.business.service.strip.SegmentTrackerService;
|
||||
import com.fizz.business.service.strip.StripPositionService;
|
||||
import com.fizz.business.utils.WebSocketUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Component
|
||||
@OpcMessageHandlerType(OpcMessageType.APP_MEASURE)
|
||||
@RequiredArgsConstructor
|
||||
public class AppMeasureHandler implements OpcMessageHandler<AppMeasureMessage> {
|
||||
|
||||
private final SegmentTrackerService tracker;
|
||||
|
||||
@Override
|
||||
public void handle(AppMeasureMessage message) {
|
||||
// 处理出口段测量逻辑
|
||||
System.out.println("处理 APP_MEASURE_EXIT 消息: " + message);
|
||||
if (message == null) return;
|
||||
|
||||
AppMeasureEntryMessage entry = message.getAppMeasureEntryMessage();
|
||||
AppMeasureFurnaceMessage furnace = message.getAppMeasureFurnaceMessage();
|
||||
AppMeasureCoatMessage coat = message.getAppMeasureCoatMessage();
|
||||
AppMeasureExitMessage exit = message.getAppMeasureExitMessage();
|
||||
|
||||
WebSocketUtil.sendMeasureMsg(message);
|
||||
|
||||
// 2) extract key fields
|
||||
String coilId = entry == null ? "UNKNOWN" : entry.getEntryCoilId();
|
||||
BigDecimal lengthAtWelder = entry == null || entry.getStripLocation() == null ? BigDecimal.ZERO : entry.getStripLocation();
|
||||
|
||||
// 3) delegate core processing to tracker
|
||||
tracker.handleMeasure(coilId, lengthAtWelder, entry, furnace, coat, exit);
|
||||
|
||||
// 调用新的方法来跟踪钢卷头部位置,并处理快照和 matmap 更新
|
||||
// 使用焊机长度作为最接近的钢卷头部位置
|
||||
tracker.trackCoilHeadPosition(coilId, lengthAtWelder, entry, exit);
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,12 @@ import com.fizz.business.constants.enums.L1OperateMatEnum;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.CrmPdiPlan;
|
||||
import com.fizz.business.domain.msg.EntryMovementMessage;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.form.L1OperateMatForm;
|
||||
import com.fizz.business.service.CrmPdiPlanService;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import com.fizz.business.service.TrackService;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -52,6 +54,17 @@ public class EntryMovementHandler implements OpcMessageHandler<EntryMovementMess
|
||||
} else {
|
||||
log.error("未找到可上卷的钢卷计划!");
|
||||
}
|
||||
}else if (action.contains("甩尾")){
|
||||
|
||||
MatmapDTO matmap = MatmapUtil.getMatmap(src);
|
||||
|
||||
log.info("获取到甩尾信息: " + matmap.getMatId());
|
||||
trackService.l1OperateMat(L1OperateMatForm.builder()
|
||||
.entryMatId(matmap.getMatId())
|
||||
.operation(L1OperateMatEnum.PAY_OVER)
|
||||
.planId(matmap.getPlanId())
|
||||
.porIdx(src)
|
||||
.build());
|
||||
}
|
||||
} else {
|
||||
log.error("未识别的组合: SRC=" + src + ", DES=" + des);
|
||||
|
||||
@@ -1,18 +1,61 @@
|
||||
package com.fizz.business.service.hanle;
|
||||
|
||||
import com.fizz.business.anno.OpcMessageHandlerType;
|
||||
import com.fizz.business.constants.enums.L1OperateMatEnum;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.ExitCutMessage;
|
||||
import com.fizz.business.dto.ExitCoilInfoDTO;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.form.L1OperateMatForm;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import com.fizz.business.service.PdoExCoilService;
|
||||
import com.fizz.business.service.TrackService;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static com.fizz.business.constants.enums.DeviceEnum.TR;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@OpcMessageHandlerType(OpcMessageType.EXIT_CUT)
|
||||
public class ExitCutHandler implements OpcMessageHandler<ExitCutMessage> {
|
||||
|
||||
// 注入 PdoExCoilService
|
||||
private final PdoExCoilService pdoExCoilService;
|
||||
private final TrackService trackService;
|
||||
|
||||
@Override
|
||||
public void handle(ExitCutMessage message) {
|
||||
// 出口剪切逻辑处理
|
||||
System.out.println("处理 EXIT_CUT 消息: " + message);
|
||||
// 1. 获取卷取机 (TR) 上的物料信息
|
||||
MatmapDTO trMatmap = MatmapUtil.getMatmap(TR.getIdx());
|
||||
|
||||
if (trMatmap == null) {
|
||||
log.error("卷取机s.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 根据剪切类型,生成产出卷信息
|
||||
ExitCoilInfoDTO exitCoilInfo = pdoExCoilService.genExitCoilInfo(trMatmap, message.getCutType());
|
||||
|
||||
// 3. 补充 ExitCutMessage 中的长度和外径信息
|
||||
exitCoilInfo.setExitCutLength(message.getCutLength().doubleValue());
|
||||
exitCoilInfo.setOuterDiameter(message.getOuterDiameter().doubleValue());
|
||||
|
||||
// 4. 调用服务进行产出卷的持久化
|
||||
pdoExCoilService.saveExCoil(exitCoilInfo);
|
||||
|
||||
if (exitCoilInfo.isLastFlag()) {
|
||||
trackService.l1OperateMat(L1OperateMatForm.builder()
|
||||
.trIdx(TR.getIdx())
|
||||
.entryMatId(trMatmap.getMatId())
|
||||
.planId(trMatmap.getPlanId())
|
||||
.operation(L1OperateMatEnum.PRODUCT)
|
||||
.build());
|
||||
}
|
||||
|
||||
log.info("成功处理 EXIT_CUT 消息,已保存成品卷: " + exitCoilInfo.getExitMatId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,34 @@ package com.fizz.business.service.hanle;
|
||||
import com.fizz.business.anno.OpcMessageHandlerType;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.ExitMeasureMessage;
|
||||
import com.fizz.business.service.CrmPdoExcoilService;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static com.fizz.business.constants.enums.DeviceEnum.TR;
|
||||
|
||||
@Component
|
||||
@OpcMessageHandlerType(OpcMessageType.EXIT_MEASURE)
|
||||
@RequiredArgsConstructor
|
||||
public class ExitMeasureHandler implements OpcMessageHandler<ExitMeasureMessage> {
|
||||
|
||||
private final CrmPdoExcoilService crmPdoExcoilService;
|
||||
|
||||
@Override
|
||||
public void handle(ExitMeasureMessage message) {
|
||||
// 出口称重逻辑处理
|
||||
System.out.println("处理 EXIT_MEASURE 消息: " + message);
|
||||
|
||||
// 1. 获取卷取机 (TR) 上的成品卷号
|
||||
String exitMatId = MatmapUtil.getMatId(TR.getIdx());
|
||||
|
||||
if (exitMatId == null) {
|
||||
System.err.println("TR device has no coil. Cannot process ExitMeasureMessage.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用服务层更新成品卷的实际重量
|
||||
crmPdoExcoilService.updateExitCoilActualWeight(exitMatId, message.getWeight());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,46 @@
|
||||
package com.fizz.business.service.hanle;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fizz.business.anno.OpcMessageHandlerType;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.ExitMovementMessage;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@OpcMessageHandlerType(OpcMessageType.EXIT_MOVEMENT)
|
||||
@RequiredArgsConstructor
|
||||
public class ExitMovementHandler implements OpcMessageHandler<ExitMovementMessage> {
|
||||
|
||||
@Override
|
||||
public void handle(ExitMovementMessage message) {
|
||||
// 出口移动逻辑处理
|
||||
System.out.println("处理 EXIT_MOVEMENT 消息: " + message);
|
||||
System.out.printf("处理 EXIT_MOVEMENT 消息: %d -> %d%n", message.getExSrc(), message.getExDesc());
|
||||
|
||||
// 1. 获取源位置的物料信息
|
||||
int srcIndex = message.getExSrc() -1 ;
|
||||
MatmapDTO srcMatmap = MatmapUtil.getMatmap(srcIndex);
|
||||
|
||||
if (ObjectUtil.isNull(srcMatmap) || ObjectUtil.isNull(srcMatmap.getMatId())) {
|
||||
log.error("源位置 {} 没有物料信息,跳过移动处理。", srcIndex);
|
||||
// 如果源位置没有物料,则可能是一次无效的移动,直接返回
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 清空源位置的物料信息
|
||||
MatmapUtil.clearMatmap(srcIndex);
|
||||
log.info("成功清空源位置 {} 的物料信息。{}", srcIndex,srcMatmap.getMatId());
|
||||
|
||||
// 3. 将物料信息设置到目标位置
|
||||
int destIndex = message.getExDesc() - 1;
|
||||
MatmapUtil.setMatmap(destIndex, srcMatmap.getMatId(), srcMatmap.getPlanId(), srcMatmap.getPlanNo());
|
||||
log.info("成功设置目标位置 {} 的物料信息为钢卷 {}", destIndex, srcMatmap.getMatId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -8,24 +8,31 @@ import com.fizz.business.domain.PdoExcoil;
|
||||
import com.fizz.business.form.CrmPdoExcoilForm;
|
||||
import com.fizz.business.mapper.CrmPdoExcoilMapper;
|
||||
import com.fizz.business.service.CrmPdoExcoilService;
|
||||
import com.fizz.business.vo.ReportDetailVO;
|
||||
import com.fizz.business.vo.ReportSummaryVO;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CrmPdoExcoilServiceImpl extends ServiceImpl<CrmPdoExcoilMapper, CrmPdoExcoil> implements CrmPdoExcoilService {
|
||||
|
||||
/**
|
||||
* 根据退出卷ID和操作员ID查询记录
|
||||
*
|
||||
* @param excoilid 退出卷ID
|
||||
* @param operid 操作员ID
|
||||
* @return 查询到的CrmPdoExcoil对象
|
||||
*/
|
||||
public CrmPdoExcoil getByExcoilIdAndOperId(String excoilid, Integer operid) {
|
||||
public CrmPdoExcoil getByExcoilId(String excoilid) {
|
||||
QueryWrapper<CrmPdoExcoil> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("exit_coilid", excoilid).eq("operid", operid);
|
||||
queryWrapper.eq("exit_coilid", excoilid);
|
||||
return this.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
@@ -98,5 +105,51 @@ public class CrmPdoExcoilServiceImpl extends ServiceImpl<CrmPdoExcoilMapper, Crm
|
||||
return baseMapper.selectCount(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportSummaryVO getReportSummary(String groupNo, String shiftNo, LocalDateTime startTime, LocalDateTime endTime) {
|
||||
return baseMapper.getReportSummary(groupNo, shiftNo, startTime, endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReportDetailVO> getReportDetails(String groupNo, String shiftNo, LocalDateTime startTime, LocalDateTime endTime) {
|
||||
return baseMapper.getReportDetails(groupNo, shiftNo, startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【新增实现】
|
||||
* 负责更新产出卷的实际重量和状态。
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateExitCoilActualWeight(String exitMatId, BigDecimal actualWeight) {
|
||||
// 1. 根据成品卷号查询记录
|
||||
CrmPdoExcoil excoil = this.getByExcoilId(exitMatId);
|
||||
|
||||
if (excoil == null) {
|
||||
log.error("未找到成品卷 {} 的数据库记录,无法更新重量。", exitMatId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 检查当前状态是否为 "UNWEIGHT" (未称重)
|
||||
// 确保我们只更新未处理过的卷
|
||||
if (Objects.equals(excoil.getStatus(), "UNWEIGHT")) {
|
||||
// 3. 更新实际重量和状态
|
||||
excoil.setActualWeight(actualWeight.doubleValue());
|
||||
excoil.setStatus("COMPLETED"); // 或其他最终状态,如 "WEIGHED"
|
||||
|
||||
// 4. 调用 CRM 服务进行数据库更新
|
||||
boolean success = this.updateCrmPdoExcoil(excoil);
|
||||
|
||||
if (success) {
|
||||
log.info("成品卷 {} 的实际重量已成功更新为 {} kg,状态变为 {}.",
|
||||
exitMatId, actualWeight, excoil.getStatus());
|
||||
} else {
|
||||
log.error("更新成品卷 {} 失败。", exitMatId);
|
||||
}
|
||||
} else {
|
||||
log.warn("成品卷 {} 的状态不是 'UNWEIGHT',当前状态为 '{}',跳过重量更新。",
|
||||
exitMatId, excoil.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class PdoExCoilServiceImpl implements PdoExCoilService {
|
||||
// 产出实际入库
|
||||
crmPdoExcoilService.addCrmPdoExcoil(pdoExCoilDTO);
|
||||
// 打包segment
|
||||
pdoStripValueService.treatStripValues(exitCoil);
|
||||
// pdoStripValueService.treatStripValues(exitCoil);
|
||||
return pdoExCoilDTO;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.fizz.business.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fizz.business.dto.SegmentDTO;
|
||||
import com.fizz.business.mapper.SegmentMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class SegmentService {
|
||||
|
||||
@Resource
|
||||
private SegmentMapper segmentMapper;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper(); // 用于JSON转换
|
||||
|
||||
/**
|
||||
* 保存完整的段数据,包含插入和更新逻辑。
|
||||
* 对应 C++ 的 saveTotalSegment() 方法。
|
||||
*
|
||||
* @param segment 待保存的段数据对象
|
||||
*/
|
||||
public void saveTotalSegment(SegmentDTO segment) {
|
||||
if (segment == null || segment.getEnCoilID() == null || segment.getEnCoilID().isEmpty()) {
|
||||
System.err.println("警告: Coil ID 为空,无法保存数据。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 将动态的 Map 数据转换为 JSON 字符串
|
||||
Map<String, BigDecimal> totalValuesAvg = new HashMap<>();
|
||||
segment.getTotalValues().forEach((key, segValue) -> {
|
||||
// 这里将 key 拼接上 "_avg" 以示区分,如果需要也可以不加
|
||||
totalValuesAvg.put(key + "_avg", segValue.getAverage());
|
||||
});
|
||||
|
||||
try {
|
||||
// 使用 Jackson ObjectMapper 将 Map 转换为 JSON 字符串
|
||||
String jsonString = objectMapper.writeValueAsString(totalValuesAvg);
|
||||
segment.setTotalValuesJson(jsonString);
|
||||
} catch (JsonProcessingException e) {
|
||||
System.err.println("转换 JSON 失败: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 先执行删除,再插入,以避免重复数据(与 C++ 逻辑保持一致)
|
||||
QueryWrapper<SegmentDTO> deleteWrapper = new QueryWrapper<>();
|
||||
deleteWrapper.eq("en_coil_id", segment.getEnCoilID())
|
||||
.eq("seg_no", segment.getSegNo());
|
||||
segmentMapper.delete(deleteWrapper);
|
||||
|
||||
// 3. 执行插入操作,MyBatis-Plus 会自动处理 totalValuesJson 字段的保存
|
||||
segmentMapper.insert(segment);
|
||||
|
||||
System.out.println("段数据保存成功。钢卷号: " + segment.getEnCoilID() + ", 段号: " + segment.getSegNo());
|
||||
}
|
||||
}
|
||||
@@ -3,30 +3,23 @@ package com.fizz.business.service.impl;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.constants.enums.PlanStatusEnum;
|
||||
import com.fizz.business.constants.enums.WebOperateMatEnum;
|
||||
import com.fizz.business.domain.DeviceDefine;
|
||||
import com.fizz.business.domain.HalfReturn;
|
||||
import com.fizz.business.dto.CoilHeadDTO;
|
||||
import com.fizz.business.dto.CoilPositionDTO;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.form.AdjustPosForm;
|
||||
import com.fizz.business.form.L1OperateMatForm;
|
||||
import com.fizz.business.form.WebOperateMatForm;
|
||||
import com.fizz.business.mapper.HalfReturnMapper;
|
||||
import com.fizz.business.mapper.SegmentMapper;
|
||||
import com.fizz.business.service.CrmPdiPlanService;
|
||||
import com.fizz.business.service.TrackService;
|
||||
import com.fizz.business.service.client.LocalCacheManager;
|
||||
import com.fizz.business.service.client.RedisCacheManager;
|
||||
import com.fizz.business.utils.CalcUtil;
|
||||
import com.fizz.business.utils.CoilMeasUtil;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import com.fizz.business.utils.WebSocketUtil;
|
||||
import com.fizz.business.vo.CrmPdiPlanVO;
|
||||
import com.fizz.business.vo.HalfReturnInfoVO;
|
||||
import com.fizz.business.vo.ReturnInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -50,8 +43,7 @@ public class TrackServiceImpl implements TrackService {
|
||||
|
||||
@Autowired
|
||||
RedisCacheManager redisCacheManager;
|
||||
@Autowired
|
||||
SegmentMapper segmentMapper;
|
||||
|
||||
@Autowired
|
||||
CrmPdiPlanService crmPdiPlanService;
|
||||
|
||||
@@ -107,10 +99,10 @@ public class TrackServiceImpl implements TrackService {
|
||||
*/
|
||||
@Override
|
||||
public void adjustPosition(AdjustPosForm form) {
|
||||
DeviceDefine targetDevice = LocalCacheManager.DEVICE_DEFINE_MAP.get(form.getTargetPos().name());
|
||||
DeviceEnum targetDevice = DeviceEnum.fromName(form.getTargetPos().name());
|
||||
Assert.notNull(targetDevice, "目标位置设备不存在");
|
||||
|
||||
DeviceDefine currentDevice = LocalCacheManager.DEVICE_DEFINE_MAP.get(form.getCurrentPos().name());
|
||||
DeviceEnum currentDevice = DeviceEnum.fromName(form.getCurrentPos().name());
|
||||
Assert.notNull(currentDevice, "当前位置设备不存在");
|
||||
|
||||
// 更新matmap
|
||||
@@ -129,16 +121,16 @@ public class TrackServiceImpl implements TrackService {
|
||||
return true;
|
||||
}
|
||||
// 多个卷取机需要跳过1#卷取机
|
||||
if (Objects.equals(endPos, DeviceEnum.TR2.getIdx())
|
||||
&& Objects.equals(currPos, DeviceEnum.TR1.getIdx())) {
|
||||
if (Objects.equals(endPos, DeviceEnum.TR.getIdx())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void refreshMatmap(DeviceDefine targetDevice, DeviceDefine currDevice, AdjustPosForm form) {
|
||||
Integer targetPosIdx = targetDevice.getPosIdx();
|
||||
Integer currPosIdx = currDevice.getPosIdx();
|
||||
private void refreshMatmap(DeviceEnum targetDevice, DeviceEnum currDevice, AdjustPosForm form) {
|
||||
Integer targetPosIdx = targetDevice.getIdx();
|
||||
Integer currPosIdx = currDevice.getIdx();
|
||||
MatmapDTO target = MatmapUtil.getMatmap(targetPosIdx);
|
||||
MatmapDTO curr = MatmapUtil.getMatmap(currPosIdx);
|
||||
if (Objects.equals(curr.getMatId(), target.getMatId())) {
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
package com.fizz.business.service.strip;
|
||||
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.constants.enums.L1OperateMatEnum;
|
||||
import com.fizz.business.domain.msg.AppMeasureCoatMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureEntryMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureExitMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureFurnaceMessage;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.dto.SegValue;
|
||||
import com.fizz.business.dto.SegmentDTO;
|
||||
import com.fizz.business.form.L1OperateMatForm;
|
||||
import com.fizz.business.service.TrackService;
|
||||
import com.fizz.business.service.impl.SegmentService;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import com.fizz.business.utils.WebSocketUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.fizz.business.constants.enums.DeviceEnum.WELDER;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class SegmentTrackerService {
|
||||
|
||||
private final StripPositionService stripPositionService;
|
||||
private final TrackService trackService;
|
||||
private final SegmentService segmentService; // 注入新创建的段服务
|
||||
|
||||
private int traceCount = 0;
|
||||
private boolean firstMeasure = true;
|
||||
private BigDecimal weldLength = BigDecimal.ZERO;
|
||||
private int coilSegNum = 1;
|
||||
|
||||
private final Deque<SegmentDTO> listSegment = new ConcurrentLinkedDeque<>();
|
||||
private static final double SEGSTRIPLEN = 2.0;
|
||||
private static final int MAX_SEG_COUNT = 2000;
|
||||
private final ConcurrentMap<String, Set<DeviceEnum>> coilReachedDevices = new ConcurrentHashMap<>();
|
||||
private static final double LOWSPEEDLIMIT = 0.05;
|
||||
|
||||
/**
|
||||
* 【主入口】
|
||||
* 负责处理新的测量数据,生成新段,并对新到达的设备做一次性快照。
|
||||
*/
|
||||
public void handleMeasure(String coilId,
|
||||
BigDecimal entryLengthAtWelder,
|
||||
AppMeasureEntryMessage entry,
|
||||
AppMeasureFurnaceMessage furnace,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit) {
|
||||
|
||||
// 1. 首次测量初始化或新卷判定
|
||||
BigDecimal weldDev;
|
||||
if (firstMeasure || entryLengthAtWelder.compareTo(weldLength) < 0) {
|
||||
weldDev = entryLengthAtWelder; // 新卷偏移量等于当前长度
|
||||
coilSegNum = 1;
|
||||
weldLength = entryLengthAtWelder;
|
||||
firstMeasure = false;
|
||||
listSegment.clear(); // 清空旧段
|
||||
coilReachedDevices.remove(coilId); // 清空旧钢卷的快照记录
|
||||
log.info("New coil detected or initialized:{} " ,coilId);
|
||||
} else {
|
||||
weldDev = entryLengthAtWelder.subtract(weldLength);
|
||||
}
|
||||
|
||||
// 更新焊机长度
|
||||
weldLength = entryLengthAtWelder;
|
||||
|
||||
// trace 控制
|
||||
traceCount++;
|
||||
if (traceCount > 5) {
|
||||
log.info(String.format("Trace: weldLen=%.2f, speed=%s",
|
||||
entryLengthAtWelder, procStripSpeed(entry, furnace, exit)));
|
||||
traceCount = 0;
|
||||
}
|
||||
|
||||
|
||||
// 2. 检查是否达到生成新段的条件
|
||||
BigDecimal segThreshold = BigDecimal.valueOf(coilSegNum * SEGSTRIPLEN);
|
||||
if (entryLengthAtWelder.compareTo(segThreshold) >= 0) {
|
||||
|
||||
// 2.1. 创建新的 SegmentDTO 并初始化基本位置
|
||||
SegmentDTO newSeg = createNewSegment(coilId, entryLengthAtWelder);
|
||||
|
||||
// 2.3. 将新段添加到队列中
|
||||
listSegment.addLast(newSeg);
|
||||
if (listSegment.size() > MAX_SEG_COUNT) {
|
||||
listSegment.removeFirst();
|
||||
}
|
||||
coilSegNum++;
|
||||
}
|
||||
|
||||
// 3. 处理队列中所有已存在的段
|
||||
treatSegAsync(entry, furnace, coat, exit, weldDev);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 【核心功能】
|
||||
* 遍历所有已存在的段,更新其位置,并累积其在设备区域内的实时数据。
|
||||
* 这部分逻辑只负责“移动”和“累积”。
|
||||
*/
|
||||
public void treatSeg(AppMeasureEntryMessage entry,
|
||||
AppMeasureFurnaceMessage furnace,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit,
|
||||
BigDecimal weldDev) {
|
||||
if (listSegment.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal celLength = entry != null ? entry.getCelLength() : BigDecimal.ZERO;
|
||||
BigDecimal cxlLength = exit != null ? exit.getCxlLength() : BigDecimal.ZERO;
|
||||
|
||||
Iterator<SegmentDTO> iterator = listSegment.descendingIterator();
|
||||
while (iterator.hasNext()) {
|
||||
SegmentDTO segment = iterator.next();
|
||||
|
||||
// 更新段在产线上的位置
|
||||
segment.setHeadPos(segment.getHeadPos().add(weldDev));
|
||||
segment.setTailPos(segment.getTailPos().add(weldDev));
|
||||
|
||||
// 遍历所有设备,累积段在设备区域内的数据
|
||||
for (DeviceEnum device : DeviceEnum.values()) {
|
||||
double currentDevicePos = stripPositionService.calculate(device, celLength, cxlLength);
|
||||
|
||||
// 判断段是否位于设备的“长区域”内
|
||||
if (segment.getHeadPos().compareTo(BigDecimal.valueOf(currentDevicePos)) > 0 &&
|
||||
segment.getTailPos().compareTo(BigDecimal.valueOf(currentDevicePos)) < 0) {
|
||||
|
||||
double currentSpeed = getSpeedForDevice(device, entry, furnace, exit);
|
||||
if (currentSpeed > LOWSPEEDLIMIT) {
|
||||
for (String fieldName : device.getParamFields()) {
|
||||
Object message = getMessageForDevice(device, entry, furnace, coat, exit);
|
||||
if (message != null) {
|
||||
BigDecimal value = getFieldFromMessage(message, fieldName);
|
||||
setSegValue(segment.getTotalValues(), fieldName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 出厂判断
|
||||
double exitPlantPos = stripPositionService.calculate(DeviceEnum.TR, celLength, cxlLength);
|
||||
if (segment.getTailPos().compareTo(BigDecimal.valueOf(exitPlantPos)) >= 0) {
|
||||
System.out.println("钢卷 " + segment.getEnCoilID() + " 的段号 " + segment.getSegNo() + " 已离开产线,开始持久化数据。");
|
||||
segmentService.saveTotalSegment(segment); // 调用服务进行持久化
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- 新增的辅助方法,将逻辑封装起来 ---
|
||||
/**
|
||||
* 【异步方法】
|
||||
* 异步处理队列中所有已存在的段,更新其位置和累积数据。
|
||||
*/
|
||||
@Async("taskExecutor") // 指定使用名为 "taskExecutor" 的线程池
|
||||
public void treatSegAsync(AppMeasureEntryMessage entry,
|
||||
AppMeasureFurnaceMessage furnace,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit,
|
||||
BigDecimal weldDev) {
|
||||
// 调用原有的同步方法
|
||||
this.treatSeg(entry, furnace, coat, exit, weldDev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建并初始化一个新的 SegmentDTO。
|
||||
*/
|
||||
private SegmentDTO createNewSegment(String coilId, BigDecimal entryLengthAtWelder) {
|
||||
SegmentDTO seg = new SegmentDTO();
|
||||
seg.setSegNo(coilSegNum);
|
||||
seg.setEnCoilID(coilId);
|
||||
|
||||
if (coilSegNum == 1) {
|
||||
// 第一个段的特殊处理
|
||||
seg.setStartPos(BigDecimal.ZERO);
|
||||
seg.setEndPos(entryLengthAtWelder);
|
||||
seg.setSegLen(entryLengthAtWelder);
|
||||
seg.setHeadPos(entryLengthAtWelder);
|
||||
seg.setTailPos(BigDecimal.ZERO);
|
||||
} else {
|
||||
// 后续段的计算
|
||||
SegmentDTO prev = listSegment.peekLast();
|
||||
seg.setStartPos(prev.getEndPos());
|
||||
seg.setEndPos(entryLengthAtWelder);
|
||||
seg.setSegLen(seg.getEndPos().subtract(seg.getStartPos()));
|
||||
// 这两个位置是全线绝对位置,后续会通过 weldDev 动态更新
|
||||
seg.setHeadPos(entryLengthAtWelder);
|
||||
seg.setTailPos(seg.getEndPos().subtract(seg.getSegLen()));
|
||||
}
|
||||
return seg;
|
||||
}
|
||||
|
||||
|
||||
// --- 辅助方法,与消息处理和反射相关 ---
|
||||
|
||||
private Object getMessageForDevice(DeviceEnum device, AppMeasureEntryMessage entry, AppMeasureFurnaceMessage furnace, AppMeasureCoatMessage coat, AppMeasureExitMessage exit) {
|
||||
if (device.getDesc().contains("开卷机") || device.getDesc().contains("活套") || device.getDesc().contains("焊机")) {
|
||||
return entry;
|
||||
} else if (device.getDesc().contains("清洗段") || device.getDesc().contains("退火炉")) {
|
||||
return furnace;
|
||||
} else if (device.getDesc().contains("涂机")) {
|
||||
return coat;
|
||||
} else {
|
||||
return exit;
|
||||
}
|
||||
}
|
||||
|
||||
private double getSpeedForDevice(DeviceEnum device, AppMeasureEntryMessage entry, AppMeasureFurnaceMessage furnace, AppMeasureExitMessage exit) {
|
||||
if (device.getDesc().contains("开卷机") || device.getDesc().contains("活套") || device.getDesc().contains("焊机")) {
|
||||
return entry != null && entry.getStripSpeed() != null ? entry.getStripSpeed().doubleValue() : 0.0;
|
||||
} else if (device.getDesc().contains("清洗段") || device.getDesc().contains("退火炉")) {
|
||||
return furnace != null && furnace.getStripSpeed() != null ? furnace.getStripSpeed().doubleValue() : 0.0;
|
||||
} else {
|
||||
return exit != null && exit.getSpeedExitSection() != null ? exit.getSpeedExitSection().doubleValue() : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private double procStripSpeed(AppMeasureEntryMessage entry, AppMeasureFurnaceMessage furnace, AppMeasureExitMessage exit) {
|
||||
if (entry != null && entry.getStripSpeed() != null) return entry.getStripSpeed().doubleValue();
|
||||
if (furnace != null && furnace.getStripSpeed() != null) return furnace.getStripSpeed().doubleValue();
|
||||
if (exit != null && exit.getSpeedExitSection() != null) return exit.getSpeedExitSection().doubleValue();
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private BigDecimal getFieldFromMessage(Object message, String fieldName) {
|
||||
if (message == null || fieldName == null) return null;
|
||||
try {
|
||||
String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
||||
Method getter = message.getClass().getMethod(getterName);
|
||||
Object value = getter.invoke(message);
|
||||
|
||||
if (value instanceof BigDecimal) {
|
||||
return (BigDecimal) value;
|
||||
} else if (value instanceof Number) {
|
||||
return BigDecimal.valueOf(((Number) value).doubleValue());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error getting field " + fieldName + " from message: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setSegValue(Map<String, SegValue> segValues, String key, BigDecimal value) {
|
||||
if (value != null) {
|
||||
segValues.computeIfAbsent(key, k -> new SegValue()).add(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【新方法】
|
||||
* 专门用于处理钢卷头部在设备间的移动和物料跟踪。
|
||||
* 这部分逻辑包含了对 Redis/DB 的写入,最适合异步化。
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
public void trackCoilHeadPosition(String coilId, BigDecimal headPos,
|
||||
AppMeasureEntryMessage entry, AppMeasureExitMessage exit) {
|
||||
|
||||
Set<DeviceEnum> prevReached = coilReachedDevices.computeIfAbsent(coilId, k -> Collections.newSetFromMap(new ConcurrentHashMap<>()));
|
||||
|
||||
BigDecimal celLength = entry != null ? entry.getCelLength() : BigDecimal.ZERO;
|
||||
BigDecimal cxlLength = exit != null ? exit.getCxlLength() : BigDecimal.ZERO;
|
||||
|
||||
for (DeviceEnum d : DeviceEnum.values()) {
|
||||
double dynPos = stripPositionService.calculate(d, celLength, cxlLength);
|
||||
|
||||
// 判断钢卷的头部是否首次到达该设备
|
||||
if (headPos.compareTo(BigDecimal.valueOf(dynPos)) >= 0) {
|
||||
if (!prevReached.contains(d)) {
|
||||
|
||||
// 1. 如果是焊机,则调用 CRM 更新计划状态
|
||||
if (d == WELDER) {
|
||||
|
||||
MatmapDTO matmap = MatmapUtil.getMatmap(WELDER.getIdx());
|
||||
trackService.l1OperateMat(L1OperateMatForm.builder()
|
||||
.entryMatId(coilId)
|
||||
.planId(matmap.getPlanId())
|
||||
.porIdx(entry.getPayOffReelNumber())
|
||||
.operation(L1OperateMatEnum.PRODUCING)
|
||||
.build());
|
||||
}
|
||||
|
||||
// 2. 更新 Matmap
|
||||
MatmapUtil.setMatId(d.getIdx(), coilId);
|
||||
WebSocketUtil.sendMatmapMsg();
|
||||
// 3. 标记为已到达,防止重复操作
|
||||
prevReached.add(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.fizz.business.service.strip;
|
||||
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.domain.msg.AppMeasureEntryMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureExitMessage;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 位置计算服务 —— 根据 entry.stripLocation(焊机参考)和活套长度动态判断设备的比较位置
|
||||
*/
|
||||
@Service
|
||||
public class StripPositionService {
|
||||
|
||||
/**
|
||||
* 计算设备在 entry 坐标系的“比较位置”
|
||||
*
|
||||
* 规则:
|
||||
* - device.basePosition < ENL_MIN : 不加活套
|
||||
* - ENL_MIN <= device.basePosition < CXL_MIN : 加 celLength
|
||||
* - >= CXL_MIN : 加 cxlLength
|
||||
*/
|
||||
public double calculate(DeviceEnum device, BigDecimal celLength, BigDecimal cxlLength) {
|
||||
double base = device.getBasePosition();
|
||||
double cel = celLength == null ? 0.0 : celLength.doubleValue();
|
||||
double cxl = cxlLength == null ? 0.0 : cxlLength.doubleValue();
|
||||
|
||||
double enlMin = findEnlMin();
|
||||
double cxlMin = findCxlMin();
|
||||
|
||||
if (base < enlMin) {
|
||||
return base;
|
||||
} else if (base < cxlMin) {
|
||||
return base + cel;
|
||||
} else {
|
||||
return base + cxl;
|
||||
}
|
||||
}
|
||||
|
||||
public double calculate(DeviceEnum device,AppMeasureEntryMessage entry,
|
||||
AppMeasureExitMessage exit) {
|
||||
BigDecimal cel = entry == null ? null : entry.getCelLength();
|
||||
BigDecimal cxl = exit == null ? null : exit.getCxlLength();
|
||||
return calculate(device, cel, cxl);
|
||||
}
|
||||
|
||||
private double findEnlMin() {
|
||||
double min = Double.MAX_VALUE;
|
||||
for (DeviceEnum d : DeviceEnum.values()) {
|
||||
if (d.name().startsWith("ENL")) {
|
||||
min = Math.min(min, d.getBasePosition());
|
||||
}
|
||||
}
|
||||
return min == Double.MAX_VALUE ? 0.0 : min;
|
||||
}
|
||||
|
||||
private double findCxlMin() {
|
||||
double min = Double.MAX_VALUE;
|
||||
for (DeviceEnum d : DeviceEnum.values()) {
|
||||
if (d.name().startsWith("CXL")) {
|
||||
min = Math.min(min, d.getBasePosition());
|
||||
}
|
||||
}
|
||||
return min == Double.MAX_VALUE ? Double.MAX_VALUE : min;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,21 @@
|
||||
package com.fizz.business.utils;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.domain.DeviceDefine;
|
||||
import com.fizz.business.dto.*;
|
||||
import com.fizz.business.dto.CoilHeadDTO;
|
||||
import com.fizz.business.dto.CoilPositionDTO;
|
||||
import com.fizz.business.dto.L1CoilLineMeasureDTO;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.service.client.RedisCacheManager;
|
||||
import com.fizz.business.service.impl.BeanFactory;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.fizz.business.constants.CommonConstants.CoilMeasure.BEFORE_TR_IDX;
|
||||
import static com.fizz.business.service.client.LocalCacheManager.DEVICE_DEFINE_MAP;
|
||||
|
||||
|
||||
/**
|
||||
@@ -67,9 +65,7 @@ public class CoilMeasUtil {
|
||||
|
||||
Integer trIdx = null;
|
||||
if (trCode == 1) {
|
||||
trIdx = DeviceEnum.TR1.getIdx();
|
||||
} else if (trCode == 2) {
|
||||
trIdx = DeviceEnum.TR2.getIdx();
|
||||
trIdx = DeviceEnum.TR.getIdx();
|
||||
} else {
|
||||
log.warn("W: invalid working TR, trCode={}", trCode);
|
||||
}
|
||||
@@ -81,7 +77,7 @@ public class CoilMeasUtil {
|
||||
}
|
||||
|
||||
public static List<Integer> getTrIdxList() {
|
||||
return Lists.newArrayList(DeviceEnum.TR1.getIdx(), DeviceEnum.TR2.getIdx());
|
||||
return Lists.newArrayList(DeviceEnum.TR.getIdx());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,147 +89,4 @@ public class CoilMeasUtil {
|
||||
return BEFORE_TR_IDX.getIdx();
|
||||
}
|
||||
|
||||
public static double initStripLocation(double stripLocation) {
|
||||
if (stripLocation < 0) {
|
||||
stripLocation = 0;
|
||||
} else if (stripLocation > 25000) {
|
||||
stripLocation = 25000;
|
||||
}
|
||||
return stripLocation;
|
||||
}
|
||||
|
||||
public static DeviceDefine matchDevice(double posLen, double entryLoopLen, double exitLoopLen) {
|
||||
DeviceDefine mCEL = DEVICE_DEFINE_MAP.get(DeviceEnum.CEL.name()); // 入口活套
|
||||
DeviceDefine mCXL = DEVICE_DEFINE_MAP.get(DeviceEnum.CXL.name()); // 出口活套
|
||||
for (DeviceDefine device : DEVICE_DEFINE_MAP.values()) {
|
||||
Double start = device.getPositionLengthStart();
|
||||
Double end = device.getPositionLengthEnd();
|
||||
// 入口活套之后的设备,需要加上entryLoopLen
|
||||
if (device.getPosIdx() >= mCEL.getPosIdx()) {
|
||||
// start = NumberUtil.add(start, entryLoopLen);
|
||||
end = NumberUtil.add(end, entryLoopLen);
|
||||
}
|
||||
// 出口活套之后的设备,还需要加上exitLoopLen
|
||||
if (device.getPosIdx() >= mCXL.getPosIdx()) {
|
||||
// start = NumberUtil.add(start, exitLoopLen);
|
||||
end = NumberUtil.add(end, exitLoopLen);
|
||||
}
|
||||
if (posLen >= start && posLen < end) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CoilPositionDTO buildCoilPos(L1CoilLineMeasureDTO measureDTO, List<CoilHeadDTO> headList) {
|
||||
List<CoilPositionDTO.CoilStripLocation> coilStripLocationList = Lists.newArrayList();
|
||||
Integer workPor = measureDTO.getWorkPor();
|
||||
Integer workTr = measureDTO.getWorkTr();
|
||||
|
||||
CoilHeadDTO prevHead = BeanFactory.getBean(RedisCacheManager.class).getPrevHead();
|
||||
if (Objects.nonNull(prevHead)) {
|
||||
coilStripLocationList.add(
|
||||
CoilPositionDTO.CoilStripLocation.builder()
|
||||
.matId(prevHead.getMatId())
|
||||
.planId(prevHead.getPlanId())
|
||||
.planNo(prevHead.getPlanNo())
|
||||
.porId(prevHead.getPorIdx())
|
||||
.stripLocation(99999).build());
|
||||
}
|
||||
headList.forEach(head -> coilStripLocationList.add(
|
||||
CoilPositionDTO.CoilStripLocation.builder()
|
||||
.matId(head.getMatId())
|
||||
.planId(head.getPlanId())
|
||||
.planNo(head.getPlanNo())
|
||||
.porId(head.getPorIdx())
|
||||
.stripLocation(head.getPos()).build()));
|
||||
|
||||
// 两个开卷机时,需要设置另一个未运行的开卷机上的钢卷数据
|
||||
Integer anotherPorIdx = getAnotherPorIdx(workPor);
|
||||
if (Objects.nonNull(anotherPorIdx)) {
|
||||
MatmapDTO matmap = MatmapUtil.getMatmap(anotherPorIdx);
|
||||
coilStripLocationList.add(
|
||||
CoilPositionDTO.CoilStripLocation.builder()
|
||||
.matId(matmap.getMatId())
|
||||
.planId(matmap.getPlanId())
|
||||
.planNo(matmap.getPlanNo())
|
||||
.porId(anotherPorIdx)
|
||||
.stripLocation(0).build());
|
||||
}
|
||||
|
||||
// 当前开卷机与焊机的卷号不同时,需要设置当前开卷机上的钢卷数据(这种情况只出现在只有一个开卷机运行的时候)
|
||||
Integer porIdx = CoilMeasUtil.getPorIdx(workPor);
|
||||
MatmapDTO welderCoil = MatmapUtil.getMatmap(DeviceEnum.WELDER.getIdx());
|
||||
if (Objects.nonNull(porIdx) && MatmapUtil.already(welderCoil)) {
|
||||
MatmapDTO porCoil = MatmapUtil.getMatmap(porIdx);
|
||||
if (!Objects.equals(welderCoil.getMatId(), porCoil.getMatId())) {
|
||||
coilStripLocationList.add(
|
||||
CoilPositionDTO.CoilStripLocation.builder()
|
||||
.matId(porCoil.getMatId())
|
||||
.planId(porCoil.getPlanId())
|
||||
.planNo(porCoil.getPlanNo())
|
||||
.porId(porIdx)
|
||||
.stripLocation(0).build());
|
||||
}
|
||||
}
|
||||
|
||||
return CoilPositionDTO.builder()
|
||||
.coilStripLocationList(coilStripLocationList)
|
||||
.entryLoopLen(measureDTO.getEntryLoopLength())
|
||||
.exitLoopLen(measureDTO.getExitLoopLength())
|
||||
.entryLoopPer(measureDTO.getEntryLoopPercent())
|
||||
.exitLoopLPer(measureDTO.getExitLoopPercent())
|
||||
.entrySpeed(measureDTO.getInSpeed())
|
||||
.technologySpeed(measureDTO.getUnitSpeed())
|
||||
.exitSpeed(measureDTO.getOutSpeed())
|
||||
.porId(CoilMeasUtil.getPorIdx(workPor))
|
||||
.trId(CoilMeasUtil.getTrIdx(workTr))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static double getPorSpeed(L1CoilLineMeasureDTO measureDTO) {
|
||||
return measureDTO.getUnitSpeed();
|
||||
}
|
||||
|
||||
// public static List<String> getParamKey(String deviceName) {
|
||||
// List<PointConfigDTO> list = DEVICE_PARAM_MAP.get(deviceName);
|
||||
// if (CollUtil.isEmpty(list)) {
|
||||
// return Collections.emptyList();
|
||||
// }
|
||||
// return list.stream().map(PointConfigDTO::getParam).collect(Collectors.toList());
|
||||
// }
|
||||
//
|
||||
// public static String getParamKey(String deviceName, String paramDesc) {
|
||||
// List<PointConfigDTO> list = DEVICE_PARAM_MAP.get(deviceName);
|
||||
// if (CollUtil.isEmpty(list)) {
|
||||
// return null;
|
||||
// }
|
||||
// List<String> keys = list.stream()
|
||||
// .filter(p -> paramDesc.equals(p.getDesc()))
|
||||
// .map(PointConfigDTO::getParam)
|
||||
// .collect(Collectors.toList());
|
||||
// if (CollUtil.isEmpty(keys)) {
|
||||
// return null;
|
||||
// }
|
||||
// return keys.get(0);
|
||||
// }
|
||||
|
||||
// public static List<String> getParamDesc(String deviceName) {
|
||||
// List<PointConfigDTO> list = DEVICE_PARAM_MAP.get(deviceName);
|
||||
// if (CollUtil.isEmpty(list)) {
|
||||
// return Collections.emptyList();
|
||||
// }
|
||||
// return list.stream().map(PointConfigDTO::getDesc).collect(Collectors.toList());
|
||||
// }
|
||||
//
|
||||
// public static LinkedHashMap<String, String> getParamMap(String deviceName) {
|
||||
// List<PointConfigDTO> list = DEVICE_PARAM_MAP.get(deviceName);
|
||||
// if (CollUtil.isEmpty(list)) {
|
||||
// return Maps.newLinkedHashMap();
|
||||
// }
|
||||
//
|
||||
// return list.stream().collect(Collectors.toMap(PointConfigDTO::getParam, PointConfigDTO::getDesc, (k1, k2) -> k1, LinkedHashMap::new));
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.fizz.business.constants.CommonConstants;
|
||||
import com.fizz.business.constants.enums.WsTypeEnum;
|
||||
import com.fizz.business.domain.msg.AppMeasureEntryMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureMessage;
|
||||
import com.fizz.business.dto.CoilPositionDTO;
|
||||
import com.fizz.business.dto.L1CoilLineMeasureDTO;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
@@ -79,6 +81,13 @@ public class WebSocketUtil {
|
||||
sendMessage(WsTypeEnum.track_measure, JSONUtil.toJsonStr(measureDTO));
|
||||
}
|
||||
|
||||
public static void sendMeasureMsg(AppMeasureMessage measureDTO) {
|
||||
|
||||
|
||||
sendMessage(WsTypeEnum.track_measure, JSONUtil.toJsonStr(measureDTO));
|
||||
}
|
||||
|
||||
|
||||
public static void sendMatmapMsg() {
|
||||
List<MatmapDTO> list = MatmapUtil.getMatmapList();
|
||||
if (CollUtil.isEmpty(list)) return;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.fizz.business.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Schema(name = "ReportDetailVO", description = "钢卷明细信息")
|
||||
public class ReportDetailVO {
|
||||
|
||||
@Schema(description = "成品卷号")
|
||||
private String exitMatId;
|
||||
|
||||
@Schema(description = "原料卷号")
|
||||
private String entryMatId;
|
||||
|
||||
@Schema(description = "班号")
|
||||
private String groupNo;
|
||||
|
||||
@Schema(description = "组号")
|
||||
private String shiftNo;
|
||||
|
||||
@Schema(description = "钢种")
|
||||
private String steelGrade;
|
||||
|
||||
@Schema(description = "成品宽度")
|
||||
private Double exitWidth;
|
||||
|
||||
@Schema(description = "成品长度")
|
||||
private Double exitLength;
|
||||
|
||||
@Schema(description = "理论重量")
|
||||
private Double theoryWeight;
|
||||
|
||||
@Schema(description = "实际重量")
|
||||
private Double actualWeight;
|
||||
|
||||
@Schema(description = "成品厚度")
|
||||
private Double exitThickness;
|
||||
|
||||
@Schema(description = "上线时间")
|
||||
private LocalDateTime onlineTime;
|
||||
|
||||
@Schema(description = "结束时间")
|
||||
private LocalDateTime endTime;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.fizz.business.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(name = "ReportSummaryVO", description = "报表汇总统计结果")
|
||||
public class ReportSummaryVO {
|
||||
|
||||
// 汇总指标
|
||||
@Schema(description = "总成品宽度")
|
||||
private Double totalExitWidth;
|
||||
|
||||
@Schema(description = "总成品长度")
|
||||
private Double totalExitLength;
|
||||
|
||||
@Schema(description = "总理论重量")
|
||||
private Double totalTheoryWeight;
|
||||
|
||||
@Schema(description = "总实际重量")
|
||||
private Double totalActualWeight;
|
||||
|
||||
@Schema(description = "总成品厚度")
|
||||
private Double totalExitThickness;
|
||||
|
||||
// 平均指标
|
||||
@Schema(description = "平均成品宽度")
|
||||
private Double avgExitWidth;
|
||||
|
||||
@Schema(description = "平均成品长度")
|
||||
private Double avgExitLength;
|
||||
|
||||
@Schema(description = "平均理论重量")
|
||||
private Double avgTheoryWeight;
|
||||
|
||||
@Schema(description = "平均实际重量")
|
||||
private Double avgActualWeight;
|
||||
|
||||
@Schema(description = "平均成品厚度")
|
||||
private Double avgExitThickness;
|
||||
|
||||
// 新增指标
|
||||
@Schema(description = "钢卷总数")
|
||||
private Long coilCount;
|
||||
|
||||
@Schema(description = "原料总重(去重计算)")
|
||||
private Double totalEntryWeight;
|
||||
|
||||
@Schema(description = "成材率(成品实际重量/原料重量)")
|
||||
private Double yieldRate;
|
||||
}
|
||||
@@ -3,4 +3,139 @@
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.fizz.business.mapper.CrmPdoExcoilMapper">
|
||||
|
||||
<select id="getReportSummary" resultType="com.fizz.business.vo.ReportSummaryVO">
|
||||
SELECT
|
||||
-- 总计
|
||||
SUM(exit_width) AS totalExitWidth,
|
||||
SUM(exit_length) AS totalExitLength,
|
||||
SUM(theory_weight) AS totalTheoryWeight,
|
||||
SUM(actual_weight) AS totalActualWeight,
|
||||
SUM(exit_thickness) AS totalExitThickness,
|
||||
|
||||
-- 平均
|
||||
AVG(exit_width) AS avgExitWidth,
|
||||
AVG(exit_length) AS avgExitLength,
|
||||
AVG(theory_weight) AS avgTheoryWeight,
|
||||
AVG(actual_weight) AS avgActualWeight,
|
||||
AVG(exit_thickness) AS avgExitThickness,
|
||||
|
||||
-- 总数
|
||||
COUNT(DISTINCT exit_mat_id) AS coilCount,
|
||||
|
||||
-- 原料总重(去重 entry_mat_id)
|
||||
(SELECT SUM(t.entry_weight)
|
||||
FROM (
|
||||
SELECT entry_mat_id, MAX(entry_weight) AS entry_weight
|
||||
FROM crm_pdo_excoil
|
||||
WHERE del_flag = 0
|
||||
<if test="groupNo != null and groupNo != ''">
|
||||
AND group_no = #{groupNo}
|
||||
</if>
|
||||
<if test="shiftNo != null and shiftNo != ''">
|
||||
AND shift_no = #{shiftNo}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
AND end_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND end_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
GROUP BY entry_mat_id
|
||||
) t
|
||||
) AS totalEntryWeight,
|
||||
|
||||
-- 成材率
|
||||
CASE
|
||||
WHEN (SELECT SUM(tt.entry_weight)
|
||||
FROM (
|
||||
SELECT entry_mat_id, MAX(entry_weight) AS entry_weight
|
||||
FROM crm_pdo_excoil
|
||||
WHERE del_flag = 0
|
||||
<if test="groupNo != null and groupNo != ''">
|
||||
AND group_no = #{groupNo}
|
||||
</if>
|
||||
<if test="shiftNo != null and shiftNo != ''">
|
||||
AND shift_no = #{shiftNo}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
AND end_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND end_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
GROUP BY entry_mat_id
|
||||
) tt
|
||||
) > 0
|
||||
THEN SUM(actual_weight) /
|
||||
(SELECT SUM(tt.entry_weight)
|
||||
FROM (
|
||||
SELECT entry_mat_id, MAX(entry_weight) AS entry_weight
|
||||
FROM crm_pdo_excoil
|
||||
WHERE del_flag = 0
|
||||
<if test="groupNo != null and groupNo != ''">
|
||||
AND group_no = #{groupNo}
|
||||
</if>
|
||||
<if test="shiftNo != null and shiftNo != ''">
|
||||
AND shift_no = #{shiftNo}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
AND end_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND end_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
GROUP BY entry_mat_id
|
||||
) tt
|
||||
)
|
||||
ELSE 0
|
||||
END AS yieldRate
|
||||
|
||||
FROM crm_pdo_excoil
|
||||
WHERE del_flag = 0
|
||||
<if test="groupNo != null and groupNo != ''">
|
||||
AND group_no = #{groupNo}
|
||||
</if>
|
||||
<if test="shiftNo != null and shiftNo != ''">
|
||||
AND shift_no = #{shiftNo}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
AND end_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND end_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getReportDetails" resultType="com.fizz.business.vo.ReportDetailVO">
|
||||
SELECT
|
||||
exit_mat_id AS exitMatId,
|
||||
entry_mat_id AS entryMatId,
|
||||
group_no AS groupNo,
|
||||
shift_no AS shiftNo,
|
||||
steel_grade AS steelGrade,
|
||||
exit_width AS exitWidth,
|
||||
exit_length AS exitLength,
|
||||
theory_weight AS theoryWeight,
|
||||
actual_weight AS actualWeight,
|
||||
exit_thickness AS exitThickness,
|
||||
online_time AS onlineTime,
|
||||
end_time AS endTime
|
||||
FROM crm_pdo_excoil
|
||||
WHERE del_flag = 0
|
||||
<if test="groupNo != null and groupNo != ''">
|
||||
AND group_no = #{groupNo}
|
||||
</if>
|
||||
<if test="shiftNo != null and shiftNo != ''">
|
||||
AND shift_no = #{shiftNo}
|
||||
</if>
|
||||
<if test="startTime != null">
|
||||
AND end_time <![CDATA[ >= ]]> #{startTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND end_time <![CDATA[ <= ]]> #{endTime}
|
||||
</if>
|
||||
ORDER BY end_time ASC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user