diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/bean/TableStateEnum.java b/src/main/java/com/chaozhanggui/system/cashierservice/bean/TableStateEnum.java new file mode 100644 index 0000000..b802123 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/bean/TableStateEnum.java @@ -0,0 +1,15 @@ +package com.chaozhanggui.system.cashierservice.bean; + +public enum TableStateEnum { + IDLE("idle"), + CLOSED("closed"), PAYING("paying"), PENDING("pending"), USING("using"); + private String state = "closed"; + + TableStateEnum(String state) { + this.state = state; + } + + public String getState() { + return state; + } +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java b/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java index 1493248..eb19f37 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/controller/PayController.java @@ -198,6 +198,26 @@ public class PayController { } + /** + * 会员支付 + * @param token + * @param loginName + * @param clientType + * @param orderId + * @return + */ + @GetMapping("vipPay") + @LimitSubmit(key = "vipPay:%s") + public Result vipPay(@RequestHeader("token") String token, + @RequestHeader("loginName") String loginName, + @RequestHeader("clientType") String clientType, + @RequestParam("orderId") String orderId, + @RequestParam("vipUserId") Integer vipUserId){ + return payService.vipPay(orderId,token, vipUserId); + } + + + /** diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbOrderInfo.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbOrderInfo.java index 3ef40ba..a6a8bbc 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbOrderInfo.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbOrderInfo.java @@ -102,6 +102,8 @@ public class TbOrderInfo implements Serializable { private Integer staffId; + private String useType; + private static final long serialVersionUID = 1L; public TbOrderInfo(){ super(); @@ -166,4 +168,4 @@ public class TbOrderInfo implements Serializable { this.payType=payType; this.tableName=tableName; } -} \ No newline at end of file +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/vo/TbShopTableVO.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/vo/TbShopTableVO.java index a5af751..bea32fc 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/entity/vo/TbShopTableVO.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/vo/TbShopTableVO.java @@ -8,4 +8,5 @@ import lombok.EqualsAndHashCode; @Data public class TbShopTableVO extends TbShopTable { private Integer userId; + private String masterId; } diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/mybatis/MpShopUserFlowMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/mybatis/MpShopUserFlowMapper.java new file mode 100644 index 0000000..2ec4dfe --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/mybatis/MpShopUserFlowMapper.java @@ -0,0 +1,7 @@ +package com.chaozhanggui.system.cashierservice.mybatis; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chaozhanggui.system.cashierservice.entity.TbShopUserFlow; + +public interface MpShopUserFlowMapper extends BaseMapper { +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/mybatis/MpShopUserMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/mybatis/MpShopUserMapper.java new file mode 100644 index 0000000..70e6689 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/mybatis/MpShopUserMapper.java @@ -0,0 +1,13 @@ +package com.chaozhanggui.system.cashierservice.mybatis; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chaozhanggui.system.cashierservice.entity.TbShopUser; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import java.math.BigDecimal; + +public interface MpShopUserMapper extends BaseMapper { + @Update("update tb_shop_user set amount=amount-#{orderAmount}, consume_amount=consume_amount+#{orderAmount} where id=#{vipUserId} and amount >= 0") + long decrBalance(@Param("vipUserId") Integer vipUserId, @Param("orderAmount") BigDecimal orderAmount); +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/rabbit/PrintMechineConsumer.java b/src/main/java/com/chaozhanggui/system/cashierservice/rabbit/PrintMechineConsumer.java index 29b540b..997b3b4 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/rabbit/PrintMechineConsumer.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/rabbit/PrintMechineConsumer.java @@ -8,10 +8,7 @@ import com.chaozhanggui.system.cashierservice.model.CategoryInfo; import com.chaozhanggui.system.cashierservice.model.OrderDetailPO; import com.chaozhanggui.system.cashierservice.sign.CodeEnum; import com.chaozhanggui.system.cashierservice.sign.Result; -import com.chaozhanggui.system.cashierservice.util.DateUtils; -import com.chaozhanggui.system.cashierservice.util.FeieyunPrintUtil; -import com.chaozhanggui.system.cashierservice.util.JSONUtil; -import com.chaozhanggui.system.cashierservice.util.PrinterUtils; +import com.chaozhanggui.system.cashierservice.util.*; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; @@ -49,6 +46,9 @@ public class PrintMechineConsumer { @Autowired private TbOrderDetailMapper tbOrderDetailMapper; + @Autowired + + private RedisUtil redisUtils; @RabbitHandler public void listener(String message) { @@ -127,7 +127,8 @@ public class PrintMechineConsumer { * @param shopInfo * @param printerNum */ - private void yxyPrinter(TbPrintMachineWithBLOBs tbPrintMachineWithBLOBs,String model,TbOrderInfo orderInfo,TbShopInfo shopInfo,String printerNum, List categoryInfos){ + private void yxyPrinter(TbPrintMachineWithBLOBs tbPrintMachineWithBLOBs,String model, + TbOrderInfo orderInfo,TbShopInfo shopInfo,String printerNum, List categoryInfos){ String orderId=orderInfo.getId().toString(); @@ -257,10 +258,13 @@ public class PrintMechineConsumer { return; }else { tbOrderDetails = tbOrderDetailMapper.selectAllByOrderId(Integer.valueOf(orderId)); - if (ObjectUtil.isNotEmpty(tbOrderDetails) && tbOrderDetails.size() > 0) { + if (ObjectUtil.isNotEmpty(tbOrderDetails) && !tbOrderDetails.isEmpty()) { tbOrderDetails.parallelStream().forEach(it -> { - + // 已经打印过的菜品不再打印 + if ("postPay".equals(orderInfo.getUseType()) && isPrint(it)) { + return; + } String categoryId = tbProductMapper.selectByPrimaryKey(Integer.valueOf(it.getProductId())).getCategoryId(); Long count = categoryInfos.stream().filter(c -> @@ -274,7 +278,9 @@ public class PrintMechineConsumer { if (ObjectUtil.isNotEmpty(tbProductSkuWithBLOBs) && ObjectUtil.isNotEmpty(tbProductSkuWithBLOBs.getSpecSnap())) { remark = tbProductSkuWithBLOBs.getSpecSnap(); } - String data = PrinterUtils.getPrintData("",orderInfo.getMasterId(), DateUtils.getTime(new Date(orderInfo.getCreatedAt())), it.getProductName(), it.getNum(), remark); + String data = PrinterUtils.getPrintData("",orderInfo.getMasterId(), + DateUtils.getTime(new Date(orderInfo.getCreatedAt())), it.getProductName(), + it.getNum(), remark); String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}"; PrinterUtils.printTickets(voiceJson,3, Integer.valueOf(printerNum), tbPrintMachineWithBLOBs.getAddress(), data); } @@ -292,6 +298,21 @@ public class PrintMechineConsumer { } } + /** + * 判断商品是否已打票 + * @return true 已打 false 未打 + */ + private boolean isPrint(TbOrderDetail orderDetail) { + String key = RedisCst.ORDER_PRINT + orderDetail.getProductId() + ":" + orderDetail.getProductSkuId(); + String info = redisUtils.getMessage(key); + redisUtils.saveMessage(key, String.valueOf(orderDetail.getNum()), 60 * 60 * 24); + if (info == null) { + return false; + } + orderDetail.setNum(orderDetail.getNum() - Integer.parseInt(info)); + return true; + } + diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/OrderService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/OrderService.java index 8f360ee..69db4ae 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/OrderService.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/OrderService.java @@ -10,6 +10,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.chaozhanggui.system.cashierservice.bean.ShopWxMsgTypeEnum; +import com.chaozhanggui.system.cashierservice.bean.TableStateEnum; import com.chaozhanggui.system.cashierservice.dao.*; import com.chaozhanggui.system.cashierservice.entity.*; import com.chaozhanggui.system.cashierservice.entity.dto.UpdateVipDTO; @@ -274,6 +275,7 @@ public class OrderService { cashierCart.setNumber(number); cashierCart.setUuid(uuid); cashierCart.setCategoryId(product.getCategoryId()); + cashierCart.setTableId(tableId); list.add(cashierCart); cashierCartMapper.insert(cashierCart); cart=cashierCart; @@ -364,9 +366,10 @@ public class OrderService { queryWrapper.isNull(TbCashierCart::getTableId).or().eq(TbCashierCart::getTableId, ""); // 台桌点单 }else if (StrUtil.isNotBlank(tableId)) { + String finalMasterId = masterId; queryWrapper.eq(TbCashierCart::getTableId, tableId) .and(query -> { - query.eq(TbCashierCart::getMasterId, masterId) + query.eq(TbCashierCart::getMasterId, finalMasterId) .or() .isNull(TbCashierCart::getMasterId); }); @@ -405,10 +408,12 @@ public class OrderService { } Map map = new HashMap<>(); map.put("list", list); - map.put("masterId", masterId); BigDecimal totalAmount = BigDecimal.ZERO; BigDecimal packAmount = BigDecimal.ZERO; for (TbCashierCart cashierCart : list) { + if (StrUtil.isNotBlank(cashierCart.getMasterId())) { + masterId = cashierCart.getMasterId(); + } totalAmount = totalAmount.add(cashierCart.getTotalAmount()); if (cashierCart.getIsPack().equals("true")) { packAmount = packAmount.add(cashierCart.getPackFee()); @@ -427,6 +432,9 @@ public class OrderService { } // TbProductSkuResult skuResult = tbProductSkuResultMapper.selectByPr imaryKey(Integer.valueOf(cashierCart.getProductId())); } + + map.put("masterId", masterId); + QueryCartPo queryCartPo = cashierCartMapper.selectProductNumByMarketId(day, shopId, masterId); queryCartPo.setPackAmount(packAmount); queryCartPo.setTotalAmount(totalAmount); @@ -557,7 +565,7 @@ public class OrderService { String orderNo = generateOrderNumber(); TbToken tbToken = tokenMapper.selectByToken(token); TbOrderInfo orderInfo = tbOrderInfoMapper.selectByPrimaryKey(orderId); - if (orderId > 0) { + if (orderId > 0 && orderInfo != null) { // if (!orderInfo.getStatus().equals("unpaid")){ // return Result.fail(CodeEnum.ORDERCREATE); // } @@ -583,6 +591,9 @@ public class OrderService { orderInfo.setMasterId(masterId); orderInfo.setRemark(orderVo.getRemark()); orderInfo.setUserId(orderVo.getUserId()); + if (StrUtil.isNotBlank(orderVo.getTableId())) { + orderInfo.setTableId(orderVo.getTableId()); + } if (Objects.nonNull(tbToken)){ orderInfo.setTokenId(tbToken.getId()); } @@ -651,6 +662,13 @@ public class OrderService { } if (flag) { redisUtil.deleteByKey("SHOP:CODE:USER:" + clientType + ":" + orderVo.getShopId() + ":" + day + orderVo.getUserId()); + // 代课下单 + if (!StrUtil.isBlank(orderVo.getTableId())) { + mpShopTableMapper.update(null, new LambdaUpdateWrapper() + .eq(TbShopTable::getQrcode, orderInfo.getTableId()) + .set(TbShopTable::getStatus, TableStateEnum.USING.getState())); + producer.printMechine(String.valueOf(orderInfo.getId())); + } } JSONObject object=new JSONObject(); @@ -673,8 +691,6 @@ public class OrderService { redisUtil.saveMessage(RedisCst.OUT_NUMBER.concat(orderInfo.getShopId().toString()),object.toString()); - - log.info("创建订单,发送更新耗材消息,订单id:{}", orderInfo.getId()); //修改耗材数据 JSONObject jsonObject=new JSONObject(); @@ -696,6 +712,16 @@ public class OrderService { return Result.success(CodeEnum.SUCCESS, orderInfo); } + public synchronized void addGlobalCode(String day, String clientType, String shopId) { + String code = redisUtil.getMessage("SHOP:CODE:" + clientType + ":" + shopId + ":" + day); + if (StrUtil.isBlank(code)) { + redisUtil.saveMessage("SHOP:CODE:" + clientType + ":" + shopId + ":" + day, "1"); + }else { + redisUtil.getMessage("SHOP:CODE:" + clientType + ":" + shopId + ":" + (Integer.parseInt(code) + 1)); + } + redisUtil.execsSet("SHOP:CODE:SET" + clientType + ":" + shopId + ":" + day, "1"); + } + public synchronized String generateOrderCode(String day, String clientType, String shopId) { String code = redisUtil.getMessage("SHOP:CODE:" + clientType + ":" + shopId + ":" + day)+""; // 使用顺序递增的计数器生成取餐码 @@ -900,6 +926,11 @@ public class OrderService { if (flag) { redisUtil.deleteByKey("SHOP:CODE:USER:" + clientType + ":" + shopId + ":" + day + userId); } + + mpShopTableMapper.update(null, new LambdaUpdateWrapper() + .eq(TbShopTable::getQrcode, tableId) + .set(TbShopTable::getStatus, TableStateEnum.PENDING.getState())); + } else { List list = mpCashierCartMapper.selectList(queryWrapper .eq(TbCashierCart::getStatus, "refund")); diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java index 187c27f..020ba31 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/PayService.java @@ -1,8 +1,10 @@ package com.chaozhanggui.system.cashierservice.service; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.chaozhanggui.system.cashierservice.dao.*; import com.chaozhanggui.system.cashierservice.entity.*; import com.chaozhanggui.system.cashierservice.entity.dto.ReturnGroupOrderDto; @@ -11,6 +13,8 @@ import com.chaozhanggui.system.cashierservice.exception.MsgException; import com.chaozhanggui.system.cashierservice.model.ReturnOrderReq; import com.chaozhanggui.system.cashierservice.model.ScanPayReq; import com.chaozhanggui.system.cashierservice.model.TradeQueryReq; +import com.chaozhanggui.system.cashierservice.mybatis.MpShopUserFlowMapper; +import com.chaozhanggui.system.cashierservice.mybatis.MpShopUserMapper; import com.chaozhanggui.system.cashierservice.rabbit.RabbitProducer; import com.chaozhanggui.system.cashierservice.sign.CodeEnum; import com.chaozhanggui.system.cashierservice.sign.Result; @@ -118,6 +122,10 @@ public class PayService { @Autowired TbPlussShopStaffMapper tbPlussShopStaffMapper; + @Autowired + private MpShopUserMapper mpShopUserMapper; + @Autowired + private MpShopUserFlowMapper mpShopUserFlowMapper; public static void main(String[] args) { @@ -710,6 +718,82 @@ public class PayService { return Result.success(CodeEnum.SUCCESS); } + public Result vipPay(String orderId, String token, Integer vipUserId) { + if (ObjectUtil.isEmpty(orderId)) { + return Result.fail(CodeEnum.PARAM); + } + + TbOrderInfo orderInfo = tbOrderInfoMapper.selectByPrimaryKey(Integer.valueOf(orderId)); + + if (ObjectUtil.isEmpty(orderInfo)) { + return Result.fail(CodeEnum.ORDERNOEXIST); + } + + if (!"unpaid".equals(orderInfo.getStatus())) { + return Result.fail(CodeEnum.ORDERSTATUSERROR); + } + + + int count = tbShopPayTypeMapper.countSelectByShopIdAndPayType(orderInfo.getShopId(), "cash"); + if (count < 1) { + return Result.fail(CodeEnum.PAYTYPENOEXIST); + } + + // 扣减会员余额 + TbShopUser shopUser = mpShopUserMapper.selectOne(new LambdaUpdateWrapper() + .eq(TbShopUser::getStatus, 1) + .eq(TbShopUser::getId, vipUserId)); + + if (shopUser == null) { + return Result.fail("用户不存在或已被禁用"); + } + + long flag = mpShopUserMapper.decrBalance(vipUserId, orderInfo.getOrderAmount()); + if (flag < 1) { + return Result.fail("余额不足或扣除余额失败"); + } + + TbShopUserFlow userFlow = new TbShopUserFlow(); + userFlow.setAmount(orderInfo.getOrderAmount()); + userFlow.setBalance(shopUser.getAmount()); + userFlow.setShopUserId(shopUser.getId()); + userFlow.setBizCode("vipCardCash"); + userFlow.setBizName("代客下单会员余额支付"); + userFlow.setCreateTime(DateUtil.date()); + userFlow.setType("-"); + mpShopUserFlowMapper.insert(userFlow); + + + orderInfo.setPayAmount(orderInfo.getOrderAmount()); + orderInfo.setPayType("cash"); + orderInfo.setStatus("closed"); + orderInfo.setPayOrderNo("cash".concat(SnowFlakeUtil.generateOrderNo())); + tbOrderInfoMapper.updateByPrimaryKeySelective(orderInfo); + //更新购物车状态 + int cartCount = tbCashierCartMapper.updateByOrderId(orderId, "final"); + + tbOrderDetailMapper.updateStatusByOrderIdAndStatus(Integer.valueOf(orderId), "closed"); + log.info("更新购物车:{}", cartCount); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("token", token); + jsonObject.put("type", "create"); + jsonObject.put("orderId", orderId); + + producer.putOrderCollect(jsonObject.toJSONString()); + + + producer.printMechine(orderId); + + // 发送库存记录mq消息 + JSONObject mqData = new JSONObject(); + mqData.put("orderId", orderId); + mqData.put("type", "pc"); + producer.sendStockSaleMsg(mqData); + + return Result.success(CodeEnum.SUCCESS); + } + @Transactional(rollbackFor = Exception.class) public Result cashPay(String orderId, String token,BigDecimal payAmount,BigDecimal discountAmount) { if (ObjectUtil.isEmpty(orderId)) { @@ -782,6 +866,10 @@ public class PayService { mqData.put("type", "pc"); producer.sendStockSaleMsg(mqData); + + redisUtil.del("SHOP:CODE:USER:" + "pc" + ":" + orderInfo.getShopId() + ":" + DateUtils.getDay() + TokenUtil.parseParamFromToken(token).getString("accountId")); + + return Result.success(CodeEnum.SUCCESS); } @@ -856,6 +944,8 @@ public class PayService { mqData.put("type", "pc"); producer.sendStockSaleMsg(mqData); + redisUtil.del("SHOP:CODE:USER:" + "pc" + ":" + orderInfo.getShopId() + ":" + DateUtils.getDay() + TokenUtil.parseParamFromToken(token).getString("accountId")); + return Result.success(CodeEnum.SUCCESS); } @@ -1156,6 +1246,7 @@ public class PayService { productStockDetailMapper.insert(tbProductStockDetail); } + redisUtil.del("SHOP:CODE:USER:" + "pc" + ":" + orderInfo.getShopId() + ":" + DateUtils.getDay() + TokenUtil.parseParamFromToken(token).getString("accountId")); return Result.success(CodeEnum.SUCCESS); } @@ -1254,6 +1345,8 @@ public class PayService { } + redisUtil.del("SHOP:CODE:USER:" + "pc" + ":" + shopId + ":" + DateUtils.getDay() + TokenUtil.parseParamFromToken(token).getString("accountId")); + return Result.fail(CodeEnum.FAIL); @@ -1310,6 +1403,7 @@ public class PayService { } } + return Result.success(CodeEnum.SUCCESS, tbQuickPay); } diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisCst.java b/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisCst.java index 4510232..25f4abf 100644 --- a/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisCst.java +++ b/src/main/java/com/chaozhanggui/system/cashierservice/util/RedisCst.java @@ -20,4 +20,5 @@ public class RedisCst { 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:"; + public static final String ORDER_PRINT = "ORDER_PRINT:"; } diff --git a/src/main/resources/mapper/TbOrderInfoMapper.xml b/src/main/resources/mapper/TbOrderInfoMapper.xml index 6d79ed9..b132347 100644 --- a/src/main/resources/mapper/TbOrderInfoMapper.xml +++ b/src/main/resources/mapper/TbOrderInfoMapper.xml @@ -47,6 +47,7 @@ + @@ -56,7 +57,7 @@ discount_amount, table_id, small_change, send_type, order_type, product_type, status, billing_id, merchant_id, shop_id, is_vip, member_id, user_id, product_score, deduct_score, user_coupon_id, user_coupon_amount, refund_able, paid_time, is_effect, is_group, - updated_at, `system_time`, created_at, is_accepted, pay_order_no,trade_day,`source`,remark,master_id,`table_name`,out_number + updated_at, `system_time`, created_at, is_accepted, pay_order_no,trade_day,`source`,remark,master_id,`table_name`,out_number, use_type