Merge remote-tracking branch 'origin/main'

main
liutao 23 hours ago
commit 9ef27c432e

@ -25,6 +25,11 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable {
OTHER_OUT(20, "其他出库"),
OTHER_OUT_CANCEL(21, "其他出库(作废)"),
MATERIAL_IN(25, "物料入库"),
MATERIAL_IN_CANCEL(26, "物料入库(作废)"),
MATERIAL_OUT(27, "物料出库"),
MATERIAL_OUT_CANCEL(28, "物料出库(作废)"),
MOVE_IN(30, "调拨入库"),
MOVE_IN_CANCEL(31, "调拨入库(作废)"),
MOVE_OUT(32, "调拨出库"),
@ -47,7 +52,6 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable {
PURCHASE_RETURN(80, "采购退货出库"),
PURCHASE_RETURN_CANCEL(81, "采购退货出库(作废)"),
SPARE_PARTS(90, "备件入库"),
SPARE_PARTS_INVALIDATION(91, "备件入库(作废)"),
@ -89,7 +93,6 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable {
if (type == null) {
return null;
}
// status = 10 表示作废
if (Objects.equals(status, 10)) {
return type + 1;
}

@ -9,12 +9,14 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockRespVO;
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.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockService;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
@ -55,6 +57,8 @@ public class ErpStockController {
private ErpWarehouseService warehouseService;
@Resource
private WarehouseAreaService warehouseAreaService;
@Resource
private ErpStockRecordService stockRecordService;
@GetMapping("/get")
@Operation(summary = "获得产品库存")
@ -110,13 +114,17 @@ public class ErpStockController {
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(pageResult.getList(), ErpStockDO::getAreaId));
return BeanUtils.toBean(pageResult, ErpStockRespVO.class, stock -> {
MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName()).setBarCode(product.getBarCode())
.setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())
.setCategoryType(product.getCategoryType()));
MapUtils.findAndThen(productMap, stock.getProductId(), product -> {
stock.setProductName(product.getName()).setBarCode(product.getBarCode())
.setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())
.setCategoryType(product.getCategoryType());
fillProductExtraInfo(stock, product);
});
MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName()));
if (stock.getAreaName() == null) {
MapUtils.findAndThen(areaMap, stock.getAreaId(), area -> stock.setAreaName(area.getAreaName()));
}
fillRecentRecordTime(stock);
});
}
@ -132,6 +140,7 @@ public class ErpStockController {
respVO.setCategoryName(product.getCategoryName());
respVO.setUnitName(product.getUnitName());
respVO.setCategoryType(product.getCategoryType());
fillProductExtraInfo(respVO, product);
}
ErpWarehouseDO warehouse = warehouseService.getWarehouse(stock.getWarehouseId());
if (warehouse != null) {
@ -143,7 +152,31 @@ public class ErpStockController {
respVO.setAreaName(area.getAreaName());
}
}
fillRecentRecordTime(respVO);
return respVO;
}
private void fillRecentRecordTime(ErpStockRespVO stock) {
stock.setRecentInTime(stockRecordService.getLatestRecordTime(
stock.getProductId(), stock.getWarehouseId(), stock.getAreaId(), true));
stock.setRecentOutTime(stockRecordService.getLatestRecordTime(
stock.getProductId(), stock.getWarehouseId(), stock.getAreaId(), false));
}
private void fillProductExtraInfo(ErpStockRespVO stock, ErpProductRespVO product) {
stock.setUnitId(product.getUnitId());
stock.setPurchaseUnitId(product.getPurchaseUnitId());
stock.setPurchaseUnitName(product.getPurchaseUnitName());
stock.setPurchaseUnitConvertQuantity(product.getPurchaseUnitConvertQuantity());
stock.setDefaultPackagingSchemeId(product.getDefaultPackagingSchemeId());
stock.setDefaultPackagingScheme(findDefaultPackagingScheme(product));
}
private ProductPackagingSchemeRespVO findDefaultPackagingScheme(ErpProductRespVO product) {
if (product.getDefaultPackagingSchemeId() == null || CollUtil.isEmpty(product.getPackagingSchemes())) {
return null;
}
return product.getPackagingSchemes().stream()
.filter(item -> product.getDefaultPackagingSchemeId().equals(item.getPackagingSchemeId()))
.findFirst()
.orElse(null);
}
}

@ -254,6 +254,13 @@ public class ErpStockInController {
item.setProductBarCode(product.getBarCode());
item.setProductUnitName(product.getUnitName());
item.setCategoryType(product.getCategoryType());
item.setSupplierId(product.getDefaultSupplierId());
if (product.getDefaultSupplierId() != null && CollUtil.isNotEmpty(product.getSuppliers())) {
product.getSuppliers().stream()
.filter(supplier -> Objects.equals(supplier.getSupplierId(), product.getDefaultSupplierId()))
.findFirst()
.ifPresent(supplier -> item.setSupplierName(supplier.getSupplierName()));
}
});
}));
stockInVO.setProductNames(CollUtil.join(stockInVO.getItems(), ",", ErpStockInRespVO.Item::getProductName));

@ -251,6 +251,13 @@ public class ErpStockOutController {
item.setProductBarCode(product.getBarCode());
item.setProductUnitName(product.getUnitName());
item.setCategoryType(product.getCategoryType());
item.setSupplierId(product.getDefaultSupplierId());
if (product.getDefaultSupplierId() != null && CollUtil.isNotEmpty(product.getSuppliers())) {
product.getSuppliers().stream()
.filter(supplier -> Objects.equals(supplier.getSupplierId(), product.getDefaultSupplierId()))
.findFirst()
.ifPresent(supplier -> item.setSupplierName(supplier.getSupplierName()));
}
});
}));
stockOutVO.setProductNames(CollUtil.join(stockOutVO.getItems(), ",", ErpStockOutRespVO.Item::getProductName));

@ -12,10 +12,15 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockOutService;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
@ -50,6 +55,10 @@ public class ErpStockRecordController {
@Resource
private ErpStockRecordService stockRecordService;
@Resource
private ErpStockInService stockInService;
@Resource
private ErpStockOutService stockOutService;
@Resource
private ErpProductService productService;
@Resource
private ErpWarehouseService warehouseService;
@ -101,6 +110,8 @@ public class ErpStockRecordController {
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(pageResult.getList(), record -> Long.parseLong(record.getCreator())));
return BeanUtils.toBean(pageResult, ErpStockRecordRespVO.class, stock -> {
stock.setBizDirection(resolveBizDirection(stock.getBizType()));
stock.setBizDocType(resolveBizDocType(stock.getBizType(), stock.getBizId()));
MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName())
.setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())
.setCategoryType(product.getCategoryType()));
@ -117,6 +128,8 @@ public class ErpStockRecordController {
return null;
}
ErpStockRecordRespVO respVO = BeanUtils.toBean(stockRecord, ErpStockRecordRespVO.class);
respVO.setBizDirection(resolveBizDirection(respVO.getBizType()));
respVO.setBizDocType(resolveBizDocType(stockRecord.getBizType(), stockRecord.getBizId()));
ErpProductRespVO product = productService.getProduct(stockRecord.getProductId());
if (product != null) {
respVO.setProductName(product.getName());
@ -143,4 +156,31 @@ public class ErpStockRecordController {
return respVO;
}
private String resolveBizDocType(Integer bizType, Long bizId) {
if (bizType == null || bizId == null) {
return null;
}
String bizDirection = resolveBizDirection(bizType);
if ("入库".equals(bizDirection)) {
ErpStockInDO stockIn = stockInService.getStockIn(bizId);
return stockIn != null ? stockIn.getInType() : null;
}
if ("出库".equals(bizDirection)) {
ErpStockOutDO stockOut = stockOutService.getStockOut(bizId);
return stockOut != null ? stockOut.getOutType() : null;
}
return null;
}
private String resolveBizDirection(Integer bizType) {
if (bizType == null) {
return null;
}
return java.util.Arrays.stream(ErpStockRecordBizTypeEnum.values())
.filter(item -> java.util.Objects.equals(item.getType(), bizType))
.findFirst()
.map(item -> item.getName().contains("入库") ? "入库" : "出库")
.orElse(null);
}
}

@ -151,6 +151,12 @@ public class ErpStockInRespVO {
@Schema(description = "产品单位名称", example = "盒")
private String productUnitName;
@Schema(description = "默认供应商编号", example = "1")
private Long supplierId;
@Schema(description = "默认供应商名称", example = "供应商A")
private String supplierName;
@Schema(description = "仓库名称", example = "A仓")
private String warehouseName;

@ -147,6 +147,12 @@ public class ErpStockOutRespVO {
@Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒")
private String productUnitName;
@Schema(description = "默认供应商编号", example = "1")
private Long supplierId;
@Schema(description = "默认供应商名称", example = "供应商A")
private String supplierName;
@Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal stockCount;

@ -51,6 +51,14 @@ public class ErpStockRecordRespVO {
@DictFormat(DictTypeConstants.STOCK_RECORD_BIZ_TYPE)
private Integer bizType;
@Schema(description = "单据方向", example = "入库")
@ExcelProperty("单据方向")
private String bizDirection;
@Schema(description = "单据类型", example = "产品入库")
@ExcelProperty("单据类型")
private String bizDocType;
@Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27093")
@ExcelProperty("业务编号")
private Long bizId;

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
@ -61,6 +62,18 @@ public class ErpStockRespVO {
@Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个")
@ExcelProperty("单位")
private String unitName;
@Schema(description = "Unit ID", example = "8869")
private Long unitId;
@Schema(description = "Purchase Unit ID", example = "8890")
private Long purchaseUnitId;
@Schema(description = "Purchase Unit Name", example = "BOX")
private String purchaseUnitName;
@Schema(description = "Purchase Unit Convert Quantity", example = "100")
private BigDecimal purchaseUnitConvertQuantity;
@Schema(description = "Default Packaging Scheme ID", example = "1")
private Long defaultPackagingSchemeId;
@Schema(description = "Default Packaging Scheme")
private ProductPackagingSchemeRespVO defaultPackagingScheme;
// ========== 仓库信息 ==========
@ -68,4 +81,12 @@ public class ErpStockRespVO {
@ExcelProperty("仓库名称")
private String warehouseName;
@Schema(description = "最近入库时间")
@ExcelProperty("最近入库时间")
private java.time.LocalDateTime recentInTime;
@Schema(description = "最近出库时间")
@ExcelProperty("最近出库时间")
private java.time.LocalDateTime recentOutTime;
}

@ -2,8 +2,10 @@ 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 cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
@ -13,4 +15,9 @@ public interface ProductSupplierRelMapper extends BaseMapperX<ProductSupplierRel
return selectList(ProductSupplierRelDO::getProductId, productId);
}
default List<ProductSupplierRelDO> selectListByProductIds(Collection<Long> productIds) {
return selectList(new LambdaQueryWrapperX<ProductSupplierRelDO>()
.inIfPresent(ProductSupplierRelDO::getProductId, productIds));
}
}

@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO;
import com.alibaba.excel.util.StringUtils;
import org.apache.ibatis.annotations.Mapper;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -47,5 +49,15 @@ public interface ErpStockRecordMapper extends BaseMapperX<ErpStockRecordDO> {
return selectPage(reqVO,erpStockRecordDOLambdaQueryWrapperX);
}
default LocalDateTime selectLatestRecordTime(Long productId, Long warehouseId, Long areaId, boolean inbound) {
ErpStockRecordDO record = selectOne(new LambdaQueryWrapperX<ErpStockRecordDO>()
.eq(ErpStockRecordDO::getProductId, productId)
.eq(ErpStockRecordDO::getWarehouseId, warehouseId)
.eqIfPresent(ErpStockRecordDO::getAreaId, areaId)
.gt(inbound, ErpStockRecordDO::getCount, BigDecimal.ZERO)
.lt(!inbound, ErpStockRecordDO::getCount, BigDecimal.ZERO)
.orderByDesc(ErpStockRecordDO::getRecordTime, ErpStockRecordDO::getId)
.last("LIMIT 1"));
return record != null ? record.getRecordTime() : null;
}
}

@ -564,12 +564,22 @@ public class ErpProductServiceImpl implements ErpProductService {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
List<ProductSupplierRelDO> supplierRels = productSupplierRelMapper.selectListByProductIds(
convertSet(list, ErpProductDO::getId));
Map<Long, List<ProductPackagingSchemeRespVO>> packagingSchemeMap =
productPackagingSchemeRelMapper.selectListByProductIds(convertSet(list, ErpProductDO::getId))
.stream()
.collect(Collectors.groupingBy(ProductPackagingSchemeRelDO::getProductId,
Collectors.mapping(rel -> BeanUtils.toBean(rel, ProductPackagingSchemeRespVO.class),
Collectors.toList())));
Map<Long, List<ProductSupplierRespVO>> supplierMap = supplierRels.stream()
.collect(Collectors.groupingBy(ProductSupplierRelDO::getProductId,
Collectors.mapping(rel -> BeanUtils.toBean(rel, ProductSupplierRespVO.class),
Collectors.toList())));
Map<Long, Long> defaultSupplierMap = supplierRels.stream()
.filter(item -> Integer.valueOf(1).equals(item.getDefaultStatus()))
.collect(Collectors.toMap(ProductSupplierRelDO::getProductId, ProductSupplierRelDO::getSupplierId,
(supplierId1, supplierId2) -> supplierId1));
Map<Long, ErpProductCategoryDO> categoryMap = productCategoryService.getProductCategoryMap(
convertSet(list, ErpProductDO::getCategoryId));
Map<Long, ErpProductCategoryDO> subCategoryMap = productCategoryService.getProductCategoryMap(
@ -594,6 +604,8 @@ public class ErpProductServiceImpl implements ErpProductService {
MapUtils.findAndThen(purchaseUnitMap, product.getPurchaseUnitId(),
unit -> product.setPurchaseUnitName(unit.getName()));
product.setPackagingSchemes(packagingSchemeMap.getOrDefault(product.getId(), Collections.emptyList()));
product.setSuppliers(supplierMap.getOrDefault(product.getId(), Collections.emptyList()));
product.setDefaultSupplierId(defaultSupplierMap.get(product.getId()));
if (Boolean.TRUE.equals(product.getDeleted())) {
product.setName(product.getName() + "(已被删除)");
}

@ -371,10 +371,8 @@ public class ErpStockInServiceImpl implements ErpStockInService {
}
} else {
ErpProductRespVO productDO = productService.getProduct(stockInItem.getProductId());
Integer recordBizType = bizType != null ? bizType
: (approve ? ErpStockRecordBizTypeEnum.getTypeByName(stockIn.getInType())
: ErpStockRecordBizTypeEnum.getTypeByName(stockIn.getInType(), 10));
stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO(
Integer recordBizType = resolveRecordBizType(stockIn.getInType(), approve, bizType);
stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO(
stockInItem.getProductId(), productDO.getCategoryId(), productDO.getCategoryType(), stockInItem.getWarehouseId(),
stockInItem.getAreaId(), stockInItem.getAreaName(), count,
recordBizType, stockInItem.getInId(), stockInItem.getId(), stockIn.getNo(), stockIn.getInTime()));
@ -382,6 +380,14 @@ public class ErpStockInServiceImpl implements ErpStockInService {
});
}
private Integer resolveRecordBizType(String inType, boolean approve, Integer bizType) {
if (bizType != null) {
return bizType;
}
return approve ? ErpStockRecordBizTypeEnum.getTypeByName(inType)
: ErpStockRecordBizTypeEnum.getTypeByName(inType, 10);
}
private boolean itemNeedUpdateMoldStatus(MoldBrandDO moldDO) {
if (Objects.equals(moldDO.getStatus(), MoldBrandStatusEnum.STANDBY.getStatus())) {
throw exception(STOCK_ALERADY_IN, moldDO.getCode() + "-" + moldDO.getName());

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import javax.validation.Valid;
import java.time.LocalDateTime;
/**
* ERP Service
@ -37,4 +38,6 @@ public interface ErpStockRecordService {
*/
void createStockRecord(@Valid ErpStockRecordCreateReqBO createReqBO);
LocalDateTime getLatestRecordTime(Long productId, Long warehouseId, Long areaId, boolean inbound);
}

@ -14,6 +14,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* ERP Service
@ -43,6 +44,11 @@ public class ErpStockRecordServiceImpl implements ErpStockRecordService {
return stockRecordMapper.selectPage(pageReqVO);
}
@Override
public LocalDateTime getLatestRecordTime(Long productId, Long warehouseId, Long areaId, boolean inbound) {
return stockRecordMapper.selectLatestRecordTime(productId, warehouseId, areaId, inbound);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createStockRecord(ErpStockRecordCreateReqBO createReqBO) {

Loading…
Cancel
Save