Browse Source

Merge branch 'mp-server-test' into 'master'

Mp server test

See merge request quanshu/mp-server!735
zhong chunping 2 years ago
parent
commit
db0e25aaf6
49 changed files with 1015 additions and 136 deletions
  1. 1 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/ChannelOrderMgrController.java
  2. 67 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/ChannelWithdrawMgrController.java
  3. 1 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/SaleSiteMgrController.java
  4. 0 5
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/TicketBoxMgrController.java
  5. 40 1
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/UserDeliverOrderMgrController.java
  6. 100 32
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/UserTicketOrderMgrController.java
  7. 30 1
      mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/mall/ChannelTicketController.java
  8. 6 2
      mp-admin/src/main/java/com/qs/mp/web/controller/api/open/LinkController.java
  9. 1 1
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserShareController.java
  10. 20 0
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserTicketController.java
  11. 4 6
      mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserTicketOrderController.java
  12. 3 1
      mp-common/src/main/java/com/qs/mp/common/enums/AsyncTaskTypeEnum.java
  13. 6 0
      mp-quartz/src/main/java/com/qs/mp/quartz/task/AsyncConsumeTask.java
  14. 145 28
      mp-quartz/src/main/java/com/qs/mp/quartz/task/DayStatTask.java
  15. 1 0
      mp-quartz/src/main/java/com/qs/mp/quartz/task/OperateToolTask.java
  16. 0 8
      mp-service/src/main/java/com/qs/mp/admin/domain/TicketBox.java
  17. 4 0
      mp-service/src/main/java/com/qs/mp/admin/domain/excel/ChannelExcel.java
  18. 51 0
      mp-service/src/main/java/com/qs/mp/admin/domain/excel/ChannelWithdrawExcel.java
  19. 4 1
      mp-service/src/main/java/com/qs/mp/admin/domain/excel/UserTicketOrderItemExcel.java
  20. 30 0
      mp-service/src/main/java/com/qs/mp/admin/domain/param/ChannelWithdrawQueryParam.java
  21. 6 0
      mp-service/src/main/java/com/qs/mp/admin/domain/param/TicketBoxParam.java
  22. 10 5
      mp-service/src/main/java/com/qs/mp/admin/domain/vo/TicketBoxListVO.java
  23. 16 0
      mp-service/src/main/java/com/qs/mp/admin/domain/vo/TicketBoxVO.java
  24. 4 1
      mp-service/src/main/java/com/qs/mp/admin/domain/vo/UserTicketOrderItemVO.java
  25. 68 22
      mp-service/src/main/java/com/qs/mp/admin/service/impl/TicketBoxServiceImpl.java
  26. 21 0
      mp-service/src/main/java/com/qs/mp/channel/domain/ChannelWithdraw.java
  27. 6 0
      mp-service/src/main/java/com/qs/mp/channel/domain/vo/ChannelWithdrawVO.java
  28. 9 0
      mp-service/src/main/java/com/qs/mp/channel/mapper/ChannelCouponVerifyLogMapper.java
  29. 9 0
      mp-service/src/main/java/com/qs/mp/channel/service/IChannelCouponVerifyLogService.java
  30. 6 1
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelCouponVerifyLogServiceImpl.java
  31. 1 0
      mp-service/src/main/java/com/qs/mp/framework/redis/RedisLockKey.java
  32. 21 0
      mp-service/src/main/java/com/qs/mp/framework/service/IAsyncTaskService.java
  33. 98 2
      mp-service/src/main/java/com/qs/mp/framework/service/impl/AsyncTaskServiceImpl.java
  34. 3 0
      mp-service/src/main/java/com/qs/mp/open/domain/param/SchemeParam.java
  35. 7 8
      mp-service/src/main/java/com/qs/mp/pay/service/impl/WalletServiceImpl.java
  36. 8 0
      mp-service/src/main/java/com/qs/mp/system/mapper/SysUserMapper.java
  37. 7 0
      mp-service/src/main/java/com/qs/mp/system/service/ISysUserService.java
  38. 5 0
      mp-service/src/main/java/com/qs/mp/system/service/impl/SysUserServiceImpl.java
  39. 5 1
      mp-service/src/main/java/com/qs/mp/user/domain/excel/DeliverOrderExcel.java
  40. 8 0
      mp-service/src/main/java/com/qs/mp/user/mapper/UserCouponMapper.java
  41. 8 0
      mp-service/src/main/java/com/qs/mp/user/service/IUserCouponService.java
  42. 7 0
      mp-service/src/main/java/com/qs/mp/user/service/IUserDeliverOrderService.java
  43. 6 0
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserCouponServiceImpl.java
  44. 102 0
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserDeliverOrderServiceImpl.java
  45. 38 9
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserTicketOrderServiceImpl.java
  46. 7 0
      mp-service/src/main/resources/mapper/channel/ChannelCouponVerifyLogMapper.xml
  47. 6 0
      mp-service/src/main/resources/mapper/system/SysUserMapper.xml
  48. 6 0
      mp-service/src/main/resources/mapper/user/UserCouponMapper.xml
  49. 3 1
      mp-service/src/main/resources/mapper/user/UserTicketOrderItemMapper.xml

+ 1 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/ChannelOrderMgrController.java

@@ -347,6 +347,7 @@ public class ChannelOrderMgrController extends BaseApiController {
 	    queryWrapper.eq(null != queryParam && null != queryParam.getChannelId(), "t1.channel_id" ,queryParam.getChannelId());
 	    queryWrapper.eq(null != queryParam && StringUtils.isNotBlank(queryParam.getOrderId()), "t1.order_id" ,queryParam.getOrderId());
 		queryWrapper.eq(null != queryParam && null != queryParam.getStatus(), "t1.`status`" ,queryParam.getStatus());
+		queryWrapper.eq(null != queryParam && null != queryParam.getType(), "t1.`type`" ,queryParam.getType());
 		queryWrapper.ge(null != queryParam && null != queryParam.getStartTime(),  "t1.created_time", queryParam.getStartTime());
 		queryWrapper.le(null != queryParam && null != queryParam.getEndTime(), "t1.created_time", queryParam.getEndTime());
 		queryWrapper.like(null != queryParam && StringUtils.isNotBlank(queryParam.getTitle()), "t1.title", queryParam.getTitle());

+ 67 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/ChannelWithdrawMgrController.java

@@ -3,6 +3,10 @@ package com.qs.mp.web.controller.api.admin;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.qs.mp.admin.domain.excel.ChannelWithdrawExcel;
+import com.qs.mp.admin.domain.excel.UserTicketOrderItemExcel;
+import com.qs.mp.admin.domain.param.ChannelWithdrawQueryParam;
 import com.qs.mp.channel.domain.ChannelOrder;
 import com.qs.mp.channel.domain.ChannelOrderItem;
 import com.qs.mp.channel.domain.ChannelWithdraw;
@@ -19,11 +23,18 @@ import com.qs.mp.common.enums.BusinessType;
 import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
 import com.qs.mp.common.enums.ErrorCodeEnum;
 import com.qs.mp.common.utils.DateUtils;
+import com.qs.mp.utils.ExcelUtil;
 import com.qs.mp.web.controller.common.BaseApiController;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+
 import lombok.AllArgsConstructor;
 import ma.glasnost.orika.MapperFacade;
 import org.apache.commons.lang3.StringUtils;
@@ -104,4 +115,60 @@ public class ChannelWithdrawMgrController extends BaseApiController {
     return AjaxResult.success("操作成功");
   }
 
+
+  @PostMapping("/export")
+  @ApiOperation("提现申请导出")
+  @PreAuthorize("@ss.hasPermi('finance:withdraw:export')")
+  public AjaxResult export(@RequestBody ChannelWithdrawQueryParam param) {
+
+    // 导出时间范围限制校验
+    Date startTime = param.getStartDay();
+    Date endTime = param.getEndDay();
+    if (startTime == null || endTime == null) {
+      return AjaxResult.error("导出数据必须设置日期范围");
+    }
+    if (DateUtils.diff(startTime, endTime) > 30) {
+      return AjaxResult.error("导出的数据不能超过31天");
+    }
+
+    List<ChannelWithdrawVO> withdrawList = channelWithdrawService.listWithdrawVO(new QueryWrapper<ChannelWithdraw>()
+            .eq(null != param.getStatus() && param.getStatus() != 0, "t1.status", param.getStatus())
+            .like(StringUtils.isNotBlank(param.getName()), "t2.name", param.getName())
+            .ge(null != param.getStartDay(), "t1.create_time", param.getStartDay())
+            .lt(null != param.getEndDay(), "t1.create_time", param.getEndDay())
+            .orderByDesc("t1.create_time"));
+
+    if (CollectionUtils.isEmpty(withdrawList)) {
+      return error("没有符合条件的记录");
+    }
+
+    List<ChannelWithdrawExcel> channelWithdrawExcelList = new ArrayList<>();
+    for (ChannelWithdrawVO channelWithdrawVO : withdrawList) {
+      ChannelWithdrawExcel channelWithdrawExcel = new ChannelWithdrawExcel();
+        channelWithdrawExcel.setCreateTime(channelWithdrawVO.getCreateTime());
+        channelWithdrawExcel.setTransferTime(channelWithdrawVO.getTransferTime());
+        channelWithdrawExcel.setName(channelWithdrawVO.getName());
+        channelWithdrawExcel.setMobile(channelWithdrawVO.getMobile());
+        Integer money = channelWithdrawVO.getMoney();
+        if (Objects.isNull(money)) {
+          money = 0;
+        }
+        channelWithdrawExcel.setMoney(BigDecimal.valueOf(money).divide(BigDecimal.valueOf(100),2 ,RoundingMode.HALF_UP));
+        if (Objects.nonNull(channelWithdrawVO.getLevel())) {
+          if (channelWithdrawVO.getLevel() == 0) {
+            channelWithdrawExcel.setLevel("经销商");
+          } else {
+            channelWithdrawExcel.setLevel("渠道商");
+          }
+        }
+      if (Objects.nonNull(channelWithdrawVO.getStatus())) {
+        channelWithdrawExcel.setStatus(channelWithdrawVO.getStatus().getDesc());
+      }
+      channelWithdrawExcelList.add(channelWithdrawExcel);
+    }
+    ExcelUtil<ChannelWithdrawExcel> util = new ExcelUtil<>(ChannelWithdrawExcel.class);
+    return util.exportExcel(channelWithdrawExcelList, "提现申请导出", false);
+  }
+
+
 }

+ 1 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/SaleSiteMgrController.java

@@ -202,6 +202,7 @@ public class SaleSiteMgrController extends BaseApiController {
 			channelExcel.setCommRate(channelVO.getCommRate());
 			channelExcel.setName(channelVO.getName());
 			channelExcel.setParentsName(channelVO.getParentsName());
+			channelExcel.setCreatedTime(channelVO.getCreatedTime());
 			if (Objects.nonNull(channelVO.getCertifyStatus())) {
 				channelExcel.setCertifyStatus(channelVO.getCertifyStatus().getDesc());
 			}

+ 0 - 5
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/TicketBoxMgrController.java

@@ -201,11 +201,6 @@ public class TicketBoxMgrController extends BaseApiController {
 		}
 		String boxId = ticketBoxService.createTicketBox(param);
 		if (StringUtils.isNotBlank(boxId)) {
-			try {
-				pulsarClientService.producer(MqTopicType.ticket_generate, boxId);
-			} catch (PulsarClientException e) {
-				LogUtil.error(logger, e, "盲票组保存成功,发送异步消息失败. {0}", boxId);
-			}
 			return AjaxResult.success();
 		}
 		return AjaxResult.error("创建失败");

+ 40 - 1
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/UserDeliverOrderMgrController.java

@@ -28,6 +28,8 @@ import com.qs.mp.web.controller.common.BaseApiController;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.*;
 
 import io.swagger.annotations.ApiResponse;
@@ -43,6 +45,7 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 @RestController
 @RequestMapping("/api/v1/mp/admin/deliver/order")
@@ -225,6 +228,37 @@ public class UserDeliverOrderMgrController extends BaseApiController {
 		return res ? AjaxResult.success() : AjaxResult.error("消息修改失败");
 	}
 
+
+	@PostMapping("/batchShip")
+	@PreAuthorize("@ss.hasPermi('order:deliver:ship')")
+	@ApiOperation(value = "批量发货")
+	public AjaxResult batchShip(MultipartFile file) {
+		// 获取文件内的提货订单数据列表
+		try {
+			ExcelUtil<DeliverOrderExcel> util = new ExcelUtil<DeliverOrderExcel>(DeliverOrderExcel.class);
+			List<DeliverOrderExcel> deliverOrderExcelList = util.importExcel(file.getInputStream());
+			if(null == deliverOrderExcelList || deliverOrderExcelList.size() == 0) {
+				return AjaxResult.error("导入失败,选择的导入文件中没有有效的数据");
+			}
+			// 过滤没有快递信息的数据
+			List<DeliverOrderExcel> deliverOrderList  = new ArrayList<>();
+			for (DeliverOrderExcel deliverOrderExcel : deliverOrderExcelList) {
+				if (StringUtils.isNotBlank(deliverOrderExcel.getDeliveryFlowId()) && StringUtils.isNotBlank(deliverOrderExcel.getCompanyName())) {
+					deliverOrderList.add(deliverOrderExcel);
+				}
+			}
+			if (CollectionUtils.isEmpty(deliverOrderList)) {
+				return AjaxResult.error("导入失败,选择的导入文件中没有有效的数据");
+			}
+
+			String content = userDeliverOrderService.batchShip(deliverOrderList);
+			return AjaxResult.success("success", content);
+		} catch (Exception e) {
+			return AjaxResult.error("导入失败,请联系管理员");
+		}
+	}
+
+
 	@Log(title = "提货订单导出", businessType = BusinessType.EXPORT)
 	@PostMapping("/export")
 	@ApiOperation("提货订单导出")
@@ -302,6 +336,7 @@ public class UserDeliverOrderMgrController extends BaseApiController {
 								deliverOrderExcel.setCode(userDeliverOrderItem.getSkuCode());
 							}
 
+							deliverOrderExcel.setItemId(userDeliverOrderItem.getItemId());
 							deliverOrderExcel.setTitle(userDeliverOrderItem.getTitle());
 							deliverOrderExcel.setProperties(userDeliverOrderItem.getProperties());
 							deliverOrderExcel.setGoodsNum(userDeliverOrderItem.getGoodsNum());
@@ -315,7 +350,11 @@ public class UserDeliverOrderMgrController extends BaseApiController {
 							deliverOrderExcel.setTel(deliverOrder.getTel());
 							deliverOrderExcel.setDeliveryFlowId(userDeliverOrderItem.getDeliveryFlowId());
 							deliverOrderExcel.setCompanyName(userDeliverOrderItem.getCompanyName());
-							deliverOrderExcel.setGoodsCost(userDeliverOrderItem.getGoodsCost());
+							Integer goodsCost = userDeliverOrderItem.getGoodsCost();
+							if (Objects.isNull(goodsCost)) {
+								goodsCost = 0;
+							}
+							deliverOrderExcel.setGoodsCost(BigDecimal.valueOf(goodsCost).divide(BigDecimal.valueOf(100),2, RoundingMode.HALF_UP));
 
 							String address = deliverOrder.getProvince() + deliverOrder.getCity()
 									+ deliverOrder.getArea() + deliverOrder.getAddress();

+ 100 - 32
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/UserTicketOrderMgrController.java

@@ -1,13 +1,16 @@
 package com.qs.mp.web.controller.api.admin;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.qs.mp.admin.domain.TicketBox;
 import com.qs.mp.admin.domain.excel.UserTicketOrderExcel;
 import com.qs.mp.admin.domain.excel.UserTicketOrderItemExcel;
 import com.qs.mp.admin.domain.param.UserTicketOrderQueryParam;
 import com.qs.mp.admin.domain.vo.UserTicketOrderDetailVO;
 import com.qs.mp.admin.domain.vo.UserTicketOrderItemVO;
 import com.qs.mp.admin.domain.vo.UserTicketOrderListVO;
+import com.qs.mp.admin.service.ITicketBoxService;
 import com.qs.mp.common.annotation.Log;
 import com.qs.mp.common.core.domain.AjaxResult;
 import com.qs.mp.common.core.page.TableDataInfo;
@@ -17,6 +20,8 @@ import com.qs.mp.common.enums.TicketPrizeTypeEnum;
 import com.qs.mp.common.enums.UserTicketOrderStatusEnum;
 import com.qs.mp.common.utils.DateUtils;
 import com.qs.mp.common.utils.StringUtils;
+import com.qs.mp.system.domain.SysUser;
+import com.qs.mp.system.service.ISysUserService;
 import com.qs.mp.user.domain.UserTicketOrder;
 import com.qs.mp.user.domain.UserTicketOrderItem;
 import com.qs.mp.user.domain.excel.DeliverOrderExcel;
@@ -60,6 +65,12 @@ public class UserTicketOrderMgrController extends BaseApiController {
     @Autowired
     private IUserTicketOrderItemService userTicketOrderItemService;
 
+    @Autowired
+    private ISysUserService sysUserService;
+
+    @Autowired
+    private ITicketBoxService ticketBoxService;
+
     @PostMapping("/list")
     @PreAuthorize("@ss.hasPermi('order:userTicket:list')")
     @ApiOperation("用户盲票订单列表")
@@ -67,31 +78,53 @@ public class UserTicketOrderMgrController extends BaseApiController {
             @ApiResponse(code = 200, message = "成功", response = UserTicketOrderListVO.class)
     )
     public TableDataInfo list(@RequestBody UserTicketOrderQueryParam userTicketOrderQueryParam) {
-        startPage();
-        QueryWrapper<UserTicketOrder> queryWrapper = new QueryWrapper<>();
+
+        LambdaQueryWrapper<UserTicketOrder> userTicketOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+
         if (StringUtils.isNotBlank(userTicketOrderQueryParam.getBoxTitle())) {
-            queryWrapper.like("t1.title", userTicketOrderQueryParam.getBoxTitle());
-        }
-        if (Objects.nonNull(userTicketOrderQueryParam.getBoxType())) {
-            queryWrapper.eq("t3.type", userTicketOrderQueryParam.getBoxType());
-        }
-        if (StringUtils.isNotBlank(userTicketOrderQueryParam.getPhone())) {
-            queryWrapper.eq("t2.phonenumber", userTicketOrderQueryParam.getPhone());
+            userTicketOrderLambdaQueryWrapper.like(UserTicketOrder::getTitle, userTicketOrderQueryParam.getBoxTitle());
         }
         if (Objects.nonNull(userTicketOrderQueryParam.getStatus())) {
-            queryWrapper.eq("t1.status", userTicketOrderQueryParam.getStatus());
+            userTicketOrderLambdaQueryWrapper.eq(UserTicketOrder::getStatus, userTicketOrderQueryParam.getStatus());
         }
         if (Objects.nonNull(userTicketOrderQueryParam.getStartTime()) && Objects.nonNull(userTicketOrderQueryParam.getEndTime())) {
-            queryWrapper.between("t1.created_time", userTicketOrderQueryParam.getStartTime(), userTicketOrderQueryParam.getEndTime());
+            userTicketOrderLambdaQueryWrapper.between(UserTicketOrder::getCreatedTime, userTicketOrderQueryParam.getStartTime(), userTicketOrderQueryParam.getEndTime());
         }
         if (Objects.nonNull(userTicketOrderQueryParam.getChannelId()) && userTicketOrderQueryParam.getChannelId() != 0) {
-            queryWrapper.eq("t1.channel_id", userTicketOrderQueryParam.getChannelId());
+            userTicketOrderLambdaQueryWrapper.eq(UserTicketOrder::getChannelId, userTicketOrderQueryParam.getChannelId());
+        }
+        if (StringUtils.isNotBlank(userTicketOrderQueryParam.getPhone())) {
+            SysUser sysUser = sysUserService.selectUserByPhoneNumber(userTicketOrderQueryParam.getPhone());
+            if (sysUser != null) {
+                userTicketOrderLambdaQueryWrapper.eq(UserTicketOrder::getUserId, sysUser.getUserId());
+            }
         }
 
-        queryWrapper.orderByDesc("t1.created_time");
+        if (Objects.nonNull(userTicketOrderQueryParam.getBoxType())) {
+            List<TicketBox> ticketBoxList = ticketBoxService.list(new LambdaQueryWrapper<TicketBox>().eq(TicketBox::getType, userTicketOrderQueryParam.getBoxType()));
+            if (CollectionUtils.isNotEmpty(ticketBoxList)) {
+                List<String> boxIds = ticketBoxList.stream().map(TicketBox::getBoxId).collect(Collectors.toList());
+                userTicketOrderLambdaQueryWrapper.in(UserTicketOrder::getBoxId, boxIds);
+            }
+        }
 
-        List<UserTicketOrderListVO> list = userTicketOrderService.listUserTicketOrder(queryWrapper);
-        return getDataTable(list);
+        userTicketOrderLambdaQueryWrapper.orderByDesc(UserTicketOrder::getCreatedTime);
+
+        startPage();
+        List<UserTicketOrder> userTicketOrderList = userTicketOrderService.list(userTicketOrderLambdaQueryWrapper);
+
+
+        if (CollectionUtils.isNotEmpty(userTicketOrderList)) {
+            List<String> orderIds = userTicketOrderList.stream().map(UserTicketOrder::getOrderId).collect(Collectors.toList());
+            QueryWrapper<UserTicketOrder> queryWrapper = new QueryWrapper<>();
+            queryWrapper.in("t1.order_id",orderIds);
+            queryWrapper.orderByDesc("t1.created_time");
+            List<UserTicketOrderListVO> list = userTicketOrderService.listUserTicketOrder(queryWrapper);
+            TableDataInfo dataTable = getDataTable(userTicketOrderList);
+            dataTable.setRows(list);
+            return dataTable;
+        }
+        return getDataTable(userTicketOrderList);
     }
 
     @PostMapping("/detail/{orderId}")
@@ -121,44 +154,71 @@ public class UserTicketOrderMgrController extends BaseApiController {
             return AjaxResult.error("导出的数据不能超过31天");
         }
 
-        QueryWrapper<UserTicketOrder> queryWrapper = new QueryWrapper<>();
+
+
+        LambdaQueryWrapper<UserTicketOrder> userTicketOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+
         if (StringUtils.isNotBlank(userTicketOrderQueryParam.getBoxTitle())) {
-            queryWrapper.like("t1.title", userTicketOrderQueryParam.getBoxTitle());
-        }
-        if (Objects.nonNull(userTicketOrderQueryParam.getBoxType())) {
-            queryWrapper.eq("t3.type", userTicketOrderQueryParam.getBoxType());
-        }
-        if (StringUtils.isNotBlank(userTicketOrderQueryParam.getPhone())) {
-            queryWrapper.eq("t2.phonenumber", userTicketOrderQueryParam.getPhone());
+            userTicketOrderLambdaQueryWrapper.like(UserTicketOrder::getTitle, userTicketOrderQueryParam.getBoxTitle());
         }
         if (Objects.nonNull(userTicketOrderQueryParam.getStatus())) {
-            queryWrapper.eq("t1.status", userTicketOrderQueryParam.getStatus());
+            userTicketOrderLambdaQueryWrapper.eq(UserTicketOrder::getStatus, userTicketOrderQueryParam.getStatus());
         }
         if (Objects.nonNull(userTicketOrderQueryParam.getStartTime()) && Objects.nonNull(userTicketOrderQueryParam.getEndTime())) {
-            queryWrapper.between("t1.created_time", userTicketOrderQueryParam.getStartTime(), userTicketOrderQueryParam.getEndTime());
+            userTicketOrderLambdaQueryWrapper.between(UserTicketOrder::getCreatedTime, userTicketOrderQueryParam.getStartTime(), userTicketOrderQueryParam.getEndTime());
         }
         if (Objects.nonNull(userTicketOrderQueryParam.getChannelId()) && userTicketOrderQueryParam.getChannelId() != 0) {
-            queryWrapper.eq("t1.channel_id", userTicketOrderQueryParam.getChannelId());
+            userTicketOrderLambdaQueryWrapper.eq(UserTicketOrder::getChannelId, userTicketOrderQueryParam.getChannelId());
         }
-        queryWrapper.orderByDesc("t1.created_time");
-        int totalSize = userTicketOrderService.countUserTicketOrder(queryWrapper);
+        if (StringUtils.isNotBlank(userTicketOrderQueryParam.getPhone())) {
+            SysUser sysUser = sysUserService.selectUserByPhoneNumber(userTicketOrderQueryParam.getPhone());
+            if (sysUser != null) {
+                userTicketOrderLambdaQueryWrapper.eq(UserTicketOrder::getUserId, sysUser.getUserId());
+            }
+        }
+
+        if (Objects.nonNull(userTicketOrderQueryParam.getBoxType())) {
+            List<TicketBox> ticketBoxList = ticketBoxService.list(new LambdaQueryWrapper<TicketBox>().eq(TicketBox::getType, userTicketOrderQueryParam.getBoxType()));
+            if (CollectionUtils.isNotEmpty(ticketBoxList)) {
+                List<String> boxIds = ticketBoxList.stream().map(TicketBox::getBoxId).collect(Collectors.toList());
+                userTicketOrderLambdaQueryWrapper.in(UserTicketOrder::getBoxId, boxIds);
+            }
+        }
+
+        userTicketOrderLambdaQueryWrapper.orderByDesc(UserTicketOrder::getCreatedTime);
+
+        int totalSize = userTicketOrderService.count(userTicketOrderLambdaQueryWrapper);
         if (totalSize == 0) {
             return AjaxResult.error("没有符合条件的用户订单");
         }
+
         int pageSize = 2000;
         List<UserTicketOrderListVO> userTicketOrderListVOList = new ArrayList<>();
         if (totalSize > pageSize) {
             int totalPage = totalSize % pageSize == 0 ? totalSize / pageSize : totalSize / pageSize + 1;
             for (int i = 0; i < totalPage; i++) {
-                queryWrapper.last("limit " + (i * pageSize) + ", " + pageSize);
-                List<UserTicketOrderListVO> list = userTicketOrderService.listUserTicketOrder(queryWrapper);
-                if (CollectionUtils.isNotEmpty(list)) {
+                userTicketOrderLambdaQueryWrapper.last("limit " + (i * pageSize) + ", " + pageSize);
+                List<UserTicketOrder> userTicketOrderList = userTicketOrderService.list(userTicketOrderLambdaQueryWrapper);
+                if (CollectionUtils.isNotEmpty(userTicketOrderList)) {
+                    List<String> orderIds = userTicketOrderList.stream().map(UserTicketOrder::getOrderId).collect(Collectors.toList());
+                    QueryWrapper<UserTicketOrder> queryWrapper = new QueryWrapper<>();
+                    queryWrapper.in("t1.order_id",orderIds);
+                    queryWrapper.orderByDesc("t1.created_time");
+                    List<UserTicketOrderListVO> list = userTicketOrderService.listUserTicketOrder(queryWrapper);
                     userTicketOrderListVOList.addAll(list);
                 }
             }
         } else {
-            userTicketOrderListVOList = userTicketOrderService.listUserTicketOrder(queryWrapper);
+            List<UserTicketOrder> userTicketOrderList = userTicketOrderService.list(userTicketOrderLambdaQueryWrapper);
+            if (CollectionUtils.isNotEmpty(userTicketOrderList)) {
+                List<String> orderIds = userTicketOrderList.stream().map(UserTicketOrder::getOrderId).collect(Collectors.toList());
+                QueryWrapper<UserTicketOrder> queryWrapper = new QueryWrapper<>();
+                queryWrapper.in("t1.order_id", orderIds);
+                queryWrapper.orderByDesc("t1.created_time");
+                userTicketOrderListVOList = userTicketOrderService.listUserTicketOrder(queryWrapper);
+            }
         }
+
         List<UserTicketOrderExcel> excelList = userTicketOrderListVOList.stream().map(userTicketOrderListVO -> {
             UserTicketOrderExcel userTicketOrderExcel = new UserTicketOrderExcel();
             BeanUtils.copyProperties(userTicketOrderListVO, userTicketOrderExcel);
@@ -253,6 +313,14 @@ public class UserTicketOrderMgrController extends BaseApiController {
                 userTicketOrderItemExcel.setTicketType(userTicketOrderItemVO.getTicketType().getDesc());
             }
 
+            if (Objects.nonNull(userTicketOrderItemVO.getIsPre())) {
+                if (userTicketOrderItemVO.getIsPre() == 1) {
+                    userTicketOrderItemExcel.setIsPre("是");
+                } else {
+                    userTicketOrderItemExcel.setIsPre("否");
+                }
+            }
+
             if (Objects.nonNull(userTicketOrderItemVO.getTicketStatus())) {
                 userTicketOrderItemExcel.setTicketStatus(userTicketOrderItemVO.getTicketStatus().getDesc());
             }

+ 30 - 1
mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/mall/ChannelTicketController.java

@@ -15,6 +15,7 @@ import com.qs.mp.common.core.domain.AjaxResult;
 import com.qs.mp.common.core.page.TableDataInfo;
 import com.qs.mp.common.enums.TicketBoxSaleChannelTypeEnum;
 import com.qs.mp.common.enums.TicketBoxStatusEnum;
+import com.qs.mp.common.enums.TicketTypeEnum;
 import com.qs.mp.common.utils.StringUtils;
 import com.qs.mp.utils.SecurityUtils;
 import com.qs.mp.web.controller.common.BaseApiController;
@@ -29,6 +30,7 @@ import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import lombok.AllArgsConstructor;
 import ma.glasnost.orika.MapperFacade;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -87,6 +89,24 @@ public class ChannelTicketController extends BaseApiController {
       queryWrapper.eq("t1.category_id",param.getCategoryId());
     }
     queryWrapper.eq("t1.status", TicketBoxStatusEnum.PUT_ON);
+
+
+    if (param.getSaleQtySort() != null) {
+      if (param.getSaleQtySort() == 1) {
+        queryWrapper.orderByAsc("t1.sale_qty");
+      } else if (param.getSaleQtySort() == 2) {
+        queryWrapper.orderByDesc("t1.sale_qty");
+      }
+    }
+
+    if (param.getSalePriceSort() != null) {
+      if (param.getSalePriceSort() == 1) {
+        queryWrapper.orderByAsc("t1.sale_price");
+      } else if (param.getSalePriceSort() == 2) {
+        queryWrapper.orderByDesc("t1.sale_price");
+      }
+    }
+
     queryWrapper.orderByDesc("t1.sort_weight");
 
     queryWrapper.nested(wrapper -> {
@@ -103,7 +123,16 @@ public class ChannelTicketController extends BaseApiController {
 //            .eq(null != param.getCategoryId() && 0 != param.getCategoryId(), TicketBox::getCategoryId, param.getCategoryId())
 //            .eq(TicketBox::getStatus, TicketBoxStatusEnum.PUT_ON)
 //            .orderByDesc(TicketBox::getSortWeight));
-    List<TicketBoxListVO> ticketBoxListVOList = mapperFacade.mapAsList(ticketBoxes, TicketBoxListVO.class);
+    List<TicketBoxListVO> ticketBoxListVOList = new ArrayList<>();
+    if (CollectionUtils.isNotEmpty(ticketBoxes)) {
+      for (TicketBox ticketBox : ticketBoxes) {
+        TicketBoxListVO ticketBoxListVO = new TicketBoxListVO();
+        BeanUtils.copyProperties(ticketBox, ticketBoxListVO);
+        // 设置经销商分佣比
+        ticketBoxListVO.setChannelCommRate(channel.getCommRate());
+        ticketBoxListVOList.add(ticketBoxListVO);
+      }
+    }
     TableDataInfo rspData = getDataTable(ticketBoxes);
     rspData.setRows(ticketBoxListVOList);
     return rspData;

+ 6 - 2
mp-admin/src/main/java/com/qs/mp/web/controller/api/open/LinkController.java

@@ -103,9 +103,13 @@ public class LinkController {
         }
 
 
+        if (StringUtils.isBlank(schemeParam.getBoxId())) {
+            // 生成scheme,并缓存到redis中,1天过期
+            scheme = wxUrlLinkService.generateUrlSchema("", "uid=" + channel.getUserId() + "&t=" + UserShareVO.SHARE_TYPE_SITE, userAppId);
+        } else {
+            scheme = wxUrlLinkService.generateUrlSchema("pages/ticketBox/detail", "uid=" + channel.getUserId() + "&t=" + UserShareVO.SHARE_TYPE_SITE + "&boxId=" + schemeParam.getBoxId(), userAppId);
+        }
 
-        // 生成scheme,并缓存到redis中,1天过期
-        scheme = wxUrlLinkService.generateUrlSchema("", "uid=" + channel.getUserId() + "&t=" + UserShareVO.SHARE_TYPE_SITE, userAppId);
         redisCache.setCacheObject(key, scheme,1, TimeUnit.DAYS);
         LogUtil.info(logger, "生成的scheme码:{0}", scheme);
         return AjaxResult.success("success",scheme);

+ 1 - 1
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserShareController.java

@@ -24,7 +24,7 @@ import java.util.Objects;
  * @create 2022-02-28 16:17:48
  * @describe 用户分享前端控制器
  */
-@Api("用户分享调用API")
+@Api(tags = "用户分享调用API")
 @RestController
 @RequestMapping("/api/v1/mp/user/share")
 @Component

+ 20 - 0
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserTicketController.java

@@ -13,6 +13,8 @@ import com.qs.mp.admin.domain.param.TicketBoxParam;
 import com.qs.mp.admin.domain.param.TicketParam;
 import com.qs.mp.admin.domain.vo.*;
 import com.qs.mp.admin.service.*;
+import com.qs.mp.channel.domain.Channel;
+import com.qs.mp.channel.service.IChannelService;
 import com.qs.mp.common.core.domain.AjaxResult;
 import com.qs.mp.common.core.page.TableDataInfo;
 import com.qs.mp.common.core.redis.DistributedLocker;
@@ -93,6 +95,9 @@ public class UserTicketController extends BaseApiController {
   @Autowired
   private DistributedLocker distributedLocker;
 
+  @Autowired
+  private IChannelService channelService;
+
   /**
    * 盲票进货列表
    */
@@ -130,6 +135,21 @@ public class UserTicketController extends BaseApiController {
       }
       TicketBox ticketBox = ticketBoxService.getById(param.getBoxId());
       TicketBoxVO ticketBoxVO = mapperFacade.map(ticketBox, TicketBoxVO.class);
+
+
+      // 设置经销商佣金比
+      if (hostHolder.getUser() != null) {
+        Long channelId = hostHolder.getUser().getChannelId();
+        if (channelId != null && channelId > 0) {
+          Channel channel = channelService.getById(channelId);
+          if (channel != null) {
+            ticketBoxVO.setChannelCommRate(channel.getCommRate());
+          }
+        }
+      }
+
+
+
       // 设置奖项标签信息
       QueryWrapper<TicketAwards> queryWrapper = new QueryWrapper<>();
       queryWrapper.eq("box_id",ticketBox.getBoxId());

+ 4 - 6
mp-admin/src/main/java/com/qs/mp/web/controller/api/user/UserTicketOrderController.java

@@ -177,11 +177,6 @@ public class UserTicketOrderController extends BaseApiController {
       jsonObject.put("needPay", 1);
     } else {
       jsonObject.put("needPay", 0);
-      try {
-          pulsarClientService.producer(MqTopicType.ticket_pay, orderId);
-      } catch (PulsarClientException e) {
-        LogUtil.error(logger, e, "盲票支付成功,发送异步消息失败. orderId:{0}", orderId);
-      }
     }
     // 清除缓存的订单
     redisCache.deleteObject(RedisKey.build(RedisKey.USER_TICKET_ORDER_KEY, userId));
@@ -280,7 +275,10 @@ public class UserTicketOrderController extends BaseApiController {
         }
       }
     }
-    return getDataTable(userCouponVOList);
+    List<UserCouponVO> countUserCouponVOList = userCouponService.queryUserCouponList(userId, orderSettleVO.getOrderAmt(), ticketBox);
+    TableDataInfo dataTable = getDataTable(userCouponVOList);
+    dataTable.setTotal(countUserCouponVOList.size());
+    return dataTable;
   }
 
 }

+ 3 - 1
mp-common/src/main/java/com/qs/mp/common/enums/AsyncTaskTypeEnum.java

@@ -11,7 +11,9 @@ import io.swagger.annotations.ApiModel;
  */
 @ApiModel("异步任务类型枚举")
 public enum AsyncTaskTypeEnum implements IEnum<Integer> {
-    CHANNEL_CONFIRM_RECEIPT(1,"经销商确认收货任务");
+    CHANNEL_CONFIRM_RECEIPT(1,"经销商确认收货任务"),
+    TICKET_PAY(2,"盲票付款任务"),
+    TICKET_GENERATE(3, "盲票生成任务");
 
     private Integer value;
     private String desc;

+ 6 - 0
mp-quartz/src/main/java/com/qs/mp/quartz/task/AsyncConsumeTask.java

@@ -72,6 +72,12 @@ public class AsyncConsumeTask {
         if (AsyncTaskTypeEnum.CHANNEL_CONFIRM_RECEIPT.getValue().equals(asyncTask.getType())) {
             // 确认收货后相关任务处理
             asyncTaskService.channelConfirmReceipt(asyncTask);
+        } else if (AsyncTaskTypeEnum.TICKET_PAY.getValue().equals(asyncTask.getType())) {
+            // 盲票支付后相关任务处理
+            asyncTaskService.ticketPay(asyncTask);
+        } else if (AsyncTaskTypeEnum.TICKET_GENERATE.getValue().equals(asyncTask.getType())) {
+            // 盲票支付后相关任务处理
+            asyncTaskService.ticketGenerate(asyncTask);
         }
 
         // 更新异步任务状态

+ 145 - 28
mp-quartz/src/main/java/com/qs/mp/quartz/task/DayStatTask.java

@@ -6,12 +6,7 @@ import com.qs.mp.admin.domain.TicketBox;
 import com.qs.mp.admin.service.ITicketBoxService;
 import com.qs.mp.channel.domain.*;
 import com.qs.mp.channel.service.*;
-import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
-import com.qs.mp.common.enums.CoinLogTypeEnum;
-import com.qs.mp.common.enums.CouponDiscountTypeEnum;
-import com.qs.mp.common.enums.TicketBoxStatusEnum;
-import com.qs.mp.common.enums.TicketTypeEnum;
-import com.qs.mp.common.enums.UserTicketOrderStatusEnum;
+import com.qs.mp.common.enums.*;
 import com.qs.mp.common.utils.DateUtils;
 import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.common.utils.StringUtils;
@@ -19,9 +14,11 @@ import com.qs.mp.common.utils.WebhookService;
 import com.qs.mp.system.domain.SysUser;
 import com.qs.mp.system.service.ISysUserService;
 import com.qs.mp.user.domain.UserCoinLog;
+import com.qs.mp.user.domain.UserCoupon;
 import com.qs.mp.user.domain.UserExchangeOrder;
 import com.qs.mp.user.domain.UserTicketOrder;
 import com.qs.mp.user.service.IUserCoinLogService;
+import com.qs.mp.user.service.IUserCouponService;
 import com.qs.mp.user.service.IUserExchangeOrderService;
 import com.qs.mp.user.service.IUserTicketOrderService;
 import java.math.BigDecimal;
@@ -78,6 +75,9 @@ public class DayStatTask {
   @Autowired
   private IChannelOrderService channelOrderService;
 
+  @Autowired
+  private IUserCouponService userCouponService;
+
   @Value("${export.page-size}")
   private int pageSize;
 
@@ -128,6 +128,16 @@ public class DayStatTask {
     }
     BigDecimal sumSaleAmt = BigDecimal.ZERO;
     BigDecimal sumAllSaleAmt = BigDecimal.ZERO;
+
+
+    // 线上销售额和汇总
+    BigDecimal onlineSumSaleAmt = BigDecimal.ZERO;
+    BigDecimal onlineSumAllSaleAmt = BigDecimal.ZERO;
+    // 线下销售额和汇总
+    BigDecimal offlineSumSaleAmt = BigDecimal.ZERO;
+    BigDecimal offlineSumAllSaleAmt = BigDecimal.ZERO;
+
+
     // 预付的金额统计
     BigDecimal sumPreSaleAmt = BigDecimal.ZERO;
     BigDecimal sumAllPreSaleAmt = BigDecimal.ZERO;
@@ -135,7 +145,13 @@ public class DayStatTask {
       queryWrapper.orderByAsc(TicketBox::getBoxNo);
       queryWrapper.last("limit " + (i * pageSize) + ", " + pageSize);
       List<TicketBox> ticketBoxList = ticketBoxService.list(queryWrapper);
+      // 区分线上和线下标识
+      boolean isOnline = true;
       for (TicketBox ticketBox : ticketBoxList) {
+        if (TicketTypeEnum.OFFLINE.equals(ticketBox.getType())) {
+          isOnline = false;
+        }
+
         Map<String, Object> orderMap = userTicketOrderService.getMap(
             new QueryWrapper<UserTicketOrder>()
                 .select("IFNULL(sum(pay_amt) ,0) as orderAmt")
@@ -160,7 +176,12 @@ public class DayStatTask {
             orderAmt = new BigDecimal(
                     Integer.valueOf(String.valueOf(orderMap.get("orderAmt")))).divide(new BigDecimal(100),
                     2, RoundingMode.DOWN);
-            sumSaleAmt = sumSaleAmt.add(orderAmt);
+//            sumSaleAmt = sumSaleAmt.add(orderAmt);
+            if (isOnline) {
+              onlineSumSaleAmt = onlineSumSaleAmt.add(orderAmt);
+            } else {
+              offlineSumSaleAmt = offlineSumSaleAmt.add(orderAmt);
+            }
           }
 
 
@@ -179,7 +200,12 @@ public class DayStatTask {
             allOrderAmt = new BigDecimal(
                 Integer.valueOf(String.valueOf(allOrderMap.get("orderAmt")))).divide(new BigDecimal(100),
                 2, RoundingMode.DOWN);
-            sumAllSaleAmt = sumAllSaleAmt.add(allOrderAmt);
+//            sumAllSaleAmt = sumAllSaleAmt.add(allOrderAmt);
+            if (isOnline) {
+              onlineSumAllSaleAmt = onlineSumAllSaleAmt.add(allOrderAmt);
+            } else {
+              offlineSumAllSaleAmt = offlineSumAllSaleAmt.add(allOrderAmt);
+            }
           }
 
           // 预付累积金额
@@ -215,8 +241,11 @@ public class DayStatTask {
       }
     }
 
-    sb.append("累计零售销售额:").append(sumAllSaleAmt).append("元,当日:").append(sumSaleAmt).append("元\n");
-    sb.append("累计预付销售额:").append(sumAllPreSaleAmt).append("元,当日:").append(sumPreSaleAmt).append("元\n");
+    sb.append("线上累计零售销售金额:").append(onlineSumAllSaleAmt).append("元,当日:").append(onlineSumSaleAmt).append("元\n");
+    sb.append("线下累计零售销售金额:").append(offlineSumAllSaleAmt).append("元,当日:").append(offlineSumSaleAmt).append("元,").append("累计预付销售金额:").append(sumAllPreSaleAmt).append("元,当日:").append(sumPreSaleAmt).append("元\n");
+
+//    sb.append("累计零售销售额:").append(sumAllSaleAmt).append("元,当日:").append(sumSaleAmt).append("元\n");
+//    sb.append("累计预付销售额:").append(sumAllPreSaleAmt).append("元,当日:").append(sumPreSaleAmt).append("元\n");
     Map<String, Object> commMap = channelCommissionService.getMap(
         new QueryWrapper<ChannelCommission>()
             .select("IFNULL(sum(comm_amt) ,0) as commAmt")
@@ -235,24 +264,48 @@ public class DayStatTask {
                   new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
     }
 
-    Map<String, Object> couponMap = channelCouponVerifyLogService.getMap(
-        new QueryWrapper<ChannelCouponVerifyLog>()
-            .select("IFNULL(sum(discount) ,0) as discount")
-            .lambda().ge(ChannelCouponVerifyLog::getCreatedTime, bizDay)
-            .lt(ChannelCouponVerifyLog::getCreatedTime, DateUtils.addDays(bizDay, 1))
-            .eq(ChannelCouponVerifyLog::getDiscountType, CouponDiscountTypeEnum.MONEY_OFF));
-    Map<String, Object> allCouponMap = channelCouponVerifyLogService.getMap(
-        new QueryWrapper<ChannelCouponVerifyLog>()
-            .select("IFNULL(sum(discount) ,0) as discount")
-            .lambda().lt(ChannelCouponVerifyLog::getCreatedTime, DateUtils.addDays(bizDay, 1))
-            .eq(ChannelCouponVerifyLog::getDiscountType, CouponDiscountTypeEnum.MONEY_OFF));
     if (null != commMap) {
-      sb.append("累计核销:").append(
-              new BigDecimal(Integer.valueOf(String.valueOf(allCouponMap.get("discount")))).divide(
-                  new BigDecimal(100), 2, RoundingMode.DOWN))
-          .append("元,当日:").append(
-              new BigDecimal(Integer.valueOf(String.valueOf(couponMap.get("discount")))).divide(
-                  new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
+      // 线上核销统计
+      QueryWrapper<ChannelCouponVerifyLog> onlineDisCountQueryWrapper = new QueryWrapper<>();
+      onlineDisCountQueryWrapper.ge("t1.created_time", bizDay);
+      onlineDisCountQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+      onlineDisCountQueryWrapper.eq("t1.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+      onlineDisCountQueryWrapper.eq("t3.type", CouponTypeEnum.TICKET_ORDER);
+      Integer onlineDisCount = channelCouponVerifyLogService.sumDisCountByQueryWrapper(onlineDisCountQueryWrapper);
+      QueryWrapper<ChannelCouponVerifyLog> onlineAllDisCountQueryWrapper = new QueryWrapper<>();
+      onlineAllDisCountQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+      onlineAllDisCountQueryWrapper.eq("t1.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+      onlineAllDisCountQueryWrapper.eq("t3.type", CouponTypeEnum.TICKET_ORDER);
+      Integer onlineAllDisCount = channelCouponVerifyLogService.sumDisCountByQueryWrapper(onlineAllDisCountQueryWrapper);
+
+      // 线下核销统计
+      QueryWrapper<ChannelCouponVerifyLog> offlineDisCountQueryWrapper = new QueryWrapper<>();
+      offlineDisCountQueryWrapper.ge("t1.created_time", bizDay);
+      offlineDisCountQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+      offlineDisCountQueryWrapper.eq("t1.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+      offlineDisCountQueryWrapper.eq("t3.type", CouponTypeEnum.SITE_CONSUME);
+      Integer offlineDisCount = channelCouponVerifyLogService.sumDisCountByQueryWrapper(offlineDisCountQueryWrapper);
+      QueryWrapper<ChannelCouponVerifyLog> offlineAllDisCountQueryWrapper = new QueryWrapper<>();
+      offlineAllDisCountQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+      offlineAllDisCountQueryWrapper.eq("t1.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+      offlineAllDisCountQueryWrapper.eq("t3.type", CouponTypeEnum.SITE_CONSUME);
+      Integer offlineAllDisCount = channelCouponVerifyLogService.sumDisCountByQueryWrapper(offlineAllDisCountQueryWrapper);
+
+
+      sb.append("线上券累计核销金额:").append(
+                      new BigDecimal(Integer.valueOf(String.valueOf(onlineAllDisCount))).divide(
+                              new BigDecimal(100), 2, RoundingMode.DOWN))
+              .append("元,当日:").append(
+                      new BigDecimal(Integer.valueOf(String.valueOf(onlineDisCount))).divide(
+                              new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
+
+      sb.append("线下券累计核销金额:").append(
+                      new BigDecimal(Integer.valueOf(String.valueOf(offlineAllDisCount))).divide(
+                              new BigDecimal(100), 2, RoundingMode.DOWN))
+              .append("元,当日:").append(
+                      new BigDecimal(Integer.valueOf(String.valueOf(offlineDisCount))).divide(
+                              new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
+
     }
 
     Map<String, Object> withdrawMap = channelWithdrawService.getMap(
@@ -281,6 +334,52 @@ public class DayStatTask {
                   new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
     }
 
+
+    // 线上和线下派发券金额统计
+    QueryWrapper<UserCoupon> onlineUserCouponQueryWrapper = new QueryWrapper<>();
+    onlineUserCouponQueryWrapper.ge("t1.created_time", bizDay);
+    onlineUserCouponQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+    onlineUserCouponQueryWrapper.eq("t2.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+    onlineUserCouponQueryWrapper.eq("t2.type", CouponTypeEnum.TICKET_ORDER);
+    Integer onlineUserCouponDisSum = userCouponService.sumDiscountByQueryWrapper(onlineUserCouponQueryWrapper);
+
+
+    QueryWrapper<UserCoupon> onlineAllUserCouponQueryWrapper = new QueryWrapper<>();
+    onlineAllUserCouponQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+    onlineAllUserCouponQueryWrapper.eq("t2.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+    onlineAllUserCouponQueryWrapper.eq("t2.type", CouponTypeEnum.TICKET_ORDER);
+    Integer onlineAllUserCouponDisSum = userCouponService.sumDiscountByQueryWrapper(onlineAllUserCouponQueryWrapper);
+
+
+    QueryWrapper<UserCoupon> offlineUserCouponQueryWrapper = new QueryWrapper<>();
+    offlineUserCouponQueryWrapper.ge("t1.created_time", bizDay);
+    offlineUserCouponQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+    offlineUserCouponQueryWrapper.eq("t2.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+    offlineUserCouponQueryWrapper.eq("t2.type", CouponTypeEnum.SITE_CONSUME);
+    Integer offlineUserCouponDisSum = userCouponService.sumDiscountByQueryWrapper(offlineUserCouponQueryWrapper);
+
+
+    QueryWrapper<UserCoupon> offlineAllUserCouponQueryWrapper = new QueryWrapper<>();
+    offlineAllUserCouponQueryWrapper.lt("t1.created_time", DateUtils.addDays(bizDay, 1));
+    offlineAllUserCouponQueryWrapper.eq("t2.discount_type", CouponDiscountTypeEnum.MONEY_OFF);
+    offlineAllUserCouponQueryWrapper.eq("t2.type", CouponTypeEnum.SITE_CONSUME);
+    Integer offlineAllUserCouponDisSum = userCouponService.sumDiscountByQueryWrapper(offlineAllUserCouponQueryWrapper);
+
+    sb.append("线上累计派券金额:").append(
+                    new BigDecimal(Integer.valueOf(String.valueOf(onlineAllUserCouponDisSum))).divide(
+                            new BigDecimal(100), 2, RoundingMode.DOWN))
+            .append("元,当日:").append(
+                    new BigDecimal(Integer.valueOf(String.valueOf(onlineUserCouponDisSum))).divide(
+                            new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
+
+    sb.append("线下累计派券金额:").append(
+                    new BigDecimal(Integer.valueOf(String.valueOf(offlineAllUserCouponDisSum))).divide(
+                            new BigDecimal(100), 2, RoundingMode.DOWN))
+            .append("元,当日:").append(
+                    new BigDecimal(Integer.valueOf(String.valueOf(offlineUserCouponDisSum))).divide(
+                            new BigDecimal(100), 2, RoundingMode.DOWN)).append("元\n");
+
+
     int exCnt = userExchangeOrderService.count(new LambdaQueryWrapper<UserExchangeOrder>()
         .ge(UserExchangeOrder::getCreatedTime, bizDay)
         .lt(UserExchangeOrder::getCreatedTime, DateUtils.addDays(bizDay, 1)));
@@ -319,7 +418,25 @@ public class DayStatTask {
     }
     sb.append("===================\n");
     sb.append(sbDetail);
-    LogUtil.info(logger, "通知发送结果:" + WebhookService.sendBizData(sb.toString()));
+
+    // 分割,超过15条则分批发送
+    String data = sb.toString();
+    String[] dataArray = data.split("------------------------");
+    if (dataArray.length >= 15) {
+      int count = 0;
+      StringBuilder body = new StringBuilder();
+      for (int i = 0; i < dataArray.length; i++) {
+        count++;
+        body.append(dataArray[i]).append("------------------------");
+        if (count >= 15 || i >= dataArray.length - 1) {
+          LogUtil.info(logger, "通知发送结果:" + WebhookService.sendBizData(body.toString()));
+          body.delete(0, body.length());
+          count = 0;
+        }
+      }
+    } else {
+      LogUtil.info(logger, "通知发送结果:" + WebhookService.sendBizData(data));
+    }
     LogUtil.info(logger, sb.toString());
     LogUtil.info(logger, "...日统计任务结束..." );
   }

+ 1 - 0
mp-quartz/src/main/java/com/qs/mp/quartz/task/OperateToolTask.java

@@ -3,6 +3,7 @@ package com.qs.mp.quartz.task;
 import com.qs.mp.common.enums.MqTopicType;
 import com.qs.mp.common.pulsar.PulsarClientService;
 import com.qs.mp.common.utils.LogUtil;
+import com.qs.mp.framework.service.IAsyncTaskService;
 import com.qs.mp.pay.service.IWalletService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

+ 0 - 8
mp-service/src/main/java/com/qs/mp/admin/domain/TicketBox.java

@@ -240,13 +240,5 @@ public class TicketBox implements Serializable {
     return 0;
   }
 
-  @ApiModelProperty("分佣金额")
-  public BigDecimal saleCommPrice() {
-    if (Objects.isNull(this.saleCommRate) || Objects.isNull(this.salePrice)) {
-      return BigDecimal.ZERO;
-    }
-
-    return this.saleCommRate.multiply(new BigDecimal(this.salePrice)).divide(new BigDecimal(100),2, RoundingMode.HALF_UP);
-  }
 
 }

+ 4 - 0
mp-service/src/main/java/com/qs/mp/admin/domain/excel/ChannelExcel.java

@@ -8,6 +8,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 /**
  * 经销商导出
@@ -30,6 +31,9 @@ public class ChannelExcel {
     @Excel(name = "经销商佣金比例(%)")
     private BigDecimal commRate;
 
+    @Excel(name = "注册时间")
+    private Date createdTime;
+
     @Excel(name = "上级渠道")
     String parentsName;
 

+ 51 - 0
mp-service/src/main/java/com/qs/mp/admin/domain/excel/ChannelWithdrawExcel.java

@@ -0,0 +1,51 @@
+package com.qs.mp.admin.domain.excel;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.qs.mp.common.annotation.Excel;
+import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 提现记录导出
+ * @author Cup
+ * @date 2022/6/13
+ */
+@ApiModel(value = "提现记录导出")
+@Data
+public class ChannelWithdrawExcel {
+
+    @Excel(name = "申请时间")
+    private Date createTime;
+
+    @Excel(name = "处理时间")
+    private Date transferTime;
+
+    @Excel(name = "渠道名称")
+    private String name;
+
+
+    @Excel(name = "渠道手机号码")
+    private String mobile;
+
+    /**
+     * 渠道级别,0:经销商;1:一级渠道;2:二级渠道
+     */
+    @Excel(name = "渠道类型")
+    private String level;
+
+
+    @Excel(name = "提现金额")
+    private BigDecimal money;
+
+
+    @Excel(name = "提现状态")
+    private String status;
+
+}

+ 4 - 1
mp-service/src/main/java/com/qs/mp/admin/domain/excel/UserTicketOrderItemExcel.java

@@ -29,6 +29,9 @@ public class UserTicketOrderItemExcel {
     @Excel(name = "盲票类型")
     private String ticketType;
 
+    @Excel(name = "是否为预付票")
+    private String isPre;
+
     @Excel(name = "盲票售价(元)")
     private BigDecimal salePrice;
 
@@ -54,7 +57,7 @@ public class UserTicketOrderItemExcel {
     private Date createdTime;
 
     @Excel(name = "用户昵称")
-    private String userName;
+    private String nickName;
 
     @Excel(name = "用户手机号")
     private String userPhone;

+ 30 - 0
mp-service/src/main/java/com/qs/mp/admin/domain/param/ChannelWithdrawQueryParam.java

@@ -0,0 +1,30 @@
+package com.qs.mp.admin.domain.param;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author Cup
+ * @date 2022/6/13
+ */
+@ApiModel(value = "提现记录查询入参类")
+@Data
+public class ChannelWithdrawQueryParam {
+
+    @ApiModelProperty("提现状态 1申请,2审核通过,3审核拒绝")
+    private Integer status;
+
+    @ApiModelProperty("渠道/经销商名称")
+    private String name;
+
+    @ApiModelProperty("开始时间")
+    private Date startDay;
+
+    @ApiModelProperty("结束时间")
+    private Date endDay;
+
+
+}

+ 6 - 0
mp-service/src/main/java/com/qs/mp/admin/domain/param/TicketBoxParam.java

@@ -27,4 +27,10 @@ public class TicketBoxParam {
 	@ApiModelProperty(value = "盲票类型",required=true)
 	private TicketTypeEnum type;
 
+	@ApiModelProperty("销量排序,1正序,2倒序")
+	private Integer saleQtySort;
+
+	@ApiModelProperty("价格排序,1正序,2倒序")
+	private Integer salePriceSort;
+
 }

+ 10 - 5
mp-service/src/main/java/com/qs/mp/admin/domain/vo/TicketBoxListVO.java

@@ -86,6 +86,9 @@ public class TicketBoxListVO {
   @ApiModelProperty("盲票票面价格")
   private Integer facePrice;
 
+  @ApiModelProperty("盲票原价")
+  private Integer originPrice;
+
   /**
    * 盲票销售价格
    */
@@ -116,12 +119,14 @@ public class TicketBoxListVO {
   @ApiModelProperty("上架时间")
   private Date onTime;
 
+  @ApiModelProperty("经销商分佣百分比")
+  private BigDecimal channelCommRate;
+
   @ApiModelProperty("分佣金额")
-  public BigDecimal saleCommPrice() {
-    if (Objects.isNull(this.saleCommRate) || Objects.isNull(this.salePrice)) {
-      return BigDecimal.ZERO;
+  public Integer getSaleCommPrice() {
+    if (Objects.isNull(this.saleCommRate) || Objects.isNull(this.salePrice) || Objects.isNull(this.channelCommRate)) {
+      return 0;
     }
-
-    return this.saleCommRate.multiply(new BigDecimal(this.salePrice)).divide(new BigDecimal(100),2, RoundingMode.HALF_UP);
+    return BigDecimal.valueOf(this.salePrice).multiply(this.saleCommRate).multiply(this.channelCommRate).divide(BigDecimal.valueOf(10000), 0).intValue();
   }
 }

+ 16 - 0
mp-service/src/main/java/com/qs/mp/admin/domain/vo/TicketBoxVO.java

@@ -1,7 +1,11 @@
 package com.qs.mp.admin.domain.vo;
 
 import com.qs.mp.admin.domain.TicketBox;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.List;
+import java.util.Objects;
 
 import com.qs.mp.channel.domain.Channel;
 import com.qs.mp.channel.domain.vo.ChannelVO;
@@ -32,4 +36,16 @@ public class TicketBoxVO extends TicketBox {
   // 奖级列表(后台显示)
   @ApiModelProperty("奖级列表(后台显示)")
   List<TicketAwardsVO> awardsList;
+
+  @ApiModelProperty("经销商分佣百分比")
+  private BigDecimal channelCommRate;
+
+  @ApiModelProperty("分佣金额")
+  public Integer getSaleCommPrice() {
+    if (Objects.isNull(super.getSaleCommRate()) || Objects.isNull(super.getSalePrice()) || Objects.isNull(this.channelCommRate)) {
+      return 0;
+    }
+    return BigDecimal.valueOf(super.getSalePrice()).multiply(super.getSaleCommRate()).multiply(this.channelCommRate).divide(BigDecimal.valueOf(10000), 0).intValue();
+
+  }
 }

+ 4 - 1
mp-service/src/main/java/com/qs/mp/admin/domain/vo/UserTicketOrderItemVO.java

@@ -29,6 +29,9 @@ public class UserTicketOrderItemVO {
     @ApiModelProperty("盲票类型")
     private TicketTypeEnum ticketType;
 
+    @ApiModelProperty("是否预付票,0否,1是")
+    private Integer isPre;
+
     @ApiModelProperty("盲票售价")
     private Integer salePrice;
 
@@ -60,7 +63,7 @@ public class UserTicketOrderItemVO {
     private Date createdTime;
 
     @ApiModelProperty("用户昵称")
-    private String userName;
+    private String nickName;
 
     @ApiModelProperty("用户手机号")
     private String userPhone;

+ 68 - 22
mp-service/src/main/java/com/qs/mp/admin/service/impl/TicketBoxServiceImpl.java

@@ -23,6 +23,7 @@ import com.qs.mp.common.pulsar.PulsarClientService;
 import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.common.utils.RSAUtil;
 import com.qs.mp.common.utils.StringUtils;
+import com.qs.mp.framework.service.IAsyncTaskService;
 import com.qs.mp.system.service.id.BizIdGenerator;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -90,12 +91,53 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
   @Autowired
   private IChannelService channelService;
 
+  @Autowired
+  private IAsyncTaskService asyncTaskService;
+
 
   @Override
   public List<TicketBox> listBySaleChannel(QueryWrapper<TicketBox> queryWrapper) {
     return getBaseMapper().listBySaleChannel(queryWrapper);
   }
 
+  public static void main(String[] args) {
+
+    String  test = "1";
+    String[] split = test.split("\\.");
+    for (String s : split) {
+      System.out.println("s = " + s);
+    }
+
+
+    List<String> channelNoList = new ArrayList<>();
+    channelNoList.add("1");
+    channelNoList.add("25.1.31");
+    channelNoList.add("47");
+    for (int i = 0; i < channelNoList.size(); i++) {
+      for (int j = 0; j < channelNoList.size(); j++) {
+        if (i == j) {
+          continue;
+        }
+
+        String[] a = channelNoList.get(i).split("\\.");
+        String[] b = channelNoList.get(j).split("\\.");
+
+        for (String s : a) {
+          for (String s1 : b) {
+            if (s.equals(s1)) {
+              System.out.println("i = " + channelNoList.get(i));
+              System.out.println("j = " + channelNoList.get(j));
+              System.out.println("重复了");
+            }
+          }
+        }
+
+
+      }
+    }
+  }
+
+
   @Override
   @Transactional(rollbackFor = Exception.class)
   public boolean updateTicketBox(TicketBoxUpdateParam param) {
@@ -139,8 +181,14 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
           if (i == j) {
             continue;
           }
-          if (channelNoList.get(i).contains(channelNoList.get(j))) {
-            throw new ServiceException("已选择更高级的渠道,不支持渠道相互嵌套!");
+          String[] splitOne = channelNoList.get(i).split("\\.");
+          String[] splitTwo = channelNoList.get(j).split("\\.");
+          for (String one : splitOne) {
+            for (String two : splitTwo) {
+              if (one.equals(two)) {
+                throw new ServiceException("已选择更高级的渠道,不支持渠道相互嵌套!");
+              }
+            }
           }
         }
       }
@@ -331,8 +379,14 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
           if (i == j) {
             continue;
           }
-          if (channelNoList.get(i).contains(channelNoList.get(j))) {
-            throw new ServiceException("已选择更高级的渠道,不支持渠道相互嵌套!");
+          String[] splitOne = channelNoList.get(i).split("\\.");
+          String[] splitTwo = channelNoList.get(j).split("\\.");
+          for (String one : splitOne) {
+            for (String two : splitTwo) {
+              if (one.equals(two)) {
+                throw new ServiceException("已选择更高级的渠道,不支持渠道相互嵌套!");
+              }
+            }
           }
         }
       }
@@ -401,11 +455,17 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
     }
     ticketAwardsService.saveBatch(ticketAwardsList);
     ticketAwardsPrizeService.saveBatch(awardsPrizeList);
+
+    if (StringUtils.isNotBlank(ticketBox.getBoxId())) {
+      // 插入盲票生成异步任务
+      Assert.isTrue(asyncTaskService.insertAsyncTask(AsyncTaskTypeEnum.TICKET_GENERATE, ticketBox.getBoxId()),"盲票组保存,创建异步任务失败. boxId:" +  ticketBox.getBoxId());
+    }
+
     return ticketBox.getBoxId();
   }
 
   @Override
-  @Transactional
+  @Transactional(rollbackFor = Exception.class)
   public void removeTicketBox(String boxId) {
     removeById(boxId);
     ticketPackageService.remove(new LambdaQueryWrapper<TicketPackage>().eq(TicketPackage::getBoxId, boxId));
@@ -415,10 +475,10 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
   }
 
   @Override
-  @Transactional
+  @Transactional(rollbackFor = Exception.class)
   public void generateTicket(String boxId) {
     TicketBox ticketBox = getById(boxId);
-    Assert.isTrue(ticketBox.getStatus() == TicketBoxStatusEnum.DOING,
+    Assert.isTrue(ticketBox.getStatus() == TicketBoxStatusEnum.WAIT,
         "盲票生成时,票组状态不是出票中,boxId=" + boxId);
     List<TicketAwards> ticketAwardsList = ticketAwardsService.list(
         new LambdaQueryWrapper<TicketAwards>()
@@ -497,7 +557,7 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
     ticketPackageService.saveBatch(ticketPackageList);
 
     boolean rst = update(new LambdaUpdateWrapper<TicketBox>().set(TicketBox::getStatus, TicketBoxStatusEnum.DONE)
-        .eq(TicketBox::getBoxId, boxId).eq(TicketBox::getStatus, TicketBoxStatusEnum.DOING));
+        .eq(TicketBox::getBoxId, boxId).eq(TicketBox::getStatus, TicketBoxStatusEnum.WAIT));
     Assert.isTrue(rst, "盲票生成完,更新盲票组状态失败。boxId:{0}" + ticketBox.getBoxId());
   }
 
@@ -653,18 +713,4 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
       this.quantity = quantity;
     }
   }
-
-  public static void main(String[] args) {
-    List<PkgAwards> prizes = new ArrayList<>();
-    prizes.add(new PkgAwards("1", "一等奖", 1, 1));
-    prizes.add(new PkgAwards("2", "二等奖", 2, 2));
-    prizes.add(new PkgAwards("3", "三等奖", 3, 3));
-    prizes.add(new PkgAwards("4", "四等奖", 4, 4));
-    TicketBoxServiceImpl boxService = new TicketBoxServiceImpl();
-    System.out.println(boxService.getRandomList(new ArrayList<>(), 10, 10));
-    /*for (int i = 0 ; i < 10; i ++ ) {
-      int random = boxService.getPrizeIndex(prizes);
-      System.out.println(random);
-    }*/
-  }
 }

+ 21 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/ChannelWithdraw.java

@@ -9,6 +9,9 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
 import java.io.Serializable;
 import java.util.Date;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 /**
@@ -18,70 +21,82 @@ import lombok.Data;
  */
 @TableName("mp_channel_withdraw")
 @Data
+@ApiModel("渠道提现表实体类")
 public class ChannelWithdraw implements Serializable {
 
   private static final long serialVersionUID = 1L;
 
   @TableId(value = "id" , type = IdType.AUTO)
+  @ApiModelProperty("id")
   private Long id;
 
   /**
    * 渠道id
    */
+  @ApiModelProperty("渠道ID")
   @TableField("channel_id")
   private Long channelId;
 
   /**
    * 提现金额
    */
+  @ApiModelProperty("提现金额")
   @TableField("money")
   private Integer money;
 
   /**
    * 手续费
    */
+  @ApiModelProperty("手续费")
   @TableField("charge_amt")
   private Integer chargeAmt;
 
   /**
    * 当前可用资金
    */
+  @ApiModelProperty("当前可用资金")
   @TableField("available_money")
   private Integer availableMoney;
 
   /**
    * 支付类型 1支付宝,2微信,3银行卡
    */
+  @ApiModelProperty("支付类型 1支付宝,2微信,3银行卡")
   @TableField("pay_type")
   private String payType;
 
   /**
    * 持卡人
    */
+  @ApiModelProperty("持卡人")
   @TableField("user_name")
   private String userName;
 
   /**
    * 卡号
    */
+  @ApiModelProperty("卡号")
   @TableField("card_no")
   private String cardNo;
 
   /**
    * 银行卡所属银行
    */
+  @ApiModelProperty("银行卡所属银行")
   @TableField("bank_name")
   private String bankName;
 
   /**
    * 开户行
    */
+  @ApiModelProperty("开户行")
   @TableField("branch_name")
   private String branchName;
 
   /**
    * 提现状态 1申请,2审核通过,3审核拒绝
    */
+  @ApiModelProperty("提现状态 1申请,2审核通过,3审核拒绝")
   @TableField("status")
   @JSONField(serialzeFeatures = SerializerFeature.WriteEnumUsingToString)
   private ChannelWithdrawStatusEnum status;
@@ -89,36 +104,42 @@ public class ChannelWithdraw implements Serializable {
   /**
    * 转账凭证
    */
+  @ApiModelProperty("转装凭证")
   @TableField("transfer_img")
   private String transferImg;
 
   /**
    * 转账时间
    */
+  @ApiModelProperty("转账时间")
   @TableField("transfer_time")
   private Date transferTime;
 
   /**
    * 审核内容备注
    */
+  @ApiModelProperty("审核内容备注")
   @TableField("verify_content")
   private String verifyContent;
 
   /**
    * 审核人用户名
    */
+  @ApiModelProperty("审核人用户名")
   @TableField("verifier")
   private String verifier;
 
   /**
    * 创建时间
    */
+  @ApiModelProperty("创建时间")
   @TableField("create_time")
   private Date createTime;
 
   /**
    * 修改时间
    */
+  @ApiModelProperty("修改时间")
   @TableField("update_time")
   private Date updateTime;
 

+ 6 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/vo/ChannelWithdrawVO.java

@@ -2,26 +2,32 @@ package com.qs.mp.channel.domain.vo;
 
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.qs.mp.channel.domain.ChannelWithdraw;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 /**
  * @author zhongcp
  * @Date 2022/3/21
  */
+@ApiModel("提现记录相关出参类")
 @Data
 public class ChannelWithdrawVO extends ChannelWithdraw {
   /**
    * 渠道名称
    */
+  @ApiModelProperty("渠道名称")
   private String name;
 
   /**
    * 渠道级别,0:经销商;1:一级渠道;2:二级渠道
    */
+  @ApiModelProperty("渠道级别,0:经销商;1:一级渠道;2:二级渠道")
   private Integer level;
 
   /**
    * 手机号
    */
+  @ApiModelProperty("手机号")
   private String mobile;
 }

+ 9 - 0
mp-service/src/main/java/com/qs/mp/channel/mapper/ChannelCouponVerifyLogMapper.java

@@ -1,7 +1,10 @@
 package com.qs.mp.channel.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.qs.mp.channel.domain.ChannelCouponVerifyLog;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * @auther quanshu
@@ -10,4 +13,10 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface ChannelCouponVerifyLogMapper extends BaseMapper<ChannelCouponVerifyLog> {
 
+    /**
+     * 根据条件统计优惠券核销金额
+     * @param queryWrapper
+     * @return
+     */
+    Integer sumDisCountByQueryWrapper(@Param(Constants.WRAPPER) QueryWrapper<ChannelCouponVerifyLog> queryWrapper);
 }

+ 9 - 0
mp-service/src/main/java/com/qs/mp/channel/service/IChannelCouponVerifyLogService.java

@@ -1,5 +1,6 @@
 package com.qs.mp.channel.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.qs.mp.channel.domain.ChannelCouponVerifyLog;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qs.mp.user.domain.UserCoupon;
@@ -20,4 +21,12 @@ public interface IChannelCouponVerifyLogService extends IService<ChannelCouponVe
    * @param userCoupon
    */
   void verify(Long channelId, UserCoupon userCoupon);
+
+  /**
+   * 根据条件统计优惠券核销金额
+   * @param queryWrapper
+   * @return
+   */
+  Integer sumDisCountByQueryWrapper(QueryWrapper<ChannelCouponVerifyLog> queryWrapper);
+
 }

+ 6 - 1
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelCouponVerifyLogServiceImpl.java

@@ -1,5 +1,6 @@
 package com.qs.mp.channel.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.qs.mp.admin.domain.Coupon;
 import com.qs.mp.admin.service.ICouponService;
@@ -48,7 +49,7 @@ public class ChannelCouponVerifyLogServiceImpl extends ServiceImpl<ChannelCoupon
   private IChannelMoneyLogService channelMoneyLogService;
 
   @Override
-  @Transactional
+  @Transactional(rollbackFor = Exception.class)
   public void verify(Long channelId, UserCoupon userCoupon) {
     Date verifyDate = new Date();
     // 核销券
@@ -95,4 +96,8 @@ public class ChannelCouponVerifyLogServiceImpl extends ServiceImpl<ChannelCoupon
     }
   }
 
+  @Override
+  public Integer sumDisCountByQueryWrapper(QueryWrapper<ChannelCouponVerifyLog> queryWrapper) {
+    return getBaseMapper().sumDisCountByQueryWrapper(queryWrapper);
+  }
 }

+ 1 - 0
mp-service/src/main/java/com/qs/mp/framework/redis/RedisLockKey.java

@@ -9,6 +9,7 @@ import com.qs.mp.common.utils.MessageHelper;
  *
  */
 public enum RedisLockKey {
+    CREATED_ONLINE_TICKET_ORDER_KEY("created_online_ticket_order_key_{0}", "线上盲票创建锁"),
     ASYNC_TASK_KEY("async_task_key_{0}", "异步任务key"),
     MARKETING_REAL_NUM_LOCK("marketing_real_num_lock_{0}", "活动真实人数增加锁"),
     MARKETING_LOTTERY_KEY("marketing_lottery_key_{0}","免费抽奖活动开奖"),

+ 21 - 0
mp-service/src/main/java/com/qs/mp/framework/service/IAsyncTaskService.java

@@ -1,5 +1,6 @@
 package com.qs.mp.framework.service;
 
+import com.qs.mp.common.enums.AsyncTaskTypeEnum;
 import com.qs.mp.framework.domain.AsyncTask;
 import com.baomidou.mybatisplus.extension.service.IService;
 
@@ -13,9 +14,29 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface IAsyncTaskService extends IService<AsyncTask> {
 
+    /**
+     * 插入异步任务
+     * @param taskType
+     * @param bizId
+     * @return
+     */
+    boolean insertAsyncTask(AsyncTaskTypeEnum taskType, String bizId);
+
     /**
      * 经销商确认收货后相关任务处理
      * @param asyncTask
      */
     void channelConfirmReceipt(AsyncTask asyncTask);
+
+    /**
+     * 盲票支付相关任务处理
+     * @param asyncTask
+     */
+    void ticketPay(AsyncTask asyncTask);
+
+    /**
+     * 盲票生成相关任务处理
+     * @param asyncTask
+     */
+    void ticketGenerate(AsyncTask asyncTask);
 }

+ 98 - 2
mp-service/src/main/java/com/qs/mp/framework/service/impl/AsyncTaskServiceImpl.java

@@ -1,21 +1,34 @@
 package com.qs.mp.framework.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.qs.mp.admin.domain.Ticket;
+import com.qs.mp.admin.domain.TicketBox;
+import com.qs.mp.admin.domain.TicketPackage;
+import com.qs.mp.admin.service.ITicketBoxService;
+import com.qs.mp.admin.service.ITicketPackageService;
+import com.qs.mp.admin.service.ITicketService;
 import com.qs.mp.channel.domain.ChannelOrder;
 import com.qs.mp.channel.service.IChannelOrderService;
 import com.qs.mp.channel.service.IChannelUserRelService;
-import com.qs.mp.common.enums.ChannelCommissionResourceEnum;
-import com.qs.mp.common.enums.ChannelOrderTypeEnum;
+import com.qs.mp.common.enums.*;
 import com.qs.mp.common.exception.ServiceException;
+import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.framework.domain.AsyncTask;
 import com.qs.mp.framework.mapper.AsyncTaskMapper;
 import com.qs.mp.framework.service.IAsyncTaskService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qs.mp.user.domain.UserTicketOrder;
+import com.qs.mp.user.domain.UserTicketOrderItem;
+import com.qs.mp.user.service.IUserTicketOrderItemService;
 import com.qs.mp.user.service.IUserTicketOrderService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -29,12 +42,41 @@ import java.util.Objects;
 @Service
 public class AsyncTaskServiceImpl extends ServiceImpl<AsyncTaskMapper, AsyncTask> implements IAsyncTaskService {
 
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+
     @Autowired
     private IChannelOrderService channelOrderService;
 
     @Autowired
     private IUserTicketOrderService userTicketService;;
 
+    @Autowired
+    private IUserTicketOrderService userTicketOrderService;
+
+    @Autowired
+    private ITicketBoxService ticketBoxService;
+
+    @Autowired
+    private IUserTicketOrderItemService userTicketOrderItemService;
+
+    @Autowired
+    private ITicketService ticketService;
+
+    @Autowired
+    private ITicketPackageService ticketPackageService;
+
+    @Autowired
+    private IChannelUserRelService channelUserRelService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean insertAsyncTask(AsyncTaskTypeEnum taskType, String bizId) {
+        AsyncTask asyncTask = new AsyncTask();
+        asyncTask.setType(taskType.getValue());
+        asyncTask.setBizId(bizId);
+        return this.save(asyncTask);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void channelConfirmReceipt(AsyncTask asyncTask) {
@@ -54,4 +96,58 @@ public class AsyncTaskServiceImpl extends ServiceImpl<AsyncTaskMapper, AsyncTask
         // 分佣
         userTicketService.commToChannel(orderId, ChannelCommissionResourceEnum.CHANNEL.getValue());
     }
+
+    @Override
+    public void ticketPay(AsyncTask asyncTask) {
+        String orderId = asyncTask.getBizId();
+        UserTicketOrder ticketOrder = userTicketOrderService.getById(orderId);
+
+        TicketBox ticketBox = ticketBoxService.getById(ticketOrder.getBoxId());
+        if (ticketBox.getType() == TicketTypeEnum.OFFLINE) {
+            // 线下票更新销量,此处不做乐观锁控制,因为不用控制库存
+            ticketBoxService.update(
+                    new LambdaUpdateWrapper<TicketBox>().set(TicketBox::getSaleQty,
+                                    ticketBox.getSaleQty() + 1)
+                            .eq(TicketBox::getBoxId, ticketBox.getBoxId()));
+        }
+
+
+        // 更新票组销售数量,此处只做累计,允许并发容错
+        List<UserTicketOrderItem> ticketOrderItemList = userTicketOrderItemService.list(new LambdaQueryWrapper<UserTicketOrderItem>()
+                .eq(UserTicketOrderItem::getOrderId, orderId));
+        for (UserTicketOrderItem orderItem : ticketOrderItemList) {
+            Ticket ticket = ticketService.getById(orderItem.getTicketId());
+            TicketPackage ticketPackage = ticketPackageService.getById(ticket.getPkgId());
+            ticketPackageService.update(new LambdaUpdateWrapper<TicketPackage>()
+                    .set(TicketPkgSaleStatusEnum.WAIT_SALE == ticketPackage.getSaleStatus(),
+                            TicketPackage::getSaleStatus, TicketPkgSaleStatusEnum.ON_SALE)
+                    .set(TicketPkgSaleStatusEnum.ON_SALE == ticketPackage.getSaleStatus()
+                                    && ticketPackage.getSaleQty() + 1 >= ticketPackage.getPkgUnit(),
+                            TicketPackage::getSaleStatus, TicketPkgSaleStatusEnum.SALE_OUT)
+                    .set(TicketPackage::getSaleQty, ticketPackage.getSaleQty() + 1)
+                    .eq(TicketPackage::getPkgId, ticketPackage.getPkgId()));
+        }
+
+        // 用户关系绑定
+        channelUserRelService.bindUser(ticketOrder.getUserId(), ticketOrder.getChannelId());
+
+        if (ticketOrder.getCommStatus() != CommStatusEnum.NO) {
+            LogUtil.warn(logger, "收到盲票支付成功任务,订单结佣状态不是未结佣,忽略任务。orderId=" + orderId);
+            return;
+        }
+        userTicketOrderService.commToChannel(orderId, ChannelCommissionResourceEnum.USER.getValue());
+
+    }
+
+
+    @Override
+    public void ticketGenerate(AsyncTask asyncTask) {
+        String boxId = asyncTask.getBizId();
+        TicketBox ticketBox = ticketBoxService.getById(boxId);
+        if (ticketBox.getStatus() != TicketBoxStatusEnum.WAIT ) {
+            LogUtil.error(logger, "收到盲票生成任务,票组状态不是待出票,忽略任务。boxId=" + boxId);
+            return;
+        }
+        ticketBoxService.generateTicket(boxId);
+    }
 }

+ 3 - 0
mp-service/src/main/java/com/qs/mp/open/domain/param/SchemeParam.java

@@ -23,4 +23,7 @@ public class SchemeParam {
     @NotBlank(message = "用户唯一标识不能为空")
     @ApiModelProperty("用户唯一标识")
     private String uid;
+
+    @ApiModelProperty("盲票组id")
+    private String boxId;
 }

+ 7 - 8
mp-service/src/main/java/com/qs/mp/pay/service/impl/WalletServiceImpl.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.qs.mp.channel.service.IChannelOrderService;
+import com.qs.mp.common.enums.AsyncTaskTypeEnum;
 import com.qs.mp.common.enums.BizTypeEnum;
 import com.qs.mp.common.enums.MqTopicType;
 import com.qs.mp.common.enums.PayOrderStatusEnum;
@@ -13,6 +14,8 @@ import com.qs.mp.common.utils.DateUtils;
 import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.common.utils.StringUtils;
 import com.qs.mp.common.utils.http.OkHttpUtil;
+import com.qs.mp.framework.domain.AsyncTask;
+import com.qs.mp.framework.service.IAsyncTaskService;
 import com.qs.mp.pay.domain.PayOrder;
 import com.qs.mp.pay.service.IPayOrderService;
 import com.qs.mp.pay.service.IWalletService;
@@ -56,6 +59,9 @@ public class WalletServiceImpl implements IWalletService {
   @Autowired
   private BizIdGenerator bizIdGenerator;
 
+  @Autowired
+  private IAsyncTaskService asyncTaskService;
+
   @Value("${pay.notifyUrl}")
   private String notifyUrl;  //支付成功前端跳转地址
   @Value("${pay.callbackUrl}")
@@ -186,14 +192,7 @@ public class WalletServiceImpl implements IWalletService {
       channelOrderService.paySuccess(order);
     } else if (BizTypeEnum.TICKET_ORDER == order.getBizType()) {
       // 用户盲票购买订单支付成功,调用业务订单服务处理
-      boolean rst = userTicketOrderService.paySuccess(order);
-      try {
-        if (rst) {
-          pulsarClientService.producer(MqTopicType.ticket_pay, order.getBizId());
-        }
-      } catch (PulsarClientException e) {
-        LogUtil.error(logger, e, "盲票支付成功,发送异步消息失败. orderId:{0}", order.getBizId());
-      }
+      userTicketOrderService.paySuccess(order);
     } else if (BizTypeEnum.DELIVER_ORDER == order.getBizType()) {
       // 用户提货订单支付成功,调用业务订单服务处理
       userDeliverOrderService.paySuccess(order);

+ 8 - 0
mp-service/src/main/java/com/qs/mp/system/mapper/SysUserMapper.java

@@ -152,4 +152,12 @@ public interface SysUserMapper  extends BaseMapper<SysUser>
      * @return
      */
     List<SysUser> selectUserListByRand(@Param("userType") String userType,@Param("num") int num);
+
+    /**
+     * 根据手机号获取用户信息
+     * @param phone
+     * @return
+     */
+    SysUser selectUserByPhoneNumber(@Param("phone") String phone);
+
 }

+ 7 - 0
mp-service/src/main/java/com/qs/mp/system/service/ISysUserService.java

@@ -229,4 +229,11 @@ public interface ISysUserService  extends IService<SysUser>
      * @return
      */
     List<SysUser> selectUserListByRand(String userType, int num);
+
+    /**
+     * 根据手机号查询用户信息
+     * @param phone
+     * @return
+     */
+    SysUser selectUserByPhoneNumber(String phone);
 }

+ 5 - 0
mp-service/src/main/java/com/qs/mp/system/service/impl/SysUserServiceImpl.java

@@ -577,4 +577,9 @@ public class SysUserServiceImpl  extends ServiceImpl<SysUserMapper, SysUser> imp
     public List<SysUser> selectUserListByRand(String userType, int num) {
         return userMapper.selectUserListByRand(userType, num);
     }
+
+    @Override
+    public SysUser selectUserByPhoneNumber(String phone) {
+        return userMapper.selectUserByPhoneNumber(phone);
+    }
 }

+ 5 - 1
mp-service/src/main/java/com/qs/mp/user/domain/excel/DeliverOrderExcel.java

@@ -3,6 +3,7 @@ package com.qs.mp.user.domain.excel;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.qs.mp.common.annotation.Excel;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 import io.swagger.annotations.ApiModelProperty;
@@ -15,6 +16,9 @@ import lombok.Data;
 @Data
 public class DeliverOrderExcel {
 
+    @Excel(name = "订单明细编号")
+    private String itemId;
+
     @Excel(name = "商品ID")
     private Long goodsId;
 
@@ -43,7 +47,7 @@ public class DeliverOrderExcel {
     private Integer goodsNum;
 
     @Excel(name = "商品成本")
-    private Integer goodsCost;
+    private BigDecimal goodsCost;
 
     @Excel(name = "供应商名称")
     private String supplierName;

+ 8 - 0
mp-service/src/main/java/com/qs/mp/user/mapper/UserCouponMapper.java

@@ -1,6 +1,7 @@
 package com.qs.mp.user.mapper;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.qs.mp.admin.domain.TicketAwardsPrize;
 import com.qs.mp.admin.domain.vo.TicketAwardsPrizeVO;
@@ -18,4 +19,11 @@ import org.apache.ibatis.annotations.Param;
 public interface UserCouponMapper extends BaseMapper<UserCoupon> {
 
   List<UserCouponVO> listUserCouponVO(@Param(Constants.WRAPPER) Wrapper<UserCoupon> queryWrapper);
+
+  /**
+   * 根据条件统计派发优惠券金额
+   * @param queryWrapper
+   * @return
+   */
+  Integer sumDiscountByQueryWrapper(@Param(Constants.WRAPPER) QueryWrapper<UserCoupon> queryWrapper);
 }

+ 8 - 0
mp-service/src/main/java/com/qs/mp/user/service/IUserCouponService.java

@@ -1,6 +1,7 @@
 package com.qs.mp.user.service;
 
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.qs.mp.admin.domain.TicketBox;
 import com.qs.mp.common.enums.UserCouponStatusEnum;
@@ -49,4 +50,11 @@ public interface IUserCouponService extends IService<UserCoupon> {
    * @return
    */
   List<UserCouponVO> queryUserCouponList(Long userId, Integer orderAmt, TicketBox ticketBox);
+
+  /**
+   * 根据条件统计派发优惠券金额
+   * @param queryWrapper
+   * @return
+   */
+  Integer sumDiscountByQueryWrapper(QueryWrapper<UserCoupon> queryWrapper);
 }

+ 7 - 0
mp-service/src/main/java/com/qs/mp/user/service/IUserDeliverOrderService.java

@@ -7,6 +7,7 @@ import com.qs.mp.user.domain.UserDeliverOrderItem;
 
 import java.util.List;
 
+import com.qs.mp.user.domain.excel.DeliverOrderExcel;
 import com.qs.mp.user.domain.param.UserDeliverOrderCancelParam;
 import org.apache.ibatis.annotations.Param;
 
@@ -93,4 +94,10 @@ public interface IUserDeliverOrderService extends IService<UserDeliverOrder> {
 	 */
     boolean updateShipInfo(UserDeliverOrderShipParam shipParam);
 
+	/**
+	 * 批量导入发货
+	 * @param deliverOrderExcelList
+	 * @return
+	 */
+    String batchShip(List<DeliverOrderExcel> deliverOrderExcelList);
 }

+ 6 - 0
mp-service/src/main/java/com/qs/mp/user/service/impl/UserCouponServiceImpl.java

@@ -115,4 +115,10 @@ public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCou
             .orderByDesc("t2.discount","t1.id"));
     return userCouponVOList;
   }
+
+
+  @Override
+  public Integer sumDiscountByQueryWrapper(QueryWrapper<UserCoupon> queryWrapper) {
+    return getBaseMapper().sumDiscountByQueryWrapper(queryWrapper);
+  }
 }

+ 102 - 0
mp-service/src/main/java/com/qs/mp/user/service/impl/UserDeliverOrderServiceImpl.java

@@ -9,10 +9,13 @@ import com.qs.mp.admin.domain.GoodsSku;
 import com.qs.mp.admin.domain.param.UserDeliverOrderShipParam;
 import com.qs.mp.admin.service.IGoodsService;
 import com.qs.mp.admin.service.IGoodsSkuService;
+import com.qs.mp.common.domain.DeliveryCompany;
 import com.qs.mp.common.enums.*;
 import com.qs.mp.common.exception.ServiceException;
+import com.qs.mp.common.service.IDeliveryCompanyService;
 import com.qs.mp.common.utils.DateUtils;
 import com.qs.mp.common.utils.LogUtil;
+import com.qs.mp.common.utils.StringUtils;
 import com.qs.mp.pay.domain.PayOrder;
 import com.qs.mp.system.service.id.BizIdGenerator;
 import com.qs.mp.user.domain.UserAddr;
@@ -20,6 +23,7 @@ import com.qs.mp.user.domain.UserDeliverOrder;
 import com.qs.mp.user.domain.UserDeliverOrderItem;
 import com.qs.mp.user.domain.UserPrizeStorage;
 import com.qs.mp.user.domain.UserTicketOrder;
+import com.qs.mp.user.domain.excel.DeliverOrderExcel;
 import com.qs.mp.user.domain.param.UserDeliverOrderCancelParam;
 import com.qs.mp.user.domain.vo.DeliverOrderSettleVO;
 import com.qs.mp.user.domain.vo.UserDeliverOrderVO;
@@ -29,6 +33,7 @@ import com.qs.mp.user.service.IUserDeliverOrderService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qs.mp.user.service.IUserPrizeStorageService;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
@@ -71,6 +76,9 @@ public class UserDeliverOrderServiceImpl extends ServiceImpl<UserDeliverOrderMap
   @Autowired
   private IGoodsSkuService goodsSkuService;
 
+  @Autowired
+  private IDeliveryCompanyService deliveryCompanyService;
+
   @Override
   @Transactional
   public String submitOrder(Long userId, String memo, DeliverOrderSettleVO orderSettleVO) {
@@ -290,6 +298,100 @@ public class UserDeliverOrderServiceImpl extends ServiceImpl<UserDeliverOrderMap
 		return false;
 	}
 
+    @Override
+    public String batchShip(List<DeliverOrderExcel> deliverOrderExcelList) {
+        // 成功数量
+        int successNum = 0;
+        // 失败数量
+        int failNum = 0;
+        // 失败原因
+        StringBuilder failSb = new StringBuilder();
+        StringBuilder sb = new StringBuilder();
+        for (DeliverOrderExcel deliverOrderExcel : deliverOrderExcelList) {
+            String failContent = "";
+            boolean flag = true;
+
+
+            DeliveryCompany deliveryCompany = deliveryCompanyService.getOne(new LambdaQueryWrapper<DeliveryCompany>().eq(DeliveryCompany::getCompanyName, deliverOrderExcel.getCompanyName()));
+            if (Objects.isNull(deliveryCompany)) {
+                flag = false;
+                failContent = "物流公司不存在";
+            }
+            if (flag) {
+                if (StringUtils.isBlank(deliverOrderExcel.getDeliveryFlowId())) {
+                    flag = false;
+                    failContent = "物流单号不存在";
+                }
+            }
+
+            if (flag) {
+                UserDeliverOrder userDeliverOrder = userDeliverOrderService.getById(deliverOrderExcel.getOrderId());
+                if (Objects.isNull(userDeliverOrder)) {
+                    flag = false;
+                    failContent = "订单不存在";
+                } else {
+                    if (!DeliverOrderStatusEnum.NOT_DELIVER.equals(userDeliverOrder.getStatus()) && !DeliverOrderStatusEnum.PART_DELIVER.equals(userDeliverOrder.getStatus())) {
+                        flag = false;
+                        failContent = "订单状态不为待发货和部分发货";
+                    }
+                }
+            }
+
+            if (flag) {
+                // 校验订单信息
+                UserDeliverOrderItem userDeliverOrderItem = userDeliverOrderItemService.getById(deliverOrderExcel.getItemId());
+                if (Objects.isNull(userDeliverOrderItem)) {
+                    flag = false;
+                    failContent = "订单明细ID不存在";
+                } else if (Objects.nonNull(userDeliverOrderItem.getDeliveryTime())) {
+                    flag = false;
+                    failContent = "商品已发货";
+                } else {
+                    List<UserDeliverOrderItem> itemList = new ArrayList<UserDeliverOrderItem>();
+                    // 构建发货参数,进行发货
+                    UserDeliverOrderItem item = new UserDeliverOrderItem();
+                    // 快递发货,设置物流信息
+                    item.setItemId(userDeliverOrderItem.getItemId());
+                    item.setDeliveryId(deliveryCompany.getDeliveryId());
+                    item.setDeliveryFlowId(deliverOrderExcel.getDeliveryFlowId());
+                    item.setDeliveryTime(new Date());
+                    itemList.add(item);
+                    boolean rtn = this.userDeliverOrderShip(userDeliverOrderItem.getOrderId(), itemList);
+                    if (!rtn) {
+                        flag = false;
+                        failContent = "发货失败,请重试";
+                    }
+                }
+            }
+
+            if (!flag) {
+                failNum++;
+                failSb.append("订单编号:")
+                        .append(deliverOrderExcel.getOrderId())
+                        .append("&nbsp;&nbsp;&nbsp;&nbsp;商品ID:")
+                        .append(deliverOrderExcel.getGoodsId())
+                        .append("&nbsp;&nbsp;&nbsp;&nbsp;商品名称:")
+                        .append(deliverOrderExcel.getTitle())
+                        .append("&nbsp;&nbsp;&nbsp;&nbsp;发货失败原因:")
+                        .append(failContent)
+                        .append("<br>");
+            } else {
+                successNum++;
+            }
+        }
+
+        sb.append("<div>发货成功:")
+                .append(successNum)
+                .append("<br>")
+                .append("发货失败:")
+                .append(failNum)
+                .append("<br>")
+                .append(failSb)
+                .append("</div>");
+
+        return sb.toString();
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean updateShipInfo(UserDeliverOrderShipParam shipParam) {

+ 38 - 9
mp-service/src/main/java/com/qs/mp/user/service/impl/UserTicketOrderServiceImpl.java

@@ -19,6 +19,7 @@ import com.qs.mp.admin.service.ITicketService;
 import com.qs.mp.channel.domain.*;
 import com.qs.mp.channel.domain.param.ChannelCommParam;
 import com.qs.mp.channel.service.*;
+import com.qs.mp.common.core.redis.DistributedLocker;
 import com.qs.mp.common.core.redis.RedisCache;
 import com.qs.mp.common.enums.*;
 import com.qs.mp.common.exception.ServiceException;
@@ -27,6 +28,8 @@ import com.qs.mp.common.utils.LogUtil;
 import com.qs.mp.common.utils.RSAUtil;
 import com.qs.mp.common.utils.StringUtils;
 import com.qs.mp.framework.redis.RedisKey;
+import com.qs.mp.framework.redis.RedisLockKey;
+import com.qs.mp.framework.service.IAsyncTaskService;
 import com.qs.mp.pay.domain.PayOrder;
 import com.qs.mp.system.service.id.BizIdGenerator;
 import com.qs.mp.user.domain.UserCoupon;
@@ -48,6 +51,7 @@ import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -110,19 +114,34 @@ public class UserTicketOrderServiceImpl extends
   @Autowired
   private RedisCache redisCache;
 
+  @Autowired
+  private IAsyncTaskService asyncTaskService;
+
+  @Autowired
+  private DistributedLocker distributedLocker;
+
   @Override
-  @Transactional
   public String submitOrder(Long userId, TicketOrderSettleVO orderSettleVO,
       UserShareVO userShareVO) {
+    UserTicketOrderServiceImpl proxy = (UserTicketOrderServiceImpl) AopContext.currentProxy();
     if (StringUtils.isBlank(orderSettleVO.getTicketId())) {
-      return createOnlineOrder(userId, orderSettleVO, userShareVO);
+      String lockKey = RedisLockKey.build(RedisLockKey.CREATED_ONLINE_TICKET_ORDER_KEY, orderSettleVO.getBoxId());
+      if (!distributedLocker.tryLock(lockKey)) {
+        throw new ServiceException("该票太火爆了,请稍后再试!");
+      }
+      try {
+        return proxy.createOnlineOrder(userId, orderSettleVO, userShareVO);
+      } finally {
+        distributedLocker.unlock(lockKey);
+      }
     }
 
     // 线下票不需锁库存,待付款成功后再更新票组销量
-    return createOfflineOrder(userId, orderSettleVO);
+    return proxy.createOfflineOrder(userId, orderSettleVO);
   }
 
-  private String createOnlineOrder(Long userId, TicketOrderSettleVO orderSettleVO,
+  @Transactional(rollbackFor = Exception.class)
+  public String createOnlineOrder(Long userId, TicketOrderSettleVO orderSettleVO,
       UserShareVO userShareVO) {
     // 线上票更新票组销量,防止超卖
     TicketBox ticketBox = ticketBoxService.getById(orderSettleVO.getBoxId());
@@ -212,12 +231,15 @@ public class UserTicketOrderServiceImpl extends
     if (orderSettleVO.getPayAmt() == 0) {
       // 无需支付的,直接置为成功
       processTicketOrder(userTicketOrder);
+      // 插入付款异步任务
+      Assert.isTrue(asyncTaskService.insertAsyncTask(AsyncTaskTypeEnum.TICKET_PAY, userTicketOrder.getOrderId()),"盲票支付,创建异步任务失败:" + userTicketOrder.getOrderId());
     }
 
     return userTicketOrder.getOrderId();
   }
 
-  private String createOfflineOrder(Long userId, TicketOrderSettleVO orderSettleVO) {
+  @Transactional(rollbackFor = Exception.class)
+  public String createOfflineOrder(Long userId, TicketOrderSettleVO orderSettleVO) {
     Ticket ticket = ticketService.getById(orderSettleVO.getTicketId());
     Assert.isTrue(ticket.getStatus() == TicketStatusEnum.NOT_PAY,
         "盲票已付款,ticketId:" + ticket.getTicketId());
@@ -278,6 +300,10 @@ public class UserTicketOrderServiceImpl extends
     if (orderSettleVO.getPayAmt() == 0) {
       // 无需支付的,直接置为成功
       processTicketOrder(ticketOrder);
+
+      // 插入付款异步任务
+      Assert.isTrue(asyncTaskService.insertAsyncTask(AsyncTaskTypeEnum.TICKET_PAY, ticketOrder.getOrderId()),"盲票支付,创建异步任务失败:" + ticketOrder.getOrderId());
+
     }
     return ticketOrder.getOrderId();
   }
@@ -373,7 +399,7 @@ public class UserTicketOrderServiceImpl extends
   }
 
   @Override
-  @Transactional
+  @Transactional(rollbackFor = Exception.class)
   public boolean paySuccess(PayOrder payOrder) {
     UserTicketOrder ticketOrder = getById(payOrder.getBizId());
     if (null == ticketOrder || ticketOrder.getStatus() != UserTicketOrderStatusEnum.NOT_PAY) {
@@ -382,6 +408,9 @@ public class UserTicketOrderServiceImpl extends
       throw new ServiceException("支付回调用户购票订单处理,订单状态异常,不是待支付。orderId:" + payOrder.getBizId());
     }
     ticketOrder.setPayTime(DateUtils.parseDate(payOrder.getCompleteDate()));
+
+    // 插入异步任务
+    Assert.isTrue(asyncTaskService.insertAsyncTask(AsyncTaskTypeEnum.TICKET_PAY, payOrder.getBizId()), "创建支付成功异步任务失败. orderId:" + payOrder.getOrderId());
     return processTicketOrder(ticketOrder);
   }
 
@@ -431,8 +460,8 @@ public class UserTicketOrderServiceImpl extends
     if (ChannelCommissionResourceEnum.USER.getValue().equals(resource)) {
       UserTicketOrder ticketOrder = getById(orderId);
       BeanUtils.copyProperties(ticketOrder, channelCommParam);
-      Assert.isTrue(channelCommParam.getCommStatus() == CommStatusEnum.DOING,
-              "结佣处理,结佣状态异常,不是结佣中。orderId=" + orderId);
+      Assert.isTrue(channelCommParam.getCommStatus() != CommStatusEnum.YES,
+              "结佣处理,结佣状态异常,不是结佣中或未结佣。orderId=" + orderId);
     } else {
       ChannelOrder channelOrder = channelOrderService.getById(orderId);
       ChannelOrderItem channelOrderItem = channelOrderItemService.getOne(new LambdaQueryWrapper<ChannelOrderItem>()
@@ -481,7 +510,7 @@ public class UserTicketOrderServiceImpl extends
               new LambdaUpdateWrapper<UserTicketOrder>().set(UserTicketOrder::getCommStatus,
                               CommStatusEnum.YES)
                       .eq(UserTicketOrder::getOrderId, orderId)
-                      .eq(UserTicketOrder::getCommStatus, CommStatusEnum.DOING));
+                      .in(UserTicketOrder::getCommStatus, CommStatusEnum.DOING, CommStatusEnum.NO));
       Assert.isTrue(rst, "渠道结佣完成,更新订单状态失败。orderId:" + orderId);
     }
     return true;

+ 7 - 0
mp-service/src/main/resources/mapper/channel/ChannelCouponVerifyLogMapper.xml

@@ -25,4 +25,11 @@
         id, channel_id, user_coupon_id, verify_code, title, discount_type, discount, distribute_time, valid_start, valid_end, verify_time, settle_status, created_time, updated_time
     </sql>
 
+    <select id="sumDisCountByQueryWrapper" resultType="java.lang.Integer">
+        select IFNULL(sum(t1.discount) ,0)
+        from mp_channel_coupon_verify_log t1
+        left join mp_user_coupon t2 on t1.user_coupon_id = t2.id
+        left join mp_coupon t3 on t2.coupon_id = t3.coupon_id
+        ${ew.customSqlSegment}
+    </select>
 </mapper>

+ 6 - 0
mp-service/src/main/resources/mapper/system/SysUserMapper.xml

@@ -243,4 +243,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			order by rand()
 			LIMIT #{num};
     </select>
+
+	<select id="selectUserByPhoneNumber" resultMap="SysUserResult">
+		select *
+		from sys_user
+		where phonenumber = #{phone}
+    </select>
 </mapper>

+ 6 - 0
mp-service/src/main/resources/mapper/user/UserCouponMapper.xml

@@ -30,4 +30,10 @@
             ${ew.customSqlSegment}
     </select>
 
+    <select id="sumDiscountByQueryWrapper" resultType="java.lang.Integer">
+        select  IFNULL(sum(t2.discount) ,0)
+        from mp_user_coupon t1
+        left join mp_coupon t2 on t1.coupon_id = t2.coupon_id
+        ${ew.customSqlSegment}
+    </select>
 </mapper>

+ 3 - 1
mp-service/src/main/resources/mapper/user/UserTicketOrderItemMapper.xml

@@ -73,6 +73,7 @@
         select t3.serial_no,
                t1.title ticketTitle,
                t2.resource ticketType,
+                t9.is_pre,
                t2.sale_price ,
                t2.sale_comm_rate,
                t3.status ticketStatus,
@@ -83,7 +84,7 @@
                t1.order_id,
                t2.status orderStatus,
                t2.created_time,
-               t8.user_name,
+               t8.nick_name,
                t8.phonenumber userPhone,
                t7.name channelName
         from mp_user_ticket_order_item t1
@@ -94,6 +95,7 @@
                  left join mp_ticket_awards_prize t6 on t4.prize_id = t6.prize_id
                  left join mp_channel t7 on t2.channel_id = t7.channel_id
                  left join sys_user t8 on t1.user_id = t8.user_id
+                left join mp_ticket_package t9 on t3.pkg_id = t9.pkg_id
         ${ew.customSqlSegment}
     </select>