耗材联动更新

This commit is contained in:
2026-04-10 10:49:35 +08:00
parent 799167a26b
commit 7e698eee0d
10 changed files with 160 additions and 232 deletions

View File

@@ -11,6 +11,7 @@ import com.czg.log.annotation.OperationLog;
import com.czg.product.dto.ProdConsBindDTO; import com.czg.product.dto.ProdConsBindDTO;
import com.czg.product.dto.ProdSkuDTO; import com.czg.product.dto.ProdSkuDTO;
import com.czg.product.dto.ProductDTO; import com.czg.product.dto.ProductDTO;
import com.czg.product.entity.ProductStockFlow;
import com.czg.product.param.*; import com.czg.product.param.*;
import com.czg.product.service.ProdConsRelationService; import com.czg.product.service.ProdConsRelationService;
import com.czg.product.service.ProductService; import com.czg.product.service.ProductService;
@@ -117,6 +118,17 @@ public class ProductController {
return CzgResult.success(); return CzgResult.success();
} }
/**
* 商品-库存变动记录
*/
@GetMapping("stockFlow")
@OperationLog("商品-库存变动记录")
//@SaAdminCheckPermission("consStockFlow:flow")
public CzgResult<Page<ProductStockFlow>> stockFlow(ProductStockFlowParam param) {
Page<ProductStockFlow> data = productService.findProductStockFlowPage(param);
return CzgResult.success(data);
}
/** /**
* 商品-修改 * 商品-修改
*/ */

View File

@@ -39,10 +39,12 @@ public class ConsStockFlow implements Serializable {
*/ */
private Long vendorId; private Long vendorId;
/** /**
* {@link com.czg.product.enums.InOutTypeEnum}
* 出入库类型 in-入库 out-出库 * 出入库类型 in-入库 out-出库
*/ */
private String inOutType; private String inOutType;
/** /**
* {@link com.czg.product.enums.InOutItemEnum}
* 出入库名目 manual-in:手动入库 manual-out:手动出库 win-in:盘盈入库 loss-out:盘亏出库 order-in:订单退款入库 order-out:订单消费出库 damage-out:损耗出库 * 出入库名目 manual-in:手动入库 manual-out:手动出库 win-in:盘盈入库 loss-out:盘亏出库 order-in:订单退款入库 order-out:订单消费出库 damage-out:损耗出库
*/ */
private String inOutItem; private String inOutItem;

View File

@@ -30,4 +30,6 @@ public interface ProdConsRelationService extends IService<ProdConsRelation> {
*/ */
void saveProdConsRelation(ProdConsBindDTO dto); void saveProdConsRelation(ProdConsBindDTO dto);
List<ProdConsRelationDTO> selectListByProdId(Long prodId);
} }

View File

@@ -1,13 +1,19 @@
package com.czg.product.service; package com.czg.product.service;
import com.czg.product.dto.ProductDTO; import com.czg.product.dto.ProductDTO;
import com.czg.product.entity.ConsStockFlow;
import com.czg.product.entity.Product; import com.czg.product.entity.Product;
import com.czg.product.entity.ProductStockFlow;
import com.czg.product.enums.InOutItemEnum;
import com.czg.product.enums.InOutTypeEnum;
import com.czg.product.param.*; import com.czg.product.param.*;
import com.czg.product.vo.ProductStatisticsVo; import com.czg.product.vo.ProductStatisticsVo;
import com.czg.product.vo.ProductStockVO;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -115,4 +121,17 @@ public interface ProductService extends IService<Product> {
* @param param 商品统计入参 * @param param 商品统计入参
*/ */
ProductStatisticsVo getProductStatistics(ProductInfoParam param); ProductStatisticsVo getProductStatistics(ProductInfoParam param);
/**
* 商品出入库流水查询
*
* @param param 查询参数
* @return 分页数据
*/
Page<ProductStockFlow> findProductStockFlowPage(ProductStockFlowParam param);
/**
* 通过商品 进行耗材库存增减
*/
void consStockByProduct(InOutTypeEnum type, InOutItemEnum item, List<ProductStockVO> products, Long orderId, String remark);
} }

View File

@@ -0,0 +1,10 @@
package com.czg.product.vo;
import java.math.BigDecimal;
/**
* 产品库存VO
* @author ww
*/
public record ProductStockVO(Long productId, BigDecimal number) {
}

View File

@@ -75,4 +75,9 @@ public class ProdConsRelationServiceImpl extends ServiceImpl<ProdConsRelationMap
mapper.insertBatchSelective(entityList, 50); mapper.insertBatchSelective(entityList, 50);
} }
@Override
public List<ProdConsRelationDTO> selectListByProdId(Long prodId) {
return mapper.selectListByProdId(prodId);
}
} }

View File

@@ -17,7 +17,9 @@ import com.czg.product.enums.InOutItemEnum;
import com.czg.product.enums.InOutTypeEnum; import com.czg.product.enums.InOutTypeEnum;
import com.czg.product.service.ConsStockFlowService; import com.czg.product.service.ConsStockFlowService;
import com.czg.product.service.ProductRpcService; import com.czg.product.service.ProductRpcService;
import com.czg.product.service.ProductService;
import com.czg.product.service.ProductStockFlowService; import com.czg.product.service.ProductStockFlowService;
import com.czg.product.vo.ProductStockVO;
import com.czg.product.vo.ProductVO; import com.czg.product.vo.ProductVO;
import com.czg.service.RedisService; import com.czg.service.RedisService;
import com.czg.service.product.mapper.ConsInfoMapper; import com.czg.service.product.mapper.ConsInfoMapper;
@@ -31,6 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -49,142 +52,38 @@ public class ProductRpcServiceImpl implements ProductRpcService {
@Resource @Resource
private ProductMapper productMapper; private ProductMapper productMapper;
@Resource @Resource
private ProdConsRelationMapper prodConsRelationMapper; private ProductService productService;
@Resource
private ConsInfoMapper consInfoMapper;
@Resource
private ConsStockFlowService consStockFlowService;
@Resource
private ProductStockFlowService productStockFlowService;
@Resource
private RabbitPublisher rabbitPublisher;
@Resource @Resource
private RedisService redisService; private RedisService redisService;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
//@CacheEvict(value = {CacheConstant.USER_CLIENT_HOTS_PRODUCT, CacheConstant.USER_CLIENT_GROUPS_PRODUCT, ADMIN_CLIENT_PRODUCT_LIST}, key = "#shopId", allEntries = true, beforeInvocation = true)
public void paySuccessSubtractStock(Long shopId, Long orderId, List<Map<String, Object>> dataList) { public void paySuccessSubtractStock(Long shopId, Long orderId, List<Map<String, Object>> dataList) {
List<ProductStockSubtractDTO> list = BeanUtil.copyToList(dataList, ProductStockSubtractDTO.class); List<ProductStockSubtractDTO> list = BeanUtil.copyToList(dataList, ProductStockSubtractDTO.class);
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
return; return;
} }
//TODO 优化耗材库存更新逻辑 耗材预警 List<ProductStockVO> productStockList = new ArrayList<>();
boolean isLowWarnLine = false;
for (ProductStockSubtractDTO dto : list) { for (ProductStockSubtractDTO dto : list) {
Product product = productMapper.selectOneById(dto.getProductId()); productStockList.add(new ProductStockVO(dto.getProductId(), dto.getNum()));
if (product == null) {
continue;
} }
// 查询商品绑定耗材信息 productService.consStockByProduct(InOutTypeEnum.OUT, InOutItemEnum.ORDER_OUT, productStockList, orderId, "订单消费");
List<ProdConsRelation> relationList = prodConsRelationMapper.selectListByQuery(QueryWrapper.create().eq(ProdConsRelation::getProductId, dto.getProductId()));
if (CollUtil.isEmpty(relationList)) {
continue;
}
for (ProdConsRelation prodConsRelation : relationList) {
// 耗材id
Long consInfoId = prodConsRelation.getConsInfoId();
// 耗材消耗数量
BigDecimal surplusStock = prodConsRelation.getSurplusStock();
if (surplusStock == null || surplusStock.compareTo(BigDecimal.ZERO) == 0) {
continue;
}
// 实际消耗数量 = 耗材消耗数量 * 商品购买数量
surplusStock = NumberUtil.mul(surplusStock, dto.getNum());
ConsInfo consInfo = consInfoMapper.selectOneById(consInfoId);
if (consInfo == null || consInfo.getIsStock() == SystemConstants.OneZero.ZERO) {
continue;
}
BigDecimal stockNumber = consInfo.getStockNumber();
consInfo.setStockNumber(NumberUtil.sub(stockNumber, surplusStock));
// 更新耗材库存数量
consInfoMapper.update(consInfo);
// 插入耗材流水记录
ConsStockFlow consStockFlow = new ConsStockFlow();
consStockFlow.setShopId(shopId);
consStockFlow.setVendorId(null);
consStockFlow.setInOutType(InOutTypeEnum.OUT.value());
consStockFlow.setInOutItem(InOutItemEnum.ORDER_OUT.value());
consStockFlow.setInOutDate(LocalDate.now());
consStockFlow.setConId(consInfo.getId());
consStockFlow.setConName(consInfo.getConName());
consStockFlow.setUnitName(consInfo.getConUnit());
consStockFlow.setBeforeNumber(stockNumber);
consStockFlow.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, surplusStock));
consStockFlow.setAfterNumber(consInfo.getStockNumber());
consStockFlow.setSubTotal(NumberUtil.mul(surplusStock, consInfo.getPrice()));
consStockFlow.setProductId(dto.getProductId());
//consStockFlow.setSkuId(0L);
consStockFlow.setOrderId(orderId);
consStockFlowService.saveFlow(consStockFlow);
}
}
if (isLowWarnLine) {
ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)));
}
log.info("ProductService.--------------------------------------------库存更新成功");
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
//@CacheEvict(value = {CacheConstant.USER_CLIENT_HOTS_PRODUCT, CacheConstant.USER_CLIENT_GROUPS_PRODUCT, ADMIN_CLIENT_PRODUCT_LIST}, key = "#shopId", allEntries = true, beforeInvocation = true)
public void orderCancelRecoverStock(Long shopId, Long orderId, List<Map<String, Object>> dataList) { public void orderCancelRecoverStock(Long shopId, Long orderId, List<Map<String, Object>> dataList) {
List<ProductStockSubtractDTO> list = BeanUtil.copyToList(dataList, ProductStockSubtractDTO.class); List<ProductStockSubtractDTO> list = BeanUtil.copyToList(dataList, ProductStockSubtractDTO.class);
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
return; return;
} }
boolean isLowWarnLine = false; List<ProductStockVO> productStockList = new ArrayList<>();
for (ProductStockSubtractDTO dto : list) { for (ProductStockSubtractDTO dto : list) {
// 查询商品绑定耗材信息 productStockList.add(new ProductStockVO(dto.getProductId(), dto.getNum()));
List<ProdConsRelation> relationList = prodConsRelationMapper.selectListByQuery(QueryWrapper.create().eq(ProdConsRelation::getProductId, dto.getProductId()));
if (CollUtil.isEmpty(relationList)) {
continue;
} }
for (ProdConsRelation prodConsRelation : relationList) { productService.consStockByProduct(InOutTypeEnum.IN, InOutItemEnum.ORDER_IN, productStockList, orderId, "订单取消/过期返还库存");
// 耗材id
Long consInfoId = prodConsRelation.getConsInfoId();
// 耗材消耗数量
BigDecimal surplusStock = prodConsRelation.getSurplusStock();
if (surplusStock == null) {
continue;
}
// 实际消耗数量 = 耗材消耗数量 * 商品购买数量
surplusStock = NumberUtil.mul(surplusStock, dto.getNum());
ConsInfo consInfo = consInfoMapper.selectOneById(consInfoId);
if (consInfo == null) {
continue;
}
BigDecimal stockNumber = consInfo.getStockNumber();
consInfo.setStockNumber(NumberUtil.add(stockNumber, surplusStock));
// 更新耗材库存数量
consInfoMapper.update(consInfo);
// 插入耗材流水记录
ConsStockFlow consStockFlow = new ConsStockFlow();
consStockFlow.setShopId(shopId);
consStockFlow.setInOutType(InOutTypeEnum.OUT.value());
consStockFlow.setInOutItem(InOutItemEnum.ORDER_OUT.value());
consStockFlow.setInOutDate(LocalDate.now());
consStockFlow.setConId(consInfo.getId());
consStockFlow.setConName(consInfo.getConName());
consStockFlow.setUnitName(consInfo.getConUnit());
consStockFlow.setBeforeNumber(stockNumber);
consStockFlow.setInOutNumber(surplusStock);
consStockFlow.setAfterNumber(consInfo.getStockNumber());
consStockFlow.setSubTotal(NumberUtil.mul(surplusStock, consInfo.getPrice()));
consStockFlow.setProductId(dto.getProductId());
consStockFlow.setRemark("红冲订单取消/退菜/退单消耗的库存");
consStockFlow.setOrderId(orderId);
consStockFlowService.saveFlow(consStockFlow);
}
}
if (isLowWarnLine) {
ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)));
}
log.info("ProductService.--------------------------------------------库存更新成功");
} }
@Override @Override
@@ -194,54 +93,11 @@ public class ProductRpcServiceImpl implements ProductRpcService {
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
return; return;
} }
boolean isLowWarnLine = false; List<ProductStockVO> productStockList = new ArrayList<>();
for (ProductStockSubtractDTO dto : list) { for (ProductStockSubtractDTO dto : list) {
// 查询商品绑定耗材信息 productStockList.add(new ProductStockVO(dto.getProductId(), dto.getNum()));
List<ProdConsRelation> relationList = prodConsRelationMapper.selectListByQuery(QueryWrapper.create().eq(ProdConsRelation::getProductId, dto.getProductId()));
if (CollUtil.isEmpty(relationList)) {
continue;
} }
for (ProdConsRelation prodConsRelation : relationList) { productService.consStockByProduct(InOutTypeEnum.IN, InOutItemEnum.ORDER_IN, productStockList, orderId, "订单退菜/退款返还库存");
// 耗材id
Long consInfoId = prodConsRelation.getConsInfoId();
// 耗材消耗数量
BigDecimal surplusStock = prodConsRelation.getSurplusStock();
if (surplusStock == null || surplusStock.compareTo(BigDecimal.ZERO) == 0) {
continue;
}
// 实际消耗数量 = 耗材消耗数量 * 商品购买数量
surplusStock = NumberUtil.mul(surplusStock, dto.getNum());
ConsInfo consInfo = consInfoMapper.selectOneById(consInfoId);
if (consInfo == null || consInfo.getIsStock() == SystemConstants.OneZero.ZERO || consInfo.getIsRefundStock() == SystemConstants.OneZero.ZERO) {
continue;
}
BigDecimal stockNumber = consInfo.getStockNumber();
consInfo.setStockNumber(NumberUtil.add(stockNumber, surplusStock));
// 更新耗材库存数量
consInfoMapper.update(consInfo);
// 插入耗材流水记录
ConsStockFlow consStockFlow = new ConsStockFlow();
consStockFlow.setShopId(shopId);
consStockFlow.setInOutType(InOutTypeEnum.OUT.value());
consStockFlow.setInOutItem(InOutItemEnum.ORDER_OUT.value());
consStockFlow.setInOutDate(LocalDate.now());
consStockFlow.setConId(consInfo.getId());
consStockFlow.setConName(consInfo.getConName());
consStockFlow.setUnitName(consInfo.getConUnit());
consStockFlow.setBeforeNumber(stockNumber);
consStockFlow.setInOutNumber(surplusStock);
consStockFlow.setAfterNumber(consInfo.getStockNumber());
consStockFlow.setSubTotal(NumberUtil.mul(surplusStock, consInfo.getPrice()));
consStockFlow.setProductId(dto.getProductId());
consStockFlow.setOrderId(orderId);
consStockFlow.setRemark("红冲订单取消/退菜/退单消耗的库存");
consStockFlowService.saveFlow(consStockFlow);
}
}
if (isLowWarnLine) {
ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)));
}
log.info("ProductService.--------------------------------------------库存更新成功");
} }
@Override @Override
@@ -254,13 +110,4 @@ public class ProductRpcServiceImpl implements ProductRpcService {
String key = ADMIN_CLIENT_PRODUCT_LIST + "::" + shopId + "::" + categoryId; String key = ADMIN_CLIENT_PRODUCT_LIST + "::" + shopId + "::" + categoryId;
redisService.del(key); redisService.del(key);
} }
private void refreshRedisProdStock(Long shopId, Long productId, BigDecimal stockNumber) {
String key = StrUtil.format(SHOP_PRODUCT_STOCK, shopId, productId);
if (NumberUtil.isLessOrEqual(stockNumber, BigDecimal.ZERO)) {
redisService.del(key);
} else {
redisService.set(key, stockNumber.intValue());
}
}
} }

View File

@@ -21,21 +21,22 @@ import com.czg.product.param.*;
import com.czg.product.service.*; import com.czg.product.service.*;
import com.czg.product.vo.ProductGroupVo; import com.czg.product.vo.ProductGroupVo;
import com.czg.product.vo.ProductStatisticsVo; import com.czg.product.vo.ProductStatisticsVo;
import com.czg.product.vo.ProductStockVO;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.service.RedisService; import com.czg.service.RedisService;
import com.czg.service.product.mapper.*; import com.czg.service.product.mapper.*;
import com.czg.utils.PageUtil; import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain; import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -63,17 +64,14 @@ import static com.czg.product.entity.table.ShopProdUnitTableDef.SHOP_PROD_UNIT;
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService { public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
private final ProdSkuMapper prodSkuMapper; private final ProdSkuMapper prodSkuMapper;
private final ProdConsRelationMapper prodConsRelationMapper; private final ProdConsRelationService prodConsRelationService;
private final ConsInfoMapper consInfoMapper; private final ConsInfoMapper consInfoMapper;
private final ProductStockFlowMapper productStockFlowMapper; private final ProductStockFlowMapper productStockFlowMapper;
private final ProductStockFlowService productStockFlowService;
private final ConsStockFlowService consStockFlowService; private final ConsStockFlowService consStockFlowService;
private final SensitiveOperationService sensitiveOperationService; private final SensitiveOperationService sensitiveOperationService;
private final ProdGroupRelationMapper prodGroupRelationMapper; private final ProdGroupRelationMapper prodGroupRelationMapper;
private final ProductStockFlowService productStockFlowService;
private final RedisService redisService; private final RedisService redisService;
@Resource
@Lazy
private ShopProdCategoryService shopProdCategoryService;
private QueryWrapper buildQueryWrapper(ProductDTO param) { private QueryWrapper buildQueryWrapper(ProductDTO param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper(); QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
@@ -147,7 +145,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
lowMemberPriceIsPresent.ifPresent(record::setLowMemberPrice); lowMemberPriceIsPresent.ifPresent(record::setLowMemberPrice);
} }
record.setSkuList(skuList); record.setSkuList(skuList);
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(record.getId()); List<ProdConsRelationDTO> consList = prodConsRelationService.selectListByProdId(record.getId());
record.setConsList(consList); record.setConsList(consList);
if (CollUtil.isNotEmpty(consList)) { if (CollUtil.isNotEmpty(consList)) {
List<Long> consIds = consList.stream().map(ProdConsRelationDTO::getConsInfoId).distinct().toList(); List<Long> consIds = consList.stream().map(ProdConsRelationDTO::getConsInfoId).distinct().toList();
@@ -181,7 +179,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
lowMemberPriceIsPresent.ifPresent(record::setLowMemberPrice); lowMemberPriceIsPresent.ifPresent(record::setLowMemberPrice);
} }
record.setSkuList(skuList); record.setSkuList(skuList);
record.setProdConsRelations(prodConsRelationMapper.selectListByQuery(query() record.setProdConsRelations(prodConsRelationService.list(query()
.eq(ProdConsRelation::getProductId, record.getId()) .eq(ProdConsRelation::getProductId, record.getId())
.eq(ProdConsRelation::getShopId, record.getShopId()))); .eq(ProdConsRelation::getShopId, record.getShopId())));
}); });
@@ -438,7 +436,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query().eq(ProdSku::getProductId, id).eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class); List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query().eq(ProdSku::getProductId, id).eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
dto.setSkuList(skuList); dto.setSkuList(skuList);
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(dto.getId()); List<ProdConsRelationDTO> consList = prodConsRelationService.selectListByProdId(dto.getId());
dto.setConsList(consList); dto.setConsList(consList);
dto.setRelatedRecommendJson(getRelateProductList(dto.getRelatedRecommend())); dto.setRelatedRecommendJson(getRelateProductList(dto.getRelatedRecommend()));
return dto; return dto;
@@ -487,6 +485,10 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
prodSkuMapper.insertBatch(prodSkuList); prodSkuMapper.insertBatch(prodSkuList);
} }
ProdConsBindDTO prodConsBindDTO = new ProdConsBindDTO();
prodConsBindDTO.setId(null);
prodConsBindDTO.setConsList(dto.getConsList());
prodConsRelationService.saveProdConsRelation(prodConsBindDTO);
} }
@Override @Override
@@ -571,7 +573,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
.eq(Product::getShopId, shopId) .eq(Product::getShopId, shopId)
.update(); .update();
prodGroupRelationMapper.deleteByQuery(query().eq(ProdGroupRelation::getProductId, id)); prodGroupRelationMapper.deleteByQuery(query().eq(ProdGroupRelation::getProductId, id));
prodConsRelationMapper.deleteByQuery(query().eq(ProdConsRelation::getProductId, id)); prodConsRelationService.remove(query().eq(ProdConsRelation::getProductId, id));
// 清除商品分类列表缓存 // 清除商品分类列表缓存
clearProductCache(categoryId); clearProductCache(categoryId);
} }
@@ -709,39 +711,27 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
Long shopId = StpKit.USER.getShopId(); Long shopId = StpKit.USER.getShopId();
Long createUserId = StpKit.USER.getLoginIdAsLong(); Long createUserId = StpKit.USER.getLoginIdAsLong();
String createUserName = StpKit.USER.getAccount(); String createUserName = StpKit.USER.getAccount();
// 如果绑定了耗材,则同步更新耗材库存 Product product = mapper.selectOneById(param.getProductId());
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(param.getProductId()); if (product == null) {
if (CollUtil.isEmpty(consList)) { throw new CzgException("商品不存在");
return;
}
for (ProdConsRelationDTO consInfo : consList) {
ConsStockFlow entity = new ConsStockFlow();
entity.setCreateUserId(createUserId);
entity.setCreateUserName(createUserName);
entity.setShopId(shopId);
entity.setConId(consInfo.getConsInfoId());
entity.setConName(consInfo.getConName());
entity.setPurchasePrice(consInfo.getPrice());
BigDecimal inOutNumber = NumberUtil.mul(param.getNumber(), consInfo.getSurplusStock());
BigDecimal balance = NumberUtil.sub(consInfo.getStockNumber(), inOutNumber);
if (NumberUtil.isLess(balance, BigDecimal.ZERO)) {
throw new CzgException(StrUtil.format("耗材{}存在发生变动,请刷新后重试", entity.getConName()));
}
entity.setBeforeNumber(consInfo.getStockNumber());
entity.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, inOutNumber));
entity.setAfterNumber(balance);
entity.setInOutType(InOutTypeEnum.OUT.value());
entity.setInOutItem(InOutItemEnum.DAMAGE_OUT.value());
entity.setSubTotal(NumberUtil.mul(inOutNumber, consInfo.getPrice()));
entity.setImgUrls(JSON.toJSONString(param.getImgUrls()));
entity.setRemark("【商品报损,自动报损相关耗材】" + StrUtil.nullToDefault(param.getRemark(), ""));
consStockFlowService.saveFlow(entity);
consInfo.setStockNumber(entity.getAfterNumber());
UpdateChain.of(ConsInfo.class)
.set(ConsInfo::getStockNumber, consInfo.getStockNumber())
.eq(ConsInfo::getId, consInfo.getConsInfoId())
.update();
} }
// 记录商品库存流水
ProductStockFlow flow = new ProductStockFlow();
flow.setCreateUserId(createUserId);
flow.setCreateUserName(createUserName);
flow.setShopId(shopId);
flow.setProductId(product.getId());
flow.setProductName(product.getName());
// flow.setBeforeNumber(NumberUtil.toBigDecimal(stockNumber));
flow.setInOutNumber(NumberUtil.sub(BigDecimal.ZERO, NumberUtil.toBigDecimal(param.getNumber())));
// flow.setAfterNumber(NumberUtil.toBigDecimal(product.getStockNumber()));
flow.setInOutType(InOutTypeEnum.OUT.value());
flow.setInOutItem(InOutItemEnum.DAMAGE_OUT.value());
flow.setImgUrls(JSON.toJSONString(param.getImgUrls()));
productStockFlowService.save(flow);
List<ProductStockVO> productStockList = new ArrayList<>();
productStockList.add(new ProductStockVO(param.getProductId(), BigDecimal.valueOf(param.getNumber())));
consStockByProduct(InOutTypeEnum.OUT, InOutItemEnum.DAMAGE_OUT, productStockList, null, "【商品报损,自动报损相关耗材】");
} }
@Override @Override
@@ -753,6 +743,67 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
return data; return data;
} }
@Override
public Page<ProductStockFlow> findProductStockFlowPage(ProductStockFlowParam param) {
Long shopId = StpKit.USER.getShopId(0L);
param.setShopId(shopId);
param.setProductId(param.getProductId());
PageHelper.startPage(PageUtil.buildPageHelp());
if (InOutItemEnum.ORDER_IN.value().equals(param.getInOutItem())) {
param.setInOutType(InOutTypeEnum.OUT.value());
param.setInOutItem(InOutItemEnum.ORDER_OUT.value());
param.setIsGreaterZero(SystemConstants.OneZero.ONE);
}
return PageUtil.convert(new PageInfo<>(productStockFlowMapper.getProductStockFlowList(param)));
}
@Override
public void consStockByProduct(InOutTypeEnum type, InOutItemEnum item, List<ProductStockVO> products, Long orderId, String remark) {
if (CollUtil.isEmpty(products)) return;
for (ProductStockVO product : products) {
List<ProdConsRelationDTO> consList = prodConsRelationService.selectListByProdId(product.productId());
if (CollUtil.isEmpty(consList)) return;
for (ProdConsRelationDTO consInfo : consList) {
BigDecimal surplusStock = consInfo.getSurplusStock();
if (surplusStock == null || surplusStock.compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
surplusStock = NumberUtil.mul(surplusStock, product.number());
BigDecimal beforeNumber = consInfo.getStockNumber();
if (InOutTypeEnum.IN.equals(type)) {
consInfo.setStockNumber(NumberUtil.add(beforeNumber, surplusStock));
} else {
consInfo.setStockNumber(NumberUtil.sub(beforeNumber, surplusStock));
}
// 更新耗材库存数量
ConsInfo consInfoUp = new ConsInfo();
consInfoUp.setStockNumber(consInfo.getStockNumber());
consInfoMapper.updateByQuery(consInfoUp, query().eq(ConsInfo::getId, consInfo.getConsInfoId()).eq(ConsInfo::getShopId, consInfo.getShopId()));
ConsStockFlow flow = new ConsStockFlow();
flow.setInOutType(type.value());
flow.setInOutItem(item.value());
flow.setShopId(consInfo.getShopId());
flow.setInOutDate(LocalDate.now());
flow.setConId(consInfo.getConsInfoId());
flow.setConName(consInfo.getConName());
flow.setUnitName(consInfo.getConUnit());
flow.setBeforeNumber(beforeNumber);
flow.setInOutNumber(surplusStock);
flow.setAfterNumber(consInfo.getStockNumber());
flow.setPurchasePrice(consInfo.getPrice());
flow.setSubTotal(BigDecimal.ZERO);
if (flow.getPurchasePrice() != null && flow.getPurchasePrice().compareTo(BigDecimal.ZERO) > 0) {
flow.setSubTotal(NumberUtil.mul(surplusStock, flow.getPurchasePrice()));
}
flow.setProductId(product.productId());
flow.setOrderId(orderId);
flow.setRemark(remark);
consStockFlowService.save(flow);
}
}
}
private List<RelatedProductDTO> getRelateProductList(String relatedProduct) { private List<RelatedProductDTO> getRelateProductList(String relatedProduct) {
if (StrUtil.isNotBlank(relatedProduct) && !"[]".equals(relatedProduct)) { if (StrUtil.isNotBlank(relatedProduct) && !"[]".equals(relatedProduct)) {
List<Long> idList = JSONArray.parseArray(relatedProduct, Long.class); List<Long> idList = JSONArray.parseArray(relatedProduct, Long.class);

View File

@@ -245,24 +245,4 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
DayOfWeek dayOfWeek = currentDate.getDayOfWeek(); DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
return dayOfWeek.getDisplayName(TextStyle.FULL, Locale.ENGLISH); return dayOfWeek.getDisplayName(TextStyle.FULL, Locale.ENGLISH);
} }
public static void main(String[] args) {
LocalTime startTime = LocalTime.of(17, 0, 0);
LocalTime endTime = LocalTime.of(23, 0, 0);
LocalTime now = LocalTime.now().withNano(0);
if (startTime.isBefore(endTime)) {
if (now.isAfter(startTime) && now.isBefore(endTime)) {
System.out.println("");
} else {
System.out.println("不在");
}
} else {
if (now.isAfter(startTime) || now.isBefore(endTime)) {
System.out.println("");
} else {
System.out.println("不在");
}
}
}
} }

View File

@@ -20,7 +20,7 @@
t2.stock_number, t2.stock_number,
t1.surplus_stock t1.surplus_stock
FROM tb_prod_cons_relation t1 FROM tb_prod_cons_relation t1
LEFT JOIN tb_cons_info t2 on t1.cons_info_id = t2.id inner JOIN tb_cons_info t2 on t1.cons_info_id = t2.id
WHERE t1.product_id = #{prodId} WHERE t1.product_id = #{prodId}
</select> </select>
</mapper> </mapper>