小改
This commit is contained in:
@@ -0,0 +1,126 @@
|
|||||||
|
package com.klp.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import com.klp.common.annotation.RepeatSubmit;
|
||||||
|
import com.klp.common.annotation.Log;
|
||||||
|
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.validate.AddGroup;
|
||||||
|
import com.klp.common.core.validate.EditGroup;
|
||||||
|
import com.klp.common.enums.BusinessType;
|
||||||
|
import com.klp.common.utils.poi.ExcelUtil;
|
||||||
|
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||||
|
import com.klp.domain.bo.WmsMaterialCoilBo;
|
||||||
|
import com.klp.service.IWmsMaterialCoilService;
|
||||||
|
import com.klp.common.core.page.TableDataInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/wms/materialCoil")
|
||||||
|
public class WmsMaterialCoilController extends BaseController {
|
||||||
|
|
||||||
|
private final IWmsMaterialCoilService iWmsMaterialCoilService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<WmsMaterialCoilVo> list(WmsMaterialCoilBo bo, PageQuery pageQuery) {
|
||||||
|
return iWmsMaterialCoilService.queryPageList(bo, pageQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出钢卷物料表列表
|
||||||
|
*/
|
||||||
|
@Log(title = "钢卷物料表", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export")
|
||||||
|
public void export(WmsMaterialCoilBo bo, HttpServletResponse response) {
|
||||||
|
List<WmsMaterialCoilVo> list = iWmsMaterialCoilService.queryList(bo);
|
||||||
|
ExcelUtil.exportExcel(list, "钢卷物料表", WmsMaterialCoilVo.class, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取钢卷物料表详细信息
|
||||||
|
*
|
||||||
|
* @param coilId 主键
|
||||||
|
*/
|
||||||
|
@GetMapping("/{coilId}")
|
||||||
|
public R<WmsMaterialCoilVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable Long coilId) {
|
||||||
|
return R.ok(iWmsMaterialCoilService.queryById(coilId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增钢卷物料表
|
||||||
|
*/
|
||||||
|
@Log(title = "钢卷物料表", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsMaterialCoilBo bo) {
|
||||||
|
return toAjax(iWmsMaterialCoilService.insertByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改钢卷物料表
|
||||||
|
*/
|
||||||
|
@Log(title = "钢卷物料表", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping()
|
||||||
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsMaterialCoilBo bo) {
|
||||||
|
return toAjax(iWmsMaterialCoilService.updateByBo(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单更新钢卷物料表
|
||||||
|
* 直接更新属性内容,不进行历史记录处理
|
||||||
|
*/
|
||||||
|
@Log(title = "钢卷物料表", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping("/update")
|
||||||
|
public R<Void> update(@Validated(EditGroup.class) @RequestBody WmsMaterialCoilBo bo) {
|
||||||
|
return toAjax(iWmsMaterialCoilService.updateSimple(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除钢卷物料表
|
||||||
|
*
|
||||||
|
* @param coilIds 主键串
|
||||||
|
*/
|
||||||
|
@Log(title = "钢卷物料表", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{coilIds}")
|
||||||
|
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
|
@PathVariable Long[] coilIds) {
|
||||||
|
return toAjax(iWmsMaterialCoilService.deleteWithValidByIds(Arrays.asList(coilIds), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷溯源查询
|
||||||
|
* 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
||||||
|
*
|
||||||
|
* @param enterCoilNo 入场钢卷号
|
||||||
|
* @param currentCoilNo 当前钢卷号(可选参数,用于查询特定子钢卷)
|
||||||
|
*/
|
||||||
|
@GetMapping("/trace")
|
||||||
|
public R<Map<String, Object>> trace(@RequestParam @NotBlank(message = "入场钢卷号不能为空") String enterCoilNo,
|
||||||
|
@RequestParam(required = false) String currentCoilNo) {
|
||||||
|
Map<String, Object> traceResult = iWmsMaterialCoilService.queryTrace(enterCoilNo, currentCoilNo);
|
||||||
|
return R.ok(traceResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@ import java.util.Arrays;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.validation.constraints.*;
|
import javax.validation.constraints.*;
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import com.klp.common.annotation.RepeatSubmit;
|
import com.klp.common.annotation.RepeatSubmit;
|
||||||
@@ -109,4 +108,15 @@ public class WmsStockController extends BaseController {
|
|||||||
return R.ok("查询到 " + list.size() + " 条库存记录,仓库ID: " + warehouseId);
|
return R.ok("查询到 " + list.size() + " 条库存记录,仓库ID: " + warehouseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询库存分布(按仓库统计)
|
||||||
|
*
|
||||||
|
* @param bo 查询参数(itemType和itemId必填)
|
||||||
|
*/
|
||||||
|
@GetMapping("/distribution")
|
||||||
|
public R<WmsStockVo> distribution(WmsStockBo bo) {
|
||||||
|
WmsStockVo result = iWmsStockService.queryStockDistribution(bo);
|
||||||
|
return R.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
91
klp-wms/src/main/java/com/klp/domain/WmsMaterialCoil.java
Normal file
91
klp-wms/src/main/java/com/klp/domain/WmsMaterialCoil.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package com.klp.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.klp.common.core.domain.BaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表对象 wms_material_coil
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@TableName("wms_material_coil")
|
||||||
|
public class WmsMaterialCoil extends BaseEntity {
|
||||||
|
|
||||||
|
private static final long serialVersionUID=1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "coil_id")
|
||||||
|
private Long coilId;
|
||||||
|
/**
|
||||||
|
* 入场钢卷号(年份后两位+月份+当月第几个,如25100001、25102422)
|
||||||
|
*/
|
||||||
|
private String enterCoilNo;
|
||||||
|
/**
|
||||||
|
* 当前钢卷号(入场钢卷号和当前钢卷号可能不同)
|
||||||
|
*/
|
||||||
|
private String currentCoilNo;
|
||||||
|
/**
|
||||||
|
* 厂家原料卷号
|
||||||
|
*/
|
||||||
|
private String supplierCoilNo;
|
||||||
|
/**
|
||||||
|
* 数据类型(0=历史,1=现存)
|
||||||
|
*/
|
||||||
|
private Integer dataType;
|
||||||
|
/**
|
||||||
|
* 所在库区ID
|
||||||
|
*/
|
||||||
|
private Long warehouseId;
|
||||||
|
/**
|
||||||
|
* 下一库区ID
|
||||||
|
*/
|
||||||
|
private Long nextWarehouseId;
|
||||||
|
/**
|
||||||
|
* 关联二维码ID(wms_generate_record.record_id)
|
||||||
|
*/
|
||||||
|
private Long qrcodeRecordId;
|
||||||
|
/**
|
||||||
|
* 班组
|
||||||
|
*/
|
||||||
|
private String team;
|
||||||
|
/**
|
||||||
|
* 是否合卷/分卷(0=否,1=分卷,2=合卷)
|
||||||
|
*/
|
||||||
|
private Integer hasMergeSplit;
|
||||||
|
/**
|
||||||
|
* 父卷号(合卷或分卷时用,逗号分隔)
|
||||||
|
*/
|
||||||
|
private String parentCoilNos;
|
||||||
|
/**
|
||||||
|
* 物品类型(raw_material/product)
|
||||||
|
*/
|
||||||
|
private String itemType;
|
||||||
|
/**
|
||||||
|
* 物品ID(指向原材料或产品主键)
|
||||||
|
*/
|
||||||
|
private Long itemId;
|
||||||
|
/**
|
||||||
|
* 状态(0=在库,1=在途,2=已出库)
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
/**
|
||||||
|
* 删除标志(0=正常,1=已删除)
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private Integer delFlag;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,10 +5,8 @@ import com.klp.common.core.domain.BaseEntity;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 库存:原材料/产品与库区/库位的存放关系对象 wms_stock
|
* 库存表:原材料-钢卷-库区的存放关系对象 wms_stock
|
||||||
*
|
*
|
||||||
* @author Joshi
|
* @author Joshi
|
||||||
* @date 2025-07-18
|
* @date 2025-07-18
|
||||||
@@ -38,13 +36,9 @@ public class WmsStock extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
private Long itemId;
|
private Long itemId;
|
||||||
/**
|
/**
|
||||||
* 库存数量
|
* 钢卷ID(指向wms_material_coil.coil_id)
|
||||||
*/
|
*/
|
||||||
private BigDecimal quantity;
|
private Long coilId;
|
||||||
/**
|
|
||||||
* 单位
|
|
||||||
*/
|
|
||||||
private String unit;
|
|
||||||
/**
|
/**
|
||||||
* 批次号(可选)
|
* 批次号(可选)
|
||||||
*/
|
*/
|
||||||
|
|||||||
103
klp-wms/src/main/java/com/klp/domain/bo/WmsMaterialCoilBo.java
Normal file
103
klp-wms/src/main/java/com/klp/domain/bo/WmsMaterialCoilBo.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package com.klp.domain.bo;
|
||||||
|
|
||||||
|
import com.klp.common.core.domain.BaseEntity;
|
||||||
|
import com.klp.common.core.validate.AddGroup;
|
||||||
|
import com.klp.common.core.validate.EditGroup;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表业务对象 wms_material_coil
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class WmsMaterialCoilBo extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
private Long coilId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入场钢卷号(年份后两位+月份+当月第几个,如25100001、25102422)
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "入场钢卷号不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String enterCoilNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前钢卷号(入场钢卷号和当前钢卷号可能不同)
|
||||||
|
*/
|
||||||
|
private String currentCoilNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 厂家原料卷号
|
||||||
|
*/
|
||||||
|
private String supplierCoilNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据类型(0=历史,1=现存)
|
||||||
|
*/
|
||||||
|
private Integer dataType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所在库区ID
|
||||||
|
*/
|
||||||
|
private Long warehouseId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一库区ID
|
||||||
|
*/
|
||||||
|
private Long nextWarehouseId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联二维码ID(wms_generate_record.record_id)
|
||||||
|
*/
|
||||||
|
private Long qrcodeRecordId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班组
|
||||||
|
*/
|
||||||
|
private String team;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否合卷/分卷(0=否,1=分卷,2=合卷)
|
||||||
|
*/
|
||||||
|
private Integer hasMergeSplit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父卷号(合卷或分卷时用,逗号分隔)
|
||||||
|
*/
|
||||||
|
private String parentCoilNos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品类型(raw_material/product)
|
||||||
|
*/
|
||||||
|
private String itemType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品ID(指向原材料或产品主键)
|
||||||
|
*/
|
||||||
|
private Long itemId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态(0=在库,1=在途,2=已出库)
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分卷/合卷的新钢卷列表(用于批量更新)
|
||||||
|
*/
|
||||||
|
private List<WmsMaterialCoilBo> newCoils;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ public class WmsStockBo extends BaseEntity {
|
|||||||
private Long warehouseId;
|
private Long warehouseId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 物品类型(raw_material/product)
|
* 原材料ID(指向wms_raw_material.raw_material_id)
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "物品类型(raw_material/product)不能为空", groups = { AddGroup.class, EditGroup.class })
|
@NotBlank(message = "物品类型(raw_material/product)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
private String itemType;
|
private String itemType;
|
||||||
@@ -42,23 +42,9 @@ public class WmsStockBo extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
@NotNull(message = "物品ID(指向原材料或产品主键)不能为空", groups = { AddGroup.class, EditGroup.class })
|
@NotNull(message = "物品ID(指向原材料或产品主键)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
private Long itemId;
|
private Long itemId;
|
||||||
|
|
||||||
/**
|
|
||||||
* 库存数量
|
|
||||||
*/
|
|
||||||
@NotNull(message = "库存数量不能为空", groups = { AddGroup.class, EditGroup.class })
|
|
||||||
private BigDecimal quantity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单位
|
|
||||||
*/
|
|
||||||
@NotBlank(message = "单位不能为空", groups = { AddGroup.class, EditGroup.class })
|
|
||||||
private String unit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批次号(可选)
|
* 批次号(可选)
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "批次号(可选)不能为空", groups = { AddGroup.class, EditGroup.class })
|
|
||||||
private String batchNo;
|
private String batchNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
144
klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilVo.java
Normal file
144
klp-wms/src/main/java/com/klp/domain/vo/WmsMaterialCoilVo.java
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
package com.klp.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.klp.common.annotation.ExcelDictFormat;
|
||||||
|
import com.klp.common.convert.ExcelDictConvert;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表视图对象 wms_material_coil
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class WmsMaterialCoilVo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "主键ID")
|
||||||
|
private Long coilId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入场钢卷号
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "入场钢卷号")
|
||||||
|
private String enterCoilNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前钢卷号
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "当前钢卷号")
|
||||||
|
private String currentCoilNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 厂家原料卷号
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "厂家原料卷号")
|
||||||
|
private String supplierCoilNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据类型(0=历史,1=现存)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "数据类型", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(readConverterExp = "0=历史,1=现存")
|
||||||
|
private Integer dataType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所在库区ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "所在库区ID")
|
||||||
|
private Long warehouseId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一库区ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "下一库区ID")
|
||||||
|
private Long nextWarehouseId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联二维码ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "关联二维码ID")
|
||||||
|
private Long qrcodeRecordId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班组
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "班组")
|
||||||
|
private String team;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否合卷/分卷
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "是否合卷/分卷", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(readConverterExp = "0=否,1=分卷,2=合卷")
|
||||||
|
private Integer hasMergeSplit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父卷号
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "父卷号")
|
||||||
|
private String parentCoilNos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品类型
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "物品类型")
|
||||||
|
private String itemType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "物品ID")
|
||||||
|
private Long itemId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(readConverterExp = "0=在库,1=在途,2=已出库")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
// ========== 关联对象属性 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所在库区信息
|
||||||
|
*/
|
||||||
|
private WmsWarehouseVo warehouse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下一库区信息
|
||||||
|
*/
|
||||||
|
private WmsWarehouseVo nextWarehouse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二维码信息
|
||||||
|
*/
|
||||||
|
private WmsGenerateRecordVo qrcodeRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原材料信息(当itemType为raw_material时)
|
||||||
|
*/
|
||||||
|
private WmsRawMaterialVo rawMaterial;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品信息(当itemType为product时)
|
||||||
|
*/
|
||||||
|
private Object product; // 产品VO待定义
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,6 @@ public class WmsStockVo {
|
|||||||
/**
|
/**
|
||||||
* 仓库/库区/库位ID
|
* 仓库/库区/库位ID
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "仓库/库区/库位ID")
|
|
||||||
private Long warehouseId;
|
private Long warehouseId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,23 +54,11 @@ public class WmsStockVo {
|
|||||||
*/
|
*/
|
||||||
private String itemCode;
|
private String itemCode;
|
||||||
|
|
||||||
/**
|
|
||||||
* 库存数量
|
|
||||||
*/
|
|
||||||
@ExcelProperty(value = "库存数量")
|
|
||||||
private BigDecimal quantity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 单位
|
|
||||||
*/
|
|
||||||
@ExcelProperty(value = "单位")
|
|
||||||
private String unit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批次号(可选)
|
* 批次号(可选)
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "批次号", converter = ExcelDictConvert.class)
|
@ExcelProperty(value = "批次号", converter = ExcelDictConvert.class)
|
||||||
@ExcelDictFormat(readConverterExp = "可=选")
|
@ExcelDictFormat(readConverterExp = "可选")
|
||||||
private String batchNo;
|
private String batchNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,4 +79,15 @@ public class WmsStockVo {
|
|||||||
@ExcelProperty(value = "在途量")
|
@ExcelProperty(value = "在途量")
|
||||||
private BigDecimal onTheWay;
|
private BigDecimal onTheWay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总量(通过item_type和item_id查询对应的钢卷总量)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "总量")
|
||||||
|
private BigDecimal totalQuantity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 库存分布列表(按仓库统计)
|
||||||
|
*/
|
||||||
|
private java.util.List<WmsStockVo> stockDistribution;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.klp.mapper;
|
||||||
|
|
||||||
|
import com.klp.domain.WmsMaterialCoil;
|
||||||
|
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||||
|
import com.klp.common.core.mapper.BaseMapperPlus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表Mapper接口
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
public interface WmsMaterialCoilMapper extends BaseMapperPlus<WmsMaterialCoilMapper, WmsMaterialCoil, WmsMaterialCoilVo> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -29,4 +29,9 @@ public interface WmsStockMapper extends BaseMapperPlus<WmsStockMapper, WmsStock,
|
|||||||
*/
|
*/
|
||||||
Page<WmsStockVo> selectVoPagePlus(Page<?> page, @Param("ew") Wrapper<WmsStock> wrapper);
|
Page<WmsStockVo> selectVoPagePlus(Page<?> page, @Param("ew") Wrapper<WmsStock> wrapper);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按仓库统计库存分布
|
||||||
|
*/
|
||||||
|
List<WmsStockVo> selectStockDistribution(@Param("itemType") String itemType, @Param("itemId") Long itemId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.klp.service;
|
||||||
|
|
||||||
|
import com.klp.domain.WmsMaterialCoil;
|
||||||
|
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||||
|
import com.klp.domain.bo.WmsMaterialCoilBo;
|
||||||
|
import com.klp.common.core.page.TableDataInfo;
|
||||||
|
import com.klp.common.core.domain.PageQuery;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表Service接口
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
public interface IWmsMaterialCoilService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表
|
||||||
|
*/
|
||||||
|
WmsMaterialCoilVo queryById(Long coilId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表列表
|
||||||
|
*/
|
||||||
|
TableDataInfo<WmsMaterialCoilVo> queryPageList(WmsMaterialCoilBo bo, PageQuery pageQuery);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表列表
|
||||||
|
*/
|
||||||
|
List<WmsMaterialCoilVo> queryList(WmsMaterialCoilBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增钢卷物料表
|
||||||
|
*/
|
||||||
|
Boolean insertByBo(WmsMaterialCoilBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改钢卷物料表
|
||||||
|
* 如果newCoils不为空,则进行批量更新(分卷/合卷)
|
||||||
|
* 如果newCoils为空,则进行单个更新
|
||||||
|
*/
|
||||||
|
Boolean updateByBo(WmsMaterialCoilBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单更新钢卷物料表
|
||||||
|
* 直接更新属性内容,不进行历史记录处理
|
||||||
|
*/
|
||||||
|
Boolean updateSimple(WmsMaterialCoilBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验并批量删除钢卷物料表信息
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷溯源查询
|
||||||
|
* 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
||||||
|
*
|
||||||
|
* @param enterCoilNo 入场钢卷号
|
||||||
|
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
|
||||||
|
* @return 溯源结果(包含二维码信息和数据库记录)
|
||||||
|
*/
|
||||||
|
Map<String, Object> queryTrace(String enterCoilNo, String currentCoilNo);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -53,5 +53,9 @@ public interface IWmsStockService {
|
|||||||
*/
|
*/
|
||||||
BigDecimal getStockByItemId(Long rawMaterialId);
|
BigDecimal getStockByItemId(Long rawMaterialId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询库存分布(按仓库统计)
|
||||||
|
*/
|
||||||
|
WmsStockVo queryStockDistribution(WmsStockBo bo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,732 @@
|
|||||||
|
package com.klp.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.klp.common.core.page.TableDataInfo;
|
||||||
|
import com.klp.common.core.domain.PageQuery;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.klp.common.utils.StringUtils;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import com.klp.domain.bo.WmsMaterialCoilBo;
|
||||||
|
import com.klp.domain.bo.WmsGenerateRecordBo;
|
||||||
|
import com.klp.domain.vo.WmsMaterialCoilVo;
|
||||||
|
import com.klp.domain.vo.WmsGenerateRecordVo;
|
||||||
|
import com.klp.domain.vo.WmsWarehouseVo;
|
||||||
|
import com.klp.domain.vo.WmsRawMaterialVo;
|
||||||
|
import com.klp.domain.WmsMaterialCoil;
|
||||||
|
import com.klp.domain.WmsStock;
|
||||||
|
import com.klp.domain.bo.WmsStockBo;
|
||||||
|
import com.klp.domain.vo.WmsStockVo;
|
||||||
|
import com.klp.mapper.WmsMaterialCoilMapper;
|
||||||
|
import com.klp.mapper.WmsStockMapper;
|
||||||
|
import com.klp.service.IWmsMaterialCoilService;
|
||||||
|
import com.klp.service.IWmsStockService;
|
||||||
|
import com.klp.service.IWmsGenerateRecordService;
|
||||||
|
import com.klp.service.IWmsWarehouseService;
|
||||||
|
import com.klp.service.IWmsRawMaterialService;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷物料表Service业务层处理
|
||||||
|
*
|
||||||
|
* @author Joshi
|
||||||
|
* @date 2025-07-18
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Service
|
||||||
|
public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
|
||||||
|
|
||||||
|
private final WmsMaterialCoilMapper baseMapper;
|
||||||
|
private final WmsStockMapper stockMapper;
|
||||||
|
private final IWmsStockService stockService;
|
||||||
|
private final IWmsGenerateRecordService generateRecordService;
|
||||||
|
private final IWmsWarehouseService warehouseService;
|
||||||
|
private final IWmsRawMaterialService rawMaterialService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public WmsMaterialCoilVo queryById(Long coilId){
|
||||||
|
WmsMaterialCoilVo vo = baseMapper.selectVoById(coilId);
|
||||||
|
if (vo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询关联对象
|
||||||
|
fillRelatedObjects(vo);
|
||||||
|
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 填充关联对象信息
|
||||||
|
*/
|
||||||
|
private void fillRelatedObjects(WmsMaterialCoilVo vo) {
|
||||||
|
// 查询所在库区信息
|
||||||
|
if (vo.getWarehouseId() != null) {
|
||||||
|
WmsWarehouseVo warehouse = warehouseService.queryById(vo.getWarehouseId());
|
||||||
|
vo.setWarehouse(warehouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询下一库区信息
|
||||||
|
if (vo.getNextWarehouseId() != null) {
|
||||||
|
WmsWarehouseVo nextWarehouse = warehouseService.queryById(vo.getNextWarehouseId());
|
||||||
|
vo.setNextWarehouse(nextWarehouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询二维码信息
|
||||||
|
if (vo.getQrcodeRecordId() != null) {
|
||||||
|
WmsGenerateRecordVo qrcodeRecord = generateRecordService.queryById(vo.getQrcodeRecordId());
|
||||||
|
vo.setQrcodeRecord(qrcodeRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询原材料信息(当itemType为raw_material时)
|
||||||
|
if ("raw_material".equals(vo.getItemType()) && vo.getItemId() != null) {
|
||||||
|
WmsRawMaterialVo rawMaterial = rawMaterialService.queryById(vo.getItemId());
|
||||||
|
vo.setRawMaterial(rawMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询产品信息(当itemType为product时)
|
||||||
|
// TODO: 当产品VO定义后,添加产品查询逻辑
|
||||||
|
if ("product".equals(vo.getItemType()) && vo.getItemId() != null) {
|
||||||
|
// 产品查询逻辑待实现
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<WmsMaterialCoilVo> queryPageList(WmsMaterialCoilBo bo, PageQuery pageQuery) {
|
||||||
|
LambdaQueryWrapper<WmsMaterialCoil> lqw = buildQueryWrapper(bo);
|
||||||
|
Page<WmsMaterialCoilVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||||
|
return TableDataInfo.build(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询钢卷物料表列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<WmsMaterialCoilVo> queryList(WmsMaterialCoilBo bo) {
|
||||||
|
LambdaQueryWrapper<WmsMaterialCoil> lqw = buildQueryWrapper(bo);
|
||||||
|
return baseMapper.selectVoList(lqw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<WmsMaterialCoil> buildQueryWrapper(WmsMaterialCoilBo bo) {
|
||||||
|
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getEnterCoilNo()), WmsMaterialCoil::getEnterCoilNo, bo.getEnterCoilNo());
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getCurrentCoilNo()), WmsMaterialCoil::getCurrentCoilNo, bo.getCurrentCoilNo());
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getSupplierCoilNo()), WmsMaterialCoil::getSupplierCoilNo, bo.getSupplierCoilNo());
|
||||||
|
lqw.eq(bo.getDataType() != null, WmsMaterialCoil::getDataType, bo.getDataType());
|
||||||
|
lqw.eq(bo.getWarehouseId() != null, WmsMaterialCoil::getWarehouseId, bo.getWarehouseId());
|
||||||
|
lqw.eq(bo.getHasMergeSplit() != null, WmsMaterialCoil::getHasMergeSplit, bo.getHasMergeSplit());
|
||||||
|
lqw.eq(bo.getStatus() != null, WmsMaterialCoil::getStatus, bo.getStatus());
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增钢卷物料表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean insertByBo(WmsMaterialCoilBo bo) {
|
||||||
|
// 1. 生成二维码
|
||||||
|
Long qrcodeRecordId = generateQrcodeForInsert(bo);
|
||||||
|
bo.setQrcodeRecordId(qrcodeRecordId);
|
||||||
|
|
||||||
|
// 2. 如果warehouseId为空,查找或创建stock
|
||||||
|
if (bo.getWarehouseId() == null) {
|
||||||
|
Long warehouseId = findOrCreateStock(bo);
|
||||||
|
bo.setWarehouseId(warehouseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 插入钢卷数据
|
||||||
|
WmsMaterialCoil add = BeanUtil.toBean(bo, WmsMaterialCoil.class);
|
||||||
|
add.setDataType(1); // 新增的钢卷默认为当前数据
|
||||||
|
validEntityBeforeSave(add);
|
||||||
|
boolean flag = baseMapper.insert(add) > 0;
|
||||||
|
if (flag) {
|
||||||
|
bo.setCoilId(add.getCoilId());
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成二维码(新增)
|
||||||
|
*/
|
||||||
|
private Long generateQrcodeForInsert(WmsMaterialCoilBo bo) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> contentMap = new HashMap<>();
|
||||||
|
String currentCoilNo = bo.getCurrentCoilNo() != null ? bo.getCurrentCoilNo() : bo.getEnterCoilNo();
|
||||||
|
|
||||||
|
contentMap.put("enter_coil_no", bo.getEnterCoilNo()); // 入场钢卷号(唯一不变)
|
||||||
|
contentMap.put("current_coil_no", currentCoilNo); // 当前钢卷号(可变)
|
||||||
|
|
||||||
|
// 创建steps数组
|
||||||
|
List<Map<String, Object>> steps = new ArrayList<>();
|
||||||
|
Map<String, Object> step1 = new HashMap<>();
|
||||||
|
step1.put("step", 1);
|
||||||
|
step1.put("action", "新增");
|
||||||
|
step1.put("current_coil_no", currentCoilNo);
|
||||||
|
|
||||||
|
// 判断是合卷还是分卷
|
||||||
|
if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 2) {
|
||||||
|
// 合卷:父编号字符串用逗号分隔
|
||||||
|
step1.put("operation", "合卷");
|
||||||
|
step1.put("parent_coil_nos", bo.getParentCoilNos());
|
||||||
|
} else if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 1) {
|
||||||
|
// 分卷:多个当前钢卷号用逗号分隔
|
||||||
|
step1.put("operation", "分卷");
|
||||||
|
step1.put("current_coil_nos", currentCoilNo);
|
||||||
|
} else {
|
||||||
|
// 默认:当前钢卷号
|
||||||
|
step1.put("operation", "新增");
|
||||||
|
}
|
||||||
|
|
||||||
|
steps.add(step1);
|
||||||
|
contentMap.put("steps", steps);
|
||||||
|
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
String contentJson = objectMapper.writeValueAsString(contentMap);
|
||||||
|
|
||||||
|
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
|
||||||
|
recordBo.setContent(contentJson);
|
||||||
|
recordBo.setSerialNumber(bo.getEnterCoilNo()); // 使用入场钢卷号作为编号
|
||||||
|
recordBo.setQrcodeType(0L);
|
||||||
|
recordBo.setIsEnabled(0L);
|
||||||
|
recordBo.setSize(200L);
|
||||||
|
|
||||||
|
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
|
||||||
|
return record.getRecordId();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("生成二维码失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找或创建stock
|
||||||
|
*/
|
||||||
|
private Long findOrCreateStock(WmsMaterialCoilBo bo) {
|
||||||
|
if (bo.getItemType() == null || bo.getItemId() == null) {
|
||||||
|
throw new RuntimeException("物品类型和物品ID不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询是否存在相同的stock
|
||||||
|
WmsStockBo stockBo = new WmsStockBo();
|
||||||
|
stockBo.setItemType(bo.getItemType());
|
||||||
|
stockBo.setItemId(bo.getItemId());
|
||||||
|
List<WmsStockVo> stockList = stockService.queryList(stockBo);
|
||||||
|
|
||||||
|
if (!stockList.isEmpty()) {
|
||||||
|
// 如果找到相同的stock,返回第一个的warehouseId
|
||||||
|
return stockList.get(0).getWarehouseId();
|
||||||
|
} else {
|
||||||
|
// 如果没有找到,创建一个新的stock
|
||||||
|
WmsStock newStock = new WmsStock();
|
||||||
|
newStock.setItemType(bo.getItemType());
|
||||||
|
newStock.setItemId(bo.getItemId());
|
||||||
|
// 新创建的stock没有指定warehouse,可以为null
|
||||||
|
stockMapper.insert(newStock);
|
||||||
|
return newStock.getWarehouseId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改钢卷物料表
|
||||||
|
* 如果newCoils不为空,则进行批量更新(分卷/合卷)
|
||||||
|
* 如果newCoils为空,则进行单个更新
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean updateByBo(WmsMaterialCoilBo bo) {
|
||||||
|
if (bo.getCoilId() == null) {
|
||||||
|
throw new RuntimeException("钢卷ID不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否批量更新
|
||||||
|
if (bo.getNewCoils() != null && !bo.getNewCoils().isEmpty()) {
|
||||||
|
// 批量更新逻辑(分卷/合卷)
|
||||||
|
return updateByBatch(bo);
|
||||||
|
} else {
|
||||||
|
// 单个更新逻辑
|
||||||
|
return updateBySingle(bo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单更新钢卷物料表
|
||||||
|
* 直接更新属性内容,不进行历史记录处理
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean updateSimple(WmsMaterialCoilBo bo) {
|
||||||
|
if (bo.getCoilId() == null) {
|
||||||
|
throw new RuntimeException("钢卷ID不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询原钢卷是否存在
|
||||||
|
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
|
||||||
|
if (oldCoil == null) {
|
||||||
|
throw new RuntimeException("钢卷不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接更新钢卷属性
|
||||||
|
WmsMaterialCoil updateCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
|
||||||
|
validEntityBeforeSave(updateCoil);
|
||||||
|
|
||||||
|
// 使用MyBatis-Plus的updateById方法直接更新
|
||||||
|
boolean flag = baseMapper.updateById(updateCoil) > 0;
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单个更新
|
||||||
|
*/
|
||||||
|
private Boolean updateBySingle(WmsMaterialCoilBo bo) {
|
||||||
|
// 查询原钢卷
|
||||||
|
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
|
||||||
|
if (oldCoil == null) {
|
||||||
|
throw new RuntimeException("原钢卷不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 更新二维码,添加操作记录
|
||||||
|
updateQrcodeContent(oldCoil.getQrcodeRecordId(), bo);
|
||||||
|
|
||||||
|
// 2. 将原数据更新为历史数据(data_type=0)
|
||||||
|
LambdaUpdateWrapper<WmsMaterialCoil> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.eq(WmsMaterialCoil::getCoilId, bo.getCoilId())
|
||||||
|
.set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据
|
||||||
|
baseMapper.update(null, updateWrapper);
|
||||||
|
|
||||||
|
// 3. 插入一条新的当前数据(data_type=1)
|
||||||
|
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
|
||||||
|
newCoil.setCoilId(null); // 清空ID,让数据库自动生成新的ID
|
||||||
|
newCoil.setDataType(1); // 设置为当前数据
|
||||||
|
newCoil.setQrcodeRecordId(oldCoil.getQrcodeRecordId()); // 继承二维码ID
|
||||||
|
validEntityBeforeSave(newCoil);
|
||||||
|
boolean flag = baseMapper.insert(newCoil) > 0;
|
||||||
|
if (flag) {
|
||||||
|
bo.setCoilId(newCoil.getCoilId());
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新(分卷/合卷)
|
||||||
|
*/
|
||||||
|
private Boolean updateByBatch(WmsMaterialCoilBo bo) {
|
||||||
|
// 查询原钢卷
|
||||||
|
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
|
||||||
|
if (oldCoil == null) {
|
||||||
|
throw new RuntimeException("原钢卷不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是分卷还是合卷
|
||||||
|
boolean isSplit = false;
|
||||||
|
boolean isMerge = false;
|
||||||
|
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
|
||||||
|
if (newCoilBo.getHasMergeSplit() != null) {
|
||||||
|
if (newCoilBo.getHasMergeSplit() == 1) {
|
||||||
|
isSplit = true;
|
||||||
|
break;
|
||||||
|
} else if (newCoilBo.getHasMergeSplit() == 2) {
|
||||||
|
isMerge = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 将原数据更新为历史数据(data_type=0)
|
||||||
|
LambdaUpdateWrapper<WmsMaterialCoil> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.eq(WmsMaterialCoil::getCoilId, bo.getCoilId())
|
||||||
|
.set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据
|
||||||
|
baseMapper.update(null, updateWrapper);
|
||||||
|
|
||||||
|
// 2. 插入多条新的当前数据(data_type=1)
|
||||||
|
List<WmsMaterialCoil> newCoils = new ArrayList<>();
|
||||||
|
List<String> allNewCoilNos = new ArrayList<>();
|
||||||
|
|
||||||
|
// 收集所有新钢卷号
|
||||||
|
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
|
||||||
|
allNewCoilNos.add(newCoilBo.getCurrentCoilNo());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSplit) {
|
||||||
|
// 分卷:为每个子钢卷生成独立的二维码
|
||||||
|
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
|
||||||
|
WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class);
|
||||||
|
newCoil.setCoilId(null);
|
||||||
|
newCoil.setDataType(1);
|
||||||
|
newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo());
|
||||||
|
|
||||||
|
// 为每个子钢卷生成独立二维码
|
||||||
|
Long newQrcodeId = generateQrcodeForSplit(oldCoil, newCoilBo, allNewCoilNos);
|
||||||
|
newCoil.setQrcodeRecordId(newQrcodeId);
|
||||||
|
|
||||||
|
validEntityBeforeSave(newCoil);
|
||||||
|
baseMapper.insert(newCoil);
|
||||||
|
newCoils.add(newCoil);
|
||||||
|
}
|
||||||
|
} else if (isMerge) {
|
||||||
|
// 合卷:合并多个二维码信息为一个
|
||||||
|
Long mergedQrcodeId = generateQrcodeForMerge(oldCoil, bo.getNewCoils());
|
||||||
|
|
||||||
|
for (WmsMaterialCoilBo newCoilBo : bo.getNewCoils()) {
|
||||||
|
WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class);
|
||||||
|
newCoil.setCoilId(null);
|
||||||
|
newCoil.setDataType(1);
|
||||||
|
newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo());
|
||||||
|
newCoil.setQrcodeRecordId(mergedQrcodeId); // 所有合卷后的钢卷共享一个二维码
|
||||||
|
|
||||||
|
validEntityBeforeSave(newCoil);
|
||||||
|
baseMapper.insert(newCoil);
|
||||||
|
newCoils.add(newCoil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为分卷生成新二维码(每个子钢卷一个)
|
||||||
|
*/
|
||||||
|
private Long generateQrcodeForSplit(WmsMaterialCoil oldCoil, WmsMaterialCoilBo newCoilBo, List<String> allNewCoilNos) {
|
||||||
|
try {
|
||||||
|
Map<String, Object> contentMap = new HashMap<>();
|
||||||
|
contentMap.put("enter_coil_no", oldCoil.getEnterCoilNo());
|
||||||
|
contentMap.put("current_coil_no", newCoilBo.getCurrentCoilNo());
|
||||||
|
|
||||||
|
// 复制原钢卷的历史steps
|
||||||
|
List<Map<String, Object>> steps = new ArrayList<>();
|
||||||
|
if (oldCoil.getQrcodeRecordId() != null) {
|
||||||
|
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId());
|
||||||
|
if (oldRecord != null) {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> oldContentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> oldSteps = (List<Map<String, Object>>) oldContentMap.get("steps");
|
||||||
|
if (oldSteps != null) {
|
||||||
|
steps.addAll(oldSteps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加分卷步骤
|
||||||
|
Map<String, Object> splitStep = new HashMap<>();
|
||||||
|
splitStep.put("step", steps.size() + 1);
|
||||||
|
splitStep.put("action", "更新");
|
||||||
|
splitStep.put("operation", "分卷");
|
||||||
|
splitStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo());
|
||||||
|
splitStep.put("new_current_coil_nos", String.join(",", allNewCoilNos));
|
||||||
|
splitStep.put("child_coils", allNewCoilNos);
|
||||||
|
steps.add(splitStep);
|
||||||
|
|
||||||
|
contentMap.put("steps", steps);
|
||||||
|
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
String contentJson = objectMapper.writeValueAsString(contentMap);
|
||||||
|
|
||||||
|
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
|
||||||
|
recordBo.setContent(contentJson);
|
||||||
|
recordBo.setSerialNumber(oldCoil.getEnterCoilNo() + "-" + newCoilBo.getCurrentCoilNo());
|
||||||
|
recordBo.setQrcodeType(0L);
|
||||||
|
recordBo.setIsEnabled(0L);
|
||||||
|
recordBo.setSize(200L);
|
||||||
|
|
||||||
|
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
|
||||||
|
return record.getRecordId();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("生成分卷二维码失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为合卷生成新二维码(合并多个父钢卷的二维码信息)
|
||||||
|
*/
|
||||||
|
private Long generateQrcodeForMerge(WmsMaterialCoil oldCoil, List<WmsMaterialCoilBo> newCoils) {
|
||||||
|
try {
|
||||||
|
if (newCoils.isEmpty()) {
|
||||||
|
throw new RuntimeException("合卷后的钢卷数据不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
WmsMaterialCoilBo mergedCoilBo = newCoils.get(0);
|
||||||
|
|
||||||
|
Map<String, Object> contentMap = new HashMap<>();
|
||||||
|
contentMap.put("enter_coil_no", oldCoil.getEnterCoilNo());
|
||||||
|
contentMap.put("current_coil_no", mergedCoilBo.getCurrentCoilNo());
|
||||||
|
|
||||||
|
// 合并所有父钢卷的历史steps
|
||||||
|
List<Map<String, Object>> steps = new ArrayList<>();
|
||||||
|
|
||||||
|
// 如果有父钢卷号,获取它们的二维码信息并合并
|
||||||
|
if (mergedCoilBo.getParentCoilNos() != null && !mergedCoilBo.getParentCoilNos().trim().isEmpty()) {
|
||||||
|
String[] parentCoilNos = mergedCoilBo.getParentCoilNos().split(",");
|
||||||
|
for (String parentCoilNo : parentCoilNos) {
|
||||||
|
// 查找父钢卷
|
||||||
|
LambdaQueryWrapper<WmsMaterialCoil> parentLqw = Wrappers.lambdaQuery();
|
||||||
|
parentLqw.eq(WmsMaterialCoil::getCurrentCoilNo, parentCoilNo.trim())
|
||||||
|
.eq(WmsMaterialCoil::getDataType, 1);
|
||||||
|
List<WmsMaterialCoil> parentCoils = baseMapper.selectList(parentLqw);
|
||||||
|
|
||||||
|
if (!parentCoils.isEmpty() && parentCoils.get(0).getQrcodeRecordId() != null) {
|
||||||
|
WmsGenerateRecordVo parentQr = generateRecordService.queryById(parentCoils.get(0).getQrcodeRecordId());
|
||||||
|
if (parentQr != null) {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> parentContentMap = objectMapper.readValue(parentQr.getContent(), Map.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> parentSteps = (List<Map<String, Object>>) parentContentMap.get("steps");
|
||||||
|
if (parentSteps != null) {
|
||||||
|
steps.addAll(parentSteps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加原钢卷的历史
|
||||||
|
if (oldCoil.getQrcodeRecordId() != null) {
|
||||||
|
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId());
|
||||||
|
if (oldRecord != null) {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> oldContentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> oldSteps = (List<Map<String, Object>>) oldContentMap.get("steps");
|
||||||
|
if (oldSteps != null) {
|
||||||
|
steps.addAll(oldSteps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加合卷步骤
|
||||||
|
Map<String, Object> mergeStep = new HashMap<>();
|
||||||
|
mergeStep.put("step", steps.size() + 1);
|
||||||
|
mergeStep.put("action", "更新");
|
||||||
|
mergeStep.put("operation", "合卷");
|
||||||
|
mergeStep.put("parent_coil_nos", mergedCoilBo.getParentCoilNos());
|
||||||
|
mergeStep.put("new_current_coil_no", mergedCoilBo.getCurrentCoilNo());
|
||||||
|
steps.add(mergeStep);
|
||||||
|
|
||||||
|
contentMap.put("steps", steps);
|
||||||
|
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
String contentJson = objectMapper.writeValueAsString(contentMap);
|
||||||
|
|
||||||
|
WmsGenerateRecordBo recordBo = new WmsGenerateRecordBo();
|
||||||
|
recordBo.setContent(contentJson);
|
||||||
|
recordBo.setSerialNumber(oldCoil.getEnterCoilNo() + "-" + mergedCoilBo.getCurrentCoilNo());
|
||||||
|
recordBo.setQrcodeType(0L);
|
||||||
|
recordBo.setIsEnabled(0L);
|
||||||
|
recordBo.setSize(200L);
|
||||||
|
|
||||||
|
WmsGenerateRecordVo record = generateRecordService.insertByBo(recordBo);
|
||||||
|
return record.getRecordId();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("生成合卷二维码失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 更新二维码内容(单个更新)
|
||||||
|
*/
|
||||||
|
private void updateQrcodeContent(Long qrcodeRecordId, WmsMaterialCoilBo bo) {
|
||||||
|
try {
|
||||||
|
// 获取原钢卷信息
|
||||||
|
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
|
||||||
|
|
||||||
|
// 获取原二维码记录
|
||||||
|
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(qrcodeRecordId);
|
||||||
|
if (oldRecord == null) {
|
||||||
|
throw new RuntimeException("二维码记录不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析现有content
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
Map<String, Object> contentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
|
||||||
|
|
||||||
|
// 获取现有steps
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
|
||||||
|
if (steps == null) {
|
||||||
|
steps = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加新的step,记录钢卷号的变化
|
||||||
|
Map<String, Object> newStep = new HashMap<>();
|
||||||
|
newStep.put("step", steps.size() + 1);
|
||||||
|
newStep.put("action", "更新");
|
||||||
|
newStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo()); // 原当前钢卷号
|
||||||
|
newStep.put("new_current_coil_no", bo.getCurrentCoilNo()); // 新当前钢卷号
|
||||||
|
|
||||||
|
// 判断操作类型
|
||||||
|
if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 2) {
|
||||||
|
newStep.put("operation", "合卷");
|
||||||
|
newStep.put("parent_coil_nos", bo.getParentCoilNos());
|
||||||
|
} else if (bo.getHasMergeSplit() != null && bo.getHasMergeSplit() == 1) {
|
||||||
|
newStep.put("operation", "分卷");
|
||||||
|
newStep.put("new_current_coil_nos", bo.getCurrentCoilNo());
|
||||||
|
} else {
|
||||||
|
newStep.put("operation", "更新");
|
||||||
|
}
|
||||||
|
|
||||||
|
steps.add(newStep);
|
||||||
|
contentMap.put("steps", steps);
|
||||||
|
// 更新当前钢卷号到最外层(方便快速查看)
|
||||||
|
contentMap.put("current_coil_no", bo.getCurrentCoilNo());
|
||||||
|
|
||||||
|
// 更新二维码记录
|
||||||
|
String newContentJson = objectMapper.writeValueAsString(contentMap);
|
||||||
|
WmsGenerateRecordBo updateBo = new WmsGenerateRecordBo();
|
||||||
|
updateBo.setRecordId(qrcodeRecordId);
|
||||||
|
updateBo.setContent(newContentJson);
|
||||||
|
generateRecordService.updateByBo(updateBo);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("更新二维码失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存前的数据校验
|
||||||
|
*/
|
||||||
|
private void validEntityBeforeSave(WmsMaterialCoil entity){
|
||||||
|
//TODO 做一些数据校验,如唯一约束
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除钢卷物料表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
|
if(isValid){
|
||||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
|
}
|
||||||
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 钢卷溯源查询
|
||||||
|
* 根据入场钢卷号查询二维码,解析content中的steps,然后根据steps中的钢卷号反向查询数据库
|
||||||
|
*
|
||||||
|
* @param enterCoilNo 入场钢卷号
|
||||||
|
* @param currentCoilNo 当前钢卷号(可选,用于查询特定子钢卷)
|
||||||
|
* @return 溯源结果(包含二维码信息和数据库记录)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> queryTrace(String enterCoilNo, String currentCoilNo) {
|
||||||
|
try {
|
||||||
|
// 1. 根据入场钢卷号查询二维码记录
|
||||||
|
WmsGenerateRecordBo qrBo = new WmsGenerateRecordBo();
|
||||||
|
qrBo.setSerialNumber(enterCoilNo);
|
||||||
|
List<WmsGenerateRecordVo> qrRecords = generateRecordService.queryList(qrBo);
|
||||||
|
|
||||||
|
if (qrRecords.isEmpty()) {
|
||||||
|
throw new RuntimeException("未找到对应的二维码记录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取第一个(应该只有一个)
|
||||||
|
WmsGenerateRecordVo qrRecord = qrRecords.get(0);
|
||||||
|
|
||||||
|
// 2. 解析二维码content中的steps
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> contentMap = objectMapper.readValue(qrRecord.getContent(), Map.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
|
||||||
|
|
||||||
|
// 3. 从steps中提取所有钢卷号
|
||||||
|
Set<String> coilNos = new HashSet<>();
|
||||||
|
if (steps != null) {
|
||||||
|
for (Map<String, Object> step : steps) {
|
||||||
|
// 提取各种可能的钢卷号字段
|
||||||
|
extractCoilNo(step, "current_coil_no", coilNos);
|
||||||
|
extractCoilNo(step, "new_current_coil_no", coilNos);
|
||||||
|
extractCoilNo(step, "old_current_coil_no", coilNos);
|
||||||
|
extractCoilNo(step, "new_current_coil_nos", coilNos);
|
||||||
|
extractCoilNo(step, "merged_from", coilNos);
|
||||||
|
extractCoilNo(step, "parent_coil_nos", coilNos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 如果指定了当前钢卷号,过滤出相关的钢卷号
|
||||||
|
Set<String> filteredCoilNos = coilNos;
|
||||||
|
if (currentCoilNo != null && !currentCoilNo.trim().isEmpty()) {
|
||||||
|
final String filterValue = currentCoilNo; // 用于lambda的final变量
|
||||||
|
filteredCoilNos = coilNos.stream()
|
||||||
|
.filter(coilNo -> coilNo.contains(filterValue))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 根据提取的钢卷号反向查询数据库
|
||||||
|
List<WmsMaterialCoilVo> result = new ArrayList<>();
|
||||||
|
if (!filteredCoilNos.isEmpty()) {
|
||||||
|
LambdaQueryWrapper<WmsMaterialCoil> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(WmsMaterialCoil::getEnterCoilNo, enterCoilNo);
|
||||||
|
|
||||||
|
// 查询包含提取出的钢卷号的记录
|
||||||
|
final Set<String> finalCoilNos = filteredCoilNos; // 用于lambda的final变量
|
||||||
|
lqw.and(wrapper -> {
|
||||||
|
int count = 0;
|
||||||
|
for (String coilNo : finalCoilNos) {
|
||||||
|
if (count == 0) {
|
||||||
|
wrapper.like(WmsMaterialCoil::getCurrentCoilNo, coilNo);
|
||||||
|
} else {
|
||||||
|
wrapper.or().like(WmsMaterialCoil::getCurrentCoilNo, coilNo);
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
lqw.orderByAsc(WmsMaterialCoil::getCreateTime);
|
||||||
|
result = baseMapper.selectVoList(lqw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 构建返回结果
|
||||||
|
Map<String, Object> resultMap = new HashMap<>();
|
||||||
|
resultMap.put("qrcode", qrRecord);
|
||||||
|
resultMap.put("steps", steps);
|
||||||
|
resultMap.put("records", result);
|
||||||
|
|
||||||
|
return resultMap;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("溯源查询失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从step中提取钢卷号
|
||||||
|
*/
|
||||||
|
private void extractCoilNo(Map<String, Object> step, String fieldName, Set<String> coilNos) {
|
||||||
|
Object value = step.get(fieldName);
|
||||||
|
if (value != null) {
|
||||||
|
String strValue = value.toString();
|
||||||
|
if (strValue.contains(",")) {
|
||||||
|
// 如果是逗号分隔的多个钢卷号,分割后添加
|
||||||
|
String[] coilArray = strValue.split(",");
|
||||||
|
for (String coilNo : coilArray) {
|
||||||
|
coilNos.add(coilNo.trim());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coilNos.add(strValue.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -102,8 +102,6 @@ public class WmsStockServiceImpl implements IWmsStockService {
|
|||||||
LambdaQueryWrapper<WmsStock> lqw = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<WmsStock> lqw = new LambdaQueryWrapper<>();
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getItemType()), WmsStock::getItemType, bo.getItemType());
|
lqw.eq(StringUtils.isNotBlank(bo.getItemType()), WmsStock::getItemType, bo.getItemType());
|
||||||
lqw.eq(bo.getItemId() != null, WmsStock::getItemId, bo.getItemId());
|
lqw.eq(bo.getItemId() != null, WmsStock::getItemId, bo.getItemId());
|
||||||
lqw.eq(bo.getQuantity() != null, WmsStock::getQuantity, bo.getQuantity());
|
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getUnit()), WmsStock::getUnit, bo.getUnit());
|
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getBatchNo()), WmsStock::getBatchNo, bo.getBatchNo());
|
lqw.eq(StringUtils.isNotBlank(bo.getBatchNo()), WmsStock::getBatchNo, bo.getBatchNo());
|
||||||
return lqw;
|
return lqw;
|
||||||
}
|
}
|
||||||
@@ -125,8 +123,6 @@ public class WmsStockServiceImpl implements IWmsStockService {
|
|||||||
|
|
||||||
qw.eq(StringUtils.isNotBlank(bo.getItemType()), "s.item_type", bo.getItemType());
|
qw.eq(StringUtils.isNotBlank(bo.getItemType()), "s.item_type", bo.getItemType());
|
||||||
qw.eq(bo.getItemId() != null, "s.item_id", bo.getItemId());
|
qw.eq(bo.getItemId() != null, "s.item_id", bo.getItemId());
|
||||||
qw.eq(bo.getQuantity() != null, "s.quantity", bo.getQuantity());
|
|
||||||
qw.eq(StringUtils.isNotBlank(bo.getUnit()), "s.unit", bo.getUnit());
|
|
||||||
qw.eq(StringUtils.isNotBlank(bo.getBatchNo()), "s.batch_no", bo.getBatchNo());
|
qw.eq(StringUtils.isNotBlank(bo.getBatchNo()), "s.batch_no", bo.getBatchNo());
|
||||||
|
|
||||||
return qw;
|
return qw;
|
||||||
@@ -179,7 +175,37 @@ public class WmsStockServiceImpl implements IWmsStockService {
|
|||||||
return baseMapper.getStockByItemId(rawMaterialId);
|
return baseMapper.getStockByItemId(rawMaterialId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询库存分布(按仓库统计)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public WmsStockVo queryStockDistribution(WmsStockBo bo) {
|
||||||
|
if (bo.getItemType() == null || bo.getItemId() == null) {
|
||||||
|
throw new RuntimeException("物品类型和物品ID不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 计算总库存量
|
||||||
|
BigDecimal totalQuantity = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
// 2. 按仓库统计库存分布
|
||||||
|
List<WmsStockVo> distributionList = baseMapper.selectStockDistribution(bo.getItemType(), bo.getItemId());
|
||||||
|
|
||||||
|
// 计算总量
|
||||||
|
for (WmsStockVo vo : distributionList) {
|
||||||
|
if (vo.getTotalQuantity() != null) {
|
||||||
|
totalQuantity = totalQuantity.add(vo.getTotalQuantity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建返回对象
|
||||||
|
WmsStockVo result = new WmsStockVo();
|
||||||
|
result.setItemType(bo.getItemType());
|
||||||
|
result.setItemId(bo.getItemId());
|
||||||
|
result.setTotalQuantity(totalQuantity);
|
||||||
|
result.setStockDistribution(distributionList);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定仓库ID及其所有子仓库ID
|
* 获取指定仓库ID及其所有子仓库ID
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.klp.mapper.WmsMaterialCoilMapper">
|
||||||
|
|
||||||
|
<resultMap type="com.klp.domain.WmsMaterialCoil" id="WmsMaterialCoilResult">
|
||||||
|
<result property="coilId" column="coil_id"/>
|
||||||
|
<result property="enterCoilNo" column="enter_coil_no"/>
|
||||||
|
<result property="currentCoilNo" column="current_coil_no"/>
|
||||||
|
<result property="supplierCoilNo" column="supplier_coil_no"/>
|
||||||
|
<result property="dataType" column="data_type"/>
|
||||||
|
<result property="warehouseId" column="warehouse_id"/>
|
||||||
|
<result property="nextWarehouseId" column="next_warehouse_id"/>
|
||||||
|
<result property="qrcodeRecordId" column="qrcode_record_id"/>
|
||||||
|
<result property="team" column="team"/>
|
||||||
|
<result property="hasMergeSplit" column="has_merge_split"/>
|
||||||
|
<result property="parentCoilNos" column="parent_coil_nos"/>
|
||||||
|
<result property="itemType" column="item_type"/>
|
||||||
|
<result property="itemId" column="item_id"/>
|
||||||
|
<result property="status" column="status"/>
|
||||||
|
<result property="remark" column="remark"/>
|
||||||
|
<result property="delFlag" column="del_flag"/>
|
||||||
|
<result property="createTime" column="create_time"/>
|
||||||
|
<result property="createBy" column="create_by"/>
|
||||||
|
<result property="updateTime" column="update_time"/>
|
||||||
|
<result property="updateBy" column="update_by"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|
||||||
@@ -9,8 +9,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="warehouseId" column="warehouse_id"/>
|
<result property="warehouseId" column="warehouse_id"/>
|
||||||
<result property="itemType" column="item_type"/>
|
<result property="itemType" column="item_type"/>
|
||||||
<result property="itemId" column="item_id"/>
|
<result property="itemId" column="item_id"/>
|
||||||
<result property="quantity" column="quantity"/>
|
|
||||||
<result property="unit" column="unit"/>
|
|
||||||
<result property="batchNo" column="batch_no"/>
|
<result property="batchNo" column="batch_no"/>
|
||||||
<result property="remark" column="remark"/>
|
<result property="remark" column="remark"/>
|
||||||
<result property="delFlag" column="del_flag"/>
|
<result property="delFlag" column="del_flag"/>
|
||||||
@@ -39,7 +37,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
WHEN s.item_type = 'product' THEN p.product_code
|
WHEN s.item_type = 'product' THEN p.product_code
|
||||||
WHEN s.item_type = 'raw_material' THEN r.raw_material_code
|
WHEN s.item_type = 'raw_material' THEN r.raw_material_code
|
||||||
ELSE NULL
|
ELSE NULL
|
||||||
END AS itemCode
|
END AS itemCode,
|
||||||
|
(SELECT COUNT(*)
|
||||||
|
FROM wms_material_coil mc
|
||||||
|
WHERE mc.item_type = s.item_type
|
||||||
|
AND mc.item_id = s.item_id
|
||||||
|
AND mc.del_flag = 0) AS totalQuantity
|
||||||
FROM wms_stock s
|
FROM wms_stock s
|
||||||
LEFT JOIN wms_product p ON s.item_type = 'product' AND s.item_id = p.product_id and p.del_flag = 0
|
LEFT JOIN wms_product p ON s.item_type = 'product' AND s.item_id = p.product_id and p.del_flag = 0
|
||||||
LEFT JOIN wms_raw_material r ON s.item_type = 'raw_material' AND s.item_id = r.raw_material_id and r.del_flag = 0
|
LEFT JOIN wms_raw_material r ON s.item_type = 'raw_material' AND s.item_id = r.raw_material_id and r.del_flag = 0
|
||||||
@@ -47,4 +50,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
${ew.customSqlSegment}
|
${ew.customSqlSegment}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 按仓库统计库存分布 -->
|
||||||
|
<select id="selectStockDistribution" resultType="com.klp.domain.vo.WmsStockVo">
|
||||||
|
SELECT
|
||||||
|
mc.warehouse_id AS warehouseId,
|
||||||
|
w.warehouse_name AS warehouseName,
|
||||||
|
COUNT(*) AS totalQuantity,
|
||||||
|
mc.item_type AS itemType,
|
||||||
|
mc.item_id AS itemId
|
||||||
|
FROM wms_material_coil mc
|
||||||
|
INNER JOIN wms_warehouse w ON mc.warehouse_id = w.warehouse_id AND w.del_flag = 0
|
||||||
|
WHERE mc.item_type = #{itemType}
|
||||||
|
AND mc.item_id = #{itemId}
|
||||||
|
AND mc.del_flag = 0
|
||||||
|
AND mc.data_type = 1
|
||||||
|
GROUP BY mc.warehouse_id, w.warehouse_name, mc.item_type, mc.item_id
|
||||||
|
ORDER BY totalQuantity DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
3549
script/sql/mysql/klp-oa.sql
Normal file
3549
script/sql/mysql/klp-oa.sql
Normal file
File diff suppressed because it is too large
Load Diff
79
script/sql/mysql/stock.sql
Normal file
79
script/sql/mysql/stock.sql
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
|
||||||
|
DROP TABLE IF EXISTS `wms_stock`;
|
||||||
|
|
||||||
|
create table wms_stock
|
||||||
|
(
|
||||||
|
stock_id bigint auto_increment comment '主键ID'
|
||||||
|
primary key,
|
||||||
|
warehouse_id bigint not null comment '仓库/库区/库位ID',
|
||||||
|
item_id bigint not null comment '物品ID(指向原材料或产品主键)',
|
||||||
|
item_type varchar(20) not null comment '物品类型(raw_material/product)',
|
||||||
|
batch_no varchar(50) null comment '批次号(可选)',
|
||||||
|
remark varchar(255) null comment '备注',
|
||||||
|
del_flag tinyint(1) default 0 not null comment '删除标志(0=正常,1=已删除)',
|
||||||
|
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
|
||||||
|
create_by varchar(50) null comment '创建人',
|
||||||
|
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
|
||||||
|
update_by varchar(50) null comment '更新人',
|
||||||
|
constraint fk_stock_warehouse
|
||||||
|
foreign key (warehouse_id) references wms_warehouse (warehouse_id),
|
||||||
|
constraint fk_stock_raw_material
|
||||||
|
foreign key (raw_material_id) references wms_raw_material (raw_material_id),
|
||||||
|
constraint fk_stock_coil
|
||||||
|
foreign key (coil_id) references wms_material_coil (coil_id)
|
||||||
|
)
|
||||||
|
comment '库存表:原材料-钢卷-库区的存放关系' charset = utf8mb4;
|
||||||
|
|
||||||
|
create index idx_stock_raw_material
|
||||||
|
on wms_stock (raw_material_id);
|
||||||
|
|
||||||
|
create index idx_stock_coil
|
||||||
|
on wms_stock (coil_id);
|
||||||
|
|
||||||
|
create index idx_stock_warehouse
|
||||||
|
on wms_stock (warehouse_id);
|
||||||
|
|
||||||
|
|
||||||
|
create table wms_material_coil
|
||||||
|
(
|
||||||
|
coil_id bigint auto_increment comment '主键ID'
|
||||||
|
primary key,
|
||||||
|
enter_coil_no varchar(50) not null comment '入场钢卷号(年份后两位+月份+当月第几个,如25100001、25102422)',
|
||||||
|
current_coil_no varchar(50) not null comment '当前钢卷号(入场钢卷号和当前钢卷号可能不同)',
|
||||||
|
supplier_coil_no varchar(50) null comment '厂家原料卷号',
|
||||||
|
data_type tinyint(1) default 1 not null comment '数据类型(0=历史,1=现存)',
|
||||||
|
warehouse_id bigint null comment '所在库区ID',
|
||||||
|
next_warehouse_id bigint null comment '下一库区ID',
|
||||||
|
qrcode_record_id bigint null comment '关联二维码ID(wms_generate_record.record_id)',
|
||||||
|
team varchar(50) null comment '班组',
|
||||||
|
has_merge_split tinyint(1) default 0 not null comment '是否合卷/分卷(0=否,1=分卷,2=合卷)',
|
||||||
|
parent_coil_nos varchar(500) null comment '父卷号(合卷或分卷时用,逗号分隔)',
|
||||||
|
item_id bigint not null comment '物品ID(指向原材料或产品主键)',
|
||||||
|
item_type varchar(20) not null comment '物品类型(raw_material/product)',
|
||||||
|
status tinyint(1) default 0 null comment '状态(0=在库,1=在途,2=已出库)',
|
||||||
|
remark varchar(255) null comment '备注',
|
||||||
|
del_flag tinyint(1) default 0 not null comment '删除标志(0=正常,1=已删除)',
|
||||||
|
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
|
||||||
|
create_by varchar(50) null comment '创建人',
|
||||||
|
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
|
||||||
|
update_by varchar(50) null comment '更新人',
|
||||||
|
constraint uk_enter_coil_no
|
||||||
|
unique (enter_coil_no) comment '入场钢卷号唯一约束',
|
||||||
|
constraint fk_coil_warehouse
|
||||||
|
foreign key (warehouse_id) references wms_warehouse (warehouse_id),
|
||||||
|
constraint fk_coil_next_warehouse
|
||||||
|
foreign key (next_warehouse_id) references wms_warehouse (warehouse_id),
|
||||||
|
constraint fk_coil_qrcode
|
||||||
|
foreign key (qrcode_record_id) references wms_generate_record (record_id)
|
||||||
|
)
|
||||||
|
comment '钢卷物料表' charset = utf8mb4;
|
||||||
|
|
||||||
|
create index idx_coil_current_no
|
||||||
|
on wms_material_coil (current_coil_no);
|
||||||
|
|
||||||
|
create index idx_coil_type
|
||||||
|
on wms_material_coil (data_type);
|
||||||
|
|
||||||
|
create index idx_coil_warehouse
|
||||||
|
on wms_material_coil (warehouse_id);
|
||||||
|
|
||||||
Reference in New Issue
Block a user