From 3f0b8e3d31a02bd94e20cf051b7e5935e72957f8 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Tue, 9 Jun 2026 11:09:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/vo/product/ErpProductRespVO.java | 27 ++++++++ .../product/vo/product/ProductSaveReqVO.java | 25 ++++++++ .../vo/product/ProductSupplierRespVO.java | 22 +++++++ .../vo/product/ProductSupplierSaveReqVO.java | 19 ++++++ .../dal/dataobject/product/ErpProductDO.java | 37 ++++++++++- .../ProductSupplierRelDO.java | 39 +++++++++++ .../ProductSupplierRelMapper.java | 16 +++++ .../product/ErpProductServiceImpl.java | 64 +++++++++++++++++++ .../service/purchase/ErpSupplierService.java | 4 +- .../purchase/ErpSupplierServiceImpl.java | 24 ++++++- 10 files changed, 274 insertions(+), 3 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/productsupplierrel/ProductSupplierRelDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/productsupplierrel/ProductSupplierRelMapper.java diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java index d3cfe5baf..ad3452d73 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -93,6 +93,27 @@ public class ErpProductRespVO extends ErpProductDO { @ExcelProperty("预警库存") private BigDecimal safetyNumber; + @Schema(description = "默认仓库 ID", example = "1") + private Long defaultWarehouseId; + + @Schema(description = "默认仓库名称", example = "成品仓") + private String defaultWarehouseName; + + @Schema(description = "是否易损件", example = "1") + private Integer fragileFlag; + + @Schema(description = "采购周期(天)", example = "30") + private Integer purchaseCycle; + + @Schema(description = "备件等级", example = "A") + private String sparePartLevel; + + @Schema(description = "品牌", example = "SKF") + private String brand; + + @Schema(description = "型号", example = "6205-2RS") + private String model; + @Schema(description = "二维码地址", example = "") private String qrcodeUrl; // @@ -116,4 +137,10 @@ public class ErpProductRespVO extends ErpProductDO { @Schema(description = "默认包装方案 ID", example = "1") private Long defaultPackagingSchemeId; + + @Schema(description = "供应商列表") + private List suppliers; + + @Schema(description = "默认供应商 ID", example = "1") + private Long defaultSupplierId; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java index 7b23e2676..6b7d42820 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java @@ -64,6 +64,24 @@ public class ProductSaveReqVO { @Schema(description = "预警库存", example = "161.87") private BigDecimal safetyNumber; + @Schema(description = "默认仓库 ID", example = "1") + private Long defaultWarehouseId; + + @Schema(description = "是否易损件", example = "1") + private Integer fragileFlag; + + @Schema(description = "采购周期(天)", example = "30") + private Integer purchaseCycle; + + @Schema(description = "备件等级", example = "A") + private String sparePartLevel; + + @Schema(description = "品牌", example = "SKF") + private String brand; + + @Schema(description = "型号", example = "6205-2RS") + private String model; + @Schema(description = "关联设备ID列表", example = "[11,15,23]") private List deviceIds; @@ -76,4 +94,11 @@ public class ProductSaveReqVO { @Schema(description = "默认包装方案 ID", example = "1") private Long defaultPackagingSchemeId; + + @Schema(description = "供应商列表") + @Valid + private List suppliers; + + @Schema(description = "默认供应商 ID", example = "1") + private Long defaultSupplierId; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierRespVO.java new file mode 100644 index 000000000..866ab251c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 产品关联供应商 Response VO") +@Data +public class ProductSupplierRespVO { + + @Schema(description = "关联记录 ID", example = "1") + private Long id; + + @Schema(description = "供应商 ID", example = "1") + private Long supplierId; + + @Schema(description = "供应商名称", example = "默认供应商") + private String supplierName; + + @Schema(description = "是否默认供应商", example = "1") + private Integer defaultStatus; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierSaveReqVO.java new file mode 100644 index 000000000..be4d61fd5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSupplierSaveReqVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 产品关联供应商 Request VO") +@Data +public class ProductSupplierSaveReqVO { + + @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "供应商 ID 不能为空") + private Long supplierId; + + @Schema(description = "是否默认供应商", example = "1") + private Integer defaultStatus; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java index e42b5f9b8..a435159de 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java @@ -105,9 +105,44 @@ public class ErpProductDO extends BaseDO { */ private BigDecimal safetyNumber; + /** + * 默认仓库编号 + */ + private Long defaultWarehouseId; + + /** + * 默认仓库名称 + */ + private String defaultWarehouseName; + + /** + * 是否易损件 + */ + private Integer fragileFlag; + + /** + * 采购周期(天) + */ + private Integer purchaseCycle; + + /** + * 备件等级 + */ + private String sparePartLevel; + + /** + * 品牌 + */ + private String brand; + + /** + * 型号 + */ + private String model; + /** * 二维码 */ @TableField(exist = false) private String qrcodeUrl; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/productsupplierrel/ProductSupplierRelDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/productsupplierrel/ProductSupplierRelDO.java new file mode 100644 index 000000000..3f6af1485 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/productsupplierrel/ProductSupplierRelDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.productsupplierrel; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@TableName("erp_product_supplier_rel") +@KeySequence("erp_product_supplier_rel_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductSupplierRelDO extends BaseDO { + + @TableId + private Long id; + + private Long productId; + + private Long supplierId; + + private String supplierName; + + private Integer defaultStatus; + + private Integer sort; + + private String remark; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/productsupplierrel/ProductSupplierRelMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/productsupplierrel/ProductSupplierRelMapper.java new file mode 100644 index 000000000..1216581c7 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/productsupplierrel/ProductSupplierRelMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.productsupplierrel; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.productsupplierrel.ProductSupplierRelDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ProductSupplierRelMapper extends BaseMapperX { + + default List selectListByProductId(Long productId) { + return selectList(ProductSupplierRelDO::getProductId, productId); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index e229d83d5..f558e7826 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -22,13 +22,19 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.module.erp.dal.dataobject.productdevicerel.ProductDeviceRelDO; import cn.iocoder.yudao.module.erp.dal.dataobject.productpackagingschemerel.ProductPackagingSchemeRelDO; import cn.iocoder.yudao.module.erp.dal.dataobject.productmoldrel.ProductMoldRelDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.productsupplierrel.ProductSupplierRelDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; import cn.iocoder.yudao.module.erp.dal.mysql.productdevicerel.ProductDeviceRelMapper; import cn.iocoder.yudao.module.erp.dal.mysql.productpackagingschemerel.ProductPackagingSchemeRelMapper; import cn.iocoder.yudao.module.erp.dal.mysql.productmoldrel.ProductMoldRelMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.productsupplierrel.ProductSupplierRelMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -88,6 +94,9 @@ public class ErpProductServiceImpl implements ErpProductService { @Resource private ProductPackagingSchemeRelMapper productPackagingSchemeRelMapper; + @Resource + private ProductSupplierRelMapper productSupplierRelMapper; + @Resource @Lazy // 延迟注入 @@ -96,6 +105,12 @@ public class ErpProductServiceImpl implements ErpProductService { @Resource private ErpPackagingSchemeService packagingSchemeService; + @Resource + private ErpWarehouseService warehouseService; + + @Resource + private ErpSupplierService supplierService; + @Resource private QrcodeRecordService qrcodeService; @@ -152,6 +167,8 @@ public class ErpProductServiceImpl implements ErpProductService { product.setBarCode(code); } + fillDefaultWarehouse(product, createReqVO.getDefaultWarehouseId()); + productMapper.insert(product); @@ -190,6 +207,7 @@ public class ErpProductServiceImpl implements ErpProductService { } saveProductPackagingSchemes(product.getId(), createReqVO.getPackagingSchemes(), createReqVO.getDefaultPackagingSchemeId()); + saveProductSuppliers(product.getId(), createReqVO.getSuppliers(), createReqVO.getDefaultSupplierId()); // 生成二维码 CodeTypeEnum codeType = autoCodeUtil.queryCodeType("PRODUCT_CODE_GENERATE"); @@ -229,6 +247,7 @@ public class ErpProductServiceImpl implements ErpProductService { updateObj.setCategoryId(id); id = productCategory.getParentId(); } + fillDefaultWarehouse(updateObj, updateReqVO.getDefaultWarehouseId()); productMapper.updateById(updateObj); // 先删除旧关联(推荐逻辑删;如果你们没做逻辑删,也可以物理删) @@ -277,6 +296,10 @@ public class ErpProductServiceImpl implements ErpProductService { .eq(ProductPackagingSchemeRelDO::getProductId, updateObj.getId())); saveProductPackagingSchemes(updateObj.getId(), updateReqVO.getPackagingSchemes(), updateReqVO.getDefaultPackagingSchemeId()); + productSupplierRelMapper.delete(Wrappers.lambdaQuery() + .eq(ProductSupplierRelDO::getProductId, updateObj.getId())); + saveProductSuppliers(updateObj.getId(), updateReqVO.getSuppliers(), updateReqVO.getDefaultSupplierId()); + } @Override @@ -342,6 +365,10 @@ public class ErpProductServiceImpl implements ErpProductService { respVO.setPackagingSchemes(BeanUtils.toBean(packagingSchemeRels, ProductPackagingSchemeRespVO.class)); packagingSchemeRels.stream().filter(item -> Integer.valueOf(1).equals(item.getDefaultStatus())).findFirst() .ifPresent(item -> respVO.setDefaultPackagingSchemeId(item.getPackagingSchemeId())); + List supplierRels = productSupplierRelMapper.selectListByProductId(id); + respVO.setSuppliers(BeanUtils.toBean(supplierRels, ProductSupplierRespVO.class)); + supplierRels.stream().filter(item -> Integer.valueOf(1).equals(item.getDefaultStatus())).findFirst() + .ifPresent(item -> respVO.setDefaultSupplierId(item.getSupplierId())); if (erpProductCategoryDO !=null ){ respVO.setCategoryType(erpProductCategoryDO.getType()); } @@ -383,6 +410,43 @@ public class ErpProductServiceImpl implements ErpProductService { productPackagingSchemeRelMapper.insertBatch(relList); } + private void fillDefaultWarehouse(ErpProductDO product, Long defaultWarehouseId) { + if (defaultWarehouseId == null) { + product.setDefaultWarehouseId(null); + product.setDefaultWarehouseName(null); + return; + } + ErpWarehouseDO warehouse = warehouseService.getWarehouse(defaultWarehouseId); + if (warehouse == null) { + throw exception(WAREHOUSE_NOT_EXISTS); + } + product.setDefaultWarehouseId(warehouse.getId()); + product.setDefaultWarehouseName(warehouse.getName()); + } + + private void saveProductSuppliers(Long productId, List suppliers, Long defaultSupplierId) { + if (CollUtil.isEmpty(suppliers)) { + return; + } + List supplierIds = suppliers.stream().map(ProductSupplierSaveReqVO::getSupplierId) + .distinct().collect(Collectors.toList()); + if (defaultSupplierId != null && !supplierIds.contains(defaultSupplierId)) { + throw exception(SUPPLIER_NOT_EXISTS); + } + List supplierList = supplierService.validSupplierList(supplierIds); + Map supplierMap = convertMap(supplierList, ErpSupplierDO::getId); + List relList = supplierIds.stream().map(supplierId -> { + ErpSupplierDO supplier = supplierMap.get(supplierId); + ProductSupplierRelDO rel = new ProductSupplierRelDO(); + rel.setProductId(productId); + rel.setSupplierId(supplierId); + rel.setSupplierName(supplier.getName()); + rel.setDefaultStatus(defaultSupplierId != null && defaultSupplierId.equals(supplierId) ? 1 : 0); + return rel; + }).collect(Collectors.toList()); + productSupplierRelMapper.insertBatch(relList); + } + @Override public ErpProductRespVO getProduct(Long id, String code) { if (id != null) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java index ba06cbdbe..3c22cf6cb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java @@ -66,6 +66,8 @@ public interface ErpSupplierService { */ List getSupplierList(Collection ids); + List validSupplierList(Collection ids); + /** * 获得供应商 Map * @@ -93,4 +95,4 @@ public interface ErpSupplierService { */ List getSupplierListByStatus(Integer status); -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java index af6f2ac23..3e2babed7 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java @@ -12,9 +12,12 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_ENABLE; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_EXISTS; @@ -82,6 +85,25 @@ public class ErpSupplierServiceImpl implements ErpSupplierService { return supplierMapper.selectBatchIds(ids); } + @Override + public List validSupplierList(Collection ids) { + if (ids == null || ids.isEmpty()) { + return Collections.emptyList(); + } + List list = supplierMapper.selectBatchIds(ids); + Map supplierMap = convertMap(list, ErpSupplierDO::getId); + for (Long id : ids) { + ErpSupplierDO supplier = supplierMap.get(id); + if (supplier == null) { + throw exception(SUPPLIER_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(supplier.getStatus())) { + throw exception(SUPPLIER_NOT_ENABLE, supplier.getName()); + } + } + return list; + } + @Override public PageResult getSupplierPage(ErpSupplierPageReqVO pageReqVO) { return supplierMapper.selectPage(pageReqVO); @@ -92,4 +114,4 @@ public class ErpSupplierServiceImpl implements ErpSupplierService { return supplierMapper.selectListByStatus(status); } -} \ No newline at end of file +}