修改取单号逻辑算法
This commit is contained in:
parent
7a26bdec49
commit
f9192c74ff
@ -2,6 +2,7 @@ package com.suisung.mall.shop.number.service;
|
||||
|
||||
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
import org.springframework.data.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -17,6 +18,14 @@ public interface ShopNumberSeqService extends IBaseService<ShopNumberSeq> {
|
||||
|
||||
String createNextSeq(String prefix);
|
||||
|
||||
/**
|
||||
* 创建下一个编号(键值对)
|
||||
*
|
||||
* @param prefix 前缀
|
||||
* @return 序号和完整编号
|
||||
*/
|
||||
Pair<Long, String> createNextSeqPair(String prefix);
|
||||
|
||||
Long createNextNo(String prefix);
|
||||
|
||||
List<Long> batchCreateNextNo(String seqName, int batchSize);
|
||||
|
||||
@ -27,6 +27,7 @@ import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -125,6 +126,44 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到下一个编号键值对
|
||||
* 方法走到这里会产生串行化,集群部署这里不能使用单机锁
|
||||
*
|
||||
* @param prefix
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
@DistributedLock(
|
||||
key = "CREATENEXTSEQ_LOCK", // 锁的key
|
||||
waitTime = 3, // 等待3秒
|
||||
leaseTime = 10, // 锁持有10秒
|
||||
errorMsg = "生成ID繁忙,请稍后重试" // 自定义错误消息
|
||||
)
|
||||
public synchronized Pair<Long, String> createNextSeqPair(String prefix) {
|
||||
String ymd = DateUtil.format(new Date(), "yyyyMMdd");
|
||||
String id = String.format("%s_%s_", prefix, ymd);
|
||||
ShopNumberSeq shopNumberSeq = this.baseMapper.selectById(id);
|
||||
if (shopNumberSeq == null) {
|
||||
shopNumberSeq = new ShopNumberSeq();
|
||||
shopNumberSeq.setPrefix(id);
|
||||
shopNumberSeq.setNumber(1L);
|
||||
if (!save(shopNumberSeq)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String order_id = String.format("%s_%s_%s", prefix, ymd, shopNumberSeq.getNumber());
|
||||
shopNumberSeq.setPrefix(id);
|
||||
boolean flag = edit(shopNumberSeq);
|
||||
if (flag) {
|
||||
return Pair.of(shopNumberSeq.getNumber(), order_id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到下一个Id
|
||||
*
|
||||
@ -280,12 +319,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
boolean isLocked = false;
|
||||
int start = 0;
|
||||
try {
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
if (!isLocked) {
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new RuntimeException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
if (null != redisService.get(RedisKey.STOREDATASPECID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATASPECID);
|
||||
redisService.set(RedisKey.STOREDATASPECID, start + batchSize);
|
||||
@ -305,12 +344,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return IntStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
|
||||
}
|
||||
@ -322,7 +361,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> getBatchSpecItemId(int batchSize) {
|
||||
public List<Integer> getBatchSpecItemId(int batchSize) {
|
||||
// 定义锁的key,这个key在所有服务实例中必须一致
|
||||
String lockKey = "LOCK:" + RedisKey.STOREDATASPECITEMID;
|
||||
// 2. 获取分布式锁对象
|
||||
@ -330,12 +369,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
boolean isLocked = false;
|
||||
int start = 0;
|
||||
try {
|
||||
isLocked=lock.tryLock(2,30,TimeUnit.SECONDS);
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
if (!isLocked) {
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new ApiException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
if (null != redisService.get(RedisKey.STOREDATASPECITEMID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATASPECITEMID);
|
||||
redisService.set(RedisKey.STOREDATASPECITEMID, start + batchSize);
|
||||
@ -355,12 +394,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return IntStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (InterruptedException e) {
|
||||
throw new ApiException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,7 +422,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new RuntimeException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
int start = 0;
|
||||
if (null != redisService.get(RedisKey.STOREDATACCOUNTBASEID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATACCOUNTBASEID);
|
||||
@ -403,12 +442,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("getBatchUserAccountBaseId获取锁时被中断", e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
|
||||
}
|
||||
@ -421,7 +460,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> getBatchLibraryProductId(int batchSize) {
|
||||
public List<Integer> getBatchLibraryProductId(int batchSize) {
|
||||
// 定义锁的key,这个key在所有服务实例中必须一致
|
||||
String lockKey = "LOCK:" + RedisKey.STOREDATALIBRARYID;
|
||||
// 2. 获取分布式锁对象
|
||||
@ -434,7 +473,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new RuntimeException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
if (null != redisService.get(RedisKey.STOREDATALIBRARYID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATALIBRARYID);
|
||||
redisService.set(RedisKey.STOREDATALIBRARYID, start + batchSize);
|
||||
@ -454,12 +493,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return IntStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
|
||||
}
|
||||
@ -478,12 +517,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
boolean isLocked = false;
|
||||
long start = 0;
|
||||
try {
|
||||
isLocked=lock.tryLock(2,30,TimeUnit.SECONDS);
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
if (!isLocked) {
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new ApiException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
QueryWrapper<ShopPageBase> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.select("max(page_id) as page_id");
|
||||
ShopPageBase shopPageBase = shopPageBaseService.getOne(queryWrapper);
|
||||
@ -493,41 +532,41 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return LongStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (InterruptedException e) {
|
||||
throw new ApiException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化主键
|
||||
*/
|
||||
private void syncPrimaryKey(){
|
||||
List<ShopNumberSeq> shopNumberSeqList=new ArrayList<>();
|
||||
QueryWrapper<ShopProductBase> baseWrapper=new QueryWrapper<>();
|
||||
private void syncPrimaryKey() {
|
||||
List<ShopNumberSeq> shopNumberSeqList = new ArrayList<>();
|
||||
QueryWrapper<ShopProductBase> baseWrapper = new QueryWrapper<>();
|
||||
baseWrapper.select("MAX(product_id) as product_id");
|
||||
ShopProductBase shopProductBase= shopProductBaseService.getOne(baseWrapper);
|
||||
Long productId= shopProductBase.getProduct_id();
|
||||
ShopProductBase shopProductBase = shopProductBaseService.getOne(baseWrapper);
|
||||
Long productId = shopProductBase.getProduct_id();
|
||||
//QueryWrapper<ShopNumberSeq> baseSeWrapper=new QueryWrapper();
|
||||
//baseSeWrapper.eq("prefix", "product_id");
|
||||
ShopNumberSeq shopNumberSeqBase= new ShopNumberSeq();
|
||||
ShopNumberSeq shopNumberSeqBase = new ShopNumberSeq();
|
||||
shopNumberSeqBase.setPrefix("product_id");
|
||||
shopNumberSeqBase.setNumber(productId);
|
||||
//shopNumberSeqServiceImpl.edit(shopNumberSeqBase,baseWrapper);
|
||||
//查询产品item
|
||||
QueryWrapper<ShopProductItem> itemQuery=new QueryWrapper<>();
|
||||
QueryWrapper<ShopProductItem> itemQuery = new QueryWrapper<>();
|
||||
itemQuery.select("MAX(item_id) as item_id");
|
||||
ShopProductItem shopProductItem= shopProductItemService.getOne(itemQuery);
|
||||
Long itemtId=1L;
|
||||
if(null!=shopProductItem){
|
||||
itemtId= shopProductItem.getItem_id();
|
||||
ShopProductItem shopProductItem = shopProductItemService.getOne(itemQuery);
|
||||
Long itemtId = 1L;
|
||||
if (null != shopProductItem) {
|
||||
itemtId = shopProductItem.getItem_id();
|
||||
}
|
||||
// QueryWrapper<ShopNumberSeq> itemWrapper=new QueryWrapper();
|
||||
//itemWrapper.eq("prefix", "item_id");
|
||||
ShopNumberSeq shopNumberSeqItem= new ShopNumberSeq();
|
||||
ShopNumberSeq shopNumberSeqItem = new ShopNumberSeq();
|
||||
shopNumberSeqItem.setNumber(itemtId);
|
||||
shopNumberSeqItem.setPrefix("item_id");
|
||||
shopNumberSeqList.add(shopNumberSeqBase);
|
||||
@ -537,5 +576,4 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -5289,17 +5289,17 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
throw new ApiException(I18nUtil._("无符合取消条件的订单!"));
|
||||
}
|
||||
|
||||
ShopOrderBase shopOrderBase = new ShopOrderBase();
|
||||
shopOrderBase.setOrder_id(order_id);
|
||||
shopOrderBase.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderBaseService.edit(shopOrderBase)) {
|
||||
ShopOrderBase shopOrderBaseUpd = new ShopOrderBase();
|
||||
shopOrderBaseUpd.setOrder_id(order_id);
|
||||
shopOrderBaseUpd.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderBaseService.edit(shopOrderBaseUpd)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
}
|
||||
|
||||
ShopOrderInfo orderInfo = new ShopOrderInfo();
|
||||
orderInfo.setOrder_id(order_id);
|
||||
orderInfo.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderInfoService.edit(orderInfo)) {
|
||||
ShopOrderInfo orderInfoUpd = new ShopOrderInfo();
|
||||
orderInfoUpd.setOrder_id(order_id);
|
||||
orderInfoUpd.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderInfoService.edit(orderInfoUpd)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
}
|
||||
|
||||
@ -5319,7 +5319,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
if (shopOrderInfo.getDelivery_type_id() != null
|
||||
&& StateCode.DELIVERY_TYPE_SAME_CITY == shopOrderInfo.getDelivery_type_id().intValue()) {
|
||||
try {
|
||||
logger.info("开始取消顺丰同城配送订单,orderId: {}, delivery_type_id: {}", order_id, shopOrderInfo.getDelivery_type_id());
|
||||
logger.warn("开始取消顺丰同城配送订单,orderId: {}, delivery_type_id: {}", order_id, shopOrderInfo.getDelivery_type_id());
|
||||
ThirdApiRes sfResult = sfExpressApiService.cancelOrder(order_id, 313, "用户或商家取消订单。");
|
||||
if (sfResult != null && !sfResult.getError_code().equals(0)) {
|
||||
log.error("顺丰同城取消订单返回错误,orderId: {}, errorCode: {}, errorMsg: {}",
|
||||
@ -6421,7 +6421,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
type_code = StrUtil.isBlank(type_code) ? "DD" : type_code;
|
||||
String xid = RootContext.getXID();
|
||||
RootContext.unbind();
|
||||
String order_id = shopNumberSeqService.createNextSeq(type_code);
|
||||
Pair<Long, String> seqPair = shopNumberSeqService.createNextSeqPair(type_code);// 位数的序号: DD_20251205_1 2025-12-05 1
|
||||
String order_id = seqPair.getSecond();
|
||||
Long seqNo = seqPair.getFirst(); // 序号: DD_20251205_1 得出 1
|
||||
RootContext.bind(xid);
|
||||
|
||||
List<ShopOrderItem> item_rows = new ArrayList();
|
||||
@ -6666,6 +6668,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
|
||||
info_row.setOrder_id(order_id);
|
||||
info_row.setOrder_pickup_num(seqNo); //重要:配送员的取单号
|
||||
info_row.setOrder_title(product_item_name); // 订单标题
|
||||
if (fixOrderVo != null && fixOrderVo.isFix_price() && StrUtil.isNotEmpty(fixOrderVo.getOrder_title())) {
|
||||
info_row.setOrder_title(fixOrderVo.getOrder_title()); // 订单标题
|
||||
|
||||
@ -207,7 +207,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
QueryWrapper<ShopOrderInfo> queryWrapper = new QueryWrapper<>();
|
||||
// 已发货,已签收
|
||||
queryWrapper.in("order_state_id", StateCode.ORDER_STATE_SHIPPED, StateCode.ORDER_STATE_RECEIVED);
|
||||
queryWrapper.eq("order_is_received",CommonConstant.Disable);
|
||||
queryWrapper.eq("order_is_received", CommonConstant.Disable);
|
||||
// 默认7天,自动收货
|
||||
// 配置了发货或已签收的订单,1天自动收货
|
||||
Float order_autofinish_time = accountBaseConfigService.getConfig("order_autofinish_time", 7f);
|
||||
@ -372,8 +372,8 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
/**
|
||||
* 已支付的订单,生成取单号,打票机并打印订单
|
||||
*
|
||||
* @param storeId
|
||||
* @param orderId
|
||||
* @param storeId 商家ID
|
||||
* @param orderId 订单ID
|
||||
* @return 取货单号
|
||||
*/
|
||||
// @Transactional
|
||||
@ -403,11 +403,22 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
}
|
||||
|
||||
try {
|
||||
// 生成取单号
|
||||
Long orderPickupNum = genTodayPickupNum(storeId);
|
||||
if (orderPickupNum == null || orderPickupNum <= 0) {
|
||||
logger.error("生成取单号失败: storeId={}", storeId);
|
||||
return 0L;
|
||||
// 生成取单号(废弃)
|
||||
// Long orderPickupNum = genTodayPickupNum(storeId);
|
||||
// if (orderPickupNum == null || orderPickupNum <= 0) {
|
||||
// logger.error("生成取单号失败: storeId={}", storeId);
|
||||
// return 0L;
|
||||
// }
|
||||
|
||||
Long orderPickupNum = 0L;
|
||||
// 如果订单中尚未设置取单号,则从订单ID中提取
|
||||
if (CheckUtil.isEmpty(orderInfoOld.getOrder_pickup_num())) {
|
||||
// 从订单ID中提取最后的数字部分作为取单号
|
||||
// 例如订单ID为 DD_20250510_11,则提取出 11 作为取单号
|
||||
orderPickupNum = Convert.toLong(StrUtil.subAfter(orderId, "_", true));
|
||||
} else {
|
||||
// 如果已有取单号,则使用现有的
|
||||
orderPickupNum = orderInfoOld.getOrder_pickup_num();
|
||||
}
|
||||
|
||||
// 更新订单信息
|
||||
@ -432,6 +443,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据订单Id、订单状态、配送方式、退款状态 获取订单的数量
|
||||
*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user