Browse Source

2025-10-13

销售发货装箱新增盒清单功能
master
fengyuan_yang 10 months ago
parent
commit
6337fc04a7
  1. 51
      src/main/java/com/gaotao/modules/boxManage/controller/BoxForNotificationController.java
  2. 8
      src/main/java/com/gaotao/modules/boxManage/dao/BoxForNotificationMapper.java
  3. 28
      src/main/java/com/gaotao/modules/boxManage/data/SoReceiveCasesData.java
  4. 171
      src/main/java/com/gaotao/modules/boxManage/entity/SoReceiveCases.java
  5. 7
      src/main/java/com/gaotao/modules/boxManage/service/BoxForNotificationService.java
  6. 113
      src/main/java/com/gaotao/modules/boxManage/service/impl/BoxForNotificationServiceImpl.java
  7. 97
      src/main/resources/mapper/boxManage/BoxForNotificationMapper.xml

51
src/main/java/com/gaotao/modules/boxManage/controller/BoxForNotificationController.java

@ -3,6 +3,7 @@ package com.gaotao.modules.boxManage.controller;
import com.gaotao.common.utils.R;
import com.gaotao.modules.boxManage.data.SoReceiveBoxRollsData;
import com.gaotao.modules.boxManage.data.SoReceiveBoxesData;
import com.gaotao.modules.boxManage.data.SoReceiveCasesData;
import com.gaotao.modules.boxManage.service.BoxForNotificationService;
import com.gaotao.modules.outboundNotification.entity.vo.OutboundNotificationHeadVo;
import org.springframework.beans.factory.annotation.Autowired;
@ -105,4 +106,54 @@ public class BoxForNotificationController {
List<SoReceiveBoxRollsData> rows = srmSupplierService.searchRollForOrderNo(data);
return R.ok().put("rows", rows);
}
// ===== 盒清单相关接口 =====
/**
* 查询盒清单
* @param data
* @return R
*/
@PostMapping(value="/searchSoReceiveCasesData")
@ResponseBody
public R searchSoReceiveCasesData(@RequestBody SoReceiveCasesData data) {
List<SoReceiveCasesData> rows = srmSupplierService.searchSoReceiveCasesData(data);
return R.ok().put("rows", rows);
}
/**
* 删除盒清单记录
* @param data
* @return R
*/
@PostMapping(value="/deleteSoReceiveCasesData")
@ResponseBody
public R deleteSoReceiveCasesData(@RequestBody SoReceiveCasesData data) {
srmSupplierService.deleteSoReceiveCasesData(data);
return R.ok();
}
/**
* 校验并扫描卷
* @param data
* @return R
*/
@PostMapping(value="/validateAndScanCaseRoll")
@ResponseBody
public R validateAndScanCaseRoll(@RequestBody SoReceiveCasesData data) {
SoReceiveCasesData rollInfo = srmSupplierService.validateAndScanCaseRoll(data);
return R.ok().put("rollInfo", rollInfo);
}
/**
* 保存盒清单列表
* @param dataList
* @return R
*/
@PostMapping(value="/saveCaseRollList")
@ResponseBody
public R saveCaseRollList(@RequestBody List<SoReceiveCasesData> dataList) {
srmSupplierService.saveCaseRollList(dataList);
return R.ok();
}
}

8
src/main/java/com/gaotao/modules/boxManage/dao/BoxForNotificationMapper.java

@ -2,6 +2,7 @@ package com.gaotao.modules.boxManage.dao;
import com.gaotao.modules.boxManage.data.SoReceiveBoxRollsData;
import com.gaotao.modules.boxManage.data.SoReceiveBoxesData;
import com.gaotao.modules.boxManage.data.SoReceiveCasesData;
import com.gaotao.modules.inventoryStock.entity.InventoryStock;
import com.gaotao.modules.outboundNotification.entity.OutboundNotificationDetailEntity;
import com.gaotao.modules.outboundNotification.entity.vo.OutboundNotificationHeadVo;
@ -37,4 +38,11 @@ public interface BoxForNotificationMapper {
void updateBoxWareHouse( @Param("site") String site, @Param("buNo") String buNo, @Param("boxNo") String boxNo, @Param("warehouseId") String warehouseId);
void deleteBoxRoll( SoReceiveBoxRollsData inData);
List<SoReceiveBoxRollsData> searchRollForOrderNo(OutboundNotificationHeadVo inData);
// 盒清单相关方法
List<SoReceiveCasesData> searchSoReceiveCasesData(SoReceiveCasesData data);
void deleteSoReceiveCasesData(SoReceiveCasesData data);
SoReceiveCasesData validateCaseRoll(@Param("site") String site, @Param("partNo") String partNo, @Param("rollNo") String rollNo, @Param("casesNo") String casesNo);
void saveSoReceiveCases(SoReceiveCasesData data);
void updateStockParentRollType(@Param("rollNo") String rollNo, @Param("parentRollNo") String parentRollNo, @Param("parentRollType") String parentRollType, @Param("site") String site, @Param("buNo") String buNo);
}

28
src/main/java/com/gaotao/modules/boxManage/data/SoReceiveCasesData.java

@ -0,0 +1,28 @@
package com.gaotao.modules.boxManage.data;
import com.gaotao.modules.boxManage.entity.SoReceiveCases;
import lombok.Data;
import org.apache.ibatis.type.Alias;
/**
* 盒清单数据对象
*/
@Data
@Alias("SoReceiveCasesData")
public class SoReceiveCasesData extends SoReceiveCases {
/**
* 合约号码
*/
private String batchNo;
/**
* 库存状态
*/
private String status;
/**
* 上级标签类型
*/
private String parentRollType;
}

171
src/main/java/com/gaotao/modules/boxManage/entity/SoReceiveCases.java

@ -0,0 +1,171 @@
package com.gaotao.modules.boxManage.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 盒清单实体类
* 对应数据库表so_receive_cases
*/
public class SoReceiveCases {
/**
* 主键自增ID
*/
private Integer id;
/**
* 工厂
*/
private String site;
/**
* BU
*/
private String buNo;
/**
* 销售出库单号关联销售通知主单
*/
private String notifyNo;
/**
* 盒标签标识包装箱或盒的唯一编号
*/
private String casesNo;
/**
* 卷标签标识物料卷的唯一编号
*/
private String rollNo;
/**
* 卷数量表示该盒/该批次中包含的卷数
*/
private Integer rollQty;
/**
* 物料编码对应物料主数据中的编码
*/
private String partNo;
/**
* 物料名称物料的中文名称或描述
*/
private String partDesc;
/**
* 记录创建时间默认为当前系统时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createDate;
/**
* 创建人操作员姓名或工号
*/
private String createBy;
/**
* 备注信息用于记录特殊说明或客户要求
*/
private String remark;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSite() {
return site;
}
public void setSite(String site) {
this.site = site;
}
public String getBuNo() {
return buNo;
}
public void setBuNo(String buNo) {
this.buNo = buNo;
}
public String getNotifyNo() {
return notifyNo;
}
public void setNotifyNo(String notifyNo) {
this.notifyNo = notifyNo;
}
public String getCasesNo() {
return casesNo;
}
public void setCasesNo(String casesNo) {
this.casesNo = casesNo;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
public Integer getRollQty() {
return rollQty;
}
public void setRollQty(Integer rollQty) {
this.rollQty = rollQty;
}
public String getPartNo() {
return partNo;
}
public void setPartNo(String partNo) {
this.partNo = partNo;
}
public String getPartDesc() {
return partDesc;
}
public void setPartDesc(String partDesc) {
this.partDesc = partDesc;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

7
src/main/java/com/gaotao/modules/boxManage/service/BoxForNotificationService.java

@ -2,6 +2,7 @@ package com.gaotao.modules.boxManage.service;
import com.gaotao.modules.boxManage.data.SoReceiveBoxRollsData;
import com.gaotao.modules.boxManage.data.SoReceiveBoxesData;
import com.gaotao.modules.boxManage.data.SoReceiveCasesData;
import com.gaotao.modules.outboundNotification.entity.vo.OutboundNotificationHeadVo;
import java.util.List;
@ -23,4 +24,10 @@ public interface BoxForNotificationService {
void deleteBoxRoll(SoReceiveBoxRollsData data);
List<SoReceiveBoxRollsData> searchRollForOrderNo(OutboundNotificationHeadVo inData);
// 盒清单相关方法
List<SoReceiveCasesData> searchSoReceiveCasesData(SoReceiveCasesData data);
void deleteSoReceiveCasesData(SoReceiveCasesData data);
SoReceiveCasesData validateAndScanCaseRoll(SoReceiveCasesData data);
void saveCaseRollList(List<SoReceiveCasesData> dataList);
}

113
src/main/java/com/gaotao/modules/boxManage/service/impl/BoxForNotificationServiceImpl.java

@ -3,6 +3,7 @@ package com.gaotao.modules.boxManage.service.impl;
import com.gaotao.modules.boxManage.dao.BoxForNotificationMapper;
import com.gaotao.modules.boxManage.data.SoReceiveBoxRollsData;
import com.gaotao.modules.boxManage.data.SoReceiveBoxesData;
import com.gaotao.modules.boxManage.data.SoReceiveCasesData;
import com.gaotao.modules.boxManage.service.BoxForNotificationService;
import com.gaotao.modules.outboundNotification.entity.OutboundNotificationDetailEntity;
import com.gaotao.modules.outboundNotification.entity.vo.OutboundNotificationHeadVo;
@ -222,4 +223,116 @@ public class BoxForNotificationServiceImpl implements BoxForNotificationService
public List<SoReceiveBoxRollsData> searchRollForOrderNo(OutboundNotificationHeadVo inData) {
return boxForNotificationMapper.searchRollForOrderNo(inData);
}
// ===== 盒清单相关方法实现 =====
@Override
public List<SoReceiveCasesData> searchSoReceiveCasesData(SoReceiveCasesData data) {
return boxForNotificationMapper.searchSoReceiveCasesData(data);
}
@Override
@Transactional
public void deleteSoReceiveCasesData(SoReceiveCasesData data) {
// 参数校验
if (data == null || data.getId() == null || data.getSite() == null || data.getBuNo() == null) {
throw new RuntimeException("参数不完整");
}
// 删除记录前需要将对应的库存卷的上级标签恢复为自己的卷号
SoReceiveCasesData caseData = boxForNotificationMapper.searchSoReceiveCasesData(data).stream()
.filter(item -> item.getId().equals(data.getId()))
.findFirst()
.orElse(null);
if (caseData != null) {
// 恢复库存的上级标签
boxForNotificationMapper.updateStockParentRollType(
caseData.getRollNo(),
caseData.getRollNo(),
null,
data.getSite(),
data.getBuNo()
);
}
// 删除盒清单记录
boxForNotificationMapper.deleteSoReceiveCasesData(data);
}
@Override
@Transactional
public SoReceiveCasesData validateAndScanCaseRoll(SoReceiveCasesData data) {
// 参数校验
if (data == null || data.getSite() == null || data.getCasesNo() == null
|| data.getRollNo() == null || data.getPartNo() == null) {
throw new RuntimeException("参数不完整");
}
// 查询卷的信息并进行校验
SoReceiveCasesData rollInfo = boxForNotificationMapper.validateCaseRoll(
data.getSite(),
data.getPartNo(),
data.getRollNo(),
data.getCasesNo()
);
if (rollInfo == null) {
throw new RuntimeException("未找到对应的卷信息,请检查卷标签和物料编码是否正确");
}
// 校验1: 检查状态是否为"在库"
if (!"在库".equals(rollInfo.getStatus())) {
throw new RuntimeException("该标签状态不是在库(当前状态:" + rollInfo.getStatus() + "),请检查");
}
// 校验2: 检查上级标签类型
if ("盒标签".equals(rollInfo.getParentRollType()) || "箱标签".equals(rollInfo.getParentRollType())) {
throw new RuntimeException("该标签已经装盒/装箱,不允许重复扫描");
}
// 校验3: 检查合约号码
// 需要查询出库单明细获取合约号进行比对
List<OutboundNotificationDetailEntity> outboundDetails = boxForNotificationMapper.searchOutboundNotificationDetail(
data.getSite(),
data.getBuNo(),
data.getNotifyNo()
);
if (outboundDetails == null || outboundDetails.isEmpty()) {
throw new RuntimeException("未找到对应的出库单明细");
}
// 检查是否有匹配的合约号只要有一行的合约号匹配即可
boolean batchMatched = outboundDetails.stream()
.filter(detail -> detail.getPartNo() != null && detail.getPartNo().equals(data.getPartNo()))
.anyMatch(detail -> detail.getOutBatchNo() != null && detail.getOutBatchNo().equals(rollInfo.getBatchNo()));
if (!batchMatched) {
throw new RuntimeException("该标签合约号码(" + rollInfo.getBatchNo() + ")不符,请检查");
}
// 校验通过返回卷信息
return rollInfo;
}
@Override
@Transactional
public void saveCaseRollList(List<SoReceiveCasesData> dataList) {
if (dataList == null || dataList.isEmpty()) {
throw new RuntimeException("保存数据为空");
}
SysUserEntity currentUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
for (SoReceiveCasesData data : dataList) {
// 设置创建人
data.setCreateBy(currentUser.getUsername());
// 保存到so_receive_cases表
boxForNotificationMapper.saveSoReceiveCases(data);
// 更新inventory_stock表的parent_roll_no为盒标签parent_roll_type为"盒标签"
boxForNotificationMapper.updateStockParentRollType(data.getRollNo(), data.getCasesNo(), "盒标签", data.getSite(), data.getBuNo());
}
}
}

97
src/main/resources/mapper/boxManage/BoxForNotificationMapper.xml

@ -130,4 +130,101 @@
left join inventory_stock c on b.site = c.site and b.final_roll_no = c.roll_no and b.bu_no = c.bu_no
where a.site = #{site} and a.order_no = #{orderNo} and a.bu_no = #{buNo}
</select>
<!-- 盒清单相关SQL -->
<select id="searchSoReceiveCasesData" resultType="SoReceiveCasesData">
SELECT
s.Id as id,
s.NotifyNo as notifyNo,
s.cases_no as casesNo,
s.roll_no as rollNo,
s.roll_qty as rollQty,
s.part_no as partNo,
s.part_desc as partDesc,
s.create_date as createDate,
s.create_by as createBy,
s.Remark as remark,
s.site,
s.bu_no as buNo
FROM so_receive_cases s
<where>
<if test="site != null and site != ''">
AND s.site = #{site}
</if>
<if test="buNo != null and buNo != ''">
AND s.bu_no = #{buNo}
</if>
<if test="notifyNo != null and notifyNo != ''">
AND s.NotifyNo = #{notifyNo}
</if>
<if test="casesNo != null and casesNo != ''">
AND s.cases_no = #{casesNo}
</if>
</where>
ORDER BY s.create_date DESC
</select>
<delete id="deleteSoReceiveCasesData">
DELETE FROM so_receive_cases
WHERE Id = #{id}
AND site = #{site}
AND bu_no = #{buNo}
</delete>
<select id="validateCaseRoll" resultType="SoReceiveCasesData">
SELECT
#{casesNo} as casesNo,
a.roll_no as rollNo,
a.qty_on_hand as rollQty,
a.part_no as partNo,
b.PartDescription as partDesc,
a.batch_no as batchNo,
a.status,
a.parent_roll_type as parentRollType
FROM
inventory_stock a
INNER JOIN part b ON a.site = b.site
AND a.part_no = b.PartNo
WHERE
a.site = #{site}
AND a.roll_no = #{rollNo}
AND a.part_no = #{partNo}
</select>
<insert id="saveSoReceiveCases">
INSERT INTO so_receive_cases (
NotifyNo,
cases_no,
roll_no,
roll_qty,
part_no,
part_desc,
create_date,
create_by,
Remark,
site,
bu_no
) VALUES (
#{notifyNo},
#{casesNo},
#{rollNo},
#{rollQty},
#{partNo},
#{partDesc},
GETDATE(),
#{createBy},
#{remark},
#{site},
#{buNo}
)
</insert>
<update id="updateStockParentRollType">
UPDATE inventory_stock
SET parent_roll_no = #{parentRollNo},
parent_roll_type = #{parentRollType}
WHERE roll_no = #{rollNo}
AND site = #{site}
AND bu_no = #{buNo}
</update>
</mapper>
Loading…
Cancel
Save