更新wip-退火 缺少实际库区选择,重新占据库位能力

This commit is contained in:
2026-03-14 18:39:19 +08:00
parent 7740531fc5
commit 9a645100df
56 changed files with 3783 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
package com.klp.controller;
import com.klp.common.core.domain.R;
import com.klp.domain.vo.anneal.WmsAnnealOverviewVo;
import com.klp.service.IWmsAnnealOverviewService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 退火总览
*
* @author klp
* @date 2026-03-14
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/anneal/overview")
public class WmsAnnealOverviewController {
private final IWmsAnnealOverviewService overviewService;
/**
* 总览数据
*/
@GetMapping
public R<WmsAnnealOverviewVo> getOverview() {
return R.ok(overviewService.queryOverview());
}
}

View File

@@ -0,0 +1,31 @@
package com.klp.controller;
import com.klp.common.core.domain.R;
import com.klp.domain.bo.WmsAnnealPerformanceBo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceVo;
import com.klp.service.IWmsAnnealPerformanceService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 炉火实绩
*
* @author klp
* @date 2026-03-14
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/anneal/performance")
public class WmsAnnealPerformanceController {
private final IWmsAnnealPerformanceService performanceService;
@GetMapping
public R<WmsAnnealPerformanceVo> getPerformance(WmsAnnealPerformanceBo bo) {
return R.ok(performanceService.queryPerformance(bo));
}
}

View File

@@ -0,0 +1,103 @@
package com.klp.controller;
import com.klp.common.annotation.Log;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.domain.bo.WmsFurnaceBo;
import com.klp.domain.bo.WmsFurnaceBusyBo;
import com.klp.domain.bo.WmsFurnaceStatusBo;
import com.klp.domain.vo.WmsFurnaceVo;
import com.klp.service.IWmsFurnaceService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
/**
* 退火炉管理
*
* @author klp
* @date 2026-03-14
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/anneal/furnace")
public class WmsFurnaceController extends BaseController {
private final IWmsFurnaceService iWmsFurnaceService;
/**
* 查询炉子列表
*/
@GetMapping("/list")
public TableDataInfo<WmsFurnaceVo> list(WmsFurnaceBo bo, PageQuery pageQuery) {
return iWmsFurnaceService.queryPageList(bo, pageQuery);
}
/**
* 获取炉子详情
*/
@GetMapping("/{furnaceId}")
public R<WmsFurnaceVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long furnaceId) {
return R.ok(iWmsFurnaceService.queryById(furnaceId));
}
/**
* 新增炉子
*/
@Log(title = "退火炉", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping("/add")
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsFurnaceBo bo) {
return toAjax(iWmsFurnaceService.insertByBo(bo));
}
/**
* 修改炉子
*/
@Log(title = "退火炉", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/edit")
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsFurnaceBo bo) {
return toAjax(iWmsFurnaceService.updateByBo(bo));
}
/**
* 启用停用
*/
@Log(title = "退火炉", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/status")
public R<Void> changeStatus(@Validated @RequestBody WmsFurnaceStatusBo bo) {
return toAjax(iWmsFurnaceService.updateStatus(bo.getFurnaceId(), bo.getStatus()));
}
/**
* 置忙/置闲
*/
@Log(title = "退火炉", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/busy")
public R<Void> changeBusy(@Validated @RequestBody WmsFurnaceBusyBo bo) {
return toAjax(iWmsFurnaceService.updateBusy(bo.getFurnaceId(), bo.getBusyFlag()));
}
/**
* 删除炉子
*/
@Log(title = "退火炉", businessType = BusinessType.DELETE)
@DeleteMapping("/{furnaceIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] furnaceIds) {
return toAjax(iWmsFurnaceService.deleteWithValidByIds(Arrays.asList(furnaceIds), true));
}
}

View File

@@ -0,0 +1,145 @@
package com.klp.controller;
import com.klp.common.annotation.Log;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.domain.bo.WmsFurnacePlanBo;
import com.klp.domain.bo.WmsFurnacePlanCoilBo;
import com.klp.domain.bo.WmsFurnacePlanInFurnaceBo;
import com.klp.domain.bo.WmsFurnacePlanLocationBo;
import com.klp.domain.bo.WmsFurnacePlanStatusBo;
import com.klp.domain.vo.WmsFurnacePlanCoilVo;
import com.klp.domain.vo.WmsFurnacePlanVo;
import com.klp.service.IWmsFurnacePlanService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
/**
* 退火计划
*
* @author klp
* @date 2026-03-14
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/anneal/plan")
public class WmsFurnacePlanController extends BaseController {
private final IWmsFurnacePlanService iWmsFurnacePlanService;
/**
* 查询退火计划列表
*/
@GetMapping("/list")
public TableDataInfo<WmsFurnacePlanVo> list(WmsFurnacePlanBo bo, PageQuery pageQuery) {
return iWmsFurnacePlanService.queryPageList(bo, pageQuery);
}
/**
* 查询退火计划详情
*/
@GetMapping("/{planId}")
public R<WmsFurnacePlanVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long planId) {
return R.ok(iWmsFurnacePlanService.queryById(planId));
}
/**
* 新增退火计划
*/
@Log(title = "退火计划", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping("/add")
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsFurnacePlanBo bo) {
return toAjax(iWmsFurnacePlanService.insertByBo(bo));
}
/**
* 修改退火计划
*/
@Log(title = "退火计划", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/edit")
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsFurnacePlanBo bo) {
return toAjax(iWmsFurnacePlanService.updateByBo(bo));
}
/**
* 更新计划状态
*/
@Log(title = "退火计划", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/status")
public R<Void> changeStatus(@Validated @RequestBody WmsFurnacePlanStatusBo bo) {
return toAjax(iWmsFurnacePlanService.updateStatus(bo.getPlanId(), bo.getStatus()));
}
/**
* 入炉
*/
@Log(title = "退火计划", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/in-furnace")
public R<Void> inFurnace(@Validated @RequestBody WmsFurnacePlanInFurnaceBo bo) {
return toAjax(iWmsFurnacePlanService.inFurnace(bo.getPlanId()));
}
/**
* 完成退火
*/
@Log(title = "退火计划", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping("/complete")
public R<Void> complete(@Validated @RequestBody WmsFurnacePlanLocationBo bo) {
return toAjax(iWmsFurnacePlanService.completePlan(bo.getPlanId(), bo.getLocations()));
}
/**
* 删除退火计划
*/
@Log(title = "退火计划", businessType = BusinessType.DELETE)
@DeleteMapping("/{planIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] planIds) {
return toAjax(iWmsFurnacePlanService.deleteWithValidByIds(Arrays.asList(planIds), true));
}
/**
* 查询计划钢卷列表
*/
@GetMapping("/coil/list")
public R<List<WmsFurnacePlanCoilVo>> listCoils(@NotNull(message = "计划ID不能为空") @RequestParam Long planId) {
return R.ok(iWmsFurnacePlanService.queryPlanCoils(planId));
}
/**
* 绑定钢卷
*/
@Log(title = "退火计划钢卷", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping("/coil/bind")
public R<Void> bindCoils(@Validated(AddGroup.class) @RequestBody WmsFurnacePlanCoilBo bo) {
return toAjax(iWmsFurnacePlanService.bindPlanCoils(bo));
}
/**
* 解绑钢卷
*/
@Log(title = "退火计划钢卷", businessType = BusinessType.DELETE)
@RepeatSubmit
@DeleteMapping("/coil/unbind")
public R<Void> unbindCoil(@Validated @RequestBody WmsFurnacePlanCoilBo bo) {
return toAjax(iWmsFurnacePlanService.unbindPlanCoil(bo));
}
}

View File

@@ -0,0 +1,59 @@
package com.klp.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 退火炉信息表对象 wms_furnace
*
* @author klp
* @date 2026-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_furnace")
public class WmsFurnace extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 炉子ID
*/
@TableId(value = "furnace_id")
private Long furnaceId;
/**
* 炉编号
*/
private String furnaceCode;
/**
* 名称
*/
private String furnaceName;
/**
* 是否忙碌0=否1=是)
*/
private Integer busyFlag;
/**
* 状态0=停用1=启用)
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 删除标志0=正常1=已删除)
*/
@TableLogic
private Integer delFlag;
}

View File

@@ -0,0 +1,71 @@
package com.klp.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 退火计划对象 wms_furnace_plan
*
* @author klp
* @date 2026-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_furnace_plan")
public class WmsFurnacePlan extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 计划ID
*/
@TableId(value = "plan_id")
private Long planId;
/**
* 计划号
*/
private String planNo;
/**
* 计划开始时间
*/
private Date planStartTime;
/**
* 实际开始时间
*/
private Date actualStartTime;
/**
* 结束时间
*/
private Date endTime;
/**
* 目标炉子ID
*/
private Long targetFurnaceId;
/**
* 计划状态0草稿 1已下发 2执行中 3已完成 4已取消
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 删除标志0=正常1=已删除)
*/
@TableLogic
private Integer delFlag;
}

View File

@@ -0,0 +1,44 @@
package com.klp.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 退火计划钢卷关系对象 wms_furnace_plan_coil
*
* @author klp
* @date 2026-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_furnace_plan_coil")
public class WmsFurnacePlanCoil extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 计划钢卷ID
*/
@TableId(value = "plan_coil_id")
private Long planCoilId;
/**
* 计划ID
*/
private Long planId;
/**
* 钢卷ID
*/
private Long coilId;
/**
* 删除标志0=正常1=已删除)
*/
@TableLogic
private Integer delFlag;
}

View File

@@ -0,0 +1,31 @@
package com.klp.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 炉火实绩查询业务对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealPerformanceBo {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
private Long targetFurnaceId;
private String planNo;
private String enterCoilNo;
}

View File

@@ -0,0 +1,57 @@
package com.klp.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 退火炉业务对象 wms_furnace
*
* @author klp
* @date 2026-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsFurnaceBo extends BaseEntity {
/**
* 炉子ID
*/
private Long furnaceId;
/**
* 炉编号
*/
@NotBlank(message = "炉编号不能为空")
private String furnaceCode;
/**
* 名称
*/
@NotBlank(message = "名称不能为空")
private String furnaceName;
/**
* 是否忙碌0=否1=是)
*/
private Integer busyFlag;
/**
* 状态0=停用1=启用)
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 批量操作ID
*/
@NotNull(message = "主键不能为空", groups = {com.klp.common.core.validate.EditGroup.class})
private Long[] furnaceIds;
}

View File

@@ -0,0 +1,21 @@
package com.klp.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 退火炉忙碌状态更新业务对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsFurnaceBusyBo {
@NotNull(message = "炉子ID不能为空")
private Long furnaceId;
@NotNull(message = "忙碌状态不能为空")
private Integer busyFlag;
}

View File

@@ -0,0 +1,70 @@
package com.klp.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* 退火计划业务对象 wms_furnace_plan
*
* @author klp
* @date 2026-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsFurnacePlanBo extends BaseEntity {
/**
* 计划ID
*/
private Long planId;
/**
* 计划号
*/
@NotBlank(message = "计划号不能为空")
private String planNo;
/**
* 计划开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date planStartTime;
/**
* 实际开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date actualStartTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 目标炉子ID
*/
@NotNull(message = "目标炉子不能为空")
private Long targetFurnaceId;
/**
* 计划状态0草稿 1已下发 2执行中 3已完成 4已取消
*/
private Integer status;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,49 @@
package com.klp.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
/**
* 退火计划钢卷关系业务对象 wms_furnace_plan_coil
*
* @author klp
* @date 2026-03-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsFurnacePlanCoilBo extends BaseEntity {
/**
* 计划钢卷ID
*/
private Long planCoilId;
/**
* 计划ID
*/
@NotNull(message = "计划ID不能为空")
private Long planId;
/**
* 钢卷ID
*/
private Long coilId;
/**
* 钢卷ID列表逗号分隔
*/
private String coilIds;
/**
* 入场钢卷号(逗号分隔)
*/
private String enterCoilNos;
/**
* 当前钢卷号(逗号分隔)
*/
private String currentCoilNos;
}

View File

@@ -0,0 +1,18 @@
package com.klp.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 退火计划入炉业务对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsFurnacePlanInFurnaceBo {
@NotNull(message = "计划ID不能为空")
private Long planId;
}

View File

@@ -0,0 +1,23 @@
package com.klp.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 退火计划库位分配业务对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsFurnacePlanLocationBo {
@NotNull(message = "计划ID不能为空")
private Long planId;
@NotEmpty(message = "库位分配不能为空")
private List<WmsFurnacePlanLocationItemBo> locations;
}

View File

@@ -0,0 +1,21 @@
package com.klp.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 退火计划钢卷库位分配项
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsFurnacePlanLocationItemBo {
@NotNull(message = "钢卷ID不能为空")
private Long coilId;
@NotNull(message = "实际库位不能为空")
private Long actualWarehouseId;
}

View File

@@ -0,0 +1,21 @@
package com.klp.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 退火计划状态更新业务对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsFurnacePlanStatusBo {
@NotNull(message = "计划ID不能为空")
private Long planId;
@NotNull(message = "状态不能为空")
private Integer status;
}

View File

@@ -0,0 +1,21 @@
package com.klp.domain.bo;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 退火炉启用状态更新业务对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsFurnaceStatusBo {
@NotNull(message = "炉子ID不能为空")
private Long furnaceId;
@NotNull(message = "状态不能为空")
private Integer status;
}

View File

@@ -0,0 +1,37 @@
package com.klp.domain.vo;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 退火炉总览信息
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealFurnaceOverviewVo {
private Long furnaceId;
private String furnaceCode;
private String furnaceName;
private Integer busyFlag;
private Integer status;
/**
* 正在执行的计划
*/
private WmsFurnacePlanVo runningPlan;
/**
* 当前炉内钢卷
*/
private List<WmsFurnacePlanCoilVo> runningCoils;
/**
* 计划结束时间(用于倒计时)
*/
private Date planEndTime;
}

View File

@@ -0,0 +1,43 @@
package com.klp.domain.vo;
import lombok.Data;
/**
* 退火总览统计信息
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealOverviewStatsVo {
/**
* 当前计划数
*/
private Long planCount;
/**
* 炉子总数
*/
private Long furnaceTotal;
/**
* 炉子忙碌数
*/
private Long furnaceBusy;
/**
* 待退火钢卷数
*/
private Long pendingCoilCount;
/**
* 今日已完成计划数
*/
private Long todayFinishedPlanCount;
/**
* 今日已完成钢卷数
*/
private Long todayFinishedCoilCount;
}

View File

@@ -0,0 +1,33 @@
package com.klp.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 退火计划钢卷关系视图对象 wms_furnace_plan_coil
*
* @author klp
* @date 2026-03-14
*/
@Data
@ExcelIgnoreUnannotated
public class WmsFurnacePlanCoilVo {
@ExcelProperty(value = "计划钢卷ID")
private Long planCoilId;
@ExcelProperty(value = "计划ID")
private Long planId;
@ExcelProperty(value = "钢卷ID")
private Long coilId;
@ExcelProperty(value = "入场钢卷号")
private String enterCoilNo;
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,51 @@
package com.klp.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 退火计划视图对象 wms_furnace_plan
*
* @author klp
* @date 2026-03-14
*/
@Data
@ExcelIgnoreUnannotated
public class WmsFurnacePlanVo {
@ExcelProperty(value = "计划ID")
private Long planId;
@ExcelProperty(value = "计划号")
private String planNo;
@ExcelProperty(value = "计划开始时间")
private Date planStartTime;
@ExcelProperty(value = "实际开始时间")
private Date actualStartTime;
@ExcelProperty(value = "结束时间")
private Date endTime;
@ExcelProperty(value = "目标炉子ID")
private Long targetFurnaceId;
@ExcelProperty(value = "目标炉子名称")
private String targetFurnaceName;
@ExcelProperty(value = "计划状态")
private Integer status;
@ExcelProperty(value = "备注")
private String remark;
@ExcelProperty(value = "创建时间")
private Date createTime;
private List<Long> coilIds;
}

View File

@@ -0,0 +1,39 @@
package com.klp.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 退火炉视图对象 wms_furnace
*
* @author klp
* @date 2026-03-14
*/
@Data
@ExcelIgnoreUnannotated
public class WmsFurnaceVo {
@ExcelProperty(value = "炉子ID")
private Long furnaceId;
@ExcelProperty(value = "炉编号")
private String furnaceCode;
@ExcelProperty(value = "名称")
private String furnaceName;
@ExcelProperty(value = "是否忙碌")
private Integer busyFlag;
@ExcelProperty(value = "状态")
private Integer status;
@ExcelProperty(value = "备注")
private String remark;
@ExcelProperty(value = "创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,33 @@
package com.klp.domain.vo.anneal;
import lombok.Data;
import java.util.Date;
/**
* 退火炉状态视图对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealFurnaceStatusVo {
private Long furnaceId;
private String furnaceCode;
private String furnaceName;
private Integer busyFlag;
private Integer status;
private Long currentPlanId;
private String currentPlanNo;
private Date planEndTime;
private Long coilCount;
}

View File

@@ -0,0 +1,31 @@
package com.klp.domain.vo.anneal;
import lombok.Data;
import java.util.List;
/**
* 退火总览视图对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealOverviewVo {
private Long totalPlanCount;
private Long furnaceTotal;
private Long furnaceBusyCount;
private Long pendingCoilCount;
private Long todayDonePlanCount;
private Long todayDoneCoilCount;
private List<WmsAnnealFurnaceStatusVo> furnaces;
private List<WmsAnnealPlanQueueVo> planQueue;
}

View File

@@ -0,0 +1,36 @@
package com.klp.domain.vo.anneal;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 炉火实绩明细视图对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealPerformanceDetailVo {
private Long planId;
private String planNo;
private Long targetFurnaceId;
private String targetFurnaceName;
private Date actualStartTime;
private Date endTime;
private Long coilId;
private String enterCoilNo;
private String currentCoilNo;
private BigDecimal netWeight;
}

View File

@@ -0,0 +1,21 @@
package com.klp.domain.vo.anneal;
import lombok.Data;
import java.math.BigDecimal;
/**
* 炉火实绩统计视图对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealPerformanceSummaryVo {
private Long planCount;
private Long coilCount;
private BigDecimal totalWeight;
}

View File

@@ -0,0 +1,19 @@
package com.klp.domain.vo.anneal;
import lombok.Data;
import java.util.List;
/**
* 炉火实绩返回视图对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealPerformanceVo {
private WmsAnnealPerformanceSummaryVo summary;
private List<WmsAnnealPerformanceDetailVo> details;
}

View File

@@ -0,0 +1,33 @@
package com.klp.domain.vo.anneal;
import lombok.Data;
import java.util.Date;
/**
* 退火计划队列视图对象
*
* @author klp
* @date 2026-03-14
*/
@Data
public class WmsAnnealPlanQueueVo {
private Long planId;
private String planNo;
private Long targetFurnaceId;
private String targetFurnaceName;
private Integer status;
private Date planStartTime;
private Date actualStartTime;
private Date endTime;
private Long coilCount;
}

View File

@@ -0,0 +1,33 @@
package com.klp.mapper;
import com.klp.domain.vo.anneal.WmsAnnealFurnaceStatusVo;
import com.klp.domain.vo.anneal.WmsAnnealPlanQueueVo;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
* 退火总览Mapper接口
*
* @author klp
* @date 2026-03-14
*/
public interface WmsAnnealOverviewMapper {
Long selectTotalPlanCount();
Long selectFurnaceTotal();
Long selectFurnaceBusyCount();
Long selectPendingCoilCount();
Long selectTodayDonePlanCount(@Param("dayStart") Date dayStart, @Param("dayEnd") Date dayEnd);
Long selectTodayDoneCoilCount(@Param("dayStart") Date dayStart, @Param("dayEnd") Date dayEnd);
List<WmsAnnealFurnaceStatusVo> selectFurnaceStatusList();
List<WmsAnnealPlanQueueVo> selectPlanQueueList();
}

View File

@@ -0,0 +1,20 @@
package com.klp.mapper;
import com.klp.domain.bo.WmsAnnealPerformanceBo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceDetailVo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceSummaryVo;
import java.util.List;
/**
* 炉火实绩Mapper
*
* @author klp
* @date 2026-03-14
*/
public interface WmsAnnealPerformanceMapper {
WmsAnnealPerformanceSummaryVo selectSummary(WmsAnnealPerformanceBo bo);
List<WmsAnnealPerformanceDetailVo> selectDetails(WmsAnnealPerformanceBo bo);
}

View File

@@ -0,0 +1,14 @@
package com.klp.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.domain.WmsFurnace;
import com.klp.domain.vo.WmsFurnaceVo;
/**
* 退火炉Mapper接口
*
* @author klp
* @date 2026-03-14
*/
public interface WmsFurnaceMapper extends BaseMapperPlus<WmsFurnaceMapper, WmsFurnace, WmsFurnaceVo> {
}

View File

@@ -0,0 +1,14 @@
package com.klp.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.domain.WmsFurnacePlanCoil;
import com.klp.domain.vo.WmsFurnacePlanCoilVo;
/**
* 退火计划钢卷关系Mapper接口
*
* @author klp
* @date 2026-03-14
*/
public interface WmsFurnacePlanCoilMapper extends BaseMapperPlus<WmsFurnacePlanCoilMapper, WmsFurnacePlanCoil, WmsFurnacePlanCoilVo> {
}

View File

@@ -0,0 +1,14 @@
package com.klp.mapper;
import com.klp.common.core.mapper.BaseMapperPlus;
import com.klp.domain.WmsFurnacePlan;
import com.klp.domain.vo.WmsFurnacePlanVo;
/**
* 退火计划Mapper接口
*
* @author klp
* @date 2026-03-14
*/
public interface WmsFurnacePlanMapper extends BaseMapperPlus<WmsFurnacePlanMapper, WmsFurnacePlan, WmsFurnacePlanVo> {
}

View File

@@ -0,0 +1,14 @@
package com.klp.service;
import com.klp.domain.vo.anneal.WmsAnnealOverviewVo;
/**
* 退火总览Service接口
*
* @author klp
* @date 2026-03-14
*/
public interface IWmsAnnealOverviewService {
WmsAnnealOverviewVo queryOverview();
}

View File

@@ -0,0 +1,15 @@
package com.klp.service;
import com.klp.domain.bo.WmsAnnealPerformanceBo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceVo;
/**
* 炉火实绩Service接口
*
* @author klp
* @date 2026-03-14
*/
public interface IWmsAnnealPerformanceService {
WmsAnnealPerformanceVo queryPerformance(WmsAnnealPerformanceBo bo);
}

View File

@@ -0,0 +1,44 @@
package com.klp.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.domain.bo.WmsFurnacePlanBo;
import com.klp.domain.bo.WmsFurnacePlanCoilBo;
import com.klp.domain.vo.WmsFurnacePlanCoilVo;
import com.klp.domain.vo.WmsFurnacePlanVo;
import java.util.Collection;
import java.util.List;
/**
* 退火计划Service接口
*
* @author klp
* @date 2026-03-14
*/
public interface IWmsFurnacePlanService {
WmsFurnacePlanVo queryById(Long planId);
TableDataInfo<WmsFurnacePlanVo> queryPageList(WmsFurnacePlanBo bo, PageQuery pageQuery);
List<WmsFurnacePlanVo> queryList(WmsFurnacePlanBo bo);
Boolean insertByBo(WmsFurnacePlanBo bo);
Boolean updateByBo(WmsFurnacePlanBo bo);
Boolean updateStatus(Long planId, Integer status);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
List<WmsFurnacePlanCoilVo> queryPlanCoils(Long planId);
Boolean bindPlanCoils(WmsFurnacePlanCoilBo bo);
Boolean unbindPlanCoil(WmsFurnacePlanCoilBo bo);
Boolean inFurnace(Long planId);
Boolean completePlan(Long planId, List<com.klp.domain.bo.WmsFurnacePlanLocationItemBo> locations);
}

View File

@@ -0,0 +1,34 @@
package com.klp.service;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.domain.bo.WmsFurnaceBo;
import com.klp.domain.vo.WmsFurnaceVo;
import java.util.Collection;
import java.util.List;
/**
* 退火炉Service接口
*
* @author klp
* @date 2026-03-14
*/
public interface IWmsFurnaceService {
WmsFurnaceVo queryById(Long furnaceId);
TableDataInfo<WmsFurnaceVo> queryPageList(WmsFurnaceBo bo, PageQuery pageQuery);
List<WmsFurnaceVo> queryList(WmsFurnaceBo bo);
Boolean insertByBo(WmsFurnaceBo bo);
Boolean updateByBo(WmsFurnaceBo bo);
Boolean updateStatus(Long furnaceId, Integer status);
Boolean updateBusy(Long furnaceId, Integer busyFlag);
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,43 @@
package com.klp.service.impl;
import com.klp.domain.vo.anneal.WmsAnnealOverviewVo;
import com.klp.mapper.WmsAnnealOverviewMapper;
import com.klp.service.IWmsAnnealOverviewService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
/**
* 退火总览Service业务层处理
*
* @author klp
* @date 2026-03-14
*/
@RequiredArgsConstructor
@Service
public class WmsAnnealOverviewServiceImpl implements IWmsAnnealOverviewService {
private final WmsAnnealOverviewMapper overviewMapper;
@Override
public WmsAnnealOverviewVo queryOverview() {
WmsAnnealOverviewVo vo = new WmsAnnealOverviewVo();
vo.setTotalPlanCount(overviewMapper.selectTotalPlanCount());
vo.setFurnaceTotal(overviewMapper.selectFurnaceTotal());
vo.setFurnaceBusyCount(overviewMapper.selectFurnaceBusyCount());
vo.setPendingCoilCount(overviewMapper.selectPendingCoilCount());
LocalDate today = LocalDate.now();
Date dayStart = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
Date dayEnd = Date.from(today.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
vo.setTodayDonePlanCount(overviewMapper.selectTodayDonePlanCount(dayStart, dayEnd));
vo.setTodayDoneCoilCount(overviewMapper.selectTodayDoneCoilCount(dayStart, dayEnd));
vo.setFurnaces(overviewMapper.selectFurnaceStatusList());
vo.setPlanQueue(overviewMapper.selectPlanQueueList());
return vo;
}
}

View File

@@ -0,0 +1,35 @@
package com.klp.service.impl;
import com.klp.domain.bo.WmsAnnealPerformanceBo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceDetailVo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceSummaryVo;
import com.klp.domain.vo.anneal.WmsAnnealPerformanceVo;
import com.klp.mapper.WmsAnnealPerformanceMapper;
import com.klp.service.IWmsAnnealPerformanceService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 炉火实绩Service业务层处理
*
* @author klp
* @date 2026-03-14
*/
@RequiredArgsConstructor
@Service
public class WmsAnnealPerformanceServiceImpl implements IWmsAnnealPerformanceService {
private final WmsAnnealPerformanceMapper performanceMapper;
@Override
public WmsAnnealPerformanceVo queryPerformance(WmsAnnealPerformanceBo bo) {
WmsAnnealPerformanceSummaryVo summary = performanceMapper.selectSummary(bo);
List<WmsAnnealPerformanceDetailVo> details = performanceMapper.selectDetails(bo);
WmsAnnealPerformanceVo vo = new WmsAnnealPerformanceVo();
vo.setSummary(summary);
vo.setDetails(details);
return vo;
}
}

View File

@@ -0,0 +1,431 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.domain.WmsFurnace;
import com.klp.domain.WmsFurnacePlan;
import com.klp.domain.WmsFurnacePlanCoil;
import com.klp.domain.WmsMaterialCoil;
import com.klp.domain.WmsActualWarehouse;
import com.klp.domain.bo.WmsFurnacePlanBo;
import com.klp.domain.bo.WmsFurnacePlanCoilBo;
import com.klp.domain.vo.WmsFurnacePlanCoilVo;
import com.klp.domain.vo.WmsFurnacePlanVo;
import com.klp.mapper.WmsActualWarehouseMapper;
import com.klp.mapper.WmsFurnaceMapper;
import com.klp.mapper.WmsFurnacePlanCoilMapper;
import com.klp.mapper.WmsFurnacePlanMapper;
import com.klp.mapper.WmsMaterialCoilMapper;
import com.klp.service.IWmsFurnacePlanService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 退火计划Service业务层处理
*
* @author klp
* @date 2026-03-14
*/
@RequiredArgsConstructor
@Service
public class WmsFurnacePlanServiceImpl implements IWmsFurnacePlanService {
private final WmsFurnacePlanMapper baseMapper;
private final WmsFurnacePlanCoilMapper planCoilMapper;
private final WmsFurnaceMapper furnaceMapper;
private final WmsMaterialCoilMapper materialCoilMapper;
private final WmsActualWarehouseMapper actualWarehouseMapper;
@Override
public WmsFurnacePlanVo queryById(Long planId) {
WmsFurnacePlanVo plan = baseMapper.selectVoById(planId);
if (plan != null) {
plan.setCoilIds(queryPlanCoils(planId).stream()
.map(WmsFurnacePlanCoilVo::getCoilId)
.collect(Collectors.toList()));
fillFurnaceNames(java.util.Collections.singletonList(plan));
}
return plan;
}
@Override
public TableDataInfo<WmsFurnacePlanVo> queryPageList(WmsFurnacePlanBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsFurnacePlan> lqw = buildQueryWrapper(bo);
Page<WmsFurnacePlanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
fillFurnaceNames(result.getRecords());
return TableDataInfo.build(result);
}
@Override
public List<WmsFurnacePlanVo> queryList(WmsFurnacePlanBo bo) {
LambdaQueryWrapper<WmsFurnacePlan> lqw = buildQueryWrapper(bo);
List<WmsFurnacePlanVo> list = baseMapper.selectVoList(lqw);
fillFurnaceNames(list);
return list;
}
private LambdaQueryWrapper<WmsFurnacePlan> buildQueryWrapper(WmsFurnacePlanBo bo) {
LambdaQueryWrapper<WmsFurnacePlan> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getPlanNo()), WmsFurnacePlan::getPlanNo, bo.getPlanNo());
lqw.eq(bo.getTargetFurnaceId() != null, WmsFurnacePlan::getTargetFurnaceId, bo.getTargetFurnaceId());
lqw.eq(bo.getStatus() != null, WmsFurnacePlan::getStatus, bo.getStatus());
lqw.ge(bo.getPlanStartTime() != null, WmsFurnacePlan::getPlanStartTime, bo.getPlanStartTime());
lqw.orderByDesc(WmsFurnacePlan::getPlanStartTime);
return lqw;
}
private void fillFurnaceNames(List<WmsFurnacePlanVo> plans) {
if (plans == null || plans.isEmpty()) {
return;
}
List<Long> furnaceIds = plans.stream()
.map(WmsFurnacePlanVo::getTargetFurnaceId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
if (furnaceIds.isEmpty()) {
return;
}
List<WmsFurnace> furnaces = furnaceMapper.selectBatchIds(furnaceIds);
java.util.Map<Long, String> nameMap = furnaces.stream()
.collect(Collectors.toMap(WmsFurnace::getFurnaceId, WmsFurnace::getFurnaceName, (a, b) -> a));
plans.forEach(plan -> {
if (plan.getTargetFurnaceId() != null) {
plan.setTargetFurnaceName(nameMap.get(plan.getTargetFurnaceId()));
}
});
}
@Override
public Boolean insertByBo(WmsFurnacePlanBo bo) {
WmsFurnacePlan add = BeanUtil.toBean(bo, WmsFurnacePlan.class);
validEntityBeforeSave(add, true);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setPlanId(add.getPlanId());
}
return flag;
}
@Override
public Boolean updateByBo(WmsFurnacePlanBo bo) {
WmsFurnacePlan update = BeanUtil.toBean(bo, WmsFurnacePlan.class);
validEntityBeforeSave(update, false);
return baseMapper.updateById(update) > 0;
}
private void validEntityBeforeSave(WmsFurnacePlan entity, boolean isNew) {
LambdaQueryWrapper<WmsFurnacePlan> planNoQuery = Wrappers.lambdaQuery();
planNoQuery.eq(WmsFurnacePlan::getPlanNo, entity.getPlanNo());
if (!isNew) {
planNoQuery.ne(WmsFurnacePlan::getPlanId, entity.getPlanId());
}
if (baseMapper.selectCount(planNoQuery) > 0) {
throw new ServiceException("计划号已存在");
}
WmsFurnace furnace = furnaceMapper.selectById(entity.getTargetFurnaceId());
if (furnace == null || furnace.getDelFlag() != null && furnace.getDelFlag() == 1) {
throw new ServiceException("目标炉子不存在");
}
}
@Override
public Boolean updateStatus(Long planId, Integer status) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
update.setStatus(status);
boolean updated = baseMapper.updateById(update) > 0;
if (updated && plan.getTargetFurnaceId() != null) {
if (status != null && (status == 2)) {
updateFurnaceBusy(plan.getTargetFurnaceId(), 1);
}
if (status != null && (status == 3 || status == 4)) {
updateFurnaceBusy(plan.getTargetFurnaceId(), 0);
}
}
return updated;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid && ids != null && !ids.isEmpty()) {
for (Long planId : ids) {
if (planCoilMapper.selectCount(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId)) > 0) {
throw new ServiceException("计划下存在钢卷,请先解绑");
}
}
}
return baseMapper.deleteBatchIds(ids) > 0;
}
@Override
public List<WmsFurnacePlanCoilVo> queryPlanCoils(Long planId) {
List<WmsFurnacePlanCoilVo> list = planCoilMapper.selectVoList(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId));
if (list == null || list.isEmpty()) {
return list;
}
List<Long> coilIds = list.stream()
.map(WmsFurnacePlanCoilVo::getCoilId)
.filter(id -> id != null)
.distinct()
.collect(Collectors.toList());
if (coilIds.isEmpty()) {
return list;
}
java.util.Map<Long, String> enterNoMap = materialCoilMapper.selectBatchIds(coilIds).stream()
.collect(Collectors.toMap(WmsMaterialCoil::getCoilId, WmsMaterialCoil::getEnterCoilNo, (a, b) -> a));
list.forEach(item -> item.setEnterCoilNo(enterNoMap.get(item.getCoilId())));
return list;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean bindPlanCoils(WmsFurnacePlanCoilBo bo) {
if (bo.getPlanId() == null) {
throw new ServiceException("计划ID不能为空");
}
List<Long> coilIds = parseCoilIds(bo);
if (coilIds.isEmpty()) {
throw new ServiceException("请至少选择一条钢卷");
}
WmsFurnacePlan plan = ensurePlanExist(bo.getPlanId());
if (plan.getStatus() != null && plan.getStatus() == 2) {
throw new ServiceException("计划进行中,无法再领料");
}
for (Long coilId : coilIds) {
if (planCoilMapper.selectCount(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, bo.getPlanId())
.eq(WmsFurnacePlanCoil::getCoilId, coilId)) > 0) {
continue;
}
WmsFurnacePlanCoil entity = new WmsFurnacePlanCoil();
entity.setPlanId(bo.getPlanId());
entity.setCoilId(coilId);
planCoilMapper.insert(entity);
}
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean unbindPlanCoil(WmsFurnacePlanCoilBo bo) {
if (bo.getPlanId() == null || bo.getCoilId() == null) {
throw new ServiceException("计划ID和钢卷ID不能为空");
}
return planCoilMapper.delete(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, bo.getPlanId())
.eq(WmsFurnacePlanCoil::getCoilId, bo.getCoilId())) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean inFurnace(Long planId) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
if (plan.getActualStartTime() != null) {
throw new ServiceException("计划已入炉");
}
if (planCoilMapper.selectCount(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId)) <= 0) {
throw new ServiceException("计划未绑定钢卷");
}
Date now = new Date();
Date endTime = new Date(now.getTime() + 48L * 60 * 60 * 1000);
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
update.setActualStartTime(now);
update.setEndTime(endTime);
update.setStatus(2);
baseMapper.updateById(update);
updateFurnaceBusy(plan.getTargetFurnaceId(), 1);
List<WmsFurnacePlanCoilVo> coils = queryPlanCoils(planId);
for (WmsFurnacePlanCoilVo coil : coils) {
releaseActualWarehouse(coil.getCoilId());
}
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean completePlan(Long planId, List<com.klp.domain.bo.WmsFurnacePlanLocationItemBo> locations) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
if (plan.getStatus() == null || plan.getStatus() != 2) {
throw new ServiceException("计划未进行中,无法完成");
}
List<WmsFurnacePlanCoilVo> coils = queryPlanCoils(planId);
if (coils == null || coils.isEmpty()) {
throw new ServiceException("计划未绑定钢卷");
}
if (locations == null || locations.isEmpty()) {
throw new ServiceException("请先分配实际库位");
}
java.util.Map<Long, Long> locationMap = locations.stream()
.collect(Collectors.toMap(com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getCoilId,
com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getActualWarehouseId, (a, b) -> a));
for (WmsFurnacePlanCoilVo coil : coils) {
Long targetLocation = locationMap.get(coil.getCoilId());
if (targetLocation == null) {
throw new ServiceException("钢卷" + coil.getEnterCoilNo() + "未分配库位");
}
occupyActualWarehouse(coil.getCoilId(), targetLocation);
}
Date now = new Date();
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
update.setStatus(3);
update.setEndTime(now);
baseMapper.updateById(update);
updateFurnaceBusy(plan.getTargetFurnaceId(), 0);
return true;
}
private void releaseActualWarehouse(Long coilId) {
WmsMaterialCoil coil = materialCoilMapper.selectById(coilId);
if (coil == null) {
return;
}
Long actualWarehouseId = coil.getActualWarehouseId();
if (actualWarehouseId != null) {
WmsActualWarehouse warehouse = new WmsActualWarehouse();
warehouse.setActualWarehouseId(actualWarehouseId);
warehouse.setIsEnabled(1);
actualWarehouseMapper.updateById(warehouse);
}
WmsMaterialCoil updateCoil = new WmsMaterialCoil();
updateCoil.setCoilId(coilId);
updateCoil.setActualWarehouseId(null);
materialCoilMapper.updateById(updateCoil);
}
private void occupyActualWarehouse(Long coilId, Long actualWarehouseId) {
if (actualWarehouseId == null) {
throw new ServiceException("实际库位不能为空");
}
WmsActualWarehouse warehouse = actualWarehouseMapper.selectById(actualWarehouseId);
if (warehouse == null || warehouse.getDelFlag() != null && warehouse.getDelFlag() == 1) {
throw new ServiceException("实际库位不存在");
}
if (warehouse.getIsEnabled() != null && warehouse.getIsEnabled() == 0) {
throw new ServiceException("实际库位已被占用");
}
WmsActualWarehouse updateWarehouse = new WmsActualWarehouse();
updateWarehouse.setActualWarehouseId(actualWarehouseId);
updateWarehouse.setIsEnabled(0);
actualWarehouseMapper.updateById(updateWarehouse);
WmsMaterialCoil updateCoil = new WmsMaterialCoil();
updateCoil.setCoilId(coilId);
updateCoil.setActualWarehouseId(actualWarehouseId);
materialCoilMapper.updateById(updateCoil);
}
private List<Long> parseCoilIds(WmsFurnacePlanCoilBo bo) {
List<Long> coilIds = new ArrayList<>();
if (bo.getCoilId() != null) {
coilIds.add(bo.getCoilId());
}
if (StringUtils.isNotBlank(bo.getCoilIds())) {
String[] parts = bo.getCoilIds().split(",");
for (String part : parts) {
if (StringUtils.isNotBlank(part)) {
coilIds.add(Long.parseLong(part.trim()));
}
}
}
if (StringUtils.isNotBlank(bo.getEnterCoilNos())) {
coilIds.addAll(resolveCoilIdsByEnterNos(bo.getEnterCoilNos()));
}
if (StringUtils.isNotBlank(bo.getCurrentCoilNos())) {
coilIds.addAll(resolveCoilIdsByCurrentNos(bo.getCurrentCoilNos()));
}
return coilIds.stream().distinct().collect(Collectors.toList());
}
private List<Long> resolveCoilIdsByEnterNos(String enterCoilNos) {
List<String> nos = splitCommaValues(enterCoilNos);
if (nos.isEmpty()) {
return new ArrayList<>();
}
return materialCoilMapper.selectList(Wrappers.<WmsMaterialCoil>lambdaQuery()
.in(WmsMaterialCoil::getEnterCoilNo, nos)
.eq(WmsMaterialCoil::getDelFlag, 0))
.stream()
.map(WmsMaterialCoil::getCoilId)
.collect(Collectors.toList());
}
private List<Long> resolveCoilIdsByCurrentNos(String currentCoilNos) {
List<String> nos = splitCommaValues(currentCoilNos);
if (nos.isEmpty()) {
return new ArrayList<>();
}
return materialCoilMapper.selectList(Wrappers.<WmsMaterialCoil>lambdaQuery()
.in(WmsMaterialCoil::getCurrentCoilNo, nos)
.eq(WmsMaterialCoil::getDelFlag, 0))
.stream()
.map(WmsMaterialCoil::getCoilId)
.collect(Collectors.toList());
}
private List<String> splitCommaValues(String values) {
List<String> result = new ArrayList<>();
if (StringUtils.isBlank(values)) {
return result;
}
String[] parts = values.split(",");
for (String part : parts) {
if (StringUtils.isNotBlank(part)) {
result.add(part.trim());
}
}
return result;
}
private WmsFurnacePlan ensurePlanExist(Long planId) {
WmsFurnacePlan plan = baseMapper.selectById(planId);
if (plan == null) {
throw new ServiceException("计划不存在");
}
return plan;
}
private void updateFurnaceBusy(Long furnaceId, Integer busyFlag) {
if (furnaceId == null) {
return;
}
WmsFurnace update = new WmsFurnace();
update.setFurnaceId(furnaceId);
update.setBusyFlag(busyFlag);
furnaceMapper.updateById(update);
}
}

View File

@@ -0,0 +1,114 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.exception.ServiceException;
import com.klp.common.utils.StringUtils;
import com.klp.domain.WmsFurnace;
import com.klp.domain.bo.WmsFurnaceBo;
import com.klp.domain.vo.WmsFurnaceVo;
import com.klp.mapper.WmsFurnaceMapper;
import com.klp.service.IWmsFurnaceService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
/**
* 退火炉Service业务层处理
*
* @author klp
* @date 2026-03-14
*/
@RequiredArgsConstructor
@Service
public class WmsFurnaceServiceImpl implements IWmsFurnaceService {
private final WmsFurnaceMapper baseMapper;
@Override
public WmsFurnaceVo queryById(Long furnaceId) {
return baseMapper.selectVoById(furnaceId);
}
@Override
public TableDataInfo<WmsFurnaceVo> queryPageList(WmsFurnaceBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsFurnace> lqw = buildQueryWrapper(bo);
Page<WmsFurnaceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public List<WmsFurnaceVo> queryList(WmsFurnaceBo bo) {
LambdaQueryWrapper<WmsFurnace> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsFurnace> buildQueryWrapper(WmsFurnaceBo bo) {
LambdaQueryWrapper<WmsFurnace> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getFurnaceCode()), WmsFurnace::getFurnaceCode, bo.getFurnaceCode());
lqw.like(StringUtils.isNotBlank(bo.getFurnaceName()), WmsFurnace::getFurnaceName, bo.getFurnaceName());
lqw.eq(bo.getStatus() != null, WmsFurnace::getStatus, bo.getStatus());
lqw.eq(bo.getBusyFlag() != null, WmsFurnace::getBusyFlag, bo.getBusyFlag());
lqw.orderByAsc(WmsFurnace::getFurnaceCode);
return lqw;
}
@Override
public Boolean insertByBo(WmsFurnaceBo bo) {
WmsFurnace add = BeanUtil.toBean(bo, WmsFurnace.class);
validEntityBeforeSave(add, true);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setFurnaceId(add.getFurnaceId());
}
return flag;
}
@Override
public Boolean updateByBo(WmsFurnaceBo bo) {
WmsFurnace update = BeanUtil.toBean(bo, WmsFurnace.class);
validEntityBeforeSave(update, false);
return baseMapper.updateById(update) > 0;
}
private void validEntityBeforeSave(WmsFurnace entity, boolean isNew) {
LambdaQueryWrapper<WmsFurnace> lqw = Wrappers.lambdaQuery();
lqw.eq(WmsFurnace::getFurnaceCode, entity.getFurnaceCode());
if (!isNew) {
lqw.ne(WmsFurnace::getFurnaceId, entity.getFurnaceId());
}
if (baseMapper.selectCount(lqw) > 0) {
throw new ServiceException("炉编号已存在");
}
}
@Override
public Boolean updateStatus(Long furnaceId, Integer status) {
WmsFurnace update = new WmsFurnace();
update.setFurnaceId(furnaceId);
update.setStatus(status);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean updateBusy(Long furnaceId, Integer busyFlag) {
WmsFurnace update = new WmsFurnace();
update.setFurnaceId(furnaceId);
update.setBusyFlag(busyFlag);
return baseMapper.updateById(update) > 0;
}
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid && ids != null && !ids.isEmpty()) {
// 暂无额外校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}