ソースを参照

Merge branch 'dev' of http://113.31.163.91:7777/quanshu/mp-server.git
into dev

Conflicts:
mp-admin/src/main/resources/application-dev.yml

Liugl 3 年 前
コミット
152908ddb4
28 ファイル変更315 行追加126 行削除
  1. 1 4
      mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/GoodsMgrController.java
  2. 21 1
      mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelMoneyController.java
  3. 23 7
      mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelWithdrawController.java
  4. 1 1
      mp-admin/src/main/resources/application-test.yml
  5. 0 41
      mp-common/src/main/java/com/qs/mp/common/enums/ChannelMoneyBizTypeEnum.java
  6. 54 0
      mp-common/src/main/java/com/qs/mp/common/enums/ChannelWithdrawStatusEnum.java
  7. 58 0
      mp-quartz/src/main/java/com/qs/mp/quartz/task/ChannelCommTask.java
  8. 2 1
      mp-service/src/main/java/com/qs/mp/admin/domain/param/TicketBoxCreateParam.java
  9. 1 1
      mp-service/src/main/java/com/qs/mp/admin/service/impl/CouponServiceImpl.java
  10. 1 1
      mp-service/src/main/java/com/qs/mp/admin/service/impl/TicketBoxServiceImpl.java
  11. 0 7
      mp-service/src/main/java/com/qs/mp/channel/domain/ChannelMoneyLog.java
  12. 7 3
      mp-service/src/main/java/com/qs/mp/channel/domain/ChannelWithdraw.java
  13. 17 0
      mp-service/src/main/java/com/qs/mp/channel/domain/vo/ChannelMoneyLogVO.java
  14. 19 8
      mp-service/src/main/java/com/qs/mp/channel/mapper/ChannelCommissionMapper.java
  15. 25 9
      mp-service/src/main/java/com/qs/mp/channel/service/IChannelCommissionService.java
  16. 50 2
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelCommissionServiceImpl.java
  17. 3 3
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelMoneyLogServiceImpl.java
  18. 4 9
      mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelWithdrawServiceImpl.java
  19. 0 6
      mp-service/src/main/java/com/qs/mp/user/domain/UserCoinLog.java
  20. 2 2
      mp-service/src/main/java/com/qs/mp/user/domain/UserHitPrize.java
  21. 0 2
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserCoinServiceImpl.java
  22. 2 2
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserDeliverOrderServiceImpl.java
  23. 6 2
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserHitPrizeServiceImpl.java
  24. 4 6
      mp-service/src/main/java/com/qs/mp/user/service/impl/UserTicketOrderServiceImpl.java
  25. 8 0
      mp-service/src/main/resources/mapper/channel/ChannelCommissionMapper.xml
  26. 2 3
      mp-service/src/main/resources/mapper/channel/ChannelMoneyLogMapper.xml
  27. 2 2
      mp-service/src/main/resources/mapper/channel/ChannelWithdrawMapper.xml
  28. 2 3
      mp-service/src/main/resources/mapper/user/UserCoinLogMapper.xml

+ 1 - 4
mp-admin/src/main/java/com/qs/mp/web/controller/api/admin/GoodsMgrController.java

@@ -123,9 +123,6 @@ public class GoodsMgrController extends BaseApiController {
 	@ApiOperation(value = "新增商品信息", notes = "后台商品管理新增商品")
 	@PostMapping("/create")
 	public AjaxResult goodsCreate(@Validated @RequestBody GoodsParam goodsParam) {
-		if (null != goodsParam.getGoodsId() || 0 !=  goodsParam.getGoodsId()) {
-			return AjaxResult.error("该商品已存在");
-		}
 		Goods goods = mapperFacade.map(goodsParam, Goods.class);
 		// 1、校验名称是否重复(商品表)
 		LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
@@ -174,7 +171,7 @@ public class GoodsMgrController extends BaseApiController {
 	@ApiOperation(value = "编辑商品信息", notes = "后台商品管理修改商品信息")
 	@PostMapping("/update")
 	public AjaxResult goodsUpdate(@Validated @RequestBody GoodsParam goodsParam) {
-		if (null == goodsParam || null != goodsParam.getGoodsId() || 0 == goodsParam.getGoodsId()) {
+		if (null == goodsParam || null == goodsParam.getGoodsId() || 0 == goodsParam.getGoodsId()) {
 			return error(ErrorCodeEnum.ERROR_CODE_1001);
 		}
 		Goods oldGoods = goodsService.getById(goodsParam.getGoodsId());

+ 21 - 1
mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelMoneyController.java

@@ -12,13 +12,18 @@ package com.qs.mp.web.controller.api.channel;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.qs.mp.channel.domain.ChannelMoneyLog;
+import com.qs.mp.channel.domain.ChannelWithdraw;
+import com.qs.mp.channel.domain.vo.ChannelMoneyLogVO;
 import com.qs.mp.channel.service.IChannelMoneyLogService;
+import com.qs.mp.channel.service.IChannelWithdrawService;
 import com.qs.mp.common.core.page.TableDataInfo;
+import com.qs.mp.common.enums.ChannelMoneyEnum;
 import com.qs.mp.utils.SecurityUtils;
 import com.qs.mp.web.controller.common.BaseApiController;
 import io.swagger.annotations.Api;
 import java.util.List;
 import lombok.AllArgsConstructor;
+import ma.glasnost.orika.MapperFacade;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -36,6 +41,12 @@ public class ChannelMoneyController extends BaseApiController {
   @Autowired
   private IChannelMoneyLogService channelMoneyLogService;
 
+  @Autowired
+  private IChannelWithdrawService channelWithdrawService;
+
+  @Autowired
+  private MapperFacade mapperFacade;
+
   @RequestMapping(value = "/money/log", method = RequestMethod.POST)
   @ResponseBody
   public TableDataInfo listMoneyLog(@RequestBody ChannelMoneyLog channelMoneyLog) {
@@ -45,6 +56,15 @@ public class ChannelMoneyController extends BaseApiController {
     queryWrapper.lambda().orderByDesc(ChannelMoneyLog::getBizTime);
     startPage();
     List<ChannelMoneyLog> list = channelMoneyLogService.list(queryWrapper);
-    return getDataTable(list);
+    List<ChannelMoneyLogVO> channelMoneyLogVOS = mapperFacade.mapAsList(list, ChannelMoneyLogVO.class);
+    for (ChannelMoneyLogVO logVO : channelMoneyLogVOS) {
+      if (logVO.getType() == ChannelMoneyEnum.WITHDRAW) {
+        ChannelWithdraw channelWithdraw = channelWithdrawService.getById(logVO.getRefId());
+        logVO.setWithdrawStatus(channelWithdraw.getStatus());
+      }
+    }
+    TableDataInfo resp = getDataTable(list);
+    resp.setRows(channelMoneyLogVOS);
+    return resp;
   }
 }

+ 23 - 7
mp-admin/src/main/java/com/qs/mp/web/controller/api/channel/ChannelWithdrawController.java

@@ -79,7 +79,7 @@ public class ChannelWithdrawController extends BaseApiController {
   /**
    * 提现费率默认值
    */
-  private final String FEE_RATE_DEFAULT_VALUE = "8";
+  private final String FEE_RATE_DEFAULT_VALUE = "0.8";
 
   /**
    * 渠道提现计算手续费
@@ -88,12 +88,26 @@ public class ChannelWithdrawController extends BaseApiController {
   @ApiOperation(value = "提现" , notes = "提现计费")
   public AjaxResult settle(@Valid @RequestBody ChannelWithdrawParam param) {
     String feeRateValue = configService.selectConfigByKey(FEE_RATE_CONFIG_KEY);
-    BigDecimal feeRate = new BigDecimal(StringUtils.isNotBlank(feeRateValue) ? feeRateValue : FEE_RATE_DEFAULT_VALUE);
+    BigDecimal feeRate = new BigDecimal(
+        StringUtils.isNotBlank(feeRateValue) ? feeRateValue : FEE_RATE_DEFAULT_VALUE);
     Long channelId = SecurityUtils.getLoginUser().getChannelId();
+    Channel channel = channelService.getById(channelId);
+    if (channel.getMoney() < 50000) {
+      return AjaxResult.error("账户余额不足500元");
+    }
+    if (param.getMoney() > channel.getMoney() ) {
+      return AjaxResult.error("提现金额超出了余额");
+    }
+    int feeAmt = new BigDecimal(param.getMoney()).multiply(feeRate)
+        .divide(new BigDecimal(100), 0, RoundingMode.HALF_UP).intValue();
     ChannelWithdraw channelWithdraw = new ChannelWithdraw();
-    channelWithdraw.setMoney(param.getMoney());
-    BigDecimal feeAmt = new BigDecimal(param.getMoney()).multiply(feeRate).divide(new BigDecimal(1000), 2, RoundingMode.DOWN);
-    channelWithdraw.setChargeAmt(feeAmt.intValue());
+    if (param.getMoney() + feeAmt > channel.getMoney()) {
+      channelWithdraw.setMoney(new BigDecimal(channel.getMoney()).divide(new BigDecimal(1).add(feeRate.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)), 0, RoundingMode.HALF_UP).intValue());
+      channelWithdraw.setChargeAmt(channel.getMoney() - channelWithdraw.getMoney());
+    } else {
+      channelWithdraw.setMoney(param.getMoney());
+      channelWithdraw.setChargeAmt(feeAmt);
+  }
     channelWithdraw.setUserName(param.getUserName());
     channelWithdraw.setCardNo(param.getCardNo());
     channelWithdraw.setBranchName(param.getBranchName());
@@ -102,7 +116,9 @@ public class ChannelWithdrawController extends BaseApiController {
     redisCache.setCacheObject(CHANNEL_WITHDRAW_CACHE_KEY + channelId, channelWithdraw, 1, TimeUnit.MINUTES);
 
     JSONObject jsonObject = new JSONObject();
+    jsonObject.put("withdrawAmt", channelWithdraw.getMoney());
     jsonObject.put("chargeAmt", channelWithdraw.getChargeAmt());
+    jsonObject.put("chargeRate", feeRate);
     return AjaxResult.success(jsonObject);
   }
 
@@ -118,12 +134,12 @@ public class ChannelWithdrawController extends BaseApiController {
       return AjaxResult.error("申请已过期,请重新提交");
     }
     Channel channel = channelService.getById(channelId);
-    if (channelWithdraw.getMoney() > channel.getMoney() ) {
+    if (channelWithdraw.getMoney() + channelWithdraw.getChargeAmt() > channel.getMoney() ) {
       return AjaxResult.error("提现金额超出账户余额");
     }
 
     channelWithdraw.setChannelId(channelId);
-    channelWithdraw.setLogMoney(channel.getMoney());
+    channelWithdraw.setAvailableMoney(channel.getMoney());
 
     channelWithdrawService.apply(channel, channelWithdraw);
 

+ 1 - 1
mp-admin/src/main/resources/application-test.yml

@@ -35,7 +35,7 @@ spring:
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://172.17.16.14:3306/mpdb_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=UTC
+                url: jdbc:mysql://172.17.16.14:3306/mpdb_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: mptest
                 password: wan789*@dfhzHu518!dr2xosn
             # 从库数据源

+ 0 - 41
mp-common/src/main/java/com/qs/mp/common/enums/ChannelMoneyBizTypeEnum.java

@@ -1,41 +0,0 @@
-package com.qs.mp.common.enums;
-
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.annotation.IEnum;
-
-/**
- *
- * 渠道账户交易类型
- *
- */
-public enum ChannelMoneyBizTypeEnum implements IEnum<Integer> {
-
-  COMMISSION(1, "佣金收入"),
-  WITHDRAW(2, "提现");
-
-
-  private final int value;
-  private final String desc;
-
-  ChannelMoneyBizTypeEnum(final int value, final String desc) {
-    this.value = value;
-    this.desc = desc;
-  }
-
-  @Override
-  public Integer getValue() {
-    return value;
-  }
-
-  /**
-   * 重写toString,单个转化成json
-   * @return
-   */
-  @Override
-  public String toString() {
-    JSONObject object = new JSONObject();
-    object.put("value",value);
-    object.put("desc", desc);
-    return object.toString();
-  }
-}

+ 54 - 0
mp-common/src/main/java/com/qs/mp/common/enums/ChannelWithdrawStatusEnum.java

@@ -0,0 +1,54 @@
+package com.qs.mp.common.enums;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONType;
+import com.baomidou.mybatisplus.annotation.IEnum;
+import com.qs.mp.common.json.EnumValueDeserializer;
+
+/**
+ * @auther zhongcp
+ * @create 2022 2022/3/7 2:30 下午
+ * @describe
+ */
+@JSONType(deserializer = EnumValueDeserializer.class)
+public enum ChannelWithdrawStatusEnum implements IEnum<Integer> {
+
+  WITHDRAWING(1, "提现中"),
+  FINISHED(2, "已完成"),
+  FAILED(3, "提现失败");
+
+
+  private final int value;
+  private final String desc;
+
+  ChannelWithdrawStatusEnum(int value, String desc) {
+    this.value = value;
+    this.desc = desc;
+  }
+
+  public static ChannelWithdrawStatusEnum getChannelMoneyTypeEnum(int value) {
+    for (ChannelWithdrawStatusEnum channelMoneyTypeEnum : ChannelWithdrawStatusEnum.values()) {
+      if (channelMoneyTypeEnum.getValue() == value) {
+        return channelMoneyTypeEnum;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public Integer getValue() {
+    return value;
+  }
+
+  public String getDesc() {
+    return desc;
+  }
+
+  @Override
+  public String toString() {
+    JSONObject object = new JSONObject();
+    object.put("value", value);
+    object.put("desc", desc);
+    return object.toString();
+  }
+}

+ 58 - 0
mp-quartz/src/main/java/com/qs/mp/quartz/task/ChannelCommTask.java

@@ -0,0 +1,58 @@
+package com.qs.mp.quartz.task;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qs.mp.channel.domain.ChannelCommission;
+import com.qs.mp.channel.service.IChannelCommissionService;
+import com.qs.mp.common.utils.DateUtils;
+import com.qs.mp.common.utils.LogUtil;
+import com.qs.mp.common.utils.StringUtils;
+import java.util.Date;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 渠道佣金按天汇总入账
+ *
+ * @author zhongcp
+ * @Date 2022/3/17
+ */
+@Component("channelCommTask")
+public class ChannelCommTask {
+
+  protected final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+
+  @Autowired
+  private IChannelCommissionService channelCommissionService;
+
+  /**
+   * 渠道佣金汇总记账任务
+   */
+  public void sumComm(String executeDay) {
+    LogUtil.info(logger, "...渠道佣金汇总入账定时任务开始...");
+    Date bizDay;
+    if (StringUtils.isNotBlank(executeDay)) {
+      bizDay = DateUtils.parseStrToDate(executeDay, DateUtils.YYYYMMDD);
+    } else {
+      bizDay = DateUtils.addDays(DateUtils.getToday(), -1);
+    }
+
+    // 捞取前一天有分佣的渠道ID
+    List<ChannelCommission> channelList = channelCommissionService.getChannelList(
+        new QueryWrapper<ChannelCommission>()
+            .gt("t2.level", 0)
+            .ge("t1.created_time", bizDay)
+            .lt("t1.created_time", DateUtils.addDays(bizDay, 1)));
+    for (ChannelCommission channelCommission : channelList) {
+      try {
+        channelCommissionService.commEntry(channelCommission.getChannelId(), bizDay);
+      } catch (Exception e) {
+        LogUtil.error(logger, e, "渠道佣金汇总入账异常。channelId:{0}", channelCommission.getChannelId());
+      }
+    }
+
+    LogUtil.info(logger, "...渠道佣金汇总入账定时任务结束...");
+  }
+}

+ 2 - 1
mp-service/src/main/java/com/qs/mp/admin/domain/param/TicketBoxCreateParam.java

@@ -3,6 +3,7 @@ package com.qs.mp.admin.domain.param;
 import com.qs.mp.common.enums.TicketTypeEnum;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import java.math.BigDecimal;
 import java.util.List;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
@@ -44,7 +45,7 @@ public class TicketBoxCreateParam {
 
 	@NotNull(message = "分佣基数不能为空")
 	@ApiModelProperty(value = "分佣基数",required=true)
-	private Integer saleCommRate;
+	private BigDecimal saleCommRate;
 
 	@NotEmpty(message = "奖级列表不能为空")
 	@ApiModelProperty(value = "奖级列表",required=true)

+ 1 - 1
mp-service/src/main/java/com/qs/mp/admin/service/impl/CouponServiceImpl.java

@@ -78,7 +78,7 @@ public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> impleme
   public void distribute(Ticket ticket, Long userId, String couponId) {
     Coupon coupon = getById(couponId);
     UserCoupon userCoupon = new UserCoupon();
-    userCoupon.setId(bizIdGenerator.newId());
+    userCoupon.setId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
     userCoupon.setUserId(userId);
     userCoupon.setVerifyCode(bizIdGenerator.newId());
     userCoupon.setCouponId(coupon.getCouponId());

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

@@ -223,7 +223,7 @@ public class TicketBoxServiceImpl extends ServiceImpl<TicketBoxMapper, TicketBox
         pkgAwards.setQuantity(pkgAwards.getQuantity() - 1);
 
         Ticket ticket = new Ticket();
-        ticket.setTicketId(bizIdGenerator.newId());
+        ticket.setTicketId(bizIdGenerator.newIdWithUidSharding(ticketBox.getBoxNo()));
         ticket.setBoxId(ticketBox.getBoxId());
         ticket.setPkgId(ticketPackage.getPkgId());
         ticket.setTitle(ticketBox.getTitle());

+ 0 - 7
mp-service/src/main/java/com/qs/mp/channel/domain/ChannelMoneyLog.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.qs.mp.common.enums.ChannelMoneyBizTypeEnum;
 import com.qs.mp.common.enums.ChannelMoneyEnum;
 import java.io.Serializable;
 import java.util.Date;
@@ -72,12 +71,6 @@ public class ChannelMoneyLog implements Serializable {
   @TableField("biz_time")
   private Date bizTime;
 
-  /**
-   * 关联交易ID类型
-   */
-  @TableField("ref_type")
-  private ChannelMoneyBizTypeEnum refType;
-
   /**
    * 关联交易ID
    */

+ 7 - 3
mp-service/src/main/java/com/qs/mp/channel/domain/ChannelWithdraw.java

@@ -1,9 +1,12 @@
 package com.qs.mp.channel.domain;
 
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
 import java.io.Serializable;
 import java.util.Date;
 import lombok.Data;
@@ -43,8 +46,8 @@ public class ChannelWithdraw implements Serializable {
   /**
    * 当前可用资金
    */
-  @TableField("log_money")
-  private Integer logMoney;
+  @TableField("available_money")
+  private Integer availableMoney;
 
   /**
    * 支付类型 1支付宝,2微信,3银行卡
@@ -80,7 +83,8 @@ public class ChannelWithdraw implements Serializable {
    * 提现状态 1申请,2审核通过,3审核拒绝
    */
   @TableField("status")
-  private String status;
+  @JSONField(serialzeFeatures = SerializerFeature.WriteEnumUsingToString)
+  private ChannelWithdrawStatusEnum status;
 
   /**
    * 转账凭证

+ 17 - 0
mp-service/src/main/java/com/qs/mp/channel/domain/vo/ChannelMoneyLogVO.java

@@ -0,0 +1,17 @@
+package com.qs.mp.channel.domain.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import com.qs.mp.channel.domain.ChannelMoneyLog;
+import com.qs.mp.common.enums.ChannelWithdrawStatusEnum;
+import lombok.Data;
+
+/**
+ * @author zhongcp
+ * @Date 2022/3/18
+ */
+@Data
+public class ChannelMoneyLogVO extends ChannelMoneyLog {
+  @JSONField(serialzeFeatures = SerializerFeature.WriteEnumUsingToString)
+  private ChannelWithdrawStatusEnum withdrawStatus;
+}

+ 19 - 8
mp-service/src/main/java/com/qs/mp/channel/mapper/ChannelCommissionMapper.java

@@ -1,7 +1,12 @@
 package com.qs.mp.channel.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.qs.mp.channel.domain.Channel;
 import com.qs.mp.channel.domain.ChannelCommission;
 
+import com.qs.mp.channel.domain.vo.ChannelVO;
+import java.util.List;
 import org.apache.ibatis.annotations.Param;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -20,8 +25,8 @@ public interface ChannelCommissionMapper extends BaseMapper<ChannelCommission> {
 	 * @return
 	 */
 	public int getChannelCommAmtCnt(@Param("channelNo") String channelNo,@Param("days") int days);
-	
-	
+
+
 	/**
 	 * 查询子渠道一定时间范围内的销售金额
 	 * @param channelNo
@@ -29,8 +34,8 @@ public interface ChannelCommissionMapper extends BaseMapper<ChannelCommission> {
 	 * @return
 	 */
 	public int getChannelSaleAmtCnt(@Param("channelNo") String channelNo,@Param("days") int days);
-	
-	
+
+
 	/**
 	 * 查询子渠道全部佣金金额 -
 	 * @param channelNo
@@ -38,14 +43,20 @@ public interface ChannelCommissionMapper extends BaseMapper<ChannelCommission> {
 	 * @return
 	 */
 	public int getChannelTotalCommAmtCnt(@Param("channelNo") String channelNo);
-	
-	
+
+
 	/**
 	 * 查询子渠道全部的销售金额
 	 * @param channelNo
-	 * @param days
 	 * @return
 	 */
 	public int getChannelTotalSaleAmtCnt(@Param("channelNo") String channelNo);
-	
+
+	/**
+	 * 查询渠道ID列表
+	 * @param wrapper
+	 * @return
+	 */
+	List<ChannelCommission> getChannelList(@Param(Constants.WRAPPER) Wrapper<ChannelCommission> wrapper);
+
 }

+ 25 - 9
mp-service/src/main/java/com/qs/mp/channel/service/IChannelCommissionService.java

@@ -1,8 +1,13 @@
 package com.qs.mp.channel.service;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.qs.mp.channel.domain.ChannelCommission;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import java.util.Date;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -21,8 +26,8 @@ public interface IChannelCommissionService extends IService<ChannelCommission> {
 	 * @return
 	 */
 	public int getChannelCommAmtCnt(String channelNo, int days);
-	
-	
+
+
 	/**
 	 * 查询子渠道一定时间范围内的销售金额
 	 * @param channelNo
@@ -30,23 +35,34 @@ public interface IChannelCommissionService extends IService<ChannelCommission> {
 	 * @return
 	 */
 	public int getChannelSaleAmtCnt(String channelNo, int days);
-	
-	
+
+
 	/**
 	 * 查询子渠道全部佣金金额 -
 	 * @param channelNo
-	 * @param days
 	 * @return
 	 */
 	public int getChannelTotalCommAmtCnt(String channelNo);
-	
-	
+
+
 	/**
 	 * 查询子渠道全部的销售金额
 	 * @param channelNo
-	 * @param days
 	 * @return
 	 */
 	public int getChannelTotalSaleAmtCnt(String channelNo);
-	
+
+	/**
+	 * 查询渠道列表
+	 * @param wrapper
+	 * @return
+	 */
+	List<ChannelCommission> getChannelList(Wrapper<ChannelCommission> wrapper);
+
+	/**
+	 * 渠道佣金收入汇总入账
+	 * @param channelId
+	 */
+	void commEntry(Long channelId, Date bizDay);
+
 }

+ 50 - 2
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelCommissionServiceImpl.java

@@ -1,10 +1,24 @@
 package com.qs.mp.channel.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qs.mp.channel.domain.Channel;
 import com.qs.mp.channel.domain.ChannelCommission;
+import com.qs.mp.channel.domain.ChannelMoneyLog;
 import com.qs.mp.channel.mapper.ChannelCommissionMapper;
 import com.qs.mp.channel.service.IChannelCommissionService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qs.mp.channel.service.IChannelMoneyLogService;
+import com.qs.mp.channel.service.IChannelService;
+import com.qs.mp.common.enums.ChannelMoneyEnum;
+import com.qs.mp.common.utils.DateUtils;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
 
 /**
  * <p>
@@ -17,6 +31,12 @@ import org.springframework.stereotype.Service;
 @Service
 public class ChannelCommissionServiceImpl extends ServiceImpl<ChannelCommissionMapper, ChannelCommission> implements IChannelCommissionService {
 
+	@Autowired
+	private IChannelService channelService;
+
+	@Autowired
+	private IChannelMoneyLogService channelMoneyLogService;
+
 	@Override
 	public int getChannelCommAmtCnt(String channelNo, int days) {
 		return getBaseMapper().getChannelCommAmtCnt(channelNo, days == 1?0:days);
@@ -36,6 +56,34 @@ public class ChannelCommissionServiceImpl extends ServiceImpl<ChannelCommissionM
 	public int getChannelTotalSaleAmtCnt(String channelNo) {
 		return getBaseMapper().getChannelTotalSaleAmtCnt(channelNo);
 	}
-	
-	
+
+	@Override
+	public List<ChannelCommission> getChannelList(Wrapper<ChannelCommission> wrapper) {
+		return getBaseMapper().getChannelList(wrapper);
+	}
+
+	@Override
+	public void commEntry(Long channelId, Date bizDay) {
+		Map<String, Object> sumCommMap = getMap(new QueryWrapper<ChannelCommission>()
+				.select("IFNULL(SUM(comm_amt),0) as commAmt")
+				.lambda().eq(ChannelCommission::getChannelId, channelId)
+				.ge(ChannelCommission::getCreatedTime, bizDay)
+				.lt(ChannelCommission::getCreatedTime, DateUtils.addDays(bizDay, 1)));
+		int sumCommAmt = sumCommMap.get("commAmt") == null ? 0 : Integer.valueOf(String.valueOf(sumCommMap.get("commAmt")));
+		Channel channel = channelService.getById(channelId);
+		int cnt = channelMoneyLogService.count(new LambdaQueryWrapper<ChannelMoneyLog>()
+				.eq(ChannelMoneyLog::getChannelId, channelId)
+				.eq(ChannelMoneyLog::getBizTime, bizDay)
+				.eq(ChannelMoneyLog::getType, ChannelMoneyEnum.COMMISSION));
+		String strBizDay = DateUtils.dateTime(bizDay);
+		Assert.isTrue(cnt == 0, "渠道" + channelId + " " + strBizDay + "的佣金收入已入账。此次入账任务忽略");
+		ChannelMoneyLog moneyLog = new ChannelMoneyLog();
+		moneyLog.setChannelId(channelId);
+		moneyLog.setType(ChannelMoneyEnum.COMMISSION);
+		moneyLog.setLogMoney(sumCommAmt);
+		moneyLog.setLogText(strBizDay);
+		moneyLog.setBizTime(bizDay);
+		moneyLog.setRefId(null);
+		channelMoneyLogService.changeMoney(moneyLog);
+	}
 }

+ 3 - 3
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelMoneyLogServiceImpl.java

@@ -7,7 +7,6 @@ import com.qs.mp.channel.mapper.ChannelMoneyLogMapper;
 import com.qs.mp.channel.service.IChannelMoneyLogService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qs.mp.channel.service.IChannelService;
-import com.qs.mp.common.enums.ChannelMoneyBizTypeEnum;
 import com.qs.mp.common.enums.ChannelMoneyEnum;
 import com.qs.mp.common.enums.ErrorCodeEnum;
 import com.qs.mp.common.exception.DataOperationException;
@@ -43,6 +42,7 @@ public class ChannelMoneyLogServiceImpl extends ServiceImpl<ChannelMoneyLogMappe
     Channel channel = channelService.getById(moneyLog.getChannelId());
 
     boolean income = checkIncome(moneyLog.getType());
+    int logMoney = moneyLog.getLogMoney();
     int money = 0;
     if (!income) {
       //根据收支方向,将金额转负,方便统一计算
@@ -63,9 +63,9 @@ public class ChannelMoneyLogServiceImpl extends ServiceImpl<ChannelMoneyLogMappe
     }
     LogUtil.info(logger, "channelId:{0}, money:{1}", new Object[]{channel.getChannelId() , channel.getMoney()});
 
-    //1、更新商户余额表
+    //1、更新渠道余额表
     boolean rtn = channelService.update(new LambdaUpdateWrapper<Channel>().set(Channel::getMoney, money)
-            .set(ChannelMoneyBizTypeEnum.WITHDRAW == moneyLog.getRefType(), Channel::getFrozenMoney, channel.getFrozenMoney() + moneyLog.getLogMoney())
+            .set(ChannelMoneyEnum.WITHDRAW == moneyLog.getType() || ChannelMoneyEnum.WITHDRAW_FEE == moneyLog.getType(), Channel::getFrozenMoney, channel.getFrozenMoney() + logMoney)
         .eq(Channel::getChannelId, channel.getChannelId()).eq(Channel::getMoney, channel.getMoney()));
     Assert.isTrue(rtn, "渠道余额更新失败,channelId:" + channel.getChannelId());
 

+ 4 - 9
mp-service/src/main/java/com/qs/mp/channel/service/impl/ChannelWithdrawServiceImpl.java

@@ -12,7 +12,6 @@ import com.qs.mp.channel.service.IChannelMoneyLogService;
 import com.qs.mp.channel.service.IChannelService;
 import com.qs.mp.channel.service.IChannelWithdrawService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qs.mp.common.enums.ChannelMoneyBizTypeEnum;
 import com.qs.mp.common.enums.ChannelMoneyEnum;
 import java.util.Date;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,11 +41,13 @@ public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMappe
   @Override
   @Transactional
   public boolean apply(Channel channel, ChannelWithdraw channelWithdraw) {
+
     // 更新用户的银行卡信息
     ChannelBankCard bankCard = channelBankCardService.getOne(new LambdaQueryWrapper<ChannelBankCard>()
         .eq(ChannelBankCard::getChannelId, channel.getChannelId()));
     if (null == bankCard) {
       bankCard = new ChannelBankCard();
+      bankCard.setChannelId(channel.getChannelId());
       bankCard.setCardNo(channelWithdraw.getCardNo());
       bankCard.setBankName(channelWithdraw.getBankName());
       bankCard.setBranchName(channelWithdraw.getBranchName());
@@ -60,19 +61,14 @@ public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMappe
       channelBankCardService.updateById(bankCard);
     }
     boolean rst = save(channelWithdraw);
-    // 冻结账户余额,乐观锁
-    channelService.update(new LambdaUpdateWrapper<Channel>()
-        .set(Channel::getFrozenMoney, channel.getFrozenMoney() + channelWithdraw.getMoney())
-        .set(Channel::getMoney, channel.getMoney() - channelWithdraw.getMoney())
-        .eq(Channel::getChannelId, channel.getChannelId()).eq(Channel::getMoney, channel.getMoney()));
 
     ChannelMoneyLog moneyLog = new ChannelMoneyLog();
     moneyLog.setChannelId(channel.getChannelId());
     moneyLog.setType(ChannelMoneyEnum.WITHDRAW);
     moneyLog.setLogMoney(channelWithdraw.getMoney());
     moneyLog.setBizTime(new Date());
-    moneyLog.setRefType(ChannelMoneyBizTypeEnum.WITHDRAW);
     moneyLog.setRefId(String.valueOf(channelWithdraw.getId()));
+    moneyLog.setLogText("银行卡尾号 " + channelWithdraw.getCardNo().substring(channelWithdraw.getCardNo().length() - 4));
     channelMoneyLogService.changeMoney(moneyLog);
 
     if (channelWithdraw.getChargeAmt() > 0) {
@@ -82,9 +78,8 @@ public class ChannelWithdrawServiceImpl extends ServiceImpl<ChannelWithdrawMappe
       feeMoneyLog.setType(ChannelMoneyEnum.WITHDRAW_FEE);
       feeMoneyLog.setLogMoney(channelWithdraw.getChargeAmt());
       feeMoneyLog.setBizTime(new Date());
-      feeMoneyLog.setRefType(ChannelMoneyBizTypeEnum.WITHDRAW);
       feeMoneyLog.setRefId(String.valueOf(channelWithdraw.getId()));
-      channelMoneyLogService.changeMoney(moneyLog);
+      channelMoneyLogService.changeMoney(feeMoneyLog);
     }
     // 创建提现记录
     return rst;

+ 0 - 6
mp-service/src/main/java/com/qs/mp/user/domain/UserCoinLog.java

@@ -71,12 +71,6 @@ public class UserCoinLog implements Serializable {
   @TableField("biz_time")
   private Date bizTime;
 
-  /**
-   * 关联交易ID类型
-   */
-  @TableField("ref_type")
-  private Integer refType;
-
   /**
    * 关联交易ID
    */

+ 2 - 2
mp-service/src/main/java/com/qs/mp/user/domain/UserHitPrize.java

@@ -22,8 +22,8 @@ public class UserHitPrize implements Serializable {
   /**
    * 主键
    */
-  @TableId(value = "id", type = IdType.AUTO)
-  private Long id;
+  @TableId(value = "id", type = IdType.INPUT)
+  private String id;
 
   /**
    * 用户ID

+ 0 - 2
mp-service/src/main/java/com/qs/mp/user/service/impl/UserCoinServiceImpl.java

@@ -51,7 +51,6 @@ public class UserCoinServiceImpl extends ServiceImpl<UserCoinMapper, UserCoin> i
     userCoinLog.setIncomeExpense(CoinLogTypeEnum.INCOME);
     userCoinLog.setLogText("盲票奖品");
     userCoinLog.setBizTime(new Date());
-    userCoinLog.setRefType(1);
     userCoinLog.setRefId(bizId);
     userCoinLogService.save(userCoinLog);
   }
@@ -73,7 +72,6 @@ public class UserCoinServiceImpl extends ServiceImpl<UserCoinMapper, UserCoin> i
     userCoinLog.setIncomeExpense(CoinLogTypeEnum.EXPENSES);
     userCoinLog.setLogText("兑换商品");
     userCoinLog.setBizTime(new Date());
-    userCoinLog.setRefType(2);
     userCoinLog.setRefId(bizId);
     userCoinLogService.save(userCoinLog);
   }

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

@@ -57,7 +57,7 @@ public class UserDeliverOrderServiceImpl extends ServiceImpl<UserDeliverOrderMap
   @Transactional
   public String submitOrder(Long userId, DeliverOrderSettleVO orderSettleVO) {
     UserDeliverOrder userDeliverOrder = new UserDeliverOrder();
-    userDeliverOrder.setOrderId(bizIdGenerator.newId());
+    userDeliverOrder.setOrderId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
     userDeliverOrder.setUserId(userId);
     UserAddr userAddr = orderSettleVO.getAddr();
     userDeliverOrder.setReceiver(userAddr.getReceiver());
@@ -79,7 +79,7 @@ public class UserDeliverOrderServiceImpl extends ServiceImpl<UserDeliverOrderMap
 
     for (UserPrizeStorage prizeStorage : orderSettleVO.getPrizeList()) {
       UserDeliverOrderItem orderItem = new UserDeliverOrderItem();
-      orderItem.setItemId(bizIdGenerator.newId());
+      orderItem.setItemId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
       orderItem.setOrderId(userDeliverOrder.getOrderId());
       orderItem.setStorageId(prizeStorage.getStorageId());
       orderItem.setGoodsId(prizeStorage.getGoodsId());

+ 6 - 2
mp-service/src/main/java/com/qs/mp/user/service/impl/UserHitPrizeServiceImpl.java

@@ -82,6 +82,9 @@ public class UserHitPrizeServiceImpl extends ServiceImpl<UserHitPrizeMapper, Use
   @Autowired
   private ITicketService ticketService;
 
+  @Autowired
+  private BizIdGenerator bizIdGenerator;
+
   @Override
   public List<TicketAwardsPrize> listPrize(Ticket ticket, Long userId) {
     UserHitPrize userHitPrize = getOne(new LambdaQueryWrapper<UserHitPrize>().eq(UserHitPrize::getTicketId, ticket.getTicketId()));
@@ -97,6 +100,7 @@ public class UserHitPrizeServiceImpl extends ServiceImpl<UserHitPrizeMapper, Use
       for (TicketDrawNumDTO ticketDrawNumDTO : drawNumDTOList) {
         if (ticketDrawNumDTO.getNum() == ticket.getPlainLuckyNum()) {
           userHitPrize = new UserHitPrize();
+          userHitPrize.setId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
           userHitPrize.setUserId(userId);
           userHitPrize.setOrderId(orderItem.getOrderId());
           userHitPrize.setOrderItemId(orderItem.getItemId());
@@ -138,11 +142,11 @@ public class UserHitPrizeServiceImpl extends ServiceImpl<UserHitPrizeMapper, Use
 
     // 放入仓库
     if (ticketAwardsPrize.getPrizeType() == TicketPrizeTypeEnum.COIN) {
-      userCoinService.produce(userId, ticketAwardsPrize.getValue(), String.valueOf(userHitPrize.getId()));
+      userCoinService.produce(userId, ticketAwardsPrize.getValue(), userHitPrize.getId());
     } else if (ticketAwardsPrize.getPrizeType() == TicketPrizeTypeEnum.COUPON) {
       couponService.distribute(ticket, userId, ticketAwardsPrize.getRefId());
     } else {
-      userPrizeStorageService.takeInStorage(userId, ticketAwardsPrize, PrizeStorageInTypeEnum.TICKET_CASHED, String.valueOf(userHitPrize.getId()));
+      userPrizeStorageService.takeInStorage(userId, ticketAwardsPrize, PrizeStorageInTypeEnum.TICKET_CASHED, userHitPrize.getId());
     }
 
     boolean rtn = ticketService.update(new LambdaUpdateWrapper<Ticket>().set(Ticket::getStatus, TicketStatusEnum.CASHED)

+ 4 - 6
mp-service/src/main/java/com/qs/mp/user/service/impl/UserTicketOrderServiceImpl.java

@@ -19,7 +19,6 @@ import com.qs.mp.channel.service.IChannelMoneyLogService;
 import com.qs.mp.channel.service.IChannelOrderDetailService;
 import com.qs.mp.channel.service.IChannelService;
 import com.qs.mp.channel.service.IChannelUserRelService;
-import com.qs.mp.common.enums.ChannelMoneyBizTypeEnum;
 import com.qs.mp.common.enums.ChannelMoneyEnum;
 import com.qs.mp.common.enums.CommStatusEnum;
 import com.qs.mp.common.enums.MqTopicType;
@@ -140,7 +139,7 @@ public class UserTicketOrderServiceImpl extends
 
     // 创建订单
     UserTicketOrder userTicketOrder = new UserTicketOrder();
-    userTicketOrder.setOrderId(bizIdGenerator.newId());
+    userTicketOrder.setOrderId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
     userTicketOrder.setUserId(userId);
     userTicketOrder.setTitle(ticketBox.getTitle());
     userTicketOrder.setBoxId(orderSettleVO.getBoxId());
@@ -165,7 +164,7 @@ public class UserTicketOrderServiceImpl extends
 
     for (int i = 0; i < orderSettleVO.getOrderNum(); i++) {
       UserTicketOrderItem orderItem = new UserTicketOrderItem();
-      orderItem.setItemId(bizIdGenerator.newId());
+      orderItem.setItemId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
       orderItem.setOrderId(userTicketOrder.getOrderId());
       orderItem.setUserId(userId);
       orderItem.setBoxId(ticketBox.getBoxId());
@@ -184,7 +183,7 @@ public class UserTicketOrderServiceImpl extends
     String couponIds = verifyUserCoupon(orderSettleVO.getCouponList());
 
     UserTicketOrder ticketOrder = new UserTicketOrder();
-    ticketOrder.setOrderId(bizIdGenerator.newId());
+    ticketOrder.setOrderId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
     ticketOrder.setUserId(userId);
     ticketOrder.setTitle(ticket.getTitle());
     ticketOrder.setBoxId(ticket.getBoxId());
@@ -214,7 +213,7 @@ public class UserTicketOrderServiceImpl extends
     save(ticketOrder);
 
     UserTicketOrderItem orderItem = new UserTicketOrderItem();
-    orderItem.setItemId(bizIdGenerator.newId());
+    orderItem.setItemId(bizIdGenerator.newIdWithUidSharding(String.valueOf(userId)));
     orderItem.setOrderId(ticketOrder.getOrderId());
     orderItem.setUserId(userId);
     orderItem.setBoxId(ticket.getBoxId());
@@ -426,7 +425,6 @@ public class UserTicketOrderServiceImpl extends
     moneyLog.setType(ChannelMoneyEnum.COMMISSION);
     moneyLog.setLogMoney(siteCommission.getCommAmt());
     moneyLog.setBizTime(new Date());
-    moneyLog.setRefType(ChannelMoneyBizTypeEnum.COMMISSION);
     moneyLog.setRefId(String.valueOf(siteCommission.getId()));
     channelMoneyLogService.changeMoney(moneyLog);
   }

+ 8 - 0
mp-service/src/main/resources/mapper/channel/ChannelCommissionMapper.xml

@@ -67,4 +67,12 @@
 		) t3
 	</select>
 
+		<!-- 查询有佣金收入的渠道列表 -->
+		<select id="getChannelList" resultMap="BaseResultMap">
+		select distinct t1.channel_id
+		from mp_channel_commission t1
+					 left join mp_channel t2 on t1.channel_id = t2.channel_id
+			${ew.customSqlSegment}
+	</select>
+
 </mapper>

+ 2 - 3
mp-service/src/main/resources/mapper/channel/ChannelMoneyLogMapper.xml

@@ -12,7 +12,6 @@
         <result column="income_expense" property="incomeExpense" />
         <result column="log_text" property="logText" />
         <result column="biz_time" property="bizTime" />
-        <result column="ref_type" property="refType" />
         <result column="ref_id" property="refId" />
         <result column="created_time" property="createdTime" />
         <result column="updated_time" property="updatedTime" />
@@ -20,7 +19,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, channel_id, type, money, log_money, income_expense, log_text, biz_time, ref_type, ref_id, created_time, updated_time
+        id, channel_id, type, money, log_money, income_expense, log_text, biz_time, ref_id, created_time, updated_time
     </sql>
 
-</mapper>
+</mapper>

+ 2 - 2
mp-service/src/main/resources/mapper/channel/ChannelWithdrawMapper.xml

@@ -8,7 +8,7 @@
         <result column="channel_id" property="channelId" />
         <result column="money" property="money" />
         <result column="charge_amt" property="chargeAmt" />
-        <result column="log_money" property="logMoney" />
+        <result column="available_money" property="availableMoney" />
         <result column="pay_type" property="payType" />
         <result column="user_name" property="userName" />
         <result column="card_no" property="cardNo" />
@@ -24,7 +24,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, channel_id, money, charge_amt, log_money, pay_type, user_name, card_no, bank_name, branch_name, status, transfer_img, verify_content, verifier, create_time, update_time
+        id, channel_id, money, charge_amt, available_money, pay_type, user_name, card_no, bank_name, branch_name, status, transfer_img, verify_content, verifier, create_time, update_time
     </sql>
 
 </mapper>

+ 2 - 3
mp-service/src/main/resources/mapper/user/UserCoinLogMapper.xml

@@ -12,7 +12,6 @@
         <result column="income_expense" property="incomeExpense" />
         <result column="log_text" property="logText" />
         <result column="biz_time" property="bizTime" />
-        <result column="ref_type" property="refType" />
         <result column="ref_id" property="refId" />
         <result column="created_time" property="createdTime" />
         <result column="updated_time" property="updatedTime" />
@@ -20,7 +19,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, user_id, type, money, log_money, income_expense, log_text, biz_time, ref_type, ref_id, created_time, updated_time
+        id, user_id, type, money, log_money, income_expense, log_text, biz_time, ref_id, created_time, updated_time
     </sql>
 
-</mapper>
+</mapper>