From 68b9b1ab98d81e3c74374e959ad2d6d0280b2a8f Mon Sep 17 00:00:00 2001 From: SongZhang <2064194730@qq.com> Date: Sat, 31 Aug 2024 16:48:37 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BB=A3=E5=AE=A2=E4=B8=8B=E5=8D=95=20?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E8=AE=A2=E5=8D=95=E4=BF=9D=E5=AD=98=E8=AE=A2?= =?UTF-8?q?=E5=8D=95id=E5=88=B0=E7=BC=93=E5=AD=98=202.=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=8C=82=E8=B5=B7=E8=AE=A2=E5=8D=95=E9=87=8D=E5=A4=8D=E6=89=93?= =?UTF-8?q?=E7=A5=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/ysk/cashier/cons/RedisConstant.java | 14 ++ .../controller/product/TbPlaceController.java | 2 +- .../cashier/dto/shoptable/CreateOrderDTO.java | 1 + .../impl/shopimpl/TbShopTableServiceImpl.java | 133 +++++++++++++++++- .../service/shop/TbShopTableService.java | 2 +- .../main/java/cn/ysk/cashier/utils/Utils.java | 74 ++++++++++ 6 files changed, 218 insertions(+), 8 deletions(-) diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/cons/RedisConstant.java b/eladmin-system/src/main/java/cn/ysk/cashier/cons/RedisConstant.java index 82dd034a..65dbe6f5 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/cons/RedisConstant.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/cons/RedisConstant.java @@ -12,4 +12,18 @@ public interface RedisConstant { public static final String ORDER_MESSAGE="ORDER:MESSAGE:"; public static final String ORDER_PRODUCT_NUM = "ORDER_NUM:"; public static final String ORDER_CART_EXISTS = "ORDER_CART_EXISTS:"; + String CURRENT_TABLE_ORDER = "CURRENT_TABLE_ORDER:"; + + public static String TABLE_CART = "TABLE:CART:"; + String ADD_TABLE_CART_LOCK = "ADD_TABLE_CART"; + String PC_OUT_NUMBER = "PC_OUT_NUMBER:"; + + + static String getCurrentOrderKey(String tableId, String shopId) { + return CURRENT_TABLE_ORDER + shopId + ":" + tableId; + } + + static String getTableCartKey(String tableId, String shopId) { + return TABLE_CART + tableId + "-" + shopId; + } } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/TbPlaceController.java b/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/TbPlaceController.java index df5936f4..285d452c 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/TbPlaceController.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/controller/product/TbPlaceController.java @@ -143,7 +143,7 @@ public class TbPlaceController { public ResponseEntity createOrder( @RequestBody CreateOrderDTO createOrderDTO ) { - return ResponseEntity.ok(tbShopTableService.createOrder(createOrderDTO, !createOrderDTO.isPostPay())); + return ResponseEntity.ok(tbShopTableService.createOrder(createOrderDTO, !createOrderDTO.isPostPay(), true)); } @AnonymousAccess diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/dto/shoptable/CreateOrderDTO.java b/eladmin-system/src/main/java/cn/ysk/cashier/dto/shoptable/CreateOrderDTO.java index ee6a793f..5b11a4ad 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/dto/shoptable/CreateOrderDTO.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/dto/shoptable/CreateOrderDTO.java @@ -16,4 +16,5 @@ public class CreateOrderDTO { private String tableId; private String note; private boolean postPay; + private Integer orderId; } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/shopimpl/TbShopTableServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/shopimpl/TbShopTableServiceImpl.java index 3f0d2009..95c8f9e9 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/shopimpl/TbShopTableServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/impl/shopimpl/TbShopTableServiceImpl.java @@ -44,6 +44,7 @@ import cn.ysk.cashier.repository.shop.TbShopInfoRepository; import cn.ysk.cashier.service.impl.TbPayServiceImpl; import cn.ysk.cashier.utils.*; import cn.ysk.cashier.vo.PendingCountVO; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; @@ -70,6 +71,7 @@ import java.util.*; import java.io.IOException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; /** @@ -110,6 +112,8 @@ public class TbShopTableServiceImpl implements TbShopTableService { private final String QRCODE = "https://kysh.sxczgkj.cn/codeplate?code="; private final RabbitMsgUtils rabbitMsgUtils; private final TbPayServiceImpl tbPayServiceImpl; + private final TbCashierCartMapper tbCashierCartMapper; + private final TbOrderDetailMapper tbOrderDetailMapper; @Override public Map queryAll(TbShopTableQueryCriteria criteria, Pageable pageable) { @@ -136,6 +140,23 @@ public class TbShopTableServiceImpl implements TbShopTableService { List tbShopTableList = tbShopTableRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)); ArrayList> infoList = new ArrayList<>(); for (TbShopTable date : tbShopTableList) { + String orderId = redisTemplate.opsForValue().get(RedisConstant.CURRENT_TABLE_ORDER + date.getShopId() + ":" + date.getQrcode()); + if (StrUtil.isBlank(date.getQrcode())) { + date.setStatus("closed"); + }else if (tbCashierCartMapper.selectCount(new LambdaQueryWrapper() + .eq(TbCashierCart::getShopId, date.getShopId()) + .eq(TbCashierCart::getTableId, date.getQrcode()) + .eq(TbCashierCart::getStatus, "create")) < 1 || (orderId != null && + tbOrderDetailMapper.selectCount(new LambdaQueryWrapper() + .eq(TbOrderDetail::getShopId, date.getShopId()) + .eq(TbOrderDetail::getStatus, "unpaid") + .eq(TbOrderDetail::getOrderId, orderId)) < 1) + ) { + date.setStatus("idle"); + mpShopTableMapper.update(null, new LambdaUpdateWrapper() + .eq(TbShopTable::getQrcode, date.getQrcode()) + .set(TbShopTable::getStatus, TableStateEnum.IDLE.getState())); + } Map itemMap = BeanUtil.beanToMap(date, false, false); if (!"".equals(date.getQrcode())) { itemMap.put("qrcode", QRCODE + date.getQrcode().trim()); @@ -320,6 +341,13 @@ public class TbShopTableServiceImpl implements TbShopTableService { .eq(TbCashierCart::getSkuId, addCartDTO.getSkuId()) .eq(TbCashierCart::getProductId, addCartDTO.getProductId()) .eq(TbCashierCart::getTableId, addCartDTO.getTableId()) + .in(TbCashierCart::getStatus, "create", "refund") +// .and(q -> { +// q.eq(TbCashierCart::getTradeDay, DateUtils.getDay()) +// .or() +// .isNull(TbCashierCart::getTradeDay); +// +// }); .and(query2 -> { query2.and(query3 -> { query3.eq(TbCashierCart::getTradeDay, DateUtils.getDay()) @@ -336,6 +364,13 @@ public class TbShopTableServiceImpl implements TbShopTableService { } TbCashierCart tbCashierCart = cashierCartMapper.selectOne(query); + // 增加redis购物车数据 + String tableCartKey = RedisConstant.getTableCartKey(addCartDTO.getTableId(), addCartDTO.getShopId().toString()); + String tableCart = redisTemplate.opsForValue().get(tableCartKey); + List cartArrayList = new ArrayList<>(); + if (tableCart != null) { + cartArrayList = JSONObject.parseArray(tableCart, TbCashierCart.class); + } // 首次加入 if (tbCashierCart == null) { tbCashierCart = new TbCashierCart(); @@ -371,6 +406,7 @@ public class TbShopTableServiceImpl implements TbShopTableService { tbCashierCart.setNumber(addCartDTO.getNum()); tbCashierCart.setCategoryId(product.getCategoryId()); cashierCartRepository.save(tbCashierCart); + } else { tbCashierCart.setTotalAmount(new BigDecimal(addCartDTO.getNum()).multiply(productSku.getSalePrice())); @@ -399,9 +435,36 @@ public class TbShopTableServiceImpl implements TbShopTableService { cashierCartRepository.save(tbCashierCart); } + setRedisTableCartInfo(addCartDTO.getTableId(), addCartDTO.getShopId().toString(), Collections.singletonList(tbCashierCart), true); + return tbCashierCart; } + private void setRedisTableCartInfo(String tableId, String shopId, List tbCashierCartList, boolean isAdd) { + String tableCartKey = RedisConstant.getTableCartKey(tableId, shopId); + String tableCart = redisTemplate.opsForValue().get(tableCartKey); + + List cartArrayList = new ArrayList<>(); + if (tableCart != null) { + cartArrayList = JSONObject.parseArray(tableCart, TbCashierCart.class); + } + + for (TbCashierCart cashierCart : tbCashierCartList) { + cartArrayList = cartArrayList.stream().filter(d -> !d.getId().equals(cashierCart.getId())).collect(Collectors.toList()); + if (isAdd) { + cartArrayList.add(cashierCart); + } + } + + List finalCartArrayList = cartArrayList; + Utils.runFunAndCheckKey(() -> { + redisTemplate.opsForValue().set(tableCartKey, + JSONObject.toJSONString(finalCartArrayList)); + return null; + }, redisTemplate, RedisConstant.ADD_TABLE_CART_LOCK); + } + + @Override public void removeCart(RemoveCartDTO removeCartDTO) { // 会员点单 @@ -414,10 +477,23 @@ public class TbShopTableServiceImpl implements TbShopTableService { if (cashierCart.getOrderId() != null) { orderDetailMapper.delete(new LambdaQueryWrapper() + .eq(TbOrderDetail::getShopId, cashierCart.getShopId()) + .eq(TbOrderDetail::getProductId, cashierCart.getProductId()) + .eq(TbOrderDetail::getProductSkuId, cashierCart.getSkuId()) .eq(TbOrderDetail::getOrderId, cashierCart.getOrderId())); } cashierCartMapper.delete(new LambdaQueryWrapper().eq(TbCashierCart::getShopId, removeCartDTO.getShopId()) .eq(TbCashierCart::getId, removeCartDTO.getCartId())); + + + // 清空购物车 出票 + long carCount = countCar(cashierCart.getTableId(), cashierCart.getShopId(), cashierCart.getMasterId()); + if (cashierCart.getOrderId() != null && carCount < 1) { + rabbitMsgUtils.printTicket(String.valueOf(cashierCart.getOrderId())); + } + + setRedisTableCartInfo(removeCartDTO.getTableId().toString(), removeCartDTO.getShopId().toString(), Collections.singletonList(cashierCart), false); + } @Override @@ -433,6 +509,15 @@ public class TbShopTableServiceImpl implements TbShopTableService { .isNull(TbCashierCart::getUserId)); } tbShopTableRepository.deleteByTableIdAndShopId(clearCartDTO.getTableId(), clearCartDTO.getShopId()); + + } + + private long countCar(Long tableId, String shopId, String masterId) { + String orderId = redisTemplate.opsForValue().get(RedisConstant.getCurrentOrderKey(tableId.toString(), shopId)); + return tbOrderDetailMapper.selectCount(new LambdaQueryWrapper() + .eq(TbOrderDetail::getShopId, shopId) + .eq(TbOrderDetail::getStatus, "unpaid") + .eq(TbOrderDetail::getOrderId, orderId)); } @Override @@ -756,9 +841,27 @@ public class TbShopTableServiceImpl implements TbShopTableService { return jsonObject; } + private void getOutNumber(String shopId, String tableId) { + String shopKey = RedisConstant.PC_OUT_NUMBER + ":" + shopId; + String outNumber = redisTemplate.opsForValue().get(shopKey); + if (outNumber == null) { + Boolean flag = redisTemplate.opsForValue().setIfAbsent(shopKey, "1"); + if (flag != null && flag.equals(Boolean.FALSE)) { + outNumber = redisTemplate.opsForValue().get(shopKey); + } + } + + String shopTableKey = RedisConstant.PC_OUT_NUMBER + ":" + shopId; + redisTemplate.opsForValue().get(shopTableKey); + } + @Override - public TbOrderInfo createOrder(CreateOrderDTO createOrderDTO, boolean addMaterId) { + public TbOrderInfo createOrder(CreateOrderDTO createOrderDTO, boolean addMaterId, boolean isPrint) { + String currentOrderKey = RedisConstant.getCurrentOrderKey(createOrderDTO.getTableId(), createOrderDTO.getShopId().toString()); + String orderIdValue = redisTemplate.opsForValue().get(currentOrderKey); + Integer orderId = orderIdValue == null ? null : Integer.parseInt(orderIdValue); + orderId = createOrderDTO.getOrderId() != null ? createOrderDTO.getOrderId() : orderId; String day = DateUtils.getDay(); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() @@ -800,7 +903,7 @@ public class TbShopTableServiceImpl implements TbShopTableService { BigDecimal feeAmount = BigDecimal.ZERO; BigDecimal saleAmount = BigDecimal.ZERO; List orderDetails = new ArrayList<>(); - Integer orderId = null; + for (TbCashierCart cashierCart : cashierCarts) { totalAmount = totalAmount.add(cashierCart.getTotalAmount()); packAMount = packAMount.add(cashierCart.getPackFee()); @@ -828,11 +931,16 @@ public class TbShopTableServiceImpl implements TbShopTableService { if (cashierCart.getOrderId() != null) { orderId = cashierCart.getOrderId(); } + orderDetail.setOrderId(orderId); } TbOrderInfo orderInfo = null; if (orderId != null) { orderInfo = orderInfoMapper.selectById(orderId); + + if (orderInfo == null || !"unpaid".equals(orderInfo.getStatus())) { + redisTemplate.delete(currentOrderKey); + } } // 修改订单信息 @@ -860,6 +968,7 @@ public class TbShopTableServiceImpl implements TbShopTableService { orderInfo.setOrderNo(orderNo); orderInfo.setUseType(createOrderDTO.isPostPay() ? "postPay" : "afterPay"); orderInfo.setAmount(totalAmount); + orderInfo.setPayAmount(BigDecimal.ZERO); orderInfo.setPackFee(packAMount); orderInfo.setSettlementAmount(totalAmount); orderInfo.setOriginAmount(totalAmount); @@ -873,6 +982,7 @@ public class TbShopTableServiceImpl implements TbShopTableService { orderInfo.setRefundAble(1); orderInfo.setTradeDay(day); orderInfo.setMasterId(createOrderDTO.getMasterId()); + orderInfo.setOutNumber(createOrderDTO.getMasterId()); orderInfo.setRemark(createOrderDTO.getNote()); orderInfo.setUserId(createOrderDTO.getVipUserId() == null ? null : String.valueOf(createOrderDTO.getVipUserId())); orderInfo.setCreatedAt(DateUtil.current()); @@ -885,6 +995,8 @@ public class TbShopTableServiceImpl implements TbShopTableService { } orderInfo.setMerchantId(merchantAccount.getId().toString()); orderInfoMapper.insert(orderInfo); + + redisTemplate.opsForValue().set(currentOrderKey, orderInfo.getId().toString()); } @@ -935,7 +1047,7 @@ public class TbShopTableServiceImpl implements TbShopTableService { .eq(TbShopTable::getQrcode, createOrderDTO.getTableId()) .set(TbShopTable::getStatus, TableStateEnum.USING.getState())); - if (createOrderDTO.isPostPay()) { + if (createOrderDTO.isPostPay() && isPrint) { rabbitMsgUtils.printTicket(String.valueOf(orderId)); } @@ -1007,7 +1119,7 @@ public class TbShopTableServiceImpl implements TbShopTableService { createOrderDTO.setMasterId(pendingDTO.getMasterId()); createOrderDTO.setVipUserId(pendingDTO.getVipUserId()); createOrderDTO.setNote(pendingDTO.getNote()); - orderId = createOrder(createOrderDTO, true).getId(); + orderId = createOrder(createOrderDTO, true, false).getId(); } @@ -1035,10 +1147,10 @@ public class TbShopTableServiceImpl implements TbShopTableService { mpShopTableMapper.update(null, new LambdaUpdateWrapper() .eq(TbShopTable::getQrcode, cashierCart.getTableId()) .set(TbShopTable::getStatus, TableStateEnum.PENDING.getState())); - - rabbitMsgUtils.printTicket(String.valueOf(orderId)); } + redisTemplate.delete(RedisConstant.getCurrentOrderKey(pendingDTO.getTableId(), pendingDTO.getShopId().toString())); + return orderInfoMapper.selectById(orderId); } @@ -1133,6 +1245,15 @@ public class TbShopTableServiceImpl implements TbShopTableService { String key = "SHOP:CODE:USER:pc" + ":" + payDTO.getShopId() + ":" + day + ":" + orderInfo.getTableId(); redisTemplate.delete(key); } + + + String currentOrderKey = RedisConstant.CURRENT_TABLE_ORDER + payDTO.getShopId() + ":" + orderInfo.getTableId(); + redisTemplate.delete(currentOrderKey); + + // 小程序购物车缓存 + String tableCartKey = RedisConstant.getTableCartKey(orderInfo.getTableId(), orderInfo.getShopId()); + redisTemplate.delete(tableCartKey); + return null; } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/service/shop/TbShopTableService.java b/eladmin-system/src/main/java/cn/ysk/cashier/service/shop/TbShopTableService.java index 44cd95a4..fb7c7f75 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/service/shop/TbShopTableService.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/service/shop/TbShopTableService.java @@ -108,7 +108,7 @@ public interface TbShopTableService { void pack(PackCartDTO packCartDTO); - Object createOrder(CreateOrderDTO createOrderDTO, boolean addMasterId); + Object createOrder(CreateOrderDTO createOrderDTO, boolean addMasterId, boolean isPrint); Object getMasterId(Integer shopId, Long tableId, Integer vipUserId); diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/utils/Utils.java b/eladmin-system/src/main/java/cn/ysk/cashier/utils/Utils.java index 9fa7ad22..3c67b37b 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/utils/Utils.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/utils/Utils.java @@ -1,11 +1,19 @@ package cn.ysk.cashier.utils; +import cn.ysk.cashier.exception.BadRequestException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; public class Utils { + public static int retryCount = 5; private static final Logger log = LoggerFactory.getLogger(Utils.class); public static void catchErrNoReturn(Supplier supplier) { @@ -15,4 +23,70 @@ public class Utils { log.error("执行方法出现异常", e); } } + + public static void runFunAndRetryNoReturn( + Supplier function, + Function check, Consumer errFun) { + log.info("工具类开始执行函数"); + R result = function.get(); + boolean flag = check.apply(result); + + log.info("执行结果: {}", result); + + while (flag && retryCount-- > 0) { + log.info("执行函数失败, 剩余尝试次数{}", retryCount); + result = function.get(); + log.info("执行结果: {}", result); + flag = check.apply(result); + } + + if (flag) { + errFun.accept(result); + } + } + + public static T runFunAndCheckKey(Supplier supplier, StringRedisTemplate redisTemplate, String lockKey) { + try{ + // 创建线程id, 用作判断 + String clientId = UUID.randomUUID().toString(); + // 设置分布式锁 + boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.MILLISECONDS)); + int count = 0; + while (!lock) { + if (count++ > 100) { + throw new BadRequestException("系统繁忙, 稍后再试"); + } + Thread.sleep(20); + lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.MILLISECONDS)); + } + return supplier.get(); + } catch (Exception e){ + log.info("执行出错:{}", e.getMessage()); + throw new BadRequestException(e.getMessage()); + }finally{ + redisTemplate.delete(lockKey); + } + } + + public static R runFunAndRetry( + Supplier function, + Function check, Consumer errFun) { + log.info("工具类开始执行函数"); + R result = function.get(); + boolean flag = check.apply(result); + + log.info("执行结果: {}", result); + + while (flag && retryCount-- > 0) { + log.info("执行函数失败, 剩余尝试次数{}", retryCount); + result = function.get(); + log.info("执行结果: {}", result); + flag = check.apply(result); + } + + if (flag) { + errFun.accept(result); + } + return result; + } }