Forráskód Böngészése

第一次校验库存优化

lhm 3 éve
szülő
commit
bc0a2a950d

+ 84 - 1
kmall-admin/src/main/java/com/kmall/admin/controller/GoodsController.java

@@ -6,6 +6,7 @@ import com.kmall.admin.dto.GoodsPanoramaDto;
 import com.kmall.admin.entity.GoodsEntity;
 import com.kmall.admin.entity.GoodsGalleryEntity;
 import com.kmall.admin.entity.SysOssEntity;
+import com.kmall.admin.haikong.constant.Constants;
 import com.kmall.admin.service.*;
 import com.kmall.admin.utils.ParamUtils;
 import com.kmall.admin.utils.ShiroUtils;
@@ -16,6 +17,7 @@ import com.kmall.common.fileserver.util.FileManager;
 import com.kmall.common.utils.*;
 import com.kmall.common.utils.excel.ExcelExport;
 import com.kmall.common.utils.excel.ExcelUtil;
+import com.kmall.manager.manager.redis.JedisUtil;
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileItemFactory;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
@@ -23,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.apache.tools.zip.ZipEntry;
 import org.apache.tools.zip.ZipFile;
+import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -33,7 +36,6 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.util.*;
-import java.util.logging.Logger;
 
 /**
  * Controller
@@ -45,6 +47,9 @@ import java.util.logging.Logger;
 @RestController
 @RequestMapping("goods")
 public class GoodsController {
+
+    private final static Logger log = LoggerFactory.getLogger(GoodsController.class);
+
     @Autowired
     private GoodsService goodsService;
     @Autowired
@@ -585,6 +590,7 @@ public class GoodsController {
         try {
             map = goodsService.calculateGoodsDetail(prodBarcode,storeId,sku);
         } catch (Exception e) {
+            log.error("查询条码:【{}】详情出现异常!", prodBarcode, e);
             return R.error("系统异常,请联系管理员!e:"+e.getMessage());
         }
         if(map == null){
@@ -607,6 +613,7 @@ public class GoodsController {
         try {
             map = goodsService.calculateGoodsDetail(prodBarcode,storeId,null);
         } catch (Exception e) {
+            log.error("查询条码:【{}】价格出现异常!", prodBarcode, e);
             return R.error("系统异常,请联系管理员!e:"+e.getMessage());
         }
         if(map == null){
@@ -615,6 +622,82 @@ public class GoodsController {
         return R.ok().put("goodsDetails", map.get("goods")).put("map",map);
     }
 
+    // storeId + sku + prodBarcode
+    @RequestMapping(value = "/number/minus/{storeId}/{sku}/{prodBarcode}", method = RequestMethod.GET)
+    public R minus(@PathVariable("storeId") String storeId, @PathVariable("sku") String sku, @PathVariable("prodBarcode") String prodBarcode) {
+        String key = Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + storeId;
+        String itemKey = storeId + sku + prodBarcode;
+
+        try {
+            String cartNumber = JedisUtil.hget(key, itemKey);
+            int number = Integer.parseInt(cartNumber);
+            JedisUtil.hset(key, itemKey, String.valueOf(++number));
+        } catch (Exception e) {
+            log.error("storeId:【{}】,sku:【{}】,prodBarcode:【{}】,扣减购物篮商品数量失败!", storeId, sku, prodBarcode);
+            return R.error("扣减购物篮商品数量失败!请删除购物篮商品后重试!");
+        }
+
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/number/add/{storeId}/{sku}/{prodBarcode}/{sellVolume}", method = RequestMethod.GET)
+    public R add(@PathVariable("storeId") String storeId,
+                 @PathVariable("sku") String sku,
+                 @PathVariable("prodBarcode") String prodBarcode,
+                 @PathVariable("sellVolume") Integer sellVolume) {
+        String key = Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + storeId;
+        String itemKey = storeId + sku + prodBarcode;
+
+        try {
+            GoodsEntity goodsEntity = goodsService.queryGoodsStockByBarcodeAndStoreIdAndSku(prodBarcode, Integer.parseInt(storeId), sku);
+            Integer exitRegionNumber = goodsEntity.getExitRegionNumber();
+            Integer stockNum = goodsEntity.getStockNum();
+            String number = JedisUtil.hget(key, itemKey);
+            int cartNumber = Integer.parseInt(number);
+            if (stockNum + cartNumber - exitRegionNumber >= sellVolume) {
+                JedisUtil.hset(key, itemKey, String.valueOf(--cartNumber));
+            } else {
+                log.error("增加商品数量失败!保税仓库存不足!storeId:【{}】,sku:【{}】,prodBarcode:【{}】,stockNum:【{}】,exitRegionNumber:【{}】,wareStockNumber:【{}】"
+                , storeId, sku, prodBarcode, stockNum, exitRegionNumber, cartNumber);
+                return R.error("增加商品数量失败!保税仓库存不足!");
+            }
+        } catch (Exception e) {
+            log.error("storeId:【{}】,sku:【{}】,prodBarcode:【{}】,增加购物篮商品数量失败!", storeId, sku, prodBarcode);
+            return R.error("增加购物篮商品数量失败!请删除购物篮商品后重试!");
+        }
+
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/number/del/{storeId}/{sku}/{prodBarcode}", method = RequestMethod.GET)
+    public R del(@PathVariable("storeId") String storeId, @PathVariable("sku") String sku, @PathVariable("prodBarcode") String prodBarcode) {
+        String key = Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + storeId;
+        String itemKey = storeId + sku + prodBarcode;
+
+        try {
+            JedisUtil.hdel(key, itemKey);
+        } catch (Exception e) {
+            log.error("storeId:【{}】,sku:【{}】,prodBarcode:【{}】,删除购物篮商品失败!", storeId, sku, prodBarcode);
+            return R.error("删除购物篮商品失败!请刷新收银端页面!");
+        }
+
+        return R.ok();
+    }
+
+    @RequestMapping(value = "/number/clear/{storeId}", method = RequestMethod.GET)
+    public R clear(@PathVariable("storeId") String storeId) {
+        String key = Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + storeId;
+
+        try {
+            JedisUtil.del(key);
+        } catch (Exception e) {
+            log.error("storeId:【{}】,清空购物篮商品失败!", storeId);
+            return R.error("清空购物篮商品失败!请刷新收银端页面!");
+        }
+
+        return R.ok();
+    }
+
 
     /**
      * 多sku可选

+ 5 - 0
kmall-admin/src/main/java/com/kmall/admin/haikong/constant/Constants.java

@@ -9,11 +9,16 @@ import java.util.Arrays;
  */
 public class Constants {
 
+    /* --------------------------------------------------redis常量----------------------------------------------- */
 
     public static final String MEMBER_SYS_ACCESS_TOKEN_REDIS_KEY = "haikong_memberSys_accessToken";
 
     public static final String MEMBER_SYS_REFRESH_TOKEN_REDIS_KEY = "haikong_memberSys_refreshToken";
 
+    public static final String WAREHOUSE_STOCK_MAP_KEY = "haikong_warehouse_stock_cache";
+
+    /* --------------------------------------------------redis常量----------------------------------------------- */
+
     /**
      * 活动主题枚举
      */

+ 68 - 274
kmall-admin/src/main/java/com/kmall/admin/service/impl/GoodsServiceImpl.java

@@ -14,6 +14,10 @@ import com.kmall.admin.entity.kmall2eccs.KtoEccsEntity;
 import com.kmall.admin.entity.mk.MkActivitiesEntity;
 import com.kmall.admin.entity.shop.ShopErrorPriceRecordEntity;
 import com.kmall.admin.haikong.client.HaiKongWarehouseTemplate;
+import com.kmall.admin.haikong.constant.Constants;
+import com.kmall.admin.haikong.dto.Criteria;
+import com.kmall.admin.haikong.dto.WareQueryStockParamDTO;
+import com.kmall.admin.haikong.dto.WareQueryStockResponseDTO;
 import com.kmall.admin.haikong.vo.QueryGoodsVO;
 import com.kmall.admin.service.*;
 import com.kmall.admin.service.kmall2eccs.KtoEccsService;
@@ -24,10 +28,13 @@ import com.kmall.admin.service.shop.ShopErrorPriceRecordService;
 import com.kmall.admin.utils.CalculateTax;
 import com.kmall.admin.utils.GoodsUtils;
 import com.kmall.admin.utils.ShiroUtils;
+import com.kmall.admin.utils.jackson.JacksonUtil;
 import com.kmall.api.entity.exportpdf.PDFGoodsDto;
 import com.kmall.common.constant.Dict;
 import com.kmall.admin.fromcomm.entity.SysUserEntity;
 import com.kmall.common.utils.*;
+import com.kmall.manager.manager.express.sf.ServiceException;
+import com.kmall.manager.manager.redis.JedisCacheManager;
 import com.kmall.manager.manager.redis.JedisUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -1749,7 +1756,7 @@ public class GoodsServiceImpl implements GoodsService {
      */
     @Override
     @Transactional
-    public Map<String,Object> calculateGoodsDetail(String prodBarcode, String storeId,String sku) {
+    public synchronized Map<String,Object> calculateGoodsDetail(String prodBarcode, String storeId, String sku) {
         /**
          * 1.首先根据商品条码跟门店id查询是否有库存,没库存直接返回
          */
@@ -1762,38 +1769,68 @@ public class GoodsServiceImpl implements GoodsService {
         * 2. 查询海仓仓库系统,判断库存是否足够
         * TODO 测试的时候注释,海控仓库系统没有测试环境,上生产时放开注释
         * */
-        /*WareQueryStockParamDTO wareQueryStockParamDTO = new WareQueryStockParamDTO();
-        List<Criteria> criteriaList = new ArrayList<>();
-        Criteria criteria = new Criteria();
-        criteria.setItemId(goods.getProdBarcode());
-        criteria.setItemCode(goods.getSku());
-        criteriaList.add(criteria);
-        wareQueryStockParamDTO.setCriteriaList(criteriaList);
-        String queryWarehouseStockResponse = haiKongWarehouseTemplate.queryWarehouseStock(wareQueryStockParamDTO);
-        log.info("调用海控仓库系统,请求参数,门店:{}、商品条码:{}、商品编码:{},响应数据:{}", storeId, prodBarcode, sku, queryWarehouseStockResponse);
-        if (org.springframework.util.StringUtils.isEmpty(queryWarehouseStockResponse)) {
-            log.error("调用库存系统接口出现错误!返回结果为空!");
-            throw new ServiceException("调用库存系统接口出现错误!");
-        }
-        WareQueryStockResponseDTO wareQueryStockResponseDTO = JacksonUtil.fromStringJson(queryWarehouseStockResponse, WareQueryStockResponseDTO.class);
-        if (Objects.isNull(wareQueryStockResponseDTO)) {
-            log.error("解析一步达库存系统响应数据出现错误!请求响应结果:{}", queryWarehouseStockResponse);
-            throw new ServiceException("解析一步达库存系统响应数据出现错误!");
-        }
-        // 校验库存
-        WareQueryStockResponseDTO.WareQueryStockResponseItemDTO itemDTO = wareQueryStockResponseDTO.getItems().get(0);
-        // 仓库可用库存
-        int wareQuantity = itemDTO.getQuantity() - itemDTO.getLockQuantity();
-        // 海控展销店出区数
+        sku = org.springframework.util.StringUtils.isEmpty(sku) ? goods.getSku() : sku;
+        String wareStockNumberKey = storeId + sku + prodBarcode;
+        String warehouseStockMapKey = Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + storeId;
+        String redisCacheWareQuantity = JedisUtil.hget(warehouseStockMapKey, wareStockNumberKey);
+        Integer wareQuantity = 0;
         Integer exitRegionNumber = goods.getExitRegionNumber();
-        // 门店库存
         String stockNum = goods.getStockNum();
-        // 扫码只会扫一件商品,保税仓库存 + 展销店库存 - 出区数 >= 购买数
-        if (!((wareQuantity + Integer.parseInt(stockNum) - exitRegionNumber) >= 1)) {
+        Integer sellVolume = Objects.isNull(goods.getSellVolume()) ? 1 : goods.getSellVolume();
+        if (org.springframework.util.StringUtils.isEmpty(redisCacheWareQuantity)) {
+
+//            WareQueryStockParamDTO wareQueryStockParamDTO = new WareQueryStockParamDTO();
+//            List<Criteria> criteriaList = new ArrayList<>();
+//            Criteria criteria = new Criteria();
+//            criteria.setItemId(goods.getProdBarcode());
+//            criteria.setItemCode(goods.getSku());
+//            criteriaList.add(criteria);
+//            wareQueryStockParamDTO.setCriteriaList(criteriaList);
+//            String queryWarehouseStockResponse = haiKongWarehouseTemplate.queryWarehouseStock(wareQueryStockParamDTO);
+//            log.info("调用海控仓库系统,请求参数,门店:{}、商品条码:{}、商品编码:{},响应数据:{}", storeId, prodBarcode, sku, queryWarehouseStockResponse);
+//            if (org.springframework.util.StringUtils.isEmpty(queryWarehouseStockResponse)) {
+//                log.error("调用库存系统接口出现错误!返回结果为空!");
+//                throw new ServiceException("调用库存系统接口出现错误!");
+//            }
+//            WareQueryStockResponseDTO wareQueryStockResponseDTO = JacksonUtil.fromStringJson(queryWarehouseStockResponse, WareQueryStockResponseDTO.class);
+
+            /* -----------------↓--------------测试数据,生产请注释-------------------↓------------ */
+            WareQueryStockResponseDTO wareQueryStockResponseDTO = new WareQueryStockResponseDTO();
+            wareQueryStockResponseDTO.setCode("0");
+            wareQueryStockResponseDTO.setFlag("success");
+            wareQueryStockResponseDTO.setMessage("");
+            WareQueryStockResponseDTO.WareQueryStockResponseItemDTO wareQueryStockResponseItemDTO = new WareQueryStockResponseDTO.WareQueryStockResponseItemDTO();
+            wareQueryStockResponseItemDTO.setQuantity(3);
+            wareQueryStockResponseItemDTO.setItemCode(sku);
+            wareQueryStockResponseItemDTO.setProduceCode(prodBarcode);
+            List<WareQueryStockResponseDTO.WareQueryStockResponseItemDTO> wareQueryStockResponseItemDTOS = new ArrayList<>();
+            wareQueryStockResponseItemDTOS.add(wareQueryStockResponseItemDTO);
+            wareQueryStockResponseDTO.setItems(wareQueryStockResponseItemDTOS);
+            /* -----------------↑--------------测试数据,生产请注释------------------↑------------- */
+
+
+            if (Objects.isNull(wareQueryStockResponseDTO)) {
+//            log.error("解析一步达库存系统响应数据出现错误!请求响应结果:{}", queryWarehouseStockResponse);
+                throw new ServiceException("解析一步达库存系统响应数据出现错误!");
+            }
+
+            // 校验库存
+            WareQueryStockResponseDTO.WareQueryStockResponseItemDTO itemDTO = wareQueryStockResponseDTO.getItems().get(0);
+            // 仓库可用库存
+            wareQuantity = itemDTO.getQuantity();
+            JedisUtil.hset(warehouseStockMapKey, wareStockNumberKey, String.valueOf(wareQuantity));
+        } else {
+            wareQuantity = Integer.parseInt(redisCacheWareQuantity);
+        }
+        // 保税仓库存 + 展销店库存 - 出区数 >= 购买数
+        if (!((wareQuantity + Integer.parseInt(stockNum) - exitRegionNumber) > sellVolume)) {
             // 库存不足
-            log.error("商品条码:【{}】,sku:【{}】,门店ID:【{}】,该商品库存不足!", prodBarcode, sku, storeId);
-            throw new ServiceException(String.format("商品条码:【%s】,sku:【%s】,门店ID:【%s】,该商品库存不足!", prodBarcode, sku, storeId));
-        }*/
+            log.error("商品条码:【{}】,sku:【{}】,门店库存:【{}】,保税仓库存:【{}】,出区数:【{}】,该商品仓库库存不足!", prodBarcode, sku, stockNum, wareQuantity, exitRegionNumber);
+            throw new ServiceException(String.format("商品条码:【%s】,sku:【%s】,门店库存:【%s】,保税仓库存:【%s】,出区数:【%s】,该商品仓库库存不足!", prodBarcode, sku, stockNum, wareQuantity, exitRegionNumber));
+        } else {
+            JedisUtil.hset(warehouseStockMapKey, wareStockNumberKey, String.valueOf(wareQuantity - sellVolume));
+        }
+
         goods.setDiscountedPrice(new BigDecimal(0));
         BigDecimal retailPrice = goods.getRetailPrice();
 
@@ -1801,252 +1838,9 @@ public class GoodsServiceImpl implements GoodsService {
 
         Map<String,Object> skuActivitiesMap = new HashMap<>();
 
-//        /**
-//         * 2.查询当前时间,该门店是否有活动,如果有活动,查询开启了哪些营销方式
-//         * 参数: 当前时间  门店id
-//         */
-//        /*List<MkActivitiesEntity> mkActivitiesEntityList = mkActivitiesService.queryByNow(storeId,format.format(new Date()));
-//
-//        if(mkActivitiesEntityList == null || mkActivitiesEntityList.size() == 0){
-//            // 计算税费
-//            GoodsEntity goodsEntity = goodsDao.queryByBarcodeAndSku(prodBarcode, goods.getGoodsSn());
-//            BigDecimal tax = CalculateTax.calculateFinalTax(goodsEntity,goods.getActualPaymentAmount(),this).setScale(3,RoundingMode.HALF_UP);
-//            goods.setGoodstaxes(tax.toString());
-//            skuActivitiesMap.put("goods",goods);
-//            return skuActivitiesMap;
-//        }
-//
-//
-//
-//        // 遍历活动集合,查询有哪些活动是开启的
-//        boolean daily = false,coupon = false,combinationPrice = false
-//                ,discount = false,fullGift = false,fullReduction = false
-//                ,getOneFree = false,promotion = false,halfPrice = false;
-//
-//        List<String> topicList = new ArrayList<>(); // 记录有哪些营销活动的topic
-//        Map<String,String> mkaIdMap = new HashMap<>(); // 记录topic跟mkaId的关系
-//        // 将所有的营销活动新增到list中
-//        for(MkActivitiesEntity mkActivitiesEntity : mkActivitiesEntityList){
-//            topicList.add(mkActivitiesEntity.getMkaTopic());
-//            String mkaId = mkaIdMap.putIfAbsent(mkActivitiesEntity.getMkaTopic(), mkActivitiesEntity.getMkaId()+"");
-//            if(StringUtils.isNotEmpty(mkaId)){
-////                mkaId = "'"+mkaId + "','" + mkActivitiesEntity.getMkaId()+"'";
-//                mkaId += String.format(",%s",mkActivitiesEntity.getMkaId());
-//                mkaIdMap.put(mkActivitiesEntity.getMkaTopic(),mkaId);
-//            }
-//        }
-//        // 判断有哪些营销活动
-//        if(topicList.contains("zhjsp")) // 组合价
-//            combinationPrice = true;
-//        if(topicList.contains("dz")) // 打折
-//            discount = true;
-//        if(topicList.contains("mz")) //满赠
-//            fullGift = true;
-//        if(topicList.contains("mj"))  // 满减
-//            fullReduction = true;
-//        if(topicList.contains("mysy")) // 买一送一
-//            getOneFree = true;
-//        if(topicList.contains("rchd")) // 日常活动
-//            daily = true;
-//        if(topicList.contains("yhq")) // 优惠券
-//            coupon = true;
-//        if(topicList.contains("lscx")) // 临时促销
-//            promotion = true;
-//        if(topicList.contains("drjbj"))
-//            halfPrice = true;
-//
-//
-//        // 获取未优惠前的商品价格
-//        retailPrice = goods.getRetailPrice();
-//
-//
-//        // 根据条码查询商品品牌名称 mall_brand  mall_product_store_rela  mall_goods
-//        String brandName = goods.getBrand();
-//
-//        *//**
-//         * 优先级:临时促销 》买一送一=满赠 》 组合价=日常活动 》 打折=满减 》 优惠券
-//         *//*
-//
-//        *//**
-//         * 组合价的做法就是将参与组合的条码带到收银端
-//         * 现根据营销活动id跟条形码,查询有哪些参与该条码组合的商品
-//         *
-//         *
-//         * TODO
-//         *//*
-//        if(combinationPrice){
-//            String mkaId = mkaIdMap.get("zhjsp");
-//            Map<String,Object> param = new HashMap<>();
-//            param.put("mkaId",mkaId);
-//            param.put("prodBarcode",prodBarcode);
-//            List<MkActivitiesCombinationPriceEntity> combinationPriceList = combinationPriceService.queryList(param);
-//            if(combinationPriceList != null && combinationPriceList.size() > 0) {
-//                Map<String, List<MkActivitiesCombinationPriceEntity>> collect =
-//                        combinationPriceList.stream().collect(Collectors.groupingBy(MkActivitiesCombinationPriceEntity::getCombinationType));
-//
-//                skuActivitiesMap.put("zhjsp",collect);
-//            }
-//        }
-//
-//
-//
-//        format = new SimpleDateFormat("yyyy-MM-dd");
-//        String nowTime = format.format(new Date());
-//        *//**
-//         * 满减可能是跟着条码,也可能跟着品牌
-//         * 根据商品品牌跟商品条码去查询是否有优惠金额
-//         *
-//         * 满足金额   购买商品条码   赠品条码
-//         *
-//         *//*
-//        Map<String,Object> fullReductionMap = new HashMap<>();
-//        if(fullReduction){
-//            String mkaId = mkaIdMap.get("mj");
-//            MkActivitiesFullReductionEntity fullReductionEntity = fullReductionService.queryByCodeOrBrand(mkaId,prodBarcode,brandName,nowTime);
-//            if(fullReductionEntity != null) {
-//                if(!StringUtils.isNullOrEmpty(fullReductionEntity.getProductBrand())){
-//                    // 跟着品牌走
-//                    fullReductionMap.put(brandName,fullReductionEntity);
-//                }else{
-//                    // 跟着条码走
-//                    fullReductionMap.put(fullReductionEntity.getBarcode(), fullReductionEntity);
-//                }
-//                skuActivitiesMap.put("mj",fullReductionMap);
-//            }
-//        }
-//
-//        *//**
-//         * 满赠可能是跟着条码,也可能跟着品牌
-//         * 根据商品品牌跟商品条码去查询是否有满赠
-//         * 1.先扫买的商品,然后查询出赠送的商品条码
-//         * 2.先扫赠的商品,然后查询出符合条件的商品条码或者品牌
-//         * 满足的金额   购买的商品条码或者品牌   赠送的商品条码
-//         * TODO
-//         *//*
-//        Map<String,Object> fullGiftMap = new HashMap<>();
-//        if(fullGift){
-//            String mkaId = mkaIdMap.get("mz");
-//            MkActivitiesFullGiftEntity giftEntity = fullGiftService.queryByCodeOrBrand(mkaId,prodBarcode,brandName,nowTime);
-//            if(giftEntity != null) {
-//                if(giftEntity.getProductBrand() != null){
-//                    // 跟着品牌走
-//                    fullGiftMap.put(brandName,giftEntity);
-//                }else{
-//                    // 跟着条码走
-//                    fullGiftMap.put(giftEntity.getBarcode(), giftEntity);
-//                }
-//                skuActivitiesMap.put("mz",fullGiftMap);
-//            }
-//        }
-//
-//        *//**
-//         * 买一送一可能是跟着条码,也可能跟着品牌
-//         * 根据商品品牌跟商品条码去查询是否有送的商品
-//         * 有两个场景
-//         * 1.先扫买的商品,然后查询出赠送的商品条码
-//         * 2.先扫赠的商品,然后查询出符合条件的商品条码或者品牌
-//         * 所以就需要一个map
-//         * key为购买的商品条码或者商品品牌  value为赠送的商品条码
-//         * 但是品牌是根据条码查询的,所以最终map里面的结构是
-//         * key 商品条码 value 赠品条码
-//         *//*
-//        if(getOneFree){
-//            String mkaId = mkaIdMap.get("mysy");
-//            MkActivitiesGetOneFreeGoodsEntity getOneFreeGoodsEntity = getOneFreeGoodsService.queryByCodeOrBrand(mkaId,prodBarcode,brandName);
-//            if(getOneFreeGoodsEntity != null){
-//                if("无".equals(getOneFreeGoodsEntity.getProductBrand())){
-//                    getOneFreeGoodsEntity.setBrand(false);
-//                    skuActivitiesMap.put("mysy",getOneFreeGoodsEntity);
-//                }else{
-//                    getOneFreeGoodsEntity.setBrand(true);
-//                    skuActivitiesMap.put("mysy",getOneFreeGoodsEntity);
-//                }
-//
-//            }
-//        }
-//
-//
-//        // 第二份半价
-//        if(halfPrice){
-//            String mkaId = mkaIdMap.get("drjbj");
-//            MkActivitiesHalfPriceEntity activitiesHalfPriceEntity = halfPriceService.queryByCodeOrBrand(mkaId,prodBarcode);
-//            if(activitiesHalfPriceEntity != null){
-//                skuActivitiesMap.put("drjbj",activitiesHalfPriceEntity);
-//
-//            }
-//
-//        }
-//
-//
-//        // --------------------------------------------------------------------------------------
-//
-//        *//**
-//         * 优惠券跟着条形码走,一般是设置一个标识,然后最后输入优惠券码后,减扣对应的标识,所以返回一个map数组
-//         *//*
-//
-//        if(coupon){
-//            String mkaId = mkaIdMap.get("yhq");
-//            MkActivitiesCouponEntity couponEntity =  couponService.queryByBarCode(mkaId,prodBarcode,nowTime);
-//            if(couponEntity != null){ // 优惠券码,优惠金额
-//                Map<String,Object> returnMap = new HashMap<>();
-//                returnMap.put(couponEntity.getCouponSn() , couponEntity.getCouponPrice());
-//                skuActivitiesMap.put("yhq",returnMap);
-//            }
-//        }
-//
-//
-//        *//**
-//         * 打折的价格是与条形码对应的,所以需要根据条形码和营销方式id去查询活动价格
-//         *//*
-//
-//        if(discount){
-//            String mkaId = mkaIdMap.get("dz");
-//            MkActivitiesDiscountEntity discountEntity =  discountService.queryByBarCode(mkaId,prodBarcode);
-//            // TODO 可能会直接替代产品价格
-//            if (discountEntity != null) {
-//                goods.setActualPaymentAmount(discountEntity.getActivityPrice());
-//                goods.setRetailPrice(discountEntity.getActivityPrice());
-//
-//                goods.setActivity("打折");
-//            }
-//        }
-//
-//
-//        *//**
-//         * 日常活动跟着条形码走,优先级比临时促销低,但是高于正常价格
-//         *//*
-//        if(daily){
-//            String mkaId = mkaIdMap.get("rchd");
-//            MkDailyActivitiesEntity dailyActivitiesEntity = dailyActivitiesService.queryByBarCode(mkaId,prodBarcode);
-//            if(dailyActivitiesEntity != null){
-//                goods.setActualPaymentAmount(dailyActivitiesEntity.getActivityPrice());
-//                goods.setRetailPrice(dailyActivitiesEntity.getActivityPrice());
-//
-//                goods.setActivity("日常活动");
-//
-//            }
-//        }
-//
-//
-//        *//**
-//         * 临时促销跟着条形码走,优先级应该最高,所以排到了最下面
-//         *//*
-//        if(promotion){
-//            String mkaId = mkaIdMap.get("lscx");
-//            MkActivitiesPromotionEntity promotionEntity = promotionService.queryByBarCode(mkaId,prodBarcode);
-//            // 如果该商品存在临时促销,直接替换活动价格
-//            if(promotionEntity != null){
-//                goods.setActualPaymentAmount(promotionEntity.getActivityPrice());
-//                goods.setRetailPrice(promotionEntity.getActivityPrice());
-//
-//                goods.setActivity("临时促销");
-//
-//            }
-//        }*/
-
         // 计算税费
         GoodsEntity goodsEntity = goodsDao.queryByBarcodeAndSku(prodBarcode, goods.getGoodsSn());
-        BigDecimal tax = CalculateTax.calculateFinalTax(goodsEntity,goods.getActualPaymentAmount(),this).setScale(3,RoundingMode.HALF_UP);
+        BigDecimal tax = CalculateTax.calculateFinalTax(goodsEntity, goods.getActualPaymentAmount(),this).setScale(3,RoundingMode.HALF_UP);
         goods.setGoodstaxes(tax.toString());
         goods.setSellVolume(1);
 

+ 1 - 0
kmall-admin/src/main/java/com/kmall/admin/service/impl/OrderServiceImpl.java

@@ -2905,6 +2905,7 @@ public class OrderServiceImpl implements OrderService {
             WebSocketServer.sendMessage(sessionId, order.getOrder_sn(), order.getStore_id()
                     + "");
 
+            JedisUtil.del(Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + storeId);
             return resultObj;
         } catch (Exception e) {
             e.printStackTrace();

+ 5 - 0
kmall-admin/src/main/java/com/kmall/admin/websocket/WebSocketServer.java

@@ -3,10 +3,12 @@ package com.kmall.admin.websocket;
 import com.alibaba.fastjson.JSONObject;
 import com.kmall.admin.entity.OrderEntity;
 import com.kmall.admin.entity.PickUpCodeEntity;
+import com.kmall.admin.haikong.constant.Constants;
 import com.kmall.admin.service.OrderService;
 import com.kmall.admin.service.PickUpCodeService;
 import com.kmall.api.util.SendMsgUtil;
 import com.kmall.common.utils.R;
+import com.kmall.manager.manager.redis.JedisUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -81,6 +83,9 @@ public class WebSocketServer {
         Map<String,Object> dataParam = new HashMap<>();
         dataParam.put("pickUpCodeCreatetime",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
         dataParam.put("storeId",param);
+
+        JedisUtil.del(Constants.WAREHOUSE_STOCK_MAP_KEY + "_" + param);
+
         pickUpList = pickUpCodeService.queryList(dataParam);
         pickUpCodeMap.put(param,pickUpList);
 //        }

+ 1 - 1
kmall-admin/src/main/resources/mybatis/mapper/GoodsDao.xml

@@ -253,7 +253,7 @@
 
     <select id="queryGoodsDetailsByProdBarcode" resultType="com.kmall.admin.dto.GoodsDetailsDto">
         SELECT distinct
-        a.goods_sn as GoodsSn,m.retail_price as retailPrice,a.prod_barcode as prodBarcode,a.name,a.brand,a.goods_desc as goodsDesc,a.goods_unit as goodsUnit,a.goods_rate as goodsRate,a.primary_pic_url ,m.stock_num as stockNum,r.value as specification
+        a.goods_sn as GoodsSn, a.goods_sn as sku, m.retail_price as retailPrice,a.prod_barcode as prodBarcode,a.name,a.brand,a.goods_desc as goodsDesc,a.goods_unit as goodsUnit,a.goods_rate as goodsRate,a.primary_pic_url ,m.stock_num as stockNum,r.value as specification
         ,a.hs_code as hsCode , a.legal_unit1_qty as legalUnit1Qty , a.legal_unit2_qty as legalUnit2Qty,a.ciq_prod_model as ciqProdModel,a.to_be_restored, m.exit_region_number as exitRegionNumber
         FROM
             mall_goods a

+ 1 - 0
kmall-admin/src/main/resources/spring/spring-shiro.xml

@@ -67,6 +67,7 @@
         <property name="filterChainDefinitions">
             <value>
                 /orderProRecordExternal/**=anon
+                /goods/number/**=anon
                 /statics/**=anon
                 /api/**=anon
                 /js/**=anon

+ 69 - 33
kmall-admin/src/main/webapp/js/sale/sale.js

@@ -739,7 +739,7 @@ let vm = new Vue({
                         handle(r.goodsDetails,"add");
                         vm.openSku = false;
                         var data = Object.assign({}, JSON.parse(JSON.stringify(r.goodsDetails)));
-                        console.log("商品详情===>" + JSON.stringify(data));
+                        console.log("商品详情=1=>" + JSON.stringify(data));
                         vm.calGoodsList.push(data);
                         //此时必须异步执行滚动条滑动至底部
                         setTimeout(()=>{
@@ -759,7 +759,7 @@ let vm = new Vue({
                 if(this.goodsList[i].id == value){
                     // var goodsDetails = JSON.parse(JSON.stringify(vm.goodsMap.get(this.goodsList[i].goodsSn)));
                     let goodsDetails = JSON.parse(JSON.stringify(vm.goodsList[i]));
-                    console.log("加法 goods detail =====>" + JSON.stringify(goodsDetails));
+                    // console.log("加法 goods detail =====>" + JSON.stringify(goodsDetails));
                     /*calculateGoodsByMj(goodsDetails,"add");
                     calculateGoodsByMysy(goodsDetails,"add");
                     calculateGoodsByHalfPrice(goodsDetails,"add");*/
@@ -776,7 +776,7 @@ let vm = new Vue({
                 if(this.goodsList[i].id == value){
                     // 获取当前购物车的数量
                     let goodsDetails = JSON.parse(JSON.stringify(vm.goodsList[i]));
-                    console.log("减法 goods detail =====>" + JSON.stringify(goodsDetails));
+                    // console.log("减法 goods detail =====>" + JSON.stringify(goodsDetails));
                     if(goodsDetails.sellVolume === 1){
                         alert("数量至少为1个");
                         return ;
@@ -813,7 +813,6 @@ let vm = new Vue({
             console.log(value);
         },
         deleteItem:function(value){
-            console.log(value);
             // 删除这条记录
             for(var i = 0 ; i < this.goodsList.length ; i++){
                 if(this.goodsList[i].id == value){
@@ -827,7 +826,7 @@ let vm = new Vue({
                     if(vm.brandGetOneFree.get(this.goodsList[i].brand)){
                         var giftBarcode = vm.brandGetOneFree.get(this.goodsList[i].brand).giftBarcode;
                         var muilty = vm.brandGetOneFree.get(this.goodsList[i].brand).buyNum;
-                        var sellNum = this.goodsList[i].sellVolume;;
+                        var sellNum = this.goodsList[i].sellVolume;
                         vm.freeBardcode.set(giftBarcode,sellNum/muilty);
 
                         for(var j = 0 ; j < vm.goodsList.length ; j++){
@@ -850,8 +849,18 @@ let vm = new Vue({
                         vm.halfPrice.set(this.goodsList[i].prodBarcode,1);
                     }
                     var goods = this.goodsList[i];
-                    console.log(goods);
-                    console.log(vm.totalPrice);
+                    // console.log(goods);
+                    // console.log(vm.totalPrice);
+
+                    $.get("../goods/number/del/" + sessionStorage.getItem("storeId") + "/" + goods.sku + "/" + goods.prodBarcode, function (res) {
+                        if (res.code === 0) {
+                            alert("删除成功!");
+                        } else if (res.code === 500) {
+                            alert(res.msg);
+                        } else {
+                            alert("未知异常!请联系管理员!");
+                        }
+                    });
 
                     if(vm.freeBardcode.get(goods.prodBarcode) || vm.freeBardcode.get(goods.prodBarcode) == 0){
                         var nnum = (((goods.retailPrice * goods.sellVolume) - goods.actualPaymentAmount)/goods.retailPrice);
@@ -877,7 +886,16 @@ let vm = new Vue({
         },
         clearGoodsList:function(){
             confirm('确认清空吗?', function () {
-                alert("清空成功");
+                $.get("../goods/number/clear/" + sessionStorage.getItem("storeId"), function (res) {
+                    if (res.code === 0) {
+                        alert("清空成功");
+                        vm.goodsList.clear();
+                    } else if (res.code === 500) {
+                        alert(res.msg);
+                    } else {
+                        alert("未知异常!请联系管理员!");
+                    }
+                })
             })
 
         },
@@ -960,9 +978,8 @@ let vm = new Vue({
         },
         // 计算优惠价格,返回订单详情数据
         calculateOrderPriceSubmit : function () {
-            console.log("11111");
 
-            console.log("点击计算=====>" + JSON.stringify(vm.goodsList));
+            // console.log("点击计算=====>" + JSON.stringify(vm.goodsList));
 
             var couponBarCode = vm.$refs.couponBarCode;
             if (couponBarCode === null || couponBarCode === '') {
@@ -1789,13 +1806,13 @@ function removeByValue(arr, val) {
 function handle(goodsDetails,operatorType){
     vm.goodsDetail = true;
     // goodsDetails.sellVolume = 1;
-    console.log("goodsDetails=====>" + JSON.stringify(goodsDetails));
+    // console.log("goodsDetails=====>" + JSON.stringify(goodsDetails));
     goodsDetails.id = vm.index;
-    console.log("vm.index====>" + vm.index);
+    // console.log("vm.index====>" + vm.index);
     if(!vm.goodsList[vm.index]){
         vm.index = vm.max;
     }
-    console.log("vm.goodsList[vm.index]=====>" + vm.goodsList[vm.index]);
+    // console.log("vm.goodsList[vm.index]=====>" + vm.goodsList[vm.index]);
     vm.max++;
     goodsDetails.goodsDesc = "";
 
@@ -2020,7 +2037,7 @@ calculateOrderPrice = function() {
         'memberCode': vm.$refs.couponBarCode.value,
         'goodsList' : vm.goodsList
     };
-    console.log("请求参数===>" + JSON.stringify(param));
+    // console.log("请求参数===>" + JSON.stringify(param));
 
     $.ajax({
         type: "POST",
@@ -2031,8 +2048,8 @@ calculateOrderPrice = function() {
             if (r.code === 0) {
                 let calGoodsList = r.data.goodsDetailsDtos;
                 // 更新购物栏中数据
-                console.log("返回====>" + JSON.stringify(r));
-                console.log("计算前数据===>" + JSON.stringify(vm.goodsList));
+                // console.log("返回====>" + JSON.stringify(r));
+                // console.log("计算前数据===>" + JSON.stringify(vm.goodsList));
                 vm.goodsList.clear();
                 calGoodsList.forEach(goods => vm.goodsList.push(goods));
                 vm.actualPrice = r.data.orderTotalPrice;
@@ -2044,8 +2061,8 @@ calculateOrderPrice = function() {
                 vm.scoreLimit = r.data.scoreLimit;
                 vm.beforeScore = r.data.beforeScore;
                 vm.afterScore = r.data.afterScore;
-                console.log("计算后数据===>" + JSON.stringify(calGoodsList));
-                console.log("替换后数据===>" + JSON.stringify(vm.goodsList));
+                // console.log("计算后数据===>" + JSON.stringify(calGoodsList));
+                // console.log("替换后数据===>" + JSON.stringify(vm.goodsList));
 
                 $("#calculateOrderPriceDialog").modal('hide');
                 alert("计算完成");
@@ -2064,7 +2081,7 @@ calculateOrderPrice = function() {
  * @param type                  类型,add:加 minus:减
  */
 handleSellVolume = function (currentGoodsDetail, type) {
-    console.log("处理前商品详情=====>" + JSON.stringify(currentGoodsDetail));
+    // console.log("处理前商品详情=====>" + JSON.stringify(currentGoodsDetail));
     // 当前未被处理的商品数量
     let number = currentGoodsDetail.sellVolume;
     // 当前商品应支付金额
@@ -2082,31 +2099,50 @@ handleSellVolume = function (currentGoodsDetail, type) {
     let currentTotalPrice = new BigNumber(vm.totalPrice);
     // 当前实际支付价
     let currentActualPrice = new BigNumber(vm.actualPrice);
+    let storeId = sessionStorage.getItem("storeId");
+    let sku = currentGoodsDetail.sku;
+    let prodBarcode = currentGoodsDetail.prodBarcode;
     if ('add' === type) {
-        currentGoodsDetail.sellVolume += 1;
-        currentGoodsDetail.goodstaxes = currentGoodsTax.add(singleTax).toString();
-        currentGoodsDetail.actualPaymentAmount = currentActualPaymentAmount.add(singleActualPaymentAmount).toString();
-        vm.totalCount += 1;
-        vm.totalPrice = currentTotalPrice.add(retailPrice).toString();
-        vm.actualPrice = currentActualPrice.add(singleActualPaymentAmount).toString();
+        $.get("../goods/number/add/"+ storeId +"/" + sku + "/" + prodBarcode + "/" + number, function (res) {
+            if (res.code === 0) {
+                currentGoodsDetail.sellVolume += 1;
+                currentGoodsDetail.goodstaxes = currentGoodsTax.add(singleTax).toString();
+                currentGoodsDetail.actualPaymentAmount = currentActualPaymentAmount.add(singleActualPaymentAmount).toString();
+                vm.totalCount += 1;
+                vm.totalPrice = currentTotalPrice.add(retailPrice).toString();
+                vm.actualPrice = currentActualPrice.add(singleActualPaymentAmount).toString();
+            } else if (res.code === 500) {
+                alert(res.msg);
+            } else {
+                alert("未知异常!请联系管理员!");
+            }
+        });
     } else {
-        currentGoodsDetail.sellVolume -= 1;
-        currentGoodsDetail.goodstaxes = currentGoodsTax.subtract(singleTax).toString();
-        currentGoodsDetail.actualPaymentAmount = currentActualPaymentAmount.subtract(singleActualPaymentAmount).toString();
-        vm.totalCount -= 1;
-        vm.totalPrice = currentTotalPrice.subtract(retailPrice).toString();
-        vm.actualPrice = currentActualPrice.subtract(singleActualPaymentAmount).toString();
+        $.get("../goods/number/minus/"+ storeId +"/" + sku + "/" + prodBarcode, function (res) {
+            if (res.code === 0) {
+                currentGoodsDetail.sellVolume -= 1;
+                currentGoodsDetail.goodstaxes = currentGoodsTax.subtract(singleTax).toString();
+                currentGoodsDetail.actualPaymentAmount = currentActualPaymentAmount.subtract(singleActualPaymentAmount).toString();
+                vm.totalCount -= 1;
+                vm.totalPrice = currentTotalPrice.subtract(retailPrice).toString();
+                vm.actualPrice = currentActualPrice.subtract(singleActualPaymentAmount).toString();
+            } else if (res.code === 500) {
+                alert(res.msg);
+            } else {
+                alert("未知异常!请联系管理员!");
+            }
+        });
     }
 
     for (let i = 0; i < vm.goodsList.length; i++) {
         let goods = vm.goodsList[i];
         if (currentGoodsDetail.prodBarcode === goods.prodBarcode && currentGoodsDetail.goodsSn === goods.goodsSn) {
             let splice = vm.goodsList.splice(i, 1, currentGoodsDetail);
-            console.log("被删除的元素====>" + JSON.stringify(splice));
+            // console.log("被删除的元素====>" + JSON.stringify(splice));
         }
     }
 
-    console.log("处理后商品详情=====>" + JSON.stringify(currentGoodsDetail))
+    // console.log("处理后商品详情=====>" + JSON.stringify(currentGoodsDetail));
 }
 
 

+ 91 - 0
kmall-manager/src/main/java/com/kmall/manager/manager/redis/JedisUtil.java

@@ -132,6 +132,97 @@ public class JedisUtil implements Serializable {
     }
 
     /**
+     * 设置缓存(hash),全
+     *
+     * @param key   键
+     * @param map   值
+     * @return      结果
+     */
+    public static String hmset(String key, Map<String, String> map) {
+        String result = null;
+        Jedis jedis = null;
+        try {
+            jedis = getResource();
+            result = jedis.hmset(key, map);
+            logger.debug("set {} = {}", key, map);
+        } catch (Exception e) {
+            logger.warn("set {} ", key, e);
+        } finally {
+            returnResource(jedis);
+        }
+        return result;
+    }
+
+    /**
+     * 设置缓存(hash),单个
+     *
+     * @param key       键
+     * @param entryKey  值
+     * @param value     值
+     * @return      结果
+     */
+    public static Long hset(String key, String entryKey, String value) {
+        Long result = null;
+        Jedis jedis = null;
+        try {
+            jedis = getResource();
+            result = jedis.hset(key, entryKey, value);
+            logger.debug("set {} : {} = {}", key, entryKey, value);
+        } catch (Exception e) {
+            logger.warn("set {} ", key, e);
+        } finally {
+            returnResource(jedis);
+        }
+        return result;
+    }
+
+    /**
+     * 删除hash单条
+     *
+     * @param key       hash key
+     * @param entryKey  entry key
+     * @return          result
+     */
+    public static Long hdel(String key, String entryKey) {
+        Long result = null;
+        Jedis jedis = null;
+        try {
+            jedis = getResource();
+            result = jedis.hdel(key, entryKey);
+            logger.debug("del {} : {}", key, entryKey);
+        } catch (Exception e) {
+            logger.warn("del {} ", key, e);
+        } finally {
+            returnResource(jedis);
+        }
+        return result;
+    }
+
+    /**
+     * 获取缓存(hash)
+     *
+     * @param key       hash的key
+     * @param entryKey  子项的key
+     * @return 值
+     */
+    public static String hget(String key, String entryKey) {
+        String value = null;
+        Jedis jedis = null;
+        try {
+            jedis = getResource();
+            if (jedis.exists(getBytesKey(key))) {
+                value = new String((jedis.hget(getBytesKey(key), getBytesKey(entryKey))));
+                logger.debug("getObject {} = {}", key, value);
+            }
+        } catch (Exception e) {
+            logger.warn("getObject {} ", key, e);
+        } finally {
+            returnResource(jedis);
+        }
+        return value;
+    }
+
+    /**
      * 设置缓存过期时间
      *
      * @param key          键