Merge remote-tracking branch 'origin/test' into test

This commit is contained in:
2024-09-14 16:24:36 +08:00
60 changed files with 2301 additions and 329 deletions

View File

@@ -1,5 +1,6 @@
package cn.ysk.cashier.service;
import cn.ysk.cashier.dto.BaseQueryDto;
import cn.ysk.cashier.dto.ShopSummaryDto;
import cn.ysk.cashier.dto.shop.ShopTableSaleInfoDto;
import cn.ysk.cashier.vo.ShopTableSaleInfoVo;
@@ -17,8 +18,9 @@ import java.util.Map;
* @author lyf
*/
public interface SummaryService {
SummaryVO selectSummary(Integer shop);
Map<String,Object> trade(BaseQueryDto param);
// SummaryVO selectSummary(Integer shop);
Map<String,Object> selectSummaryDate(Integer shopId, Integer day);
Map<String,Object> selectSummaryToday(Integer shopId);

View File

@@ -7,14 +7,15 @@ import cn.ysk.cashier.pojo.order.TbOrderInfo;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
public interface TbPayService {
TbOrderInfo scanPay(PayDTO payDTO);
TbOrderInfo scanPay(Integer shopId, String code, Integer merchantId, Integer memberId, BigDecimal payMount, TbOrderInfo orderInfo);
TbOrderInfo vipPay(@NotNull Integer shopId, @NotNull Integer orderId, Double discount, Integer vipUserId);
void vipPay(BigDecimal payMount, Integer vipUserId);
TbOrderInfo cashPay(PayDTO payDTO);
TbOrderInfo memberAccountPay(String memberId, String shopId, String accountCode, Integer orderId, Double discount) throws Exception;
TbOrderInfo memberAccountPay(String memberId, String shopId, String accountCode, TbOrderInfo orderInfo, BigDecimal payMount) throws Exception;
}

View File

@@ -0,0 +1,10 @@
package cn.ysk.cashier.service;
import java.util.Map;
public interface WxService {
String getFetchQRCode(Map<String, Object> params);
String getSmallQrcode(String shopId);
}

View File

@@ -0,0 +1,25 @@
package cn.ysk.cashier.service.app;
import cn.ysk.cashier.dto.calltable.*;
public interface TbCallService {
Object add(CallTableDTO addCallTableDTO);
Object update(UpdateCallTableDTO callTableDTO);
Object delete(BaseCallTableDTO baseCallTableDTO);
Object takeNumber(TakeNumberDTO takeNumber);
Object call(CallQueueDTO callQueueDTO);
Object updateInfo(UpdateCallQueueDTO updateCallQueueDTO);
Object get(Integer page, Integer size, Integer shopId, Integer callTableId, Integer state);
Object takeNumberCode(Integer shopId, Integer callTableId);
Object getQueue(Integer shopId, Integer callTableId, Integer state, Integer page, Integer size);
Object getCallRecord(Integer shopId, Integer callTableId, Integer page, Integer size);
}

View File

@@ -1,15 +1,19 @@
package cn.ysk.cashier.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.ysk.cashier.dto.ShopSummaryDto;
import cn.ysk.cashier.dto.BaseQueryDto;
import cn.ysk.cashier.dto.shop.ShopTableSaleInfoDto;
import cn.ysk.cashier.enums.PayTypeEnum;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mybatis.mapper.TbShopUserFlowMapper;
import cn.ysk.cashier.mybatis.service.TbShopUserFlowService;
import cn.ysk.cashier.repository.ShopUserDutyDetailRepository;
import cn.ysk.cashier.repository.ShopUserDutyRepository;
import cn.ysk.cashier.repository.TbTokenRepository;
import cn.ysk.cashier.repository.order.TbOrderDetailRepository;
import cn.ysk.cashier.repository.order.TbOrderInfoRepository;
import cn.ysk.cashier.repository.shop.TbShopTableRepository;
import cn.ysk.cashier.repository.shop.TbShopUserRepository;
import cn.ysk.cashier.service.SummaryService;
import cn.ysk.cashier.utils.DateUtil;
@@ -56,106 +60,167 @@ public class SummaryServiceImpl implements SummaryService {
@Resource
private TbTokenRepository tbTokenRepository;
@Autowired
private TbShopUserFlowMapper tbShopUserFlowMapper;
@Resource
private TbShopUserFlowService tbShopUserFlowService;
@Autowired
private TbOrderDetailRepository tbOrderDetailRepository;
private final TbShopTableRepository tbShopTableRepository;
@Override
public SummaryVO selectSummary(Integer shopId) {
SummaryVO summaryVO = new SummaryVO();
//支付笔数,
Tuple result = tbOrderInfoRepository.countByShopId(shopId.toString());
summaryVO.setPaymentsNumber(result.get(0, Long.class) == null ? 0L : result.get(0, Long.class));
summaryVO.setTotalSales(result.get(1, BigDecimal.class) == null ? new BigDecimal("0") : result.get(1, BigDecimal.class));
if (summaryVO.getPaymentsNumber() == 0) {
summaryVO.setAverageSales(new BigDecimal("0"));
} else {
summaryVO.setAverageSales(summaryVO.getTotalSales().divide(new BigDecimal(summaryVO.getPaymentsNumber()), 2, RoundingMode.DOWN));
public Map<String, Object> trade(BaseQueryDto param) {
if (ObjectUtil.isNull(param.getShopId())) {
throw new BadRequestException("参数不合法");
}
//用户数
Tuple count = tbShopUserRepository.searchByCount(shopId.toString());
summaryVO.setTotalUser(count == null ? 0L : count.get(0, Long.class));
//支付笔数柱形图
List<Object[]> objects = tbOrderInfoRepository.sumByDateOrderNum(shopId.toString(), DateUtil.getDate30DaysAgo(), DateUtil.getDayEnd());
List<CountDateVO> countDateList = new ArrayList<>();
for (Object[] o : objects) {
CountDateVO countDateVO = new CountDateVO();
BigInteger integers = (BigInteger) o[0];
countDateVO.setCount(new BigDecimal(integers.toString()));
countDateVO.setTradeDay((String) o[1]);
countDateList.add(countDateVO);
Map<String, Object> result = new HashMap<>();
Map<String, Object> sale = new HashMap<>();
Map<String, Object> vip = new HashMap<>();
Map<String, Object> count = new HashMap<>();
//订单 销售金额 saleAmount /订单数 saleNum /优惠金额 saveAmount /优惠笔数 saveNum
Map<String, Object> orderMap = tbOrderInfoRepository.tradeIndex(param.getShopId(), param.getStartTime().getTime(), param.getEndTime().getTime());
//退款金额
BigDecimal refundAmount = tbOrderInfoRepository.tradeIndexRefund(param.getShopId(), param.getStartTime().getTime(), param.getEndTime().getTime());
//会员 充值金额 inAmount /退款金额 outAmount /会员消费金额 useAmount /会员消费笔数 useNum
Map<String, Object> flowMap = tbShopUserFlowMapper.tradeIndexFlow(param.getShopId(), DateUtil.getStrTime(param.getStartTime()), DateUtil.getStrTime(param.getEndTime()));
// 新增会员数
Integer newFlow = tbShopUserFlowMapper.tradeIndexNewFlow(param.getShopId(), DateUtil.getStrTime(param.getStartTime()), DateUtil.getStrTime(param.getEndTime()));
//台桌数
int tables = tbShopTableRepository.countAllByShopId(param.getShopId());
//收款金额
BigDecimal incomeAmount = new BigDecimal(orderMap.get("saleAmount").toString()).subtract(new BigDecimal(orderMap.get("saveAmount").toString()));//订单金额 - 优惠金额
sale.put("totalSaleAmount", incomeAmount.add(refundAmount));//总金额 销售收款金额+销售退款金额
sale.put("incomeAmount", incomeAmount);//销售 收款金额
sale.put("refundAmount", refundAmount);//销售 退款金额
sale.put("totalVipAmount", new BigDecimal(flowMap.get("inAmount").toString()).add(new BigDecimal(flowMap.get("outAmount").toString())));//会员总金额
sale.put("inAmount", flowMap.get("inAmount")); //会员 充值金额
sale.put("outAmount", flowMap.get("outAmount"));//会员 退款金额
sale.put("incomeAmountAll",incomeAmount.add(new BigDecimal(flowMap.get("inAmount").toString())));//总实收 销售实收+会员实收
result.put("sale",sale);
vip.put("useAmount", flowMap.get("useAmount"));//会员消费金额
vip.put("newFlow",newFlow);//新增会员数
vip.put("useNum",flowMap.get("useNum"));//会员消费笔数
result.put("vip",vip);
BigDecimal saleAmount = new BigDecimal(orderMap.get("saleAmount").toString()).add(refundAmount);
//客单价
if(saleAmount.compareTo(BigDecimal.ZERO) == 0){
count.put("unitPrice",BigDecimal.ZERO);
}else {
count.put("unitPrice",saleAmount.divide(new BigDecimal(orderMap.get("saleNum").toString()),2,RoundingMode.DOWN));
}
//填充日期
Map<String, CountDateVO> dataMap = new HashMap<>();
for (CountDateVO entry : countDateList) {
String tradeDay = entry.getTradeDay();
BigDecimal countOrder = entry.getCount();
dataMap.put(tradeDay, new CountDateVO(tradeDay, countOrder));
BigDecimal saleNum = new BigDecimal(orderMap.get("saleNum").toString());
if(saleNum.compareTo(BigDecimal.ZERO) == 0 || saleNum.compareTo(new BigDecimal(tables)) < 0){
count.put("turnoverRate","0%");//翻台率
}else {
count.put("turnoverRate",saleNum.divide(new BigDecimal(tables),0,RoundingMode.DOWN).subtract(BigDecimal.ONE).multiply(new BigDecimal("100"))+"%");//翻台率
}
// 获取今天的日期
LocalDate today = LocalDate.now();
// 定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 转换为字符串
List<CountDateVO> countDateLists = new ArrayList<>();
for (int i = 0; i < 30; i++) {
LocalDate tradeDayLocalDate = today.minusDays(i);
String tradeDayString = tradeDayLocalDate.format(formatter);
CountDateVO countDateVO;
// 检查数据Map中是否存在该日期的数据
if (dataMap.containsKey(tradeDayString)) {
countDateVO = dataMap.get(tradeDayString);
} else {
// 如果不存在则创建新的SumDateVO对象amount设为0
countDateVO = new CountDateVO(tradeDayString, BigDecimal.ZERO);
}
// 将SumDateVO对象添加到列表中
countDateLists.add(countDateVO);
}
countDateLists.sort((a, b) -> a.getTradeDay().compareTo(b.getTradeDay()));
summaryVO.setCountDateList(countDateLists);
//访问量
Tuple tuple = tbTokenRepository.countByAccountId(shopId);
summaryVO.setTotalVisits(tuple == null ? 0L : tuple.get(0, Long.class));
//访问量柱状图
List<Object[]> objectsVisits = tbTokenRepository.countByMonth(shopId, DateUtil.getDate30DaysAgo(), DateUtil.getDayEnd());
List<CountVisitsVO> visitsList = new ArrayList<>();
for (Object[] o : objectsVisits) {
CountVisitsVO countDateVO = new CountVisitsVO();
countDateVO.setCount((BigInteger) o[0]);
countDateVO.setTradeDay((String) o[1]);
visitsList.add(countDateVO);
}
//填充日期
Map<String, CountVisitsVO> dataVisitsMap = new HashMap<>();
for (CountVisitsVO entry : visitsList) {
String tradeDay = entry.getTradeDay();
BigInteger countOrder = entry.getCount();
dataVisitsMap.put(tradeDay, new CountVisitsVO(tradeDay, countOrder));
}
// 转换为字符串
List<CountVisitsVO> countVisitsLists = new ArrayList<>();
for (int i = 0; i < 30; i++) {
LocalDate tradeDayLocalDate = today.minusDays(i);
String tradeDayString = tradeDayLocalDate.format(formatter);
CountVisitsVO countDateVO;
// 检查数据Map中是否存在该日期的数据
if (dataVisitsMap.containsKey(tradeDayString)) {
countDateVO = dataVisitsMap.get(tradeDayString);
} else {
// 如果不存在则创建新的SumDateVO对象amount设为0
countDateVO = new CountVisitsVO(tradeDayString, BigInteger.ZERO);
}
// 将SumDateVO对象添加到列表中
countVisitsLists.add(countDateVO);
}
countVisitsLists.sort((a, b) -> a.getTradeDay().compareTo(b.getTradeDay()));
summaryVO.setVisitsCountList(countVisitsLists);
return summaryVO;
count.put("saveAmount",orderMap.get("saveAmount"));//优惠金额
count.put("saveNum",orderMap.get("saveNum"));//优惠单数
result.put("count",count);
return result;
}
// @Override
// public SummaryVO selectSummary(Integer shopId) {
// SummaryVO summaryVO = new SummaryVO();
// //支付笔数,
// Tuple result = tbOrderInfoRepository.countByShopId(shopId.toString());
// summaryVO.setPaymentsNumber(result.get(0, Long.class) == null ? 0L : result.get(0, Long.class));
// summaryVO.setTotalSales(result.get(1, BigDecimal.class) == null ? new BigDecimal("0") : result.get(1, BigDecimal.class));
// if (summaryVO.getPaymentsNumber() == 0) {
// summaryVO.setAverageSales(new BigDecimal("0"));
// } else {
// summaryVO.setAverageSales(summaryVO.getTotalSales().divide(new BigDecimal(summaryVO.getPaymentsNumber()), 2, RoundingMode.DOWN));
// }
// //用户数
// Tuple count = tbShopUserRepository.searchByCount(shopId.toString());
// summaryVO.setTotalUser(count == null ? 0L : count.get(0, Long.class));
// //支付笔数柱形图
// List<Object[]> objects = tbOrderInfoRepository.sumByDateOrderNum(shopId.toString(), DateUtil.getDate30DaysAgo(), DateUtil.getDayEnd());
// List<CountDateVO> countDateList = new ArrayList<>();
// for (Object[] o : objects) {
// CountDateVO countDateVO = new CountDateVO();
// BigInteger integers = (BigInteger) o[0];
// countDateVO.setCount(new BigDecimal(integers.toString()));
// countDateVO.setTradeDay((String) o[1]);
// countDateList.add(countDateVO);
// }
// //填充日期
// Map<String, CountDateVO> dataMap = new HashMap<>();
// for (CountDateVO entry : countDateList) {
// String tradeDay = entry.getTradeDay();
// BigDecimal countOrder = entry.getCount();
// dataMap.put(tradeDay, new CountDateVO(tradeDay, countOrder));
// }
// // 获取今天的日期
// LocalDate today = LocalDate.now();
// // 定义日期格式
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// // 转换为字符串
// List<CountDateVO> countDateLists = new ArrayList<>();
// for (int i = 0; i < 30; i++) {
// LocalDate tradeDayLocalDate = today.minusDays(i);
// String tradeDayString = tradeDayLocalDate.format(formatter);
// CountDateVO countDateVO;
// // 检查数据Map中是否存在该日期的数据
// if (dataMap.containsKey(tradeDayString)) {
// countDateVO = dataMap.get(tradeDayString);
// } else {
// // 如果不存在则创建新的SumDateVO对象amount设为0
// countDateVO = new CountDateVO(tradeDayString, BigDecimal.ZERO);
// }
// // 将SumDateVO对象添加到列表中
// countDateLists.add(countDateVO);
// }
// countDateLists.sort((a, b) -> a.getTradeDay().compareTo(b.getTradeDay()));
// summaryVO.setCountDateList(countDateLists);
// //访问量
// Tuple tuple = tbTokenRepository.countByAccountId(shopId);
// summaryVO.setTotalVisits(tuple == null ? 0L : tuple.get(0, Long.class));
// //访问量柱状图
// List<Object[]> objectsVisits = tbTokenRepository.countByMonth(shopId, DateUtil.getDate30DaysAgo(), DateUtil.getDayEnd());
// List<CountVisitsVO> visitsList = new ArrayList<>();
// for (Object[] o : objectsVisits) {
// CountVisitsVO countDateVO = new CountVisitsVO();
// countDateVO.setCount((BigInteger) o[0]);
// countDateVO.setTradeDay((String) o[1]);
// visitsList.add(countDateVO);
// }
// //填充日期
// Map<String, CountVisitsVO> dataVisitsMap = new HashMap<>();
// for (CountVisitsVO entry : visitsList) {
// String tradeDay = entry.getTradeDay();
// BigInteger countOrder = entry.getCount();
// dataVisitsMap.put(tradeDay, new CountVisitsVO(tradeDay, countOrder));
// }
// // 转换为字符串
// List<CountVisitsVO> countVisitsLists = new ArrayList<>();
// for (int i = 0; i < 30; i++) {
// LocalDate tradeDayLocalDate = today.minusDays(i);
// String tradeDayString = tradeDayLocalDate.format(formatter);
// CountVisitsVO countDateVO;
// // 检查数据Map中是否存在该日期的数据
// if (dataVisitsMap.containsKey(tradeDayString)) {
// countDateVO = dataVisitsMap.get(tradeDayString);
// } else {
// // 如果不存在则创建新的SumDateVO对象amount设为0
// countDateVO = new CountVisitsVO(tradeDayString, BigInteger.ZERO);
// }
// // 将SumDateVO对象添加到列表中
// countVisitsLists.add(countDateVO);
// }
// countVisitsLists.sort((a, b) -> a.getTradeDay().compareTo(b.getTradeDay()));
// summaryVO.setVisitsCountList(countVisitsLists);
// return summaryVO;
// }
@Override
public Map<String, Object> selectSummaryDate(Integer shopId, Integer day) {
Date startTime = new Date();

View File

@@ -106,29 +106,20 @@ public class TbPayServiceImpl implements TbPayService {
}
@Override
public TbOrderInfo scanPay(PayDTO scanPayDTO) {
if (StrUtil.isBlank(scanPayDTO.getCode())) {
public TbOrderInfo scanPay(Integer shopId, String code, Integer merchantId, Integer memberId, BigDecimal payMount, TbOrderInfo orderInfo) {
if (StrUtil.isBlank(code)) {
throw new BadRequestException("无效码");
}
TbOrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaUpdateWrapper<TbOrderInfo>()
.in(TbOrderInfo::getStatus, "unpaid", "paying")
.eq(TbOrderInfo::getId, scanPayDTO.getOrderId())
.eq(TbOrderInfo::getShopId, scanPayDTO.getShopId()));
if (orderInfo == null) {
throw new BadRequestException("订单不存在或已支付");
}
if (ObjectUtil.isNull(orderInfo.getMerchantId()) || ObjectUtil.isEmpty(orderInfo.getMerchantId())) {
if (merchantId == null) {
throw new BadRequestException("订单商户id为空");
}
List<TbCashierCart> cashierCarts = cashierCartMapper.selectList(new LambdaUpdateWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, scanPayDTO.getShopId())
.eq(TbCashierCart::getOrderId, scanPayDTO.getOrderId()));
.eq(TbCashierCart::getShopId, shopId)
.eq(TbCashierCart::getOrderId, orderInfo.getId()));
if (cashierCarts.isEmpty()) {
throw new BadRequestException("购物车为空");
}
@@ -138,10 +129,8 @@ public class TbPayServiceImpl implements TbPayService {
body.append(cashierCart.getName());
}
BigDecimal payMount = orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(scanPayDTO.getDiscount())).setScale(2, RoundingMode.HALF_UP);
TbMerchantThirdApply thirdApply = merchantThirdApplyRepository.getById(Integer.valueOf(orderInfo.getMerchantId()));
TbMerchantThirdApply thirdApply = merchantThirdApplyRepository.getById(merchantId);
if (ObjectUtil.isEmpty(thirdApply) || ObjectUtil.isNull(thirdApply)) {
throw new BadRequestException("三方支付信息不存在");
}
@@ -149,7 +138,7 @@ public class TbPayServiceImpl implements TbPayService {
String payType;
String payName;
String qpay;
String payTypeCode = scanPayDTO.getCode().substring(0, 2);// 判断收款码
String payTypeCode = code.substring(0, 2);// 判断收款码
if(Integer.parseInt(payTypeCode) >=25 && Integer.parseInt(payTypeCode) <= 30){
payType = "aliPay";
@@ -168,32 +157,32 @@ public class TbPayServiceImpl implements TbPayService {
}
long count = shopPayTypeMapper.selectCount(new LambdaUpdateWrapper<TbShopPayType>()
.eq(TbShopPayType::getShopId, scanPayDTO.getShopId())
.eq(TbShopPayType::getShopId, shopId)
.eq(TbShopPayType::getIsDisplay, 1)
.eq(TbShopPayType::getPayType, qpay));
if (count < 1) {
throw new BadRequestException("未到找支付方式");
}
TbOrderPayment payment = orderPaymentService.getById(scanPayDTO.getOrderId());
TbOrderPayment payment = orderPaymentService.getById(orderInfo.getId());
if (ObjectUtil.isEmpty(payment) || payment == null) {
payment = new TbOrderPayment();
payment.setPayTypeId("ysk");
payment.setAmount(payMount.doubleValue());
payment.setPaidAmount(orderInfo.getPayAmount().doubleValue());
payment.setPaidAmount(payMount.doubleValue());
payment.setHasRefundAmount((double) 0);
payment.setPayName(payName);
payment.setPayType(payType);
payment.setReceived(payment.getAmount());
payment.setChangeFee((double) 0);
payment.setMemberId(orderInfo.getMemberId());
payment.setShopId(orderInfo.getShopId());
payment.setOrderId(orderInfo.getId().toString());
payment.setMemberId(String.valueOf(memberId));
payment.setShopId(String.valueOf(shopId));
payment.setOrderId(String.valueOf(orderInfo.getId()));
payment.setCreatedAt(System.currentTimeMillis());
payment.setAuthCode(scanPayDTO.getCode());
payment.setAuthCode(code);
orderPaymentService.save(payment);
} else {
payment.setAuthCode(scanPayDTO.getCode());
payment.setAuthCode(code);
payment.setUpdatedAt(System.currentTimeMillis());
orderPaymentService.updateById(payment);
}
@@ -202,15 +191,13 @@ public class TbPayServiceImpl implements TbPayService {
orderInfo.setPayAmount(payMount);
orderInfo.setPayType(qpay);
orderInfo.setUpdatedAt(System.currentTimeMillis());
orderInfoMapper.update(orderInfo, new LambdaUpdateWrapper<TbOrderInfo>()
.eq(TbOrderInfo::getId, scanPayDTO.getOrderId()));
if ("ysk".equals(thirdPayType)) {
ScanPayReq scanPayReq = new ScanPayReq();
scanPayReq.setAppId(thirdApply.getAppId());
scanPayReq.setTimestamp(System.currentTimeMillis());
scanPayReq.setAuthCode(scanPayDTO.getCode());
scanPayReq.setAuthCode(code);
scanPayReq.setNotifyUrl(backUrl);
scanPayReq.setConsumeFee(BigDecimal.valueOf(payment.getAmount()).setScale(2, RoundingMode.DOWN).toPlainString());
@@ -231,20 +218,20 @@ public class TbPayServiceImpl implements TbPayService {
orderInfo.setStatus("closed");
orderInfo.setPayOrderNo(object.getJSONObject("data").get("orderNumber").toString());
orderInfoMapper.update(orderInfo, new LambdaQueryWrapper<TbOrderInfo>()
.eq(TbOrderInfo::getId, scanPayDTO.getOrderId()));
.eq(TbOrderInfo::getId, orderInfo.getId()));
//更新购物车状态
TbCashierCart cashierCart = new TbCashierCart();
cashierCart.setStatus("final");
int cartCount = cashierCartMapper.update(cashierCart, new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getOrderId, scanPayDTO.getOrderId()));
.eq(TbCashierCart::getOrderId, orderInfo.getId()));
log.info("更新购物车:{}", cartCount);
//更新子单状态
TbOrderDetail orderDetail = new TbOrderDetail();
orderDetail.setStatus("closed");
orderDetailMapper.update(orderDetail, new LambdaQueryWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getOrderId, scanPayDTO.getOrderId()));
.eq(TbOrderDetail::getOrderId, orderInfo.getId()));
return orderInfo;
@@ -282,7 +269,7 @@ public class TbPayServiceImpl implements TbPayService {
reqbody, reqbody,
BigDecimal.valueOf(payment.getAmount()).setScale(2, RoundingMode.DOWN).multiply(new BigDecimal(100)).longValue(),
payType.equals("wechatPay") ? thirdApply.getSmallAppid() : null,
scanPayDTO.getCode(), DateUtils.getSsdfTimes(), thirdApply.getStoreId(), callBack, thirdApply.getAppToken());
code, DateUtils.getSsdfTimes(), thirdApply.getStoreId(), callBack, thirdApply.getAppToken());
log.info("响应信息, {}", publicResp);
if (ObjectUtil.isNotNull(publicResp) && ObjectUtil.isNotEmpty(publicResp)) {
if ("000000".equals(publicResp.getCode())) {
@@ -331,41 +318,25 @@ public class TbPayServiceImpl implements TbPayService {
}
@Override
public TbOrderInfo vipPay(@NotNull Integer shopId, @NotNull Integer orderId, Double discount, Integer vipUserId) {
TbOrderInfo orderInfo = orderInfoMapper.selectById(orderId);
if (ObjectUtil.isEmpty(orderInfo)) {
throw new BadRequestException("订单不存在");
}
if (!"unpaid".equals(orderInfo.getStatus()) && !"pending".equals(orderInfo.getStatus())) {
throw new BadRequestException("订单非未支付状态");
}
if (vipUserId != null) {
orderInfo.setUserId(String.valueOf(vipUserId));
}
public void vipPay(BigDecimal payMount, Integer vipUserId) {
// 扣减会员余额
TbShopUser shopUser = shopUserMapper.selectOne(new LambdaUpdateWrapper<TbShopUser>()
.eq(TbShopUser::getStatus, 1)
.eq(TbShopUser::getId, orderInfo.getUserId()));
.eq(TbShopUser::getId, vipUserId));
if (shopUser == null) {
throw new BadRequestException("用户不存在或已被禁用");
}
BigDecimal finalAmount = orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(discount)).setScale(2, RoundingMode.HALF_UP);
long flag = shopUserMapper.decrBalance(Integer.valueOf(orderInfo.getUserId()), finalAmount);
long flag = shopUserMapper.decrBalance(vipUserId, payMount);
if (flag < 1) {
throw new BadRequestException("余额不足或扣除余额失败");
}
TbShopUserFlow userFlow = new TbShopUserFlow();
userFlow.setAmount(finalAmount);
userFlow.setBalance(shopUser.getAmount().subtract(finalAmount));
userFlow.setAmount(payMount);
userFlow.setBalance(shopUser.getAmount().subtract(payMount));
userFlow.setShopUserId(shopUser.getId());
userFlow.setBizCode("vipCardCash");
userFlow.setBizName("余额支付");
@@ -373,22 +344,6 @@ public class TbPayServiceImpl implements TbPayService {
userFlow.setType("-");
shopUserFlowMapper.insert(userFlow);
orderInfo.setPayAmount(finalAmount);
orderInfo.setPayType("cash");
orderInfo.setStatus("closed");
orderInfo.setPayOrderNo("cash".concat(SnowFlakeUtil.generateOrderNo()));
orderInfo.setDiscountRatio(BigDecimal.valueOf(discount));
orderInfo.setDiscountAmount(orderInfo.getAmount().subtract(finalAmount));
orderInfoMapper.updateById(orderInfo);
//更新购物车状态
int cartCount = cashierCartMapper.update(null, new LambdaUpdateWrapper<TbCashierCart>()
.eq(TbCashierCart::getOrderId, orderId)
.set(TbCashierCart::getStatus, "final"));
orderDetailMapper.update(null, new LambdaUpdateWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getOrderId, orderId)
.set(TbOrderDetail::getStatus, "closed"));
return orderInfo;
}
@@ -442,33 +397,11 @@ public class TbPayServiceImpl implements TbPayService {
return orderInfo;
}
public TbOrderInfo memberAccountPay(String memberId, String shopId, String accountCode, Integer orderId, Double discount) {
public TbOrderInfo memberAccountPay(String memberId, String shopId, String accountCode, TbOrderInfo orderInfo, BigDecimal payMount) {
if (StrUtil.isBlank(accountCode)) {
throw new BadRequestException("无效码");
}
TbOrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaUpdateWrapper<TbOrderInfo>()
.eq(TbOrderInfo::getId, orderId)
.eq(TbOrderInfo::getShopId, shopId));
if (orderInfo == null) {
throw new BadRequestException("订单不存在或已支付");
}
if (!"unpaid".equals(orderInfo.getStatus()) && !"pending".equals(orderInfo.getStatus())) {
throw new BadRequestException("此订单不处于未支付状态");
}
BigDecimal payMount = orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(discount)).setScale(2, RoundingMode.HALF_UP);
long count = tbShopPayTypeMapper.selectCount(new LambdaQueryWrapper<TbShopPayType>()
.eq(TbShopPayType::getShopId, shopId)
.eq(TbShopPayType::getIsDisplay, 1)
.eq(TbShopPayType::getPayType, "deposit"));
if (count < 1) {
throw new BadRequestException("未知支付方式");
}
TbShopUser user = null;
@@ -520,22 +453,7 @@ public class TbPayServiceImpl implements TbPayService {
orderInfo.setUserId(user.getUserId());
orderInfo.setMemberId(user.getId().toString());
orderInfo.setPayType("deposit");
orderInfo.setStatus("closed");
orderInfo.setPayOrderNo("deposit".concat(SnowFlakeUtil.generateOrderNo()));
orderInfoMapper.updateById(orderInfo);
//更新购物车状态
int cartCount = cashierCartMapper.update(null, new LambdaUpdateWrapper<TbCashierCart>()
.eq(TbCashierCart::getId, orderId)
.set(TbCashierCart::getStatus, "final"));
orderDetailMapper.update(null, new LambdaUpdateWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getOrderId, orderId)
.set(TbOrderDetail::getStatus, "closed"));
log.info("更新购物车:{}", cartCount);
return orderInfo;
}
}

View File

@@ -0,0 +1,80 @@
package cn.ysk.cashier.service.impl;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.HttpUtil;
import cn.ysk.cashier.domain.QiniuContent;
import cn.ysk.cashier.service.QiNiuService;
import cn.ysk.cashier.service.WxService;
import cn.ysk.cashier.utils.CacheKey;
import cn.ysk.cashier.utils.RedisUtils;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class WxServiceImpl implements WxService {
private final QiNiuService qiNiuService;
private final RedisUtils redisUtils;
private static final String APP_ID = "wxd88fffa983758a30";
private static final String APP_SECRET = "a34a61adc0602118b49400baa8812454";
private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
private static final String QR_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacode";
@Override
public String getFetchQRCode(Map<String, Object> params) {
InputStream qrCodeStream = fetchQRCode(params);
QiniuContent qiniuContent = qiNiuService.uploadByte(IoUtil.readBytes(qrCodeStream),qiNiuService.findCloud());
redisUtils.set(CacheKey.VIPCODE + params.get("shopId"),qiniuContent.getUrl());
return qiniuContent.getUrl();
}
@Override
public String getSmallQrcode(String shopId) {
InputStream shopQRCodeStream = smallQrcode(shopId);
QiniuContent qiniuContent = qiNiuService.uploadByte(IoUtil.readBytes(shopQRCodeStream),qiNiuService.findCloud());
return qiniuContent.getUrl();
}
public InputStream fetchQRCode(Map<String, Object> params) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("path", "pages/member/index?shopId="+params.get("shopId"));//路径
jsonObject.addProperty("is_hyaline", true);//是否需要透明底色,为 true 时,生成透明底色的小程序码
if (params.containsKey("env_version")) jsonObject.addProperty("env_version", "trial");//正式版为 release体验版为 trial开发版为 develop
String accessToken = getAccessToken();
String url = String.format("%s?access_token=%s", QR_CODE_URL, accessToken);
return HttpUtil.createPost(url)
.body(jsonObject.toString(), "application/json")
.execute()
.bodyStream();
}
public InputStream smallQrcode(String shopId) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("path", "pages/index/index?shopId="+shopId);//路径
jsonObject.addProperty("is_hyaline", true);//是否需要透明底色,为 true 时,生成透明底色的小程序码
String accessToken = getAccessToken();
String url = String.format("%s?access_token=%s", QR_CODE_URL, accessToken);
return HttpUtil.createPost(url)
.body(jsonObject.toString(), "application/json")
.execute()
.bodyStream();
}
private String getAccessToken() {
String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, APP_ID, APP_SECRET);
String response = HttpUtil.get(url);
JSONObject jsonResponse = JSONObject.parseObject(response);
if (!jsonResponse.containsKey("access_token")) {
throw new RuntimeException("Failed to retrieve access token: " + response);
}
return jsonResponse.getString("access_token");
}
}

View File

@@ -0,0 +1,399 @@
package cn.ysk.cashier.service.impl.app;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.ysk.cashier.cons.RedisConstant;
import cn.ysk.cashier.dto.calltable.*;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mybatis.entity.TbCallQueue;
import cn.ysk.cashier.mybatis.entity.TbCallTable;
import cn.ysk.cashier.mybatis.mapper.TbCallQueueMapper;
import cn.ysk.cashier.mybatis.mapper.TbShopUserMapper;
import cn.ysk.cashier.mybatis.service.TbCallQueueService;
import cn.ysk.cashier.mybatis.service.TbCallTableService;
import cn.ysk.cashier.pojo.shop.TbShopInfo;
import cn.ysk.cashier.pojo.shop.TbShopUser;
import cn.ysk.cashier.repository.shop.TbShopInfoRepository;
import cn.ysk.cashier.service.app.TbCallService;
import cn.ysk.cashier.utils.Utils;
import cn.ysk.cashier.utils.WxMiniUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class TbCallServiceImpl implements TbCallService {
private final TbCallTableService callTableService;
private final TbCallQueueService callQueueService;
private final TbShopUserMapper shopUserMapper;
private final TbShopInfoRepository shopInfoRepository;
private final StringRedisTemplate redisTemplate;
private final TbCallQueueMapper tbCallQueueMapper;
private final WxMiniUtils wxMiniUtils;
@Override
public Object add(CallTableDTO addCallTableDTO) {
Long count = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, addCallTableDTO.getShopId())
.and(q -> {
q.eq(TbCallTable::getName, addCallTableDTO.getName())
.or()
.eq(TbCallTable::getPrefix, addCallTableDTO.getPrefix());
}).count();
if (count > 0) {
throw new BadRequestException("名称或前缀已存在");
}
TbCallTable callTable = BeanUtil.copyProperties(addCallTableDTO, TbCallTable.class);
callTable.setCreateTime(DateUtil.date().toInstant());
return callTableService.save(callTable);
}
@Override
public Object update(UpdateCallTableDTO callTableDTO) {
TbCallTable callTable = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, callTableDTO.getShopId())
.eq(TbCallTable::getId, callTableDTO.getCallTableId()).one();
if (callTable == null) {
throw new BadRequestException("桌型不存在");
}
TbCallTable newInfo = BeanUtil.copyProperties(callTableDTO, TbCallTable.class);
newInfo.setId(callTable.getId());
newInfo.setUpdateTime(DateUtil.date().toInstant());
return callTableService.updateById(newInfo);
}
@Override
public Object delete(BaseCallTableDTO baseCallTableDTO) {
return callTableService.remove(new LambdaQueryWrapper<TbCallTable>()
.eq(TbCallTable::getId, baseCallTableDTO.getCallTableId())
.eq(TbCallTable::getShopId, baseCallTableDTO.getShopId()));
}
private String getCallNumber(Integer shopId, TbCallTable callTable) {
return Utils.runFunAndCheckKey(() -> {
String callNumKey = RedisConstant.getTableCallNumKey(shopId, callTable.getId());
String value = redisTemplate.opsForValue().get(callNumKey);
AtomicReference<String> newVal = new AtomicReference<>("");
// 初始化
if (StrUtil.isBlank(value)) {
Boolean setFlag = Utils.runFunAndRetry(() -> redisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
r -> newVal.set(redisTemplate.opsForValue().get(callNumKey)));
if (setFlag) {
return callTable.getPrefix() + callTable.getStart();
}else if (StrUtil.isNotBlank(newVal.get())){
value = String.valueOf((Integer.parseInt(newVal.get()) + 1));
redisTemplate.opsForValue().set(callNumKey, value);
return callTable.getPrefix() + value;
}else {
throw new BadRequestException("生成排队号码失败");
}
}else {
value = String.valueOf((Integer.parseInt(value) + 1));
redisTemplate.opsForValue().set(callNumKey, value);
return callTable.getPrefix() + value;
}
}, redisTemplate, RedisConstant.getLockKey("UPDATE_TABLE", shopId, callTable.getId()));
}
@Override
public Object takeNumber(TakeNumberDTO takeNumberDTO) {
TbShopInfo shopInfo = shopInfoRepository.findById(takeNumberDTO.getShopId()).orElse(null);
if (shopInfo == null) {
throw new BadRequestException("店铺信息不存在");
}
TbCallTable callTable = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, takeNumberDTO.getShopId())
.eq(TbCallTable::getId, takeNumberDTO.getCallTableId()).one();
if (callTable == null) {
throw new BadRequestException("桌型不存在");
}
// 查询当前
// 拿取系统内部用户信息
TbCallQueue callQueue;
if (takeNumberDTO.getUserId() != null) {
TbShopUser shopUser = shopUserMapper.selectOne(new LambdaQueryWrapper<TbShopUser>()
.eq(TbShopUser::getStatus, 1)
.eq(TbShopUser::getShopId, takeNumberDTO.getShopId())
.eq(TbShopUser::getId, takeNumberDTO.getUserId()));
if (shopUser == null) {
throw new BadRequestException("用户不存在");
}
callQueue = callQueueService.lambdaQuery()
.eq(TbCallQueue::getUserId, shopUser.getId())
.eq(TbCallQueue::getShopId, takeNumberDTO.getShopId())
.in(TbCallQueue::getState, 0, 1)
.eq(TbCallQueue::getCallTableId, takeNumberDTO.getCallTableId()).one();
if (callQueue != null) {
throw new BadRequestException("当前用户已取号");
}
callQueue = BeanUtil.copyProperties(takeNumberDTO, TbCallQueue.class);
callQueue.setPhone(StrUtil.isBlank(takeNumberDTO.getPhone()) ? shopUser.getTelephone() : takeNumberDTO.getPhone());
// callQueue.setOpenId(shopUser.getMiniOpenId());
}else {
// if (StrUtil.isBlank(takeNumberDTO.getPhone()) || StrUtil.isBlank(takeNumberDTO.getOpenId())) {
// throw new BadRequestException("手机号或openId不能为空");
// }
callQueue = callQueueService.lambdaQuery()
.eq(TbCallQueue::getPhone, takeNumberDTO.getPhone())
.eq(TbCallQueue::getShopId, takeNumberDTO.getShopId())
.eq(TbCallQueue::getCallTableId, takeNumberDTO.getCallTableId()).one();
if (callQueue != null) {
throw new BadRequestException("当前用户已取号");
}
callQueue = BeanUtil.copyProperties(takeNumberDTO, TbCallQueue.class);
callQueue.setPhone(takeNumberDTO.getPhone());
// callQueue.setOpenId(takeNumberDTO.getOpenId());
callQueue.setSubState(1);
}
callQueue.setCallNum(getCallNumber(takeNumberDTO.getShopId(), callTable));
callQueue.setCreateTime(DateUtil.date().toInstant());
callQueue.setShopId(shopInfo.getId());
callQueue.setShopName(shopInfo.getShopName());
return callQueueService.save(callQueue);
}
@Override
public Object call(CallQueueDTO callQueueDTO) {
TbCallQueue callQueue = callQueueService.lambdaQuery()
.notIn(TbCallQueue::getState, -1, 2)
.eq(TbCallQueue::getShopId, callQueueDTO.getShopId())
.one();
if (callQueue == null) {
throw new BadRequestException("叫号用户不存在");
}
if (callQueue.getSubState().equals(0)) {
throw new BadRequestException("当前用户未订阅微信提醒");
}
callQueue.setState((byte) 1);
callQueue.setCallCount(callQueue.getCallCount() + 1);
callQueue.setCallTime(DateUtil.date().toInstant());
// 发送模板消息通知用户
TbShopInfo shopInfo = shopInfoRepository.findById(callQueue.getShopId()).orElse(null);
if (shopInfo == null) {
throw new BadRequestException("店铺信息不存在");
}
List<TbCallQueue> current = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, callQueue.getCallTableId())
.and(r -> {
r.eq(TbCallQueue::getState, 1)
.or()
.eq(TbCallQueue::getState, 0);
})
.orderByAsc(TbCallQueue::getCreateTime)
.page(new Page<>(1, 1)).getRecords();
if (StrUtil.isBlank(callQueue.getOpenId())) {
throw new BadRequestException("此用户未订阅微信小程序消息");
}
wxMiniUtils.sendNearCallMsg(shopInfo.getShopName(), getStrByState(Integer.valueOf(callQueue.getState())),
callQueue.getCallNum(), current.isEmpty() ? "" : current.get(0).getCallNum(), "排号信息", callQueue.getOpenId());
return callQueueService.updateById(callQueue);
}
private String getStrByState(Integer state) {
String msg = "";
switch (state) {
case -1:
msg = "已取消";
break;
case 0:
msg = "排队中";
break;
case 1:
msg = "已到号";
break;
case 3:
msg = "已过号";
}
return msg;
}
@Override
public Object updateInfo(UpdateCallQueueDTO updateCallQueueDTO) {
TbCallQueue callQueue = callQueueService.lambdaQuery()
.eq(TbCallQueue::getShopId, updateCallQueueDTO.getShopId())
.eq(TbCallQueue::getId, updateCallQueueDTO.getCallQueueId()).one();
if (callQueue == null) {
throw new BadRequestException("叫号用户不存在");
}
switch (updateCallQueueDTO.getState()) {
case -1:
callQueue.setCancelTime(DateUtil.date().toInstant());
break;
case 0:
if (callQueue.getSubState().equals(0)) {
throw new BadRequestException("当前用户未订阅微信提醒");
}
callQueue.setState((byte) 1);
callQueue.setCallCount(callQueue.getCallCount() + 1);
callQueue.setCallTime(DateUtil.date().toInstant());
break;
case 2:
callQueue.setConfirmTime(DateUtil.date().toInstant());
break;
case 3:
callQueue.setPassTime(DateUtil.date().toInstant());
break;
default:
throw new BadRequestException("错误类型");
}
callQueue.setState(updateCallQueueDTO.getState());
return callQueueService.updateById(callQueue);
}
@Override
public Object get(Integer page, Integer size, Integer shopId, Integer callTableId, Integer state) {
LambdaQueryWrapper<TbCallTable> query = new LambdaQueryWrapper<TbCallTable>()
.eq(TbCallTable::getShopId, shopId)
.eq(TbCallTable::getState, 1);
if (callTableId != null) {
query.eq(TbCallTable::getId, callTableId);
}
if (state != null) {
query.eq(TbCallTable::getState, state);
}
Page<TbCallTable> pageInfo = callTableService.page(new Page<>(page, size), query);
ArrayList<Map<String, Object>> info = new ArrayList<>();
pageInfo.getRecords().forEach(item -> {
Long count = callQueueService.lambdaQuery()
.eq(TbCallQueue::getCallTableId, item.getId())
.in(TbCallQueue::getState, 0, 1)
.count();
Map<String, Object> map = BeanUtil.beanToMap(item, false, false);
map.put("totalCount", count);
info.add(map);
});
Map<String, Object> toMap = BeanUtil.beanToMap(pageInfo);
toMap.put("records", info);
return toMap;
}
@Override
public Object takeNumberCode(Integer shopId, Integer callTableId) {
// 创建二维码配置对象设置宽度和高度为400
QrConfig config = new QrConfig(400, 400);
// 使用字节数组输出流来存储二维码图片
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 生成二维码图片,输出到字节数组输出流
QrCodeUtil.generate("Your QR Code Content Here", config, "png", outputStream);
// 将图片转换为 Base64 字符串
String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
// 返回Base64格式的图片字符串
return "data:image/png;base64," + base64;
}
@Override
public Object getQueue(Integer shopId, Integer callTableId, Integer state, Integer page, Integer size) {
List<Integer> tableIds;
if (callTableId != null) {
tableIds = Collections.singletonList(callTableId);
}else {
List<TbCallTable> list = callTableService.lambdaQuery()
.eq(TbCallTable::getShopId, shopId)
.eq(TbCallTable::getState, 1).list();
if (list.isEmpty()) {
return new Page<>();
}
tableIds = list.stream()
.map(TbCallTable::getId)
.collect(Collectors.toList());
}
LambdaQueryChainWrapper<TbCallQueue> query = callQueueService.lambdaQuery()
.eq(TbCallQueue::getShopId, shopId)
.in(TbCallQueue::getCallTableId, tableIds);
if (state != null) {
query.eq(TbCallQueue::getState, state);
}
Page<TbCallQueue> pageInfo = query
.orderByAsc(TbCallQueue::getCreateTime)
.orderByDesc(TbCallQueue::getState)
.page(new Page<>(page, size));
List<TbCallQueue> list1 = pageInfo.getRecords();
// 创建返回的结果集
List<Map<String, Object>> resultList = new ArrayList<>();
// 遍历每一个叫号中的记录,计算前面状态为"0" (排队中) 的人数
for (TbCallQueue calling : list1) {
// 计算前面等待的人数 (状态为"0"且在叫号记录创建时间之前的)
long waitingCount = 0;
if (calling.getState() == 0) {
waitingCount = list1.stream()
.filter(item -> item.getState() == 0 || item.getState() == 1) // 过滤出状态为"排队中"的
.filter(item -> item.getCreateTime().compareTo(calling.getCreateTime()) < 0 ) // 时间在当前叫号之前
.count();
}
// 创建一个Map来保存叫号中的记录及其前面排队的人数
Map<String, Object> map = BeanUtil.beanToMap(calling, false, false);
map.put("waitingCount", waitingCount);
// 将该map加入结果集
resultList.add(map);
}
Map<String, Object> toMap = BeanUtil.beanToMap(pageInfo, false, false);
toMap.put("records", resultList);
// 返回结果列表
return toMap;
}
@Override
public Object getCallRecord(Integer shopId, Integer callTableId, Integer page, Integer size) {
return tbCallQueueMapper.selectCallRecord(shopId, callTableId, new Page<>(page, size));
}
}

View File

@@ -28,6 +28,7 @@ import cn.ysk.cashier.pojo.shop.TbPlussShopStaff;
import cn.ysk.cashier.pojo.shop.TbShopInfo;
import cn.ysk.cashier.repository.TbShopPayTypeRepository;
import cn.ysk.cashier.repository.shop.*;
import cn.ysk.cashier.service.WxService;
import cn.ysk.cashier.service.shop.TbShopInfoService;
import cn.ysk.cashier.system.domain.Dept;
import cn.ysk.cashier.system.domain.Job;
@@ -84,6 +85,7 @@ public class TbShopInfoServiceImpl implements TbShopInfoService {
private final RedisUtils redisUtils;
private final TbShopPayTypeRepository tbShopPayTypeRepository;
private final WxService wxService;
@Override
public Map<String,Object> queryAll(TbShopInfoQueryCriteria criteria){
@@ -102,6 +104,11 @@ public class TbShopInfoServiceImpl implements TbShopInfoService {
@Transactional
public TbShopInfoDto findById(Integer id) {
TbShopInfo tbShopInfo = tbShopInfoRepository.findById(id).orElseGet(TbShopInfo::new);
if(StringUtils.isBlank(tbShopInfo.getSmallQrcode())){
String smallQrcode = wxService.getSmallQrcode(id.toString());
tbShopInfo.setSmallQrcode(smallQrcode);
tbShopInfoRepository.save(tbShopInfo);
}
ValidationUtil.isNull(tbShopInfo.getId(),"TbShopInfo","id",id);
return tbShopInfoMapper.toDto(tbShopInfo);
}
@@ -239,7 +246,7 @@ public class TbShopInfoServiceImpl implements TbShopInfoService {
@Transactional(rollbackFor = Exception.class)
public void update(TbShopInfo resources) {
TbShopInfo tbShopInfo = tbShopInfoRepository.findById(resources.getId()).orElseGet(TbShopInfo::new);
if (!resources.getShopName().equals(tbShopInfo.getShopName())) {
if (StringUtils.isNotBlank(resources.getShopName()) && !resources.getShopName().equals(tbShopInfo.getShopName())) {
shopStaffRepository.updateNameById(resources.getShopName(),resources.getId().toString());
userRepository.updateNickName(resources.getAccount(),resources.getShopName());
}

View File

@@ -18,6 +18,7 @@ package cn.ysk.cashier.service.impl.shopimpl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.ysk.cashier.config.security.security.TokenProvider;
import cn.ysk.cashier.cons.RedisConstant;
@@ -28,12 +29,15 @@ import cn.ysk.cashier.enums.TableStateEnum;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mybatis.entity.TbShopOpenId;
import cn.ysk.cashier.mybatis.mapper.*;
import cn.ysk.cashier.mybatis.service.MpShopTableService;
import cn.ysk.cashier.pojo.TbShopPayType;
import cn.ysk.cashier.pojo.order.TbCashierCart;
import cn.ysk.cashier.pojo.order.TbOrderDetail;
import cn.ysk.cashier.pojo.order.TbOrderInfo;
import cn.ysk.cashier.pojo.product.TbProduct;
import cn.ysk.cashier.pojo.product.TbProductSku;
import cn.ysk.cashier.pojo.shop.TbMerchantAccount;
import cn.ysk.cashier.pojo.shop.TbShopArea;
import cn.ysk.cashier.pojo.shop.TbShopInfo;
import cn.ysk.cashier.pojo.shop.TbShopTable;
import cn.ysk.cashier.repository.TbShopPayTypeRepository;
@@ -44,7 +48,6 @@ 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;
@@ -66,11 +69,13 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.util.*;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
@@ -105,6 +110,9 @@ public class TbShopTableServiceImpl implements TbShopTableService {
private final WxMsgUtils wxMsgUtils;
private final TbShopPayTypeRepository payTypeRepository;
private final MpShopTableMapper mpShopTableMapper;
private final TbShopPayTypeMapper tbShopPayTypeMapper;
private final MpShopTableService mpShopTableService;
/**
* 桌码前缀
@@ -115,6 +123,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
private final TbCashierCartMapper tbCashierCartMapper;
private final TbOrderDetailMapper tbOrderDetailMapper;
private final StringRedisTemplate stringRedisTemplate;
private final MpShopAreaMapper mpShopAreaMapper;
@Override
public Map<String, Object> queryAll(TbShopTableQueryCriteria criteria, Pageable pageable) {
@@ -147,13 +156,8 @@ public class TbShopTableServiceImpl implements TbShopTableService {
} else if (tbCashierCartMapper.selectCount(new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, date.getShopId())
.eq(TbCashierCart::getTableId, date.getQrcode())
.eq(TbCashierCart::getTradeDay, cn.ysk.cashier.utils.DateUtils.getDay())
.eq(TbCashierCart::getStatus, "create")) < 1 || (orderId != null &&
tbOrderDetailMapper.selectCount(new LambdaQueryWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getShopId, date.getShopId())
.eq(TbOrderDetail::getStatus, "unpaid")
.ge(TbOrderDetail::getCreateTime, DateUtil.beginOfDay(new Date()))
.eq(TbOrderDetail::getOrderId, orderId)) < 1)
.eq(TbCashierCart::getTradeDay, cn.ysk.cashier.utils.DateUtils.getDay())
.eq(TbCashierCart::getStatus, "create")) < 1
) {
date.setStatus("idle");
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
@@ -161,6 +165,11 @@ public class TbShopTableServiceImpl implements TbShopTableService {
.set(TbShopTable::getStatus, TableStateEnum.IDLE.getState()));
}
Map<String, Object> itemMap = BeanUtil.beanToMap(date, false, false);
if ((date.getStatus().equals("using") || date.getStatus().equals("cleaning")) && date.getUseTime() != null) {
itemMap.put("durationTime", DateUtil.current() - date.getUseTime().getTime());
}else {
itemMap.put("durationTime", 0);
}
if (!"".equals(date.getQrcode())) {
itemMap.put("qrcode", QRCODE + date.getQrcode().trim());
itemMap.put("tableId", date.getQrcode());
@@ -224,6 +233,9 @@ public class TbShopTableServiceImpl implements TbShopTableService {
TbShopTable tbShopTable = tbShopTableRepository.findById(resources.getId()).orElseGet(TbShopTable::new);
ValidationUtil.isNull(tbShopTable.getId(), "TbShopTable", "id", resources.getId());
tbShopTable.copy(resources);
if ("idle".equals(resources.getStatus())) {
tbShopTable.setUseNum(0);
}
tbShopTableRepository.save(tbShopTable);
}
@@ -265,6 +277,12 @@ public class TbShopTableServiceImpl implements TbShopTableService {
throw new BadRequestException("购物车商品不存在");
}
int currentPlaceNum = getCurrentPlaceNum(tbCashierCart.getTableId().toString(), tbCashierCart.getShopId());
if (tbCashierCart.getPlaceNum() != null && !tbCashierCart.getPlaceNum().equals(currentPlaceNum)) {
throw new BadRequestException("已下单商品仅支持退单操作");
}
if (updateCartDTO.getNum() == 0) {
cashierCartRepository.deleteById(updateCartDTO.getCartId());
return null;
@@ -322,10 +340,25 @@ public class TbShopTableServiceImpl implements TbShopTableService {
return shopTable;
}
private int getCurrentPlaceNum(String tableId, String shopId) {
String currentOrderKey = RedisConstant.getCurrentOrderKey(tableId,
shopId);
String orderId = redisTemplate.opsForValue().get(currentOrderKey);
if (StrUtil.isBlank(orderId)) {
return 1;
}
TbOrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<TbOrderInfo>()
.eq(TbOrderInfo::getUseType, "postPay")
.eq(TbOrderInfo::getId, orderId).select(TbOrderInfo::getPlaceNum));
return orderInfo == null ? 1 : orderInfo.getPlaceNum() + 1;
}
@Override
public TbCashierCart addCartForUser(AddCartDTO addCartDTO) {
checkTableIsOpen(addCartDTO.getTableId());
int currentPlaceNum = getCurrentPlaceNum(addCartDTO.getTableId(), addCartDTO.getShopId().toString());
TbProductSku productSku = productMapper.selectSkuByIdAndShopId(addCartDTO.getShopId(), addCartDTO.getSkuId());
TbProduct product = productMapper.selectByIdAndShopId(addCartDTO.getShopId(), addCartDTO.getProductId());
@@ -344,6 +377,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
.eq(TbCashierCart::getSkuId, addCartDTO.getSkuId())
.eq(TbCashierCart::getProductId, addCartDTO.getProductId())
.eq(TbCashierCart::getTableId, addCartDTO.getTableId())
.isNull(TbCashierCart::getPlaceNum)
.in(TbCashierCart::getStatus, "create", "refund")
// .and(q -> {
// q.eq(TbCashierCart::getTradeDay, DateUtils.getDay())
@@ -404,9 +438,11 @@ public class TbShopTableServiceImpl implements TbShopTableService {
tbCashierCart.setTotalNumber(addCartDTO.getNum());
tbCashierCart.setNumber(addCartDTO.getNum());
tbCashierCart.setCategoryId(product.getCategoryId());
tbCashierCart.setNote(addCartDTO.getNote());
cashierCartRepository.save(tbCashierCart);
} else {
tbCashierCart.setNote(addCartDTO.getNote());
tbCashierCart.setTotalAmount(new BigDecimal(addCartDTO.getNum()).multiply(productSku.getSalePrice()));
if (!addCartDTO.isPack()) {
@@ -425,11 +461,6 @@ public class TbShopTableServiceImpl implements TbShopTableService {
tbCashierCart.setIsGift(String.valueOf(addCartDTO.isGift()));
tbCashierCart.setTotalNumber(addCartDTO.getNum());
tbCashierCart.setNumber(addCartDTO.getNum());
// 数量0删除
if (tbCashierCart.getNumber() == 0) {
cashierCartRepository.deleteById(tbCashierCart.getId());
return null;
}
tbCashierCart.setUpdatedAt(DateUtil.current());
cashierCartRepository.save(tbCashierCart);
}
@@ -466,6 +497,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
@Override
public void removeCart(RemoveCartDTO removeCartDTO) {
int currentPlaceNum = getCurrentPlaceNum(removeCartDTO.getTableId().toString(), removeCartDTO.getShopId().toString());
// 会员点单
TbCashierCart cashierCart = cashierCartMapper.selectOne(new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, removeCartDTO.getShopId())
@@ -474,16 +506,20 @@ public class TbShopTableServiceImpl implements TbShopTableService {
throw new BadRequestException("购物车商品不存在");
}
if (cashierCart.getPlaceNum() != null && !cashierCart.getPlaceNum().equals(currentPlaceNum)) {
throw new BadRequestException("已下单商品仅支持退单操作");
}
if (cashierCart.getOrderId() != null) {
orderDetailMapper.delete(new LambdaQueryWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getShopId, cashierCart.getShopId())
.eq(TbOrderDetail::getProductId, cashierCart.getProductId())
.eq(TbOrderDetail::getProductSkuId, cashierCart.getSkuId())
.isNull(TbOrderDetail::getPlaceNum)
.eq(TbOrderDetail::getOrderId, cashierCart.getOrderId()));
}
cashierCartMapper.delete(new LambdaQueryWrapper<TbCashierCart>().eq(TbCashierCart::getShopId, removeCartDTO.getShopId())
.eq(TbCashierCart::getId, removeCartDTO.getCartId()));
cashierCartMapper.deleteById(cashierCart.getId());
// 清空购物车 出票
long carCount = countCar(cashierCart.getTableId(), cashierCart.getShopId(), cashierCart.getMasterId());
@@ -497,13 +533,56 @@ public class TbShopTableServiceImpl implements TbShopTableService {
}
@Override
public void returnCart(RemoveCartDTO removeCartDTO) {
rabbitMsgUtils.printDishesReturnTicket(4450, 9313);
int currentPlaceNum = getCurrentPlaceNum(removeCartDTO.getTableId().toString(), removeCartDTO.getShopId().toString());
// 会员点单
TbCashierCart cashierCart = cashierCartMapper.selectOne(new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, removeCartDTO.getShopId())
.in(TbCashierCart::getStatus, "create", "refund")
.eq(TbCashierCart::getId, removeCartDTO.getCartId()));
if (cashierCart == null) {
throw new BadRequestException("购物车商品不存在或已退单");
}
TbOrderDetail tbOrderDetail = orderDetailMapper.selectOne(new LambdaQueryWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getShopId, removeCartDTO.getShopId())
.eq(TbOrderDetail::getCartId, cashierCart.getId())
.eq(TbOrderDetail::getProductId, cashierCart.getProductId())
.eq(TbOrderDetail::getProductSkuId, cashierCart.getSkuId())
.eq(TbOrderDetail::getOrderId, cashierCart.getOrderId()));
if (tbOrderDetail == null) {
throw new BadRequestException("购物车商品不存在或已退单");
}
if (cashierCart.getOrderId() == null) {
throw new BadRequestException("此商品还未下单,无需退单");
}
cashierCartMapper.update(null, new LambdaUpdateWrapper<TbCashierCart>()
.eq(TbCashierCart::getId, cashierCart.getId())
.set(TbCashierCart::getStatus, "return"));
orderDetailMapper.update(null, new LambdaUpdateWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getId, tbOrderDetail.getId())
.set(TbOrderDetail::getUpdateTime, DateUtil.date())
.set(TbOrderDetail::getStatus, "return"));
rabbitMsgUtils.printDishesReturnTicket(tbOrderDetail.getOrderId(), tbOrderDetail.getOrderId());
}
@Override
public void clearCart(ClearCartDTO clearCartDTO) {
String orderId = redisTemplate.opsForValue().get(RedisConstant.getCurrentOrderKey(clearCartDTO.getTableId().toString(), clearCartDTO.getShopId()));
int currentPlaceNum = getCurrentPlaceNum(clearCartDTO.getTableId().toString(), clearCartDTO.getShopId());
cashierCartMapper.delete(new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, clearCartDTO.getShopId())
.eq(TbCashierCart::getTableId, clearCartDTO.getTableId())
.eq(TbCashierCart::getPlaceNum, currentPlaceNum)
.and(q -> {
q.eq(TbCashierCart::getMasterId, clearCartDTO.getMasterId())
.or()
@@ -518,10 +597,13 @@ public class TbShopTableServiceImpl implements TbShopTableService {
})
);
// tbShopTableRepository.deleteByTableIdAndShopId(clearCartDTO.getTableId(), clearCartDTO.getShopId());
if (StrUtil.isNotBlank(orderId)) {
orderDetailMapper.delete(new LambdaQueryWrapper<TbOrderDetail>().eq(TbOrderDetail::getShopId, clearCartDTO.getShopId())
orderDetailMapper.delete(new LambdaQueryWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getShopId, clearCartDTO.getShopId())
.eq(TbOrderDetail::getPlaceNum, currentPlaceNum)
.eq(TbOrderDetail::getOrderId, orderId));
rabbitMsgUtils.printTicket(orderId);
}
@@ -537,11 +619,11 @@ public class TbShopTableServiceImpl implements TbShopTableService {
}
@Override
public com.baomidou.mybatisplus.extension.plugins.pagination.Page<TbCashierCart> getCart(Long tableId, Integer page,
Integer size, Integer shopId, Integer vipUserId, String masterId) {
public Map<String, Object> getCart(Long tableId, Integer page,
Integer size, Integer shopId, Integer vipUserId, String masterId) {
LambdaQueryWrapper<TbCashierCart> queryWrapper = new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getTableId, tableId)
.in(TbCashierCart::getStatus, "create", "refund")
.in(TbCashierCart::getStatus, "create", "refund", "return")
.eq(TbCashierCart::getShopId, shopId)
.and(query2 -> {
query2.or(query3 -> {
@@ -570,6 +652,8 @@ public class TbShopTableServiceImpl implements TbShopTableService {
skuIds.add(Integer.valueOf(item.getSkuId()));
});
AtomicReference<TbCashierCart> mealCashierCart = new AtomicReference<>();
if (!skuIds.isEmpty()) {
List<TbProductSku> skuList = productSkuRepository.findAllById(skuIds);
HashMap<String, TbProductSku> skuMap = new HashMap<>();
@@ -577,17 +661,37 @@ public class TbShopTableServiceImpl implements TbShopTableService {
ArrayList<Map<String, Object>> infos = new ArrayList<>();
records.forEach(item -> {
if (item.getProductId().equals("-999")) {
mealCashierCart.set(item);
return;
}
Map<String, Object> map = BeanUtil.beanToMap(item, false, false);
TbProductSku tbProductSku = skuMap.get(item.getSkuId());
map.put("specSnap", tbProductSku != null ? tbProductSku.getSpecSnap() : null);
map.put("placeNum", item.getPlaceNum() == null ? 0 : item.getPlaceNum());
infos.add(map);
});
com.baomidou.mybatisplus.extension.plugins.pagination.Page copyPage = BeanUtil.copyProperties(cartPage, com.baomidou.mybatisplus.extension.plugins.pagination.Page.class);
copyPage.setRecords(infos);
return copyPage;
// 根据placeNum进行分组
Map<Object, List<Map<String, Object>>> groupedByPlaceNum = infos.stream()
.collect(Collectors.groupingBy(info -> info.get("placeNum")));
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
groupedByPlaceNum.forEach((k, v) -> {
HashMap<String, Object> item = new HashMap<>();
item.put("placeNum", k);
item.put("info", v);
list.add(item);
});
copyPage.setRecords(list);
Map<String, Object> map = BeanUtil.beanToMap(copyPage, false, false);
map.put("seatFee", mealCashierCart);
return map;
}
return cartPage;
return BeanUtil.beanToMap(cartPage);
}
@Override
@@ -835,7 +939,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
private final StringRedisTemplate redisTemplate;
@Override
public Object getMasterId(Integer shopId, Long tableId, Integer vipUserId) {
public JSONObject getMasterId(Integer shopId, Long tableId, Integer vipUserId) {
String account = tokenProvider.getSubject();
if (account == null) {
throw new BadRequestException("token解析失败");
@@ -873,14 +977,34 @@ public class TbShopTableServiceImpl implements TbShopTableService {
@Override
public TbOrderInfo createOrder(CreateOrderDTO createOrderDTO, boolean addMaterId, boolean isPrint) {
public TbOrderInfo createOrder(CreateOrderDTO createOrderDTO, boolean addMaterId, boolean isPrint) {
return Utils.runFunAndCheckKey(() -> {
TbShopTable tbShopTable = mpShopTableMapper.selectOne(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, createOrderDTO.getTableId())
.in(TbShopTable::getStatus, "idle", "using"));
if (tbShopTable == null) {
throw new BadRequestException("台桌未开台或不存在");
}
// 传递orderId直接取否则取当前缓存id
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;
// 查询订单
TbOrderInfo orderInfo = null;
if (orderId != null) {
orderInfo = orderInfoMapper.selectById(orderId);
if (orderInfo == null || !"unpaid".equals(orderInfo.getStatus())) {
redisTemplate.delete(currentOrderKey);
}
}
String day = DateUtils.getDay();
LambdaQueryWrapper<TbCashierCart> queryWrapper = new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, createOrderDTO.getShopId())
@@ -896,36 +1020,37 @@ public class TbShopTableServiceImpl implements TbShopTableService {
.isNull(TbCashierCart::getMasterId);
}));
});
// if (createOrderDTO.getVipUserId() != null) {
// queryWrapper.eq(TbCashierCart::getUserId, createOrderDTO.getVipUserId());
// }else {
// queryWrapper.eq(TbCashierCart::getMasterId, createOrderDTO.getMasterId())
// .isNull(TbCashierCart::getUserId);
// }
List<TbCashierCart> cashierCarts = cashierCartMapper
.selectList(queryWrapper);
if (cashierCarts.isEmpty()) {
throw new BadRequestException("购物车为空,请先添加商品");
}
TbShopTable tbShopTable = mpShopTableMapper.selectOne(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, createOrderDTO.getTableId())
.in(TbShopTable::getStatus, "idle", "using"));
if (tbShopTable == null) {
throw new BadRequestException("台桌未开台或不存在");
}
BigDecimal totalAmount = BigDecimal.ZERO;
BigDecimal packAMount = BigDecimal.ZERO;
BigDecimal feeAmount = BigDecimal.ZERO;
BigDecimal saleAmount = BigDecimal.ZERO;
// 当前下单次数
int placeNum = getCurrentPlaceNum(createOrderDTO.getTableId(), createOrderDTO.getShopId().toString());
List<TbOrderDetail> orderDetails = new ArrayList<>();
Integer mealNum = null;
boolean unAdd = cashierCarts.stream().noneMatch(item -> item.getPlaceNum() == null);
if (addMaterId && unAdd) {
throw new BadRequestException("此次未添加新商品,清先添加商品");
}
for (TbCashierCart cashierCart : cashierCarts) {
totalAmount = totalAmount.add(cashierCart.getTotalAmount());
packAMount = packAMount.add(cashierCart.getPackFee());
feeAmount = cashierCart.getPackFee();
if ("-999".equals(cashierCart.getProductId())) {
mealNum = cashierCart.getNumber();
}
if (!"return".equals(cashierCart.getStatus())) {
totalAmount = totalAmount.add(cashierCart.getTotalAmount());
packAMount = packAMount.add(cashierCart.getPackFee());
feeAmount = cashierCart.getPackFee();
}
TbProductSku productSku = productSkuRepository.findById(Integer.valueOf(cashierCart.getSkuId())).orElse(null);
TbOrderDetail orderDetail = new TbOrderDetail();
@@ -934,6 +1059,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
orderDetail.setProductSkuName(productSku.getSpecSnap());
}
orderDetail.setNote(cashierCart.getNote());
orderDetail.setCreateTime(DateUtil.date().toTimestamp());
orderDetail.setNum(cashierCart.getNumber());
orderDetail.setPrice(cashierCart.getSalePrice());
@@ -945,20 +1071,17 @@ public class TbShopTableServiceImpl implements TbShopTableService {
orderDetail.setPackAmount(cashierCart.getPackFee());
orderDetail.setStatus("unpaid");
orderDetail.setProductImg(cashierCart.getCoverImg());
orderDetail.setCartId(cashierCart.getId());
orderDetails.add(orderDetail);
if (cashierCart.getOrderId() != null) {
orderId = cashierCart.getOrderId();
}
orderDetail.setOrderId(orderId);
orderDetail.setPlaceNum(placeNum);
}
TbOrderInfo orderInfo = null;
if (orderId != null) {
orderInfo = orderInfoMapper.selectById(orderId);
if (orderInfo == null || !"unpaid".equals(orderInfo.getStatus())) {
redisTemplate.delete(currentOrderKey);
}
if (mealNum == null) {
throw new BadRequestException("请选择用餐人数");
}
// 修改订单信息
@@ -980,6 +1103,9 @@ public class TbShopTableServiceImpl implements TbShopTableService {
orderInfo.setUseType(createOrderDTO.isPostPay() ? "postPay" : "afterPay");
orderInfo.setUserId(createOrderDTO.getVipUserId() == null ? null : String.valueOf(createOrderDTO.getVipUserId()));
orderInfo.setCreatedAt(DateUtil.current());
if (!unAdd) {
orderInfo.setPlaceNum(placeNum);
}
orderInfoMapper.updateById(orderInfo);
} else {
String orderNo = generateOrderNumber();
@@ -1006,6 +1132,7 @@ public class TbShopTableServiceImpl implements TbShopTableService {
orderInfo.setUserId(createOrderDTO.getVipUserId() == null ? null : String.valueOf(createOrderDTO.getVipUserId()));
orderInfo.setCreatedAt(DateUtil.current());
orderInfo.setTableName(tbShopTable.getName());
orderInfo.setPlaceNum(placeNum);
TbMerchantAccount merchantAccount = merchantAccountMapper.selectOne(new LambdaQueryWrapper<TbMerchantAccount>()
.eq(TbMerchantAccount::getShopId, createOrderDTO.getShopId())
.eq(TbMerchantAccount::getStatus, 1));
@@ -1030,6 +1157,9 @@ public class TbShopTableServiceImpl implements TbShopTableService {
// 是否是第一次添加的商品
boolean isFirst = true;
for (TbCashierCart cashierCart : cashierCarts) {
if ("-999".equals(cashierCart.getProductId())) {
continue;
}
TbProduct product = productMapper.selectById(cashierCart.getProductId());
TbProductSku productSku = productSkuRepository.findById(Integer.valueOf(cashierCart.getSkuId())).orElse(null);
@@ -1041,6 +1171,9 @@ public class TbShopTableServiceImpl implements TbShopTableService {
cashierCart.setOrderId(orderId);
cashierCart.setUpdatedAt(System.currentTimeMillis());
cashierCart.setStatus("pending".equals(orderInfo.getStatus()) ? "refund" : cashierCart.getStatus());
if (cashierCart.getPlaceNum() == null) {
cashierCart.setPlaceNum(placeNum);
}
cashierCartMapper.updateById(cashierCart);
}
if (isFirst) {
@@ -1061,8 +1194,6 @@ public class TbShopTableServiceImpl implements TbShopTableService {
// 推送耗材信息
pushConsMsg(orderInfo, cashierCarts);
if (createOrderDTO.isPostPay() && isPrint) {
Long count = orderInfoMapper.selectCount(new LambdaQueryWrapper<TbOrderInfo>()
.eq(TbOrderInfo::getStatus, "unpaid")
@@ -1072,15 +1203,24 @@ public class TbShopTableServiceImpl implements TbShopTableService {
}
}
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
LambdaUpdateWrapper<TbShopTable> wrapper = new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getShopId, createOrderDTO.getShopId())
.eq(TbShopTable::getQrcode, createOrderDTO.getTableId())
.set(TbShopTable::getStatus, TableStateEnum.USING.getState()));
.set(TbShopTable::getProductNum, cashierCarts.size())
.set(TbShopTable::getTotalAmount, orderInfo.getOrderAmount())
.set(TbShopTable::getRealAmount, orderInfo.getOrderAmount())
.set(TbShopTable::getUseNum, mealNum)
.set(TbShopTable::getStatus, TableStateEnum.USING.getState());
if (isFirst) {
wrapper.set(TbShopTable::getUseTime, DateUtil.date());
}
// 设置台桌信息
mpShopTableMapper.update(null, wrapper);
String tableCartKey = RedisConstant.getTableCartKey(createOrderDTO.getTableId(), createOrderDTO.getShopId().toString());
redisTemplate.delete(tableCartKey);
return orderInfo;
}, stringRedisTemplate, RedisConstant.getLockKey(RedisConstant.CREATE_ORDER,createOrderDTO.getShopId(),
}, stringRedisTemplate, RedisConstant.getLockKey(RedisConstant.CREATE_ORDER, createOrderDTO.getShopId(),
createOrderDTO.getTableId(), createOrderDTO.getMasterId(), createOrderDTO.isPostPay()));
}
@@ -1236,25 +1376,70 @@ public class TbShopTableServiceImpl implements TbShopTableService {
@Override
public Object pay(PayDTO payDTO) {
return Utils.runFunAndCheckKey(() -> {
TbOrderInfo orderInfo = null;
long count = tbShopPayTypeMapper.selectCount(new LambdaQueryWrapper<TbShopPayType>()
.eq(TbShopPayType::getShopId, payDTO.getShopId())
.eq(TbShopPayType::getIsDisplay, 1)
.eq(TbShopPayType::getPayType, "deposit"));
if (count < 1) {
throw new BadRequestException("未知支付方式");
}
TbOrderInfo orderInfo = orderInfoMapper.selectById(payDTO.getOrderId());
if (ObjectUtil.isEmpty(orderInfo)) {
throw new BadRequestException("订单不存在");
}
if (!"unpaid".equals(orderInfo.getStatus()) && !"pending".equals(orderInfo.getStatus())) {
throw new BadRequestException("订单非未支付状态");
}
if (payDTO.getDiscount() == null) {
payDTO.setDiscount((double) 1);
}
BigDecimal finalAmount = orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(payDTO.getDiscount())).setScale(2, RoundingMode.HALF_UP);
switch (payDTO.getPayType()) {
case "vipPay":
orderInfo = tbPayServiceImpl.vipPay(payDTO.getShopId(), payDTO.getOrderId(), payDTO.getDiscount(), payDTO.getVipUserId());
if (payDTO.getVipUserId() != null) {
orderInfo.setUserId(String.valueOf(payDTO.getVipUserId()));
}
tbPayServiceImpl.vipPay(finalAmount, Integer.valueOf(orderInfo.getUserId()));
orderInfo.setPayOrderNo("vipPay".concat(SnowFlakeUtil.generateOrderNo()));
orderInfo.setPayType("deposit");
break;
case "cash":
orderInfo = tbPayServiceImpl.cashPay(payDTO);
orderInfo.setPayType("cash");
orderInfo.setPayOrderNo("cash".concat(SnowFlakeUtil.generateOrderNo()));
// orderInfo = tbPayServiceImpl.cashPay(payDTO);
break;
case "scanCode":
orderInfo = tbPayServiceImpl.scanPay(payDTO);
orderInfo = tbPayServiceImpl.scanPay(payDTO.getShopId(), payDTO.getCode(), Integer.valueOf(orderInfo.getMerchantId()), Integer.valueOf(orderInfo.getMemberId()), finalAmount, orderInfo);
break;
case "deposit":
orderInfo = tbPayServiceImpl.memberAccountPay("", String.valueOf(payDTO.getShopId()), payDTO.getCode(), payDTO.getOrderId(), payDTO.getDiscount());
orderInfo = tbPayServiceImpl.memberAccountPay("", String.valueOf(payDTO.getShopId()), payDTO.getCode(), orderInfo, finalAmount);
break;
default:
throw new BadRequestException("未知支付方式");
}
log.info("更新购物车");
orderInfo.setPayAmount(finalAmount);
orderInfo.setStatus("closed");
orderInfo.setDiscountRatio(BigDecimal.valueOf(payDTO.getDiscount()));
orderInfo.setDiscountAmount(orderInfo.getAmount().subtract(finalAmount));
orderInfoMapper.updateById(orderInfo);
//更新购物车状态
cashierCartMapper.update(null, new LambdaUpdateWrapper<TbCashierCart>()
.eq(TbCashierCart::getOrderId, orderInfo.getId())
.set(TbCashierCart::getStatus, "final"));
orderDetailMapper.update(null, new LambdaUpdateWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getOrderId, orderInfo.getId())
.set(TbOrderDetail::getStatus, "closed"));
JSONObject jsonObject = new JSONObject();
jsonObject.put("token", null);
@@ -1272,9 +1457,21 @@ public class TbShopTableServiceImpl implements TbShopTableService {
rabbitTemplate.convertAndSend(RabbitConstants.EXCHANGE_STOCK_RECORD, RabbitConstants.ROUTING_STOCK_RECORD_SALE, mqData.toJSONString(), new CorrelationData(UUID.randomUUID().toString()));
// 修改台桌状态
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, orderInfo.getTableId())
.set(TbShopTable::getStatus, TableStateEnum.IDLE.getState()));
TbShopTable tbShopTable = mpShopTableMapper.selectOne(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getShopId, payDTO.getShopId())
.eq(TbShopTable::getQrcode, orderInfo.getTableId()));
if (tbShopTable.getAutoClear().equals(1)) {
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, orderInfo.getTableId())
.set(TbShopTable::getEndTime, DateUtil.date())
.set(TbShopTable::getUseNum, 0)
.set(TbShopTable::getStatus, TableStateEnum.IDLE.getState()));
} else {
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, orderInfo.getTableId())
.set(TbShopTable::getEndTime, DateUtil.date())
.set(TbShopTable::getStatus, TableStateEnum.CLEANING.getState()));
}
if ("postPay".equals(orderInfo.getUseType())) {
String day = DateUtils.getDay();
@@ -1327,4 +1524,224 @@ public class TbShopTableServiceImpl implements TbShopTableService {
}
return cashierCartMapper.update(null, queryWrapper);
}
private String getCurrentOrderId(String tableId, String shopId) {
String currentOrderKey = RedisConstant.getCurrentOrderKey(tableId, shopId);
return redisTemplate.opsForValue().get(currentOrderKey);
}
private void setCurrentOrderId(String tableId, String shopId, String orderId) {
String currentOrderKey = RedisConstant.getCurrentOrderKey(tableId, shopId);
redisTemplate.opsForValue().set(currentOrderKey, orderId);
}
private String removeCurrentOrderId(String tableId, String shopId) {
String currentOrderKey = RedisConstant.getCurrentOrderKey(tableId, shopId);
String orderId = redisTemplate.opsForValue().get(currentOrderKey);
redisTemplate.delete(currentOrderKey);
return orderId;
}
@Override
public Object choseTable(ChoseTableDTO choseTableDTO) {
String masterId = getMasterId(choseTableDTO.getShopId(), Long.valueOf(choseTableDTO.getNewTableId()), null).getString("masterId");
String currentOrderId = choseTableDTO.getOrderId() == null ? getCurrentOrderId(choseTableDTO.getOldTableId(),
choseTableDTO.getShopId().toString()) : choseTableDTO.getOrderId().toString();
TbShopTable shopTable = mpShopTableMapper.selectOne(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, choseTableDTO.getNewTableId())
.eq(TbShopTable::getStatus, "idle"));
if (shopTable == null) {
throw new BadRequestException("台桌不存在或非空闲状态");
}
cashierCartMapper.update(null, new LambdaUpdateWrapper<TbCashierCart>()
.eq(TbCashierCart::getTableId, choseTableDTO.getOldTableId())
.in(TbCashierCart::getStatus, "create", "return")
.eq(TbCashierCart::getShopId, choseTableDTO.getShopId())
.and(q -> {
q.isNull(TbCashierCart::getOrderId)
.or()
.eq(TbCashierCart::getOrderId, currentOrderId);
})
.and(query2 -> {
query2.or(query3 -> {
query3.eq(TbCashierCart::getTradeDay, DateUtils.getDay())
.isNotNull(TbCashierCart::getMasterId);
})
.or((query4 -> {
query4.isNull(TbCashierCart::getTradeDay)
.isNull(TbCashierCart::getMasterId);
}));
})
.set(TbCashierCart::getMasterId, masterId)
.set(TbCashierCart::getTableId, choseTableDTO.getNewTableId()));
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, choseTableDTO.getNewTableId())
.set(TbShopTable::getStatus, TableStateEnum.USING.getState()));
mpShopTableMapper.update(null, new LambdaUpdateWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, choseTableDTO.getOldTableId())
.set(TbShopTable::getStatus, TableStateEnum.IDLE.getState()));
// 将台桌redis数据迁移
String orderId = removeCurrentOrderId(choseTableDTO.getOldTableId(), choseTableDTO.getShopId().toString());
setCurrentOrderId(choseTableDTO.getNewTableId(), choseTableDTO.getShopId().toString(), orderId);
return orderInfoMapper.update(null, new LambdaUpdateWrapper<TbOrderInfo>()
.eq(TbOrderInfo::getId, currentOrderId)
.set(TbOrderInfo::getMasterId, masterId)
.set(TbOrderInfo::getTableId, choseTableDTO.getNewTableId()));
}
@Override
public Object choseCount(ChoseCountDTO choseCountDTO) {
TbShopTable shopTable = mpShopTableService.lambdaQuery().eq(TbShopTable::getQrcode, choseCountDTO.getTableId()).one();
if (shopTable == null) {
throw new BadRequestException("台桌不存在");
}
if (shopTable.getMaxCapacity() < choseCountDTO.getNum()) {
throw new BadRequestException("当前台桌最大人数为: " + shopTable.getMaxCapacity());
}
LambdaQueryWrapper<TbCashierCart> query = new LambdaQueryWrapper<TbCashierCart>()
.eq(TbCashierCart::getShopId, choseCountDTO.getShopId())
.eq(TbCashierCart::getMasterId, choseCountDTO.getMasterId())
.eq(TbCashierCart::getProductId, "-999")
.eq(TbCashierCart::getSkuId, "-999")
.eq(TbCashierCart::getTradeDay, cn.ysk.cashier.utils.DateUtils.getDay())
.eq(TbCashierCart::getTableId, choseCountDTO.getTableId());
TbCashierCart tbCashierCart = cashierCartMapper.selectOne(query);
if (tbCashierCart == null) {
tbCashierCart = new TbCashierCart();
tbCashierCart.setStatus("create");
tbCashierCart.setCreatedAt(System.currentTimeMillis());
tbCashierCart.setTableId(Long.valueOf(choseCountDTO.getTableId()));
tbCashierCart.setName("客座费");
tbCashierCart.setSalePrice(BigDecimal.ONE);
tbCashierCart.setMasterId(choseCountDTO.getMasterId());
tbCashierCart.setShopId(String.valueOf(choseCountDTO.getShopId()));
tbCashierCart.setTradeDay(DateUtils.getDay());
tbCashierCart.setStatus("create");
tbCashierCart.setTotalAmount(new BigDecimal(choseCountDTO.getNum()).multiply(BigDecimal.ONE));
tbCashierCart.setPlaceNum(1);
tbCashierCart.setProductId("-999");
tbCashierCart.setSkuId("-999");
tbCashierCart.setPackFee(BigDecimal.ZERO);
tbCashierCart.setNumber(choseCountDTO.getNum());
tbCashierCart.setTotalNumber(choseCountDTO.getNum());
tbCashierCartMapper.insert(tbCashierCart);
} else {
tbCashierCart.setTotalAmount(new BigDecimal(choseCountDTO.getNum()).multiply(BigDecimal.ONE));
tbCashierCart.setNumber(choseCountDTO.getNum());
tbCashierCart.setTotalNumber(choseCountDTO.getNum());
tbCashierCartMapper.updateById(tbCashierCart);
}
return tbCashierCart;
}
@Override
public Object printOrder(BaseTableDTO baseTableDTO) {
checkTableState(baseTableDTO.getTableId());
String currentOrderId = getCurrentOrderId(baseTableDTO.getTableId(), baseTableDTO.getShopId().toString());
if (StrUtil.isBlank(currentOrderId)) {
throw new BadRequestException("当前台桌不存在订单");
}
TbOrderInfo orderInfo = orderInfoMapper.selectById(currentOrderId);
rabbitMsgUtils.printPlaceTicket(orderInfo.getId(), false);
return true;
}
@Override
public Object generate(TableGenerateDTO generateDTO) {
TbShopArea shopArea = mpShopAreaMapper.selectOne(new LambdaQueryWrapper<TbShopArea>()
.eq(TbShopArea::getShopId, generateDTO.getShopId())
.eq(TbShopArea::getId, generateDTO.getAreaId()));
if (shopArea == null) {
throw new BadRequestException("台桌区域不存在");
}
List<TbShopTable> tbShopTables = mpShopTableMapper.selectList(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getShopId, generateDTO.getShopId())
.select(TbShopTable::getName));
HashMap<String, Object> tableMap = new HashMap<>();
tbShopTables.forEach(item -> {
tableMap.put(item.getName(), item);
});
StringBuilder msg = new StringBuilder();
ArrayList<TbShopTable> tableArrayList = new ArrayList<>();
for (int i = generateDTO.getStart(); i <= generateDTO.getEnd(); i++) {
String name = generateDTO.getSign() + i;
if (tableMap.get(name) != null) {
msg.append(name).append(";");
continue;
}
TbShopTable shopTable = new TbShopTable();
shopTable.setShopId(generateDTO.getShopId());
shopTable.setName(name);
shopTable.setMaxCapacity(generateDTO.getCapacity());
shopTable.setAreaId(generateDTO.getAreaId());
shopTable.setCreatedAt(DateUtil.current());
shopTable.setStatus(TableStateEnum.CLOSED.getState());
tableArrayList.add(shopTable);
}
mpShopTableService.saveBatch(tableArrayList);
if (StrUtil.isNotBlank(msg.toString())) {
msg.append("台桌名已存在,未添加");
throw new BadRequestException(msg.toString());
}
return true;
}
private TbShopTable checkTableState(String tableId) {
TbShopTable tbShopTable = mpShopTableMapper.selectOne(new LambdaQueryWrapper<TbShopTable>()
.eq(TbShopTable::getQrcode, tableId)
.in(TbShopTable::getStatus, TableStateEnum.USING.getState(), TableStateEnum.PAYING.getState(), TableStateEnum.CLEANING.getState()));
if (tbShopTable == null) {
throw new BadRequestException("台桌不存在或当前台桌未开台");
}
return tbShopTable;
}
private TbOrderInfo getCurrentOrder(String tableId, String shopId) {
String currentOrderId = getCurrentOrderId(tableId, shopId);
if (StrUtil.isBlank(currentOrderId)) {
throw new BadRequestException("当前台桌不存在订单");
}
TbOrderInfo orderInfo = orderInfoMapper.selectById(currentOrderId);
if (orderInfo == null) {
throw new BadRequestException("当前台桌不存在订单");
}
return orderInfo;
}
@Override
public Object printDishes(BaseTableDTO baseTableDTO) {
checkTableState(baseTableDTO.getTableId());
TbOrderInfo currentOrder = getCurrentOrder(baseTableDTO.getTableId(), baseTableDTO.getShopId().toString());
List<TbOrderDetail> detailList = orderDetailMapper.selectList(new LambdaQueryWrapper<TbOrderDetail>()
.eq(TbOrderDetail::getOrderId, currentOrder.getId())
.eq(TbOrderDetail::getStatus, "unpaid")
.ne(TbOrderDetail::getProductId, -999)
.select(TbOrderDetail::getId));
if (detailList.isEmpty()) {
throw new BadRequestException("当前台桌还未下单任何菜品, 请先下单");
}
Integer[] detailIds = new Integer[detailList.size()];
for (int i = 0; i < detailList.size(); i++) {
detailIds[i] = detailList.get(i).getId();
}
rabbitMsgUtils.printDishesTicket(currentOrder.getId(), false, detailIds);
return true;
}
}

View File

@@ -20,7 +20,7 @@ import cn.ysk.cashier.pojo.order.TbCashierCart;
import cn.ysk.cashier.pojo.shop.TbShopTable;
import cn.ysk.cashier.dto.shop.TbShopTableDto;
import cn.ysk.cashier.dto.shop.TbShopTableQueryCriteria;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.alibaba.fastjson.JSONObject;
import org.springframework.data.domain.Pageable;
import java.util.Map;
import java.util.List;
@@ -100,9 +100,11 @@ public interface TbShopTableService {
void removeCart(RemoveCartDTO removeCartDTO);
void returnCart(RemoveCartDTO removeCartDTO);
void clearCart(ClearCartDTO clearCartDTO);
Page<TbCashierCart> getCart(Long tableId, Integer page, Integer size, Integer shopId, Integer vipUserId, String masterId);
Map<String, Object> getCart(Long tableId, Integer page, Integer size, Integer shopId, Integer vipUserId, String masterId);
TbCashierCart updateCart(UpdateCartDTO updateCartDTO);
@@ -110,7 +112,7 @@ public interface TbShopTableService {
Object createOrder(CreateOrderDTO createOrderDTO, boolean addMasterId, boolean isPrint);
Object getMasterId(Integer shopId, Long tableId, Integer vipUserId);
JSONObject getMasterId(Integer shopId, Long tableId, Integer vipUserId);
Object pending(PendingDTO pendingDTO);
@@ -123,4 +125,14 @@ public interface TbShopTableService {
Object deleteOrder(DeleteOrderDTO deleteOrderDTO);
Object updateVip(UpdateVipDTO updateVipDTO);
Object choseTable(ChoseTableDTO choseTableDTO);
Object choseCount(ChoseCountDTO choseCountDTO);
Object printOrder(BaseTableDTO baseTableDTO);
Object generate(TableGenerateDTO generateDTO);
Object printDishes(BaseTableDTO baseTableDTO);
}