Compare commits
No commits in common. "1a841f3f85083ab1a7f249097bcba8cebdedd1b2" and "61228d9c35c66d50dec7dc896154f9067d65344d" have entirely different histories.
1a841f3f85
...
61228d9c35
@ -3,25 +3,16 @@ package com.small.client.dao;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.json.JSONArray;
|
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.small.client.Utils.BigDecimalFormatter;
|
import com.small.client.Utils.BigDecimalFormatter;
|
||||||
import com.small.client.Utils.CommonUtil;
|
|
||||||
import com.small.client.Utils.HttpUtils;
|
|
||||||
import com.small.client.dto.*;
|
import com.small.client.dto.*;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 考虑到每个思迅软件都是自己的数据,所以采用动态获取的方式获取数据
|
* 考虑到每个思迅软件都是自己的数据,所以采用动态获取的方式获取数据
|
||||||
@ -31,10 +22,7 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SxDataDao extends BaseDao{
|
public class SxDataDao extends BaseDao{
|
||||||
@Autowired
|
|
||||||
private RestTemplate restTemplate;
|
|
||||||
@Value("${remoteIp}")
|
|
||||||
private String remoteIp;
|
|
||||||
private final static String T_BD_ITEM_CLS="t_bd_item_cls";//商品分类
|
private final static String T_BD_ITEM_CLS="t_bd_item_cls";//商品分类
|
||||||
private final static String T_BD_ITEM_INFO="t_bd_item_info b";//商品表
|
private final static String T_BD_ITEM_INFO="t_bd_item_info b";//商品表
|
||||||
private final static String T_RM_VIP_INFO="t_rm_vip_info";//会员表
|
private final static String T_RM_VIP_INFO="t_rm_vip_info";//会员表
|
||||||
@ -470,8 +458,7 @@ public class SxDataDao extends BaseDao{
|
|||||||
* @param dataBaseInfo
|
* @param dataBaseInfo
|
||||||
* @param map
|
* @param map
|
||||||
*/
|
*/
|
||||||
public void updateStoreData(DataBaseInfo dataBaseInfo, Map map,List<ProductQuantityConsumptionDto> productQuantityConsumptionDtoList,
|
public void updateStoreData(DataBaseInfo dataBaseInfo, Map map){
|
||||||
CommentModel commentModel){
|
|
||||||
if(CollectionUtil.isEmpty(map)){
|
if(CollectionUtil.isEmpty(map)){
|
||||||
log.info("同步数据为空");
|
log.info("同步数据为空");
|
||||||
return;
|
return;
|
||||||
@ -495,12 +482,8 @@ public class SxDataDao extends BaseDao{
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
Set<Map.Entry> sme=map.entrySet();
|
Set<Map.Entry> sme=map.entrySet();
|
||||||
for (Map.Entry entry : sme) {
|
for (Map.Entry entry : sme) {
|
||||||
BigDecimal stock_qty= (BigDecimal) entry.getValue();
|
|
||||||
if(stock_qty.compareTo(BigDecimal.ZERO)==0){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ps.setString(1, (String) entry.getKey());
|
ps.setString(1, (String) entry.getKey());
|
||||||
ps.setDouble(2, stock_qty.doubleValue());
|
ps.setDouble(2, (double) entry.getValue());
|
||||||
ps.setTimestamp(3, timestamp);
|
ps.setTimestamp(3, timestamp);
|
||||||
ps.addBatch(); // 添加至批处理
|
ps.addBatch(); // 添加至批处理
|
||||||
count++;
|
count++;
|
||||||
@ -512,37 +495,22 @@ public class SxDataDao extends BaseDao{
|
|||||||
}
|
}
|
||||||
// 执行剩余未满 batchSize 的批次
|
// 执行剩余未满 batchSize 的批次
|
||||||
int[] remainingCounts = ps.executeBatch();
|
int[] remainingCounts = ps.executeBatch();
|
||||||
|
|
||||||
List<String> consumIds=productQuantityConsumptionDtoList
|
|
||||||
.stream()
|
|
||||||
.map(ProductQuantityConsumptionDto::getConsumeId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
Gson gson=new Gson();
|
|
||||||
String jsonString=gson.toJson(consumIds);
|
|
||||||
JSONArray jsonArray = JSONUtil.parseArray(jsonString);
|
|
||||||
String sign= CommonUtil.generateOpenSign(jsonString,commentModel.getAppKey(),commentModel.getAppId());
|
|
||||||
String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_POST_STORE_DATA_RESPONSE
|
|
||||||
+"?appKey="+commentModel.getAppKey()
|
|
||||||
+"&sign="+sign, jsonArray);
|
|
||||||
if (!HttpUtils.SUCCESSCODE.equals(code)) {
|
|
||||||
throw new Exception("服务器异常");
|
|
||||||
}
|
|
||||||
log.info("剩余批次更新数: {}", Arrays.toString(remainingCounts));
|
log.info("剩余批次更新数: {}", Arrays.toString(remainingCounts));
|
||||||
conn.commit(); // 最终提交事务
|
conn.commit(); // 最终提交事务
|
||||||
log.info("批量更新完成,总记录数: {}" , count);
|
log.info("批量更新完成,总记录数: {}" , count);
|
||||||
//baseUpdateImBrancStock(dataBaseInfo);
|
//baseUpdateImBrancStock(dataBaseInfo);
|
||||||
} catch (Exception e) {
|
} catch (SQLException e) {
|
||||||
conn.rollback(); // 出错时回滚整个事务
|
conn.rollback(); // 出错时回滚整个事务
|
||||||
log.info("业务失败:: {}", e.getMessage());
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.info("sql失败:: {}", e.getMessage());
|
e.printStackTrace();
|
||||||
}finally {
|
}finally {
|
||||||
if(conn!=null){
|
if(conn!=null){
|
||||||
try {
|
try {
|
||||||
conn.close();
|
conn.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.info("最后sql失败:: {}", e.getMessage());
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
package com.small.client.dto;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步消费中间表,同步数据时保存数据到这个表中,消费完更新已消费,证明数据已经同步给思迅客户端
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ApiModel("商品数量消费表")
|
|
||||||
public class ProductQuantityConsumptionDto {
|
|
||||||
@ApiModelProperty("自定义主键ID")
|
|
||||||
private String consumeId;
|
|
||||||
|
|
||||||
@ApiModelProperty("订单编号")
|
|
||||||
private String orderId;
|
|
||||||
|
|
||||||
@ApiModelProperty("商品编号")
|
|
||||||
private String productNumber;
|
|
||||||
|
|
||||||
@ApiModelProperty("数量(正数表示入库/增加,负数表示出库/减少)")
|
|
||||||
private BigDecimal quantity;
|
|
||||||
|
|
||||||
@ApiModelProperty("消费状态:0-未消费,1-已消费")
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
@ApiModelProperty("店铺ID")
|
|
||||||
private Integer storeId;
|
|
||||||
|
|
||||||
@ApiModelProperty("创建时间")
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "更新时间")
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date updateTime;
|
|
||||||
}
|
|
||||||
@ -218,7 +218,6 @@ public class SxDataServiceImp extends SxDataAbstService implements SxDataService
|
|||||||
String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_MEMBER
|
String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_MEMBER
|
||||||
+"?appKey="+commentModel.getAppKey()
|
+"?appKey="+commentModel.getAppKey()
|
||||||
+"&sign="+sign,memberList);//todo 后期改为文件传输
|
+"&sign="+sign,memberList);//todo 后期改为文件传输
|
||||||
|
|
||||||
if (!HttpUtils.SUCCESSCODE.equals(code)) {
|
if (!HttpUtils.SUCCESSCODE.equals(code)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -740,22 +739,8 @@ public class SxDataServiceImp extends SxDataAbstService implements SxDataService
|
|||||||
+"?appKey="+commentModel.getAppKey()
|
+"?appKey="+commentModel.getAppKey()
|
||||||
+"&sign="+commentModel.getAppId(),JSONObject.class);
|
+"&sign="+commentModel.getAppId(),JSONObject.class);
|
||||||
if(null!=jsonObject.get("result")){
|
if(null!=jsonObject.get("result")){
|
||||||
// Map map=(Map)jsonObject.get("result");
|
Map map=(Map)jsonObject.get("result");
|
||||||
List<ProductQuantityConsumptionDto> productQuantityConsumptionDtoList =
|
sxDataDao.updateStoreData(dataBaseInfo,map);
|
||||||
JSONUtil.toList(jsonObject.getStr("result"),ProductQuantityConsumptionDto.class);
|
|
||||||
if(!productQuantityConsumptionDtoList.isEmpty()){
|
|
||||||
Map map = productQuantityConsumptionDtoList.stream()
|
|
||||||
.collect(Collectors.groupingBy(
|
|
||||||
ProductQuantityConsumptionDto::getProductNumber,
|
|
||||||
Collectors.reducing(
|
|
||||||
BigDecimal.ZERO,
|
|
||||||
ProductQuantityConsumptionDto::getQuantity,
|
|
||||||
BigDecimal::add
|
|
||||||
)
|
|
||||||
));
|
|
||||||
sxDataDao.updateStoreData(dataBaseInfo,map,productQuantityConsumptionDtoList,commentModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
package com.suisung.mall.common.modules.sync;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步消费中间表,同步数据时保存数据到这个表中,消费完更新已消费,证明数据已经同步给思迅客户端
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@TableName("product_quantity_consumption")
|
|
||||||
@ApiModel("商品数量消费表")
|
|
||||||
public class ProductQuantityConsumption {
|
|
||||||
@TableId(value = "consume_id", type = IdType.INPUT)
|
|
||||||
@ApiModelProperty("自定义主键ID")
|
|
||||||
private String consumeId;
|
|
||||||
|
|
||||||
@TableField(value = "order_id",updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
@ApiModelProperty("订单编号")
|
|
||||||
private String orderId;
|
|
||||||
|
|
||||||
@TableField(value = "product_number", updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
@ApiModelProperty("商品编号")
|
|
||||||
private String productNumber;
|
|
||||||
|
|
||||||
@ApiModelProperty("数量(正数表示入库/增加,负数表示出库/减少)")
|
|
||||||
@TableField(value = "quantity",updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
private BigDecimal quantity;
|
|
||||||
|
|
||||||
@ApiModelProperty("消费状态:0-未消费,1-已消费")
|
|
||||||
@TableField(value = "status",updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
private Integer status;
|
|
||||||
|
|
||||||
@TableField(value = "store_id",updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
@ApiModelProperty("店铺ID")
|
|
||||||
private Integer storeId;
|
|
||||||
|
|
||||||
@TableField(value = "update_time",updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
@ApiModelProperty("创建时间")
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date createTime;
|
|
||||||
|
|
||||||
@TableField(value = "update_time",updateStrategy = FieldStrategy.NOT_EMPTY)
|
|
||||||
@ApiModelProperty(value = "更新时间")
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
|
||||||
private Date updateTime;
|
|
||||||
}
|
|
||||||
@ -3300,7 +3300,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
|||||||
|
|
||||||
// RMK 第三方数据同步相关:redis 给这个商品减去对应的库存
|
// RMK 第三方数据同步相关:redis 给这个商品减去对应的库存
|
||||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||||
stockDeltaMap.put(item_src_id+"_"+order_item_row.getOrder_id(), -order_item_quantity);
|
stockDeltaMap.put(item_src_id, -order_item_quantity);
|
||||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
|
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4223,7 +4223,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
|||||||
log.debug("释放库存Item_src_id:{},数量:{}",shopProductItem.getItem_src_id(),order_item_quantity);
|
log.debug("释放库存Item_src_id:{},数量:{}",shopProductItem.getItem_src_id(),order_item_quantity);
|
||||||
// RMK 第三方数据同步相关:redis 给这个商品加上对应的库存
|
// RMK 第三方数据同步相关:redis 给这个商品加上对应的库存
|
||||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||||
stockDeltaMap.put(shopProductItem.getItem_src_id()+"_"+order_item_row.getOrder_id(), order_item_quantity);
|
stockDeltaMap.put(Convert.toStr(shopProductItem.getItem_src_id()), order_item_quantity);
|
||||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
|
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7236,7 +7236,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
|||||||
// RMK 第三方数据同步相关:redis 给这个商品减去上对应的库存
|
// RMK 第三方数据同步相关:redis 给这个商品减去上对应的库存
|
||||||
log.debug("减库存Item_src_id:{},数量:{}",item_src_id,cart_quantity);
|
log.debug("减库存Item_src_id:{},数量:{}",item_src_id,cart_quantity);
|
||||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||||
stockDeltaMap.put(item_src_id+"_"+order_id, -cart_quantity);
|
stockDeltaMap.put(Convert.toStr(item_src_id), -cart_quantity);
|
||||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
|
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,15 +137,6 @@ public class SyncThirdDataController {
|
|||||||
return syncThirdDataService.getStoreDataRelease(appKey,sign);
|
return syncThirdDataService.getStoreDataRelease(appKey,sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "扣完库存之后做确认", notes = "扣完库存之后做确认")
|
|
||||||
@RequestMapping(value = "/syncStoreDataReleaseResponse", method = RequestMethod.POST)
|
|
||||||
public ThirdApiRes syncStoreDataReleaseResponse(@RequestBody List<String> consumIds,
|
|
||||||
@RequestParam String appKey,
|
|
||||||
@RequestParam String sign) {
|
|
||||||
syncThirdDataService.getStoreDataReleaseResponse(appKey,sign,consumIds);
|
|
||||||
return new ThirdApiRes().success("请求成功!");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ApiOperation(value = "通知上传商品文件到cos", notes = "通知上传商品文件到cos")
|
@ApiOperation(value = "通知上传商品文件到cos", notes = "通知上传商品文件到cos")
|
||||||
@RequestMapping(value = "/uploudToCos", method = RequestMethod.POST)
|
@RequestMapping(value = "/uploudToCos", method = RequestMethod.POST)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ public class RedisKey {
|
|||||||
|
|
||||||
//public static final String SXCLIENTKEYVERSION="sxclientKey:version";//客户端版本
|
//public static final String SXCLIENTKEYVERSION="sxclientKey:version";//客户端版本
|
||||||
|
|
||||||
public static final String STOREDATARELEASE="shopQuality:release";
|
public static final String STOREDATARELEASE="storedata:release";
|
||||||
|
|
||||||
public static final String STOREDATAPRODUCTMAPING="storedata:productMaping";
|
public static final String STOREDATAPRODUCTMAPING="storedata:productMaping";
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
package com.suisung.mall.shop.sync.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.suisung.mall.common.modules.sync.ProductQuantityConsumption;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface ProductQuantityConsumptionMapper extends BaseMapper<ProductQuantityConsumption> {
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
package com.suisung.mall.shop.sync.service;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.suisung.mall.common.modules.sync.ProductQuantityConsumption;
|
|
||||||
|
|
||||||
public interface ProductQuantityConsumptionService extends IService<ProductQuantityConsumption> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -12,7 +12,6 @@ import cn.hutool.json.JSONArray;
|
|||||||
import com.suisung.mall.common.api.CommonResult;
|
import com.suisung.mall.common.api.CommonResult;
|
||||||
import com.suisung.mall.common.modules.base.ShopBaseProductBrand;
|
import com.suisung.mall.common.modules.base.ShopBaseProductBrand;
|
||||||
import com.suisung.mall.common.modules.base.ShopBaseProductCategory;
|
import com.suisung.mall.common.modules.base.ShopBaseProductCategory;
|
||||||
import com.suisung.mall.common.modules.sync.ProductQuantityConsumption;
|
|
||||||
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
||||||
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@ -111,14 +110,6 @@ public interface SyncThirdDataService {
|
|||||||
*/
|
*/
|
||||||
ThirdApiRes getStoreDataRelease(String appKey, String sign);
|
ThirdApiRes getStoreDataRelease(String appKey, String sign);
|
||||||
|
|
||||||
/**
|
|
||||||
* 扣减完库存之后做确认,确认完成更新队列表为已消费
|
|
||||||
* @param appKey
|
|
||||||
* @param sign
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ThirdApiRes getStoreDataReleaseResponse(String appKey, String sign,List<String> consumIds);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存一个或多个商品刚刚变化的库存到 redis hash 缓存
|
* 保存一个或多个商品刚刚变化的库存到 redis hash 缓存
|
||||||
*
|
*
|
||||||
@ -131,7 +122,7 @@ public interface SyncThirdDataService {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<ProductQuantityConsumption> getProductStockFromRedis(String storeId,Map<String, Double> redisHash);
|
Map<String, Double> getProductStockFromRedis(String storeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下单或支付后,批量累加减商品库存,使用 Redis Hash 的原子自增操作,保证并发安全
|
* 下单或支付后,批量累加减商品库存,使用 Redis Hash 的原子自增操作,保证并发安全
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
package com.suisung.mall.shop.sync.service.impl;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.suisung.mall.common.modules.sync.ProductQuantityConsumption;
|
|
||||||
|
|
||||||
import com.suisung.mall.shop.sync.mapper.ProductQuantityConsumptionMapper;
|
|
||||||
import com.suisung.mall.shop.sync.service.ProductQuantityConsumptionService;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@lombok.extern.slf4j.Slf4j
|
|
||||||
@Transactional
|
|
||||||
public class ProductQuantityConsumptionServiceImpl extends ServiceImpl<ProductQuantityConsumptionMapper, ProductQuantityConsumption> implements ProductQuantityConsumptionService {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -13,7 +13,10 @@ import cn.hutool.core.collection.CollectionUtil;
|
|||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.*;
|
import cn.hutool.core.util.CharsetUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.core.util.ZipUtil;
|
||||||
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONArray;
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
@ -24,7 +27,6 @@ import com.google.gson.GsonBuilder;
|
|||||||
import com.qcloud.cos.model.COSObjectSummary;
|
import com.qcloud.cos.model.COSObjectSummary;
|
||||||
import com.suisung.mall.common.adapter.BigDecimalTypeAdapter;
|
import com.suisung.mall.common.adapter.BigDecimalTypeAdapter;
|
||||||
import com.suisung.mall.common.api.CommonResult;
|
import com.suisung.mall.common.api.CommonResult;
|
||||||
import com.suisung.mall.common.api.ResultCode;
|
|
||||||
import com.suisung.mall.common.api.StateCode;
|
import com.suisung.mall.common.api.StateCode;
|
||||||
import com.suisung.mall.common.enums.DicEnum;
|
import com.suisung.mall.common.enums.DicEnum;
|
||||||
import com.suisung.mall.common.exception.ApiException;
|
import com.suisung.mall.common.exception.ApiException;
|
||||||
@ -40,7 +42,10 @@ import com.suisung.mall.common.modules.sixun.SxSyncGoods;
|
|||||||
import com.suisung.mall.common.modules.sixun.SxSyncVip;
|
import com.suisung.mall.common.modules.sixun.SxSyncVip;
|
||||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||||
import com.suisung.mall.common.modules.store.ShopStoreActivityItem;
|
import com.suisung.mall.common.modules.store.ShopStoreActivityItem;
|
||||||
import com.suisung.mall.common.modules.sync.*;
|
import com.suisung.mall.common.modules.sync.StoreDbConfig;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncApp;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncConfig;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncFileLog;
|
||||||
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
||||||
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
@ -72,7 +77,6 @@ import com.suisung.mall.shop.sync.dto.BrandModel;
|
|||||||
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
||||||
import com.suisung.mall.shop.sync.service.*;
|
import com.suisung.mall.shop.sync.service.*;
|
||||||
import io.seata.spring.annotation.GlobalTransactional;
|
import io.seata.spring.annotation.GlobalTransactional;
|
||||||
import org.apache.commons.collections4.ListUtils;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -176,11 +180,9 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ProductMappingService productMappingService;
|
private ProductMappingService productMappingService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ShopProductIndexService shopProductIndexService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProductQuantityConsumptionService productQuantityConsumptionService;
|
private ShopProductIndexService shopProductIndexService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存商品的分类
|
* 批量保存商品的分类
|
||||||
@ -778,91 +780,18 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
if (syncAppO == null) {
|
if (syncAppO == null) {
|
||||||
return new ThirdApiRes().fail(1001, I18nUtil._("签名有误!"));
|
return new ThirdApiRes().fail(1001, I18nUtil._("签名有误!"));
|
||||||
}
|
}
|
||||||
//持久化保存数据到数据库队列
|
|
||||||
String key=RedisKey.STOREDATARELEASE+":"+syncAppO.getStore_id();
|
|
||||||
Map<String, Double> redisHash = redisTemplate.opsForHash().entries(key);
|
|
||||||
List<ProductQuantityConsumption> productQuantityConsumptionList=getProductStockFromRedis(syncAppO.getStore_id(),redisHash);
|
|
||||||
List<ProductQuantityConsumption> productQuantityConsumptions=new ArrayList<>();
|
|
||||||
if (!productQuantityConsumptionList.isEmpty()) {
|
|
||||||
boolean result= productQuantityConsumptionService.saveBatch(productQuantityConsumptionList,productQuantityConsumptionList.size());
|
|
||||||
if(result){
|
|
||||||
Set<String> fields = redisHash.keySet();
|
|
||||||
redisTemplate.opsForHash().delete(key, fields.toArray());//清除持久化数据
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//查询未消费数据
|
|
||||||
QueryWrapper<ProductQuantityConsumption> queryWrapper = new QueryWrapper<>();
|
|
||||||
queryWrapper.eq("store_id", syncAppO.getStore_id());
|
|
||||||
queryWrapper.eq("status",0);//未消费数据
|
|
||||||
productQuantityConsumptions=productQuantityConsumptionService.list(queryWrapper);
|
|
||||||
return new ThirdApiRes().success("success", productQuantityConsumptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
// Object obRst = redisService.get(RedisKey.STOREDATARELEASE);//商品库存扣减
|
||||||
public ThirdApiRes getStoreDataReleaseResponse(String appKey, String sign,List<String> consumIds) {
|
// Map storeDataResultMap = new HashMap();
|
||||||
if (StrUtil.isBlank(appKey) || StrUtil.isBlank(sign)) {
|
// if (obRst != null) {
|
||||||
logger.info("缺少必要参数!");
|
// Map resultMap = (Map) obRst;
|
||||||
}
|
// Set<Map.Entry> sme = resultMap.entrySet();
|
||||||
Gson gson = new Gson();
|
// storeDataResultMap = sme.stream().filter(m -> !(m.getValue().equals((double) 0))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
String jsonStr = gson.toJson(consumIds);
|
// }
|
||||||
SyncApp syncApp = syncAppService.checkAppSign(appKey, sign, jsonStr); // 验签、appid,必要参数判断
|
|
||||||
if (syncApp == null) {
|
|
||||||
logger.info("签名有误!");
|
|
||||||
return new ThirdApiRes().fail(250,"签名有误");
|
|
||||||
}
|
|
||||||
if(consumIds!=null){
|
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(6);
|
|
||||||
List<Future<?>> futures = new ArrayList<>();
|
|
||||||
Integer pages=CommonUtil.getPagesCount(consumIds.size(),limitCnt);
|
|
||||||
List<List<String>> pagesPatition = ListUtils.partition(consumIds, limitCnt);
|
|
||||||
AtomicInteger success = new AtomicInteger();
|
|
||||||
AtomicInteger fails = new AtomicInteger();
|
|
||||||
for (int i = 1; i <=pages ; i++) {
|
|
||||||
int finalI = i;
|
|
||||||
int finalI1 = i;
|
|
||||||
futures.add(executor.submit(() -> {
|
|
||||||
try {
|
|
||||||
List<String> pageData = pagesPatition.get(finalI - 1);
|
|
||||||
productQuantityConsumptionPageSave(pageData);
|
|
||||||
success.getAndIncrement();
|
|
||||||
return "成功执行"+ finalI1;
|
|
||||||
}catch (Exception e){
|
|
||||||
fails.getAndIncrement();
|
|
||||||
return "执行失败:"+finalI+":"+e.getMessage();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
// 等待所有任务完成
|
|
||||||
for (Future<?> future : futures) {
|
|
||||||
try {
|
|
||||||
logger.info("任务结果: {}", future.get());
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("任务执行异常: {}", e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
executor.shutdown();
|
|
||||||
logger.info("总任务数据:{}", pagesPatition.size());
|
|
||||||
logger.info("成功数据:{}", success.get());
|
|
||||||
logger.info("失败数据:{}", fails.get());
|
|
||||||
}
|
|
||||||
return new ThirdApiRes().success("success");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
Map<String, Double> storeDataResultMap = getProductStockFromRedis(syncAppO.getStore_id());
|
||||||
* 更新消费状态
|
|
||||||
* @param consumIds
|
return new ThirdApiRes().success("success", storeDataResultMap);
|
||||||
*/
|
|
||||||
private void productQuantityConsumptionPageSave(List<String> consumIds){
|
|
||||||
List<ProductQuantityConsumption> productQuantityConsumptionList=new ArrayList<>();
|
|
||||||
for (String consumeId : consumIds) {
|
|
||||||
ProductQuantityConsumption productQuantityConsumption=new ProductQuantityConsumption();
|
|
||||||
productQuantityConsumption.setConsumeId(consumeId);
|
|
||||||
productQuantityConsumption.setStatus(1);
|
|
||||||
productQuantityConsumptionList.add(productQuantityConsumption);
|
|
||||||
}
|
|
||||||
if(!productQuantityConsumptionList.isEmpty()){
|
|
||||||
productQuantityConsumptionService.updateBatchById(productQuantityConsumptionList,productQuantityConsumptionList.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
@ -884,34 +813,23 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductQuantityConsumption> getProductStockFromRedis(String storeId,Map<String, Double> redisHash) {
|
public Map<String, Double> getProductStockFromRedis(String storeId) {
|
||||||
try {
|
try {
|
||||||
// 从 Redis 获取 hash 结构的所有键值对
|
// 从 Redis 获取 hash 结构的所有键值对
|
||||||
|
String key=RedisKey.STOREDATARELEASE+":"+storeId;
|
||||||
|
Map<Object, Object> redisHash = redisTemplate.opsForHash().entries(key);
|
||||||
if (redisHash.isEmpty()) {
|
if (redisHash.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
// 转换为 list
|
// 转换为 Map<String, Integer>
|
||||||
List<ProductQuantityConsumption> productQuantityConsumptionList=new ArrayList<>();
|
return redisHash.entrySet().stream()
|
||||||
redisHash.forEach((k, v)->{
|
.collect(Collectors.toMap(
|
||||||
ProductQuantityConsumption productQuantityConsumption=new ProductQuantityConsumption();
|
entry -> String.valueOf(entry.getKey()),
|
||||||
String[] productKeyArrys=k.split("_");
|
entry -> Convert.toDouble(entry.getValue(), 0.00) // 转换失败时默认为 0
|
||||||
if(productKeyArrys.length!=2){
|
));
|
||||||
return;
|
|
||||||
}
|
|
||||||
String productNumber=productKeyArrys[0];
|
|
||||||
String orderId=productKeyArrys[1];
|
|
||||||
productQuantityConsumption.setConsumeId(IdUtil.getSnowflakeNextIdStr());
|
|
||||||
productQuantityConsumption.setOrderId(orderId);
|
|
||||||
productQuantityConsumption.setProductNumber(productNumber);
|
|
||||||
productQuantityConsumption.setQuantity(Convert.toBigDecimal(v));
|
|
||||||
productQuantityConsumption.setStoreId(Integer.valueOf(storeId));
|
|
||||||
productQuantityConsumption.setStatus(0);
|
|
||||||
productQuantityConsumptionList.add(productQuantityConsumption);
|
|
||||||
});
|
|
||||||
return productQuantityConsumptionList;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("从 Redis 获取商品库存失败: {}", e.getMessage(), e);
|
logger.error("从 Redis 获取商品库存失败: {}", e.getMessage(), e);
|
||||||
return Collections.emptyList();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,15 +847,9 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
if (StrUtil.isBlank(productKey) || delta == null) {
|
if (StrUtil.isBlank(productKey) || delta == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String[] productKeyArrys=productKey.split("_");
|
|
||||||
if(productKeyArrys.length!=2){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
String item_src_id=productKeyArrys[0];
|
|
||||||
String orderId=productKeyArrys[1];
|
|
||||||
QueryWrapper<ShopProductItem> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<ShopProductItem> queryWrapper = new QueryWrapper<>();
|
||||||
queryWrapper.eq("item_src_id", item_src_id);
|
queryWrapper.eq("item_src_id", productKey);
|
||||||
List<ShopProductItem> shopProductItems=shopProductItemService.list(queryWrapper);
|
List<ShopProductItem> shopProductItems=shopProductItemService.list(queryWrapper);
|
||||||
if(shopProductItems==null || shopProductItems.isEmpty()){
|
if(shopProductItems==null || shopProductItems.isEmpty()){
|
||||||
continue;
|
continue;
|
||||||
@ -959,7 +871,7 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
|||||||
String name = Convert.toStr(item.get("name"));
|
String name = Convert.toStr(item.get("name"));
|
||||||
BigDecimal itemQuaryty = getBigDecimal(delta, name);
|
BigDecimal itemQuaryty = getBigDecimal(delta, name);
|
||||||
// 使用 Redis 的 HINCRBY 保证原子性和高性能
|
// 使用 Redis 的 HINCRBY 保证原子性和高性能
|
||||||
redisTemplate.opsForHash().increment(key, itemId+"_"+orderId, itemQuaryty.doubleValue());
|
redisTemplate.opsForHash().increment(key, itemId, itemQuaryty.doubleValue());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("库存累计失败,productKey={}, delta={}, error={}", productKey, delta, e.getMessage(), e);
|
logger.error("库存累计失败,productKey={}, delta={}, error={}", productKey, delta, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
CREATE TABLE `product_quantity_consumption` (
|
|
||||||
`consume_id` varchar(32) NOT NULL COMMENT '自定义主键ID',
|
|
||||||
`product_number` varchar(50) NOT NULL COMMENT '商品编号',
|
|
||||||
`order_id` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '' COMMENT '订单编号',
|
|
||||||
`quantity` decimal(15,3) NOT NULL COMMENT '数量(正数表示入库/增加,负数表示出库/减少)',
|
|
||||||
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '消费状态:0-未消费,1-已消费',
|
|
||||||
`store_id` int(20) NOT NULL COMMENT '店铺ID',
|
|
||||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
||||||
PRIMARY KEY (`consume_id`),
|
|
||||||
KEY `idx_shop_product` (`store_id`, `product_number`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品数量消费表';
|
|
||||||
Loading…
Reference in New Issue
Block a user