feat(box): 重构装箱清单功能并增强序列号生成服务

- 重命名 BoxController 为 BoxListController
- 扩展 BasdeSerialNumberControllerService 中的 generateSerialNumber 方法,支持自定义中间字符串和长度参数
- 在 BoxListController 中新增 getItems 和 getForwards 接口用于获取明细和代发物料列表
- 实现装箱清单 Excel 导出功能,包含基础信息和物料清单数据
- 新增 MaterialCodeForwardImportDTO 数据传输对象用于代发物料导入导出
- 实现代发物料的 Excel 导入导出功能,支持批量处理
- 在 PackagingCodeController 中使用序列号服务生成包装码编号
- 扩展 ShipmentMaterialCodeItemVO 和 ShipmentMaterialCodeQRVO 对象,增加状态和序号字段
- 新增数据库查询方法 getByPackagingCodeId 和 getItemsVOById
- 更新 MyBatis 映射文件,优化查询逻辑并添加排序功能
This commit is contained in:
曹鹏飞 2026-02-06 16:24:01 +08:00
parent be8586f56c
commit 7ac9f182ed
19 changed files with 262 additions and 53 deletions

View File

@ -60,6 +60,11 @@ public class ShipmentMaterialCodeItemVO {
*/
private BigDecimal minPackagingNum;
/**
* 状态0未装箱1已装箱5已安装
*/
private Integer status;
/**
* 创建人
*/

View File

@ -9,6 +9,11 @@ public class ShipmentMaterialCodeQRVO {
private Long id;
/**
* 序号
*/
private Integer index;
/**
* 唯一码
*/
@ -25,10 +30,15 @@ public class ShipmentMaterialCodeQRVO {
private String materialDescribe;
/**
* 数量
* 应发数量
*/
private BigDecimal num;
/**
* 实发数量
*/
private BigDecimal actualNum;
/**
* 单位
*/
@ -38,4 +48,5 @@ public class ShipmentMaterialCodeQRVO {
* 状态0未装箱1已装箱
*/
private Integer status;
}

View File

@ -13,4 +13,5 @@ import com.nflg.wms.repository.entity.WmsShipmentDelivery;
*/
public interface WmsShipmentDeliveryMapper extends BaseMapper<WmsShipmentDelivery> {
WmsShipmentDelivery getByPackagingCodeId(Long id);
}

View File

@ -4,9 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.BoxSearchQO;
import com.nflg.wms.common.pojo.vo.BoxVO;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO;
import com.nflg.wms.common.pojo.vo.ShipmentPackagingCodeVO;
import com.nflg.wms.common.pojo.qo.ShipmentSiteStockItemQO;
import com.nflg.wms.common.pojo.vo.*;
import com.nflg.wms.repository.entity.WmsShipmentPackagingCode;
import java.util.List;
@ -30,4 +29,6 @@ public interface WmsShipmentPackagingCodeMapper extends BaseMapper<WmsShipmentPa
List<ShipmentPackagingCodeVO> searchForUnload(String code);
List<ShipmentMaterialCodeQRVO> getForInstall(Long id);
PageData<ShipmentMaterialCodeItemVO> getItemsVOById(ShipmentSiteStockItemQO qo, Page<?> objectPage);
}

View File

@ -16,4 +16,5 @@ import java.util.List;
*/
public interface IWmsShipmentDeliveryService extends IService<WmsShipmentDelivery> {
WmsShipmentDelivery getByPackagingCodeId(Long id);
}

View File

@ -2,11 +2,11 @@ package com.nflg.wms.repository.service;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.BoxSearchQO;
import com.nflg.wms.common.pojo.vo.BoxVO;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO;
import com.nflg.wms.common.pojo.vo.ShipmentPackagingCodeVO;
import com.nflg.wms.common.pojo.qo.ShipmentSiteStockItemQO;
import com.nflg.wms.common.pojo.vo.*;
import com.nflg.wms.repository.entity.WmsShipmentPackagingCode;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@ -33,4 +33,6 @@ public interface IWmsShipmentPackagingCodeService extends IService<WmsShipmentPa
List<ShipmentPackagingCodeVO> searchForUnload(String code);
List<ShipmentMaterialCodeQRVO> getForInstall(Long id);
PageData<ShipmentMaterialCodeItemVO> getItemsVOById(ShipmentSiteStockItemQO qo);
}

View File

@ -17,4 +17,8 @@ import org.springframework.stereotype.Service;
@Service
public class WmsShipmentDeliveryServiceImpl extends ServiceImpl<WmsShipmentDeliveryMapper, WmsShipmentDelivery> implements IWmsShipmentDeliveryService {
@Override
public WmsShipmentDelivery getByPackagingCodeId(Long id) {
return baseMapper.getByPackagingCodeId(id);
}
}

View File

@ -4,9 +4,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.BoxSearchQO;
import com.nflg.wms.common.pojo.vo.BoxVO;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO;
import com.nflg.wms.common.pojo.vo.ShipmentPackagingCodeVO;
import com.nflg.wms.common.pojo.qo.ShipmentSiteStockItemQO;
import com.nflg.wms.common.pojo.vo.*;
import com.nflg.wms.repository.entity.WmsShipmentPackagingCode;
import com.nflg.wms.repository.mapper.WmsShipmentPackagingCodeMapper;
import com.nflg.wms.repository.service.IWmsShipmentPackagingCodeService;
@ -55,4 +54,9 @@ public class WmsShipmentPackagingCodeServiceImpl extends ServiceImpl<WmsShipment
public List<ShipmentMaterialCodeQRVO> getForInstall(Long id) {
return baseMapper.getForInstall(id);
}
@Override
public PageData<ShipmentMaterialCodeItemVO> getItemsVOById(ShipmentSiteStockItemQO qo) {
return baseMapper.getItemsVOById(qo, new Page<>(qo.getPage(), qo.getPageSize()));
}
}

View File

@ -2,4 +2,10 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.wms.repository.mapper.WmsShipmentDeliveryMapper">
<select id="getByPackagingCodeId" resultType="com.nflg.wms.repository.entity.WmsShipmentDelivery">
SELECT d.*
FROM wms_shipment_delivery d
INNER JOIN wms_shipment_delivery_item di ON d."id"=di.delivery_id
WHERE di.packaging_code_id=#{id}
</select>
</mapper>

View File

@ -3,11 +3,12 @@
<mapper namespace="com.nflg.wms.repository.mapper.WmsShipmentPackagingCodeItemMapper">
<select id="getPackList" resultType="com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO">
SELECT it."id",cit.material_no,cit.material_describe,qr.num
SELECT ROW_NUMBER() OVER () AS "index",it."id",qr.no,cit.material_no,cit.material_describe,cit.num,qr.num as actualNum,cit.unit
FROM wms_shipment_packaging_code_item it
INNER JOIN wms_shipment_material_code_item_qr qr ON it.material_code_item_qr_id=qr."id"
INNER JOIN wms_shipment_material_code_item cit ON qr.item_id=cit."id"
where it.packaging_code_id=#{packagingCodeId}
order by cit.id
</select>
<select id="getList" resultType="com.nflg.wms.common.pojo.vo.ShipmentPackagingCodeMaterialVO">

View File

@ -77,4 +77,13 @@
INNER JOIN wms_shipment_material_code_item mci ON mciq.item_id=mci."id"
where mciq.status!=5 and pci.packaging_code_id=#{id}
</select>
<select id="getItemsVOById" resultType="com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeItemVO">
SELECT mci.material_no,mci.material_describe,mci.num,mciq.num as "actual_num",mci.unit,mci.project_type
,mci.parent_material_describe,mci.production_order_number,mci.box_no,mciq.status
FROM wms_shipment_packaging_code_item pci
INNER JOIN wms_shipment_material_code_item_qr mciq ON pci.material_code_item_qr_id=mciq."id"
INNER JOIN wms_shipment_material_code_item mci ON mciq.item_id=mci."id"
where mciq.status!=5 and pci.packaging_code_id=#{id}
</select>
</mapper>

View File

@ -1,34 +0,0 @@
package com.nflg.wms.shipment.controller;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.BoxSearchQO;
import com.nflg.wms.common.pojo.vo.BoxVO;
import com.nflg.wms.repository.service.IWmsShipmentPackagingCodeService;
import com.nflg.wms.starter.BaseController;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 装箱清单
*/
@RestController
@RequestMapping("box")
public class BoxController extends BaseController {
@Resource
private IWmsShipmentPackagingCodeService packagingCodeService;
/**
* 搜索
*/
@PostMapping("search")
public ApiResult<PageData<BoxVO>> search(@Valid @RequestBody BoxSearchQO qo){
return ApiResult.success(packagingCodeService.searchInCar(qo));
}
}

View File

@ -0,0 +1,111 @@
package com.nflg.wms.shipment.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.BoxSearchQO;
import com.nflg.wms.common.pojo.qo.ShipmentSiteStockItemQO;
import com.nflg.wms.common.pojo.vo.BoxVO;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeItemVO;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO;
import com.nflg.wms.common.util.VUtil;
import com.nflg.wms.repository.entity.WmsShipmentDelivery;
import com.nflg.wms.repository.entity.WmsShipmentMaterialCodeForward;
import com.nflg.wms.repository.entity.WmsShipmentPackagingCode;
import com.nflg.wms.repository.service.IWmsShipmentDeliveryService;
import com.nflg.wms.repository.service.IWmsShipmentMaterialCodeForwardService;
import com.nflg.wms.repository.service.IWmsShipmentPackagingCodeItemService;
import com.nflg.wms.repository.service.IWmsShipmentPackagingCodeService;
import com.nflg.wms.starter.BaseController;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.ttzero.excel.entity.TemplateSheet;
import org.ttzero.excel.entity.Workbook;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 装箱清单
*/
@RestController
@RequestMapping("box")
public class BoxListController extends BaseController {
@Resource
private IWmsShipmentPackagingCodeService packagingCodeService;
@Resource
private IWmsShipmentMaterialCodeForwardService materialCodeForwardService;
@Resource
private IWmsShipmentDeliveryService deliveryService;
@Resource
private IWmsShipmentPackagingCodeItemService packagingCodeItemService;
/**
* 搜索
*/
@PostMapping("search")
public ApiResult<PageData<BoxVO>> search(@Valid @RequestBody BoxSearchQO qo) {
return ApiResult.success(packagingCodeService.searchInCar(qo));
}
/**
* 获取明细
*/
@PostMapping("getItems")
public ApiResult<PageData<ShipmentMaterialCodeItemVO>> getItems(@Valid @RequestBody ShipmentSiteStockItemQO qo) {
return ApiResult.success(packagingCodeService.getItemsVOById(qo));
}
/**
* 获取代发物料列表
*/
@PostMapping("getForwards")
public ApiResult<PageData<WmsShipmentMaterialCodeForward>> getForwards(@Valid @RequestBody ShipmentSiteStockItemQO qo) {
return ApiResult.success(materialCodeForwardService.lambdaQuery()
.eq(WmsShipmentMaterialCodeForward::getPackagingCodeId, qo.getId())
.orderByAsc(WmsShipmentMaterialCodeForward::getId)
.page(new Page<>(qo.getPage(), qo.getPageSize()))
);
}
/**
* 导出装箱清单
* @param id 装箱清单id
*/
@GetMapping("export")
public void export(HttpServletResponse response, @RequestParam Long id) throws IOException {
WmsShipmentPackagingCode info = packagingCodeService.getById(id);
VUtil.trueThrowBusinessError(Objects.isNull(info)).throwMessage("包装箱不存在");
WmsShipmentDelivery delivery = deliveryService.getByPackagingCodeId(id);
VUtil.trueThrowBusinessError(Objects.isNull(delivery)).throwMessage("发货单不存在");
Map<String, String> base = new HashMap<>();
base.put("name", info.getName());
base.put("materialNo", delivery.getMaterialNo());
base.put("deviceNo", delivery.getDeviceNo());
base.put("customerName", delivery.getCustomerName());
base.put("soNo", delivery.getSoNo());
List<ShipmentMaterialCodeQRVO> list = packagingCodeItemService.getPackList(id);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("装箱清单-" + info.getName() + ".xlsx", StandardCharsets.UTF_8));
new Workbook()
.addSheet(new TemplateSheet(new ClassPathResource("template/装箱清单模版.xlsx").getInputStream())
.setData("base", base)
.setData("list", list)
).writeTo(response.getOutputStream());
}
}

View File

@ -10,10 +10,12 @@ import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.*;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeQRVO;
import com.nflg.wms.common.pojo.vo.ShipmentMaterialCodeItemVO;
import com.nflg.wms.common.util.EecExcelUtil;
import com.nflg.wms.common.util.UserUtil;
import com.nflg.wms.common.util.VUtil;
import com.nflg.wms.repository.entity.*;
import com.nflg.wms.repository.service.*;
import com.nflg.wms.shipment.pojo.dto.MaterialCodeForwardImportDTO;
import com.nflg.wms.shipment.service.BasdeSerialNumberControllerService;
import com.nflg.wms.shipment.util.KeyUtil;
import com.nflg.wms.starter.BaseController;
@ -28,6 +30,7 @@ import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.ttzero.excel.entity.ListSheet;
import org.ttzero.excel.entity.TemplateSheet;
import org.ttzero.excel.entity.Workbook;
import org.ttzero.excel.reader.ExcelReader;
@ -498,6 +501,47 @@ public class MaterialCodeController extends BaseController {
return ApiResult.success(info);
}
/**
* 代发物料-导出
*/
@GetMapping("exportForward")
public void exportForward(HttpServletResponse response, @RequestParam Long id) throws IOException {
WmsShipmentMaterialCode materialCode = shipmentMaterialCodeService.getById(id);
VUtil.trueThrowBusinessError(Objects.isNull(materialCode)).throwMessage("清单不存在");
List<WmsShipmentMaterialCodeForward> list = materialCodeForwardService.lambdaQuery()
.eq(WmsShipmentMaterialCodeForward::getMaterialCodeId, id)
.list();
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("代发物料-" + materialCode.getDeviceNo() + ".xlsx", StandardCharsets.UTF_8));
new Workbook()
.addSheet(new ListSheet<>(Convert.toList(MaterialCodeForwardImportDTO.class, list)))
.writeTo(response.getOutputStream());
}
/**
* 代发物料-导入
* @param id 清单ID
*/
@PostMapping("importForward")
public ApiResult<Void> importForward(@RequestParam("file") MultipartFile file, @RequestParam Long id) throws IOException {
List<MaterialCodeForwardImportDTO> list = EecExcelUtil.readTo(file.getInputStream(), MaterialCodeForwardImportDTO.class);
list.removeIf(it -> StrUtil.isBlank(it.getMaterialName())
|| Objects.isNull(it.getNum())
|| StrUtil.isBlank(it.getBoxNo()));
if (CollectionUtil.isNotEmpty(list)) {
materialCodeForwardService.saveBatch(
list.stream()
.map(it -> Convert.convert(WmsShipmentMaterialCodeForward.class, it)
.setMaterialCodeId(id)
.setCreateBy(UserUtil.getUserName())
.setCreateTime(LocalDateTime.now())
)
.toList()
);
}
return ApiResult.success();
}
/**
* 代发物料-添加
*/

View File

@ -17,6 +17,7 @@ import com.nflg.wms.repository.entity.WmsShipmentMaterialCodeItemQr;
import com.nflg.wms.repository.entity.WmsShipmentPackagingCode;
import com.nflg.wms.repository.entity.WmsShipmentPackagingCodeItem;
import com.nflg.wms.repository.service.*;
import com.nflg.wms.shipment.service.BasdeSerialNumberControllerService;
import com.nflg.wms.shipment.util.KeyUtil;
import com.nflg.wms.starter.BaseController;
import jakarta.annotation.Resource;
@ -54,6 +55,9 @@ public class PackagingCodeController extends BaseController {
@Resource
private IDictionaryItemService dictionaryItemService;
@Resource
private BasdeSerialNumberControllerService serialNumberControllerService;
/**
* 新增包装码
*/
@ -62,7 +66,7 @@ public class PackagingCodeController extends BaseController {
List<WmsShipmentPackagingCode> datas = new ArrayList<>();
IntStream.range(0, count).forEach(i -> {
WmsShipmentPackagingCode packagingCode = new WmsShipmentPackagingCode();
packagingCode.setNo(KeyUtil.next());
packagingCode.setNo(serialNumberControllerService.generateSerialNumber(28,"",3));
packagingCode.setCreateBy(UserUtil.getUserName());
packagingCode.setCreateTime(LocalDateTime.now());
datas.add(packagingCode);

View File

@ -0,0 +1,38 @@
package com.nflg.wms.shipment.pojo.dto;
import lombok.Data;
import org.ttzero.excel.annotation.ExcelColumn;
import java.math.BigDecimal;
@Data
public class MaterialCodeForwardImportDTO {
/**
* 物料名称
*/
@ExcelColumn("物料名称*")
private String materialName;
/**
* 应发数量
*/
@ExcelColumn("应发数量*")
private BigDecimal num;
/**
* 装箱号
*/
@ExcelColumn("装箱号*")
private String boxNo;
/**
* 单位
*/
private String unit;
/**
* 备注
*/
private String remark;
}

View File

@ -22,29 +22,30 @@ public class BasdeSerialNumberControllerService {
@Resource
private IBasdeSerialNumberService basdeSerialNumberService;
public String generateSerialNumber(Integer businessType) {
return generateSerialNumber(businessType, LocalDate.now().format(DATE_FORMATTER), 4);
}
@Retryable(
maxAttempts = MAX_RETRY, // 最大重试次数包括第一次调用
backoff = @Backoff(delay = 1000) // 重试间隔1秒
)
public String generateSerialNumber(Integer businessType) {
String currentDate = LocalDate.now().format(DATE_FORMATTER);
public String generateSerialNumber(Integer businessType, String middle, Integer length) {
BasdeSerialNumber serialNumber = basdeSerialNumberService.lambdaQuery()
.eq(BasdeSerialNumber::getBusinessType, businessType)
.one();
if (Objects.isNull(serialNumber)) {
return null;
}
int nextSerial = 0;
if (StrUtil.equals(currentDate, serialNumber.getCurrentDateStr())) {
if (StrUtil.equals(middle, serialNumber.getCurrentDateStr())) {
nextSerial = serialNumber.getMaxSerial();
}
nextSerial = nextSerial + 1;
serialNumber.setMaxSerial(nextSerial);
serialNumber.setCurrentDateStr(currentDate);
serialNumber.setCurrentDateStr(middle);
basdeSerialNumberService.updateById(serialNumber);
// 格式化为4位数字不足补零
return serialNumber.getBusinessPrefixNumber() + currentDate + String.format("%04d", nextSerial);
return serialNumber.getBusinessPrefixNumber() + middle + String.format("%0" + length + "d", nextSerial);
}
}