Browse Source

Merge branch 'master' of http://115.29.66.169:10080/yiyao_shop/api

lubo 4 months ago
parent
commit
d6c5aea8ad
21 changed files with 385 additions and 33 deletions
  1. 11 14
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/IndexController.java
  2. 24 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/shop/withdrawal/WithdrawalController.java
  3. 14 0
      ruoyi-api/src/main/java/com/ruoyi/api/controller/business/ApiBusinessIntegralVerifierController.java
  4. 20 0
      ruoyi-api/src/main/java/com/ruoyi/api/controller/shop/ApiSaleRightsOrderController.java
  5. 20 1
      ruoyi-api/src/main/java/com/ruoyi/api/controller/shop/ApiShopOrderPackageController.java
  6. 2 0
      ruoyi-api/src/main/java/com/ruoyi/api/controller/shop/ApiUserBusinessRoleController.java
  7. 5 1
      ruoyi-line/src/main/java/com/ruoyi/subsidy/domain/bo/SubsidyQueueBo.java
  8. 3 1
      ruoyi-line/src/main/java/com/ruoyi/subsidy/service/impl/SubsidyQueueServiceImpl.java
  9. 2 1
      ruoyi-shop/src/main/java/com/ruoyi/shop/order/service/impl/ShopOrderPackageServiceImpl.java
  10. 4 0
      ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/domain/Withdrawal.java
  11. 19 0
      ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/domain/bo/WithdrawalBo.java
  12. 7 1
      ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/exception/WithdrawalExceptionEnum.java
  13. 9 0
      ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/mapper/WithdrawalMapper.java
  14. 9 3
      ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/service/IWithdrawalService.java
  15. 142 3
      ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/service/impl/WithdrawalServiceImpl.java
  16. 69 0
      ruoyi-shop/src/main/resources/mapper/withdrawal/WithdrawalMapper.xml
  17. 2 1
      ruoyi-user/src/main/java/com/ruoyi/user/enums/BalanceSourceType.java
  18. 2 3
      ruoyi-user/src/main/java/com/ruoyi/user/mapper/UserMapper.java
  19. 2 0
      ruoyi-user/src/main/java/com/ruoyi/user/service/IUserService.java
  20. 8 4
      ruoyi-user/src/main/java/com/ruoyi/user/service/impl/UserServiceImpl.java
  21. 11 0
      ruoyi-user/src/main/resources/mapper/user/UserMapper.xml

+ 11 - 14
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/IndexController.java

@@ -1,34 +1,25 @@
 package com.ruoyi.web.controller.common;
 
-import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.ruoyi.businessDayBill.domain.bo.BusinessDayBillBo;
 import com.ruoyi.businessDayBill.domain.bo.BusinessDayBillCountBo;
 import com.ruoyi.businessDayBill.domain.vo.BusinessDayBillVo;
 import com.ruoyi.businessDayBill.service.IBusinessDayBillService;
-import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.R;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.validate.QueryGroup;
-import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.onlineorder.domain.bo.OnlineOrderBo;
-import com.ruoyi.onlineorder.domain.vo.OnlineOrderVo;
 import com.ruoyi.onlineorder.service.IOnlineOrderService;
-import com.ruoyi.subsidy.enums.SubsidyCountType;
+import com.ruoyi.shop.withdrawal.service.IWithdrawalService;
 import com.ruoyi.subsidy.service.ISubsidyQueueService;
+import com.ruoyi.user.service.IUserService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
 import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.constraints.NotNull;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -50,6 +41,8 @@ public class IndexController extends BaseController {
     private final IOnlineOrderService iOnlineOrderService;
     private final ISubsidyQueueService iSubsidyQueueService;
     private final IBusinessDayBillService iBusinessDayBillService;
+    private final IUserService userService;
+    private final IWithdrawalService withdrawalService;
 
     /**
      * 平台顶部简单统计
@@ -64,6 +57,8 @@ public class IndexController extends BaseController {
         map.put("todayAmount", ObjectUtil.isNotNull( statistics)? statistics.getActualReceivePayment() : 0);
         map.put("todayOrderNum", ObjectUtil.isNotNull( statistics)? statistics.getOnlineOrderNum()+statistics.getShopOrderNum() : 0);
         map.put("queueCount", iSubsidyQueueService.validQueueCount(null,false));
+        map.put("activeUser", userService.activeUserCount(null));
+        map.put("withdrawalAmount", withdrawalService.auditingWithdrawalAmount());
         return R.ok( map);
     }
 
@@ -82,6 +77,8 @@ public class IndexController extends BaseController {
         map.put("todayAmount", ObjectUtil.isNotNull( statistics)? statistics.getActualReceivePayment() : 0);
         map.put("todayOrderNum", ObjectUtil.isNotNull( statistics)? statistics.getOnlineOrderNum()+statistics.getShopOrderNum() : 0);
         map.put("queueCount", iSubsidyQueueService.validQueueCount(businessId,false));
+        //活跃用户
+        map.put("activeUser", userService.activeUserCount(businessId));
         return R.ok( map);
     }
 

+ 24 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/shop/withdrawal/WithdrawalController.java

@@ -3,6 +3,7 @@ package com.ruoyi.web.controller.shop.withdrawal;
 import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.hutool.json.JSONArray;
 import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.domain.R;
@@ -57,6 +58,16 @@ public class WithdrawalController extends BaseController {
         return R.ok(map);
     }
 
+    /**
+     * 查询提现统计
+     */
+    @ApiOperation("查询提现统计")
+    @SaCheckPermission("withdrawal:withdrawal:list")
+    @GetMapping("/statistics")
+    public R<WithdrawalVo> statistics(WithdrawalBo bo) {
+        return R.ok(iWithdrawalService.statistics(bo));
+    }
+
     /**
      * 分页查询提现列表
      */
@@ -91,4 +102,17 @@ public class WithdrawalController extends BaseController {
         ExcelUtil.exportExcel(list, "提现", WithdrawalVo.class, response);
     }
 
+    /**
+     * 审核提现
+     */
+    @ApiOperation("审核提现")
+    @SaCheckPermission("withdrawal:withdrawal:audit")
+    @Log(title = "提现", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PostMapping("/audit")
+    public R<Void> audit(@Validated @RequestBody WithdrawalBo bo) {
+        bo.setAuditUserId(getUserId());
+        return toAjax(iWithdrawalService.audit(bo));
+    }
+
 }

+ 14 - 0
ruoyi-api/src/main/java/com/ruoyi/api/controller/business/ApiBusinessIntegralVerifierController.java

@@ -16,10 +16,13 @@ import com.ruoyi.shop.business.service.IUserBusinessRoleService;
 import com.ruoyi.user.domain.vo.UserVo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
 import lombok.RequiredArgsConstructor;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.constraints.NotBlank;
+
 /**
  * 商家积分核销
  *
@@ -46,6 +49,17 @@ public class ApiBusinessIntegralVerifierController extends AbstractApiController
         return R.ok(userBusinessRoleService.queryUserInfo(userId, getBusinessByUserId(getUserId(true), true)));
     }
 
+    @ApiOperation("判断核销码是否有效")
+    @GetMapping("/verificationCodeIsValid")
+    public R<Void> verificationCodeIsValid(@ApiParam("核销码") @NotBlank(message = "核销码不能为空") String verificationCode) {
+        Long userId = RedisUtils.getCacheObject(Constants.MEMBER_CODE + verificationCode);
+        if(userId == null)
+        {
+            return R.fail("核销码不存在");
+        }
+        return R.ok();
+    }
+
     /**
      * 积分核销
      */

+ 20 - 0
ruoyi-api/src/main/java/com/ruoyi/api/controller/shop/ApiSaleRightsOrderController.java

@@ -1,5 +1,6 @@
 package com.ruoyi.api.controller.shop;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.api.controller.common.AbstractApiController;
@@ -10,6 +11,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.FilePathSplicingType;
 import com.ruoyi.common.filepathsplicing.FilePathSplicing;
+import com.ruoyi.shop.order.enums.OrderType;
 import com.ruoyi.shop.rights.domain.bo.SaleRightsOrderBo;
 import com.ruoyi.shop.rights.domain.bo.SaleRightsOrderShipRecordBo;
 import com.ruoyi.shop.rights.domain.vo.RightsMoneyVo;
@@ -41,6 +43,23 @@ public class ApiSaleRightsOrderController extends AbstractApiController {
     private final ISaleRightsOrderService iSaleRightsOrderService;
     private final IRightsMqService rightsMqService;
 
+    @FilePathSplicing(type = FilePathSplicingType.RESPONSE)
+    @ApiOperation("商家分页查询维权单列表")
+    @GetMapping("/business-page")
+    public TableDataInfo<SaleRightsOrderVo> businessPage(@Validated(QueryGroup.class) SaleRightsOrderBo bo, PageQuery pageQuery) {
+        bo.setBusinessId(getBusinessByUserId(getUserId(true),true));
+        bo.setOrderType(OrderType.NORMAL);
+        if(ObjectUtil.isNotNull(bo.getStartTime()))
+        {
+            bo.setStartTime(DateUtil.beginOfDay(bo.getStartTime()));
+        }
+        if(ObjectUtil.isNotNull(bo.getEndTime()))
+        {
+            bo.setEndTime(DateUtil.endOfDay(bo.getEndTime()));
+        }
+        return iSaleRightsOrderService.queryPageList(bo, pageQuery);
+    }
+
     /**
      * 分页查询维权单列表
      */
@@ -49,6 +68,7 @@ public class ApiSaleRightsOrderController extends AbstractApiController {
     @GetMapping("/page")
     public TableDataInfo<SaleRightsOrderVo> page(@Validated(QueryGroup.class) SaleRightsOrderBo bo, PageQuery pageQuery) {
         bo.setUserId(getUserId(true));
+        bo.setOrderType(OrderType.NORMAL);
         return iSaleRightsOrderService.queryPageList(bo, pageQuery);
     }
 

+ 20 - 1
ruoyi-api/src/main/java/com/ruoyi/api/controller/shop/ApiShopOrderPackageController.java

@@ -13,7 +13,7 @@ import com.ruoyi.common.core.validate.EditGroup;
 import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.FilePathSplicingType;
 import com.ruoyi.common.filepathsplicing.FilePathSplicing;
-import com.ruoyi.shop.order.domain.ShopOrder;
+import com.ruoyi.shop.order.domain.ShopOrderPackagePickup;
 import com.ruoyi.shop.order.domain.bo.*;
 import com.ruoyi.shop.order.domain.vo.ShopOrderPackageExpressVo;
 import com.ruoyi.shop.order.domain.vo.ShopOrderPackageVo;
@@ -21,6 +21,8 @@ import com.ruoyi.shop.order.domain.vo.ShopOrderVo;
 import com.ruoyi.shop.order.enums.PackageStatus;
 import com.ruoyi.shop.order.enums.PackageType;
 import com.ruoyi.shop.order.enums.VerificationRole;
+import com.ruoyi.shop.order.enums.VerificationStatus;
+import com.ruoyi.shop.order.service.IShopOrderPackagePickupService;
 import com.ruoyi.shop.order.service.IShopOrderPackageService;
 import com.ruoyi.shop.order.service.mqproduct.IShopOrderMqProductService;
 import io.swagger.annotations.Api;
@@ -31,6 +33,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.util.Date;
 import java.util.HashMap;
@@ -53,6 +56,7 @@ public class ApiShopOrderPackageController extends AbstractApiController {
 
     private final IShopOrderPackageService shopOrderPackageService;
     private final IShopOrderMqProductService shopOrderMqProductService;
+    private final IShopOrderPackagePickupService shopOrderPackagePickupService;
 
     /**
      * 查看物流跟踪
@@ -123,6 +127,7 @@ public class ApiShopOrderPackageController extends AbstractApiController {
         Map<String, Object> map = new HashMap<>();
         map.put("todayCount", todayCount);
         map.put("weekCount", weekCount);
+        map.put("totalCount", shopOrderPackageService.businessSimpleCount(BusinessCountBo.builder().businessId(businessId).build()));
         return R.ok(map);
     }
 
@@ -185,6 +190,20 @@ public class ApiShopOrderPackageController extends AbstractApiController {
         return R.ok(order);
     }
 
+    @ApiOperation("判断核销码是否有效")
+    @GetMapping("/verificationCodeIsValid")
+    public R<Void> verificationCodeIsValid(@ApiParam("核销码") @NotBlank(message = "核销码不能为空") String verificationCode) {
+        ShopOrderPackagePickup shopOrderPackagePickup = shopOrderPackagePickupService.loadByVerificationCode(verificationCode);
+        if(ObjectUtil.isNull(shopOrderPackagePickup))
+        {
+            return R.fail("核销码无效");
+        }
+        if(VerificationStatus.VERIFIED.equals(shopOrderPackagePickup.getVerificationStatus()))
+        {
+            return R.fail("核销码已核销");
+        }
+        return R.ok();
+    }
 
 
     /**

+ 2 - 0
ruoyi-api/src/main/java/com/ruoyi/api/controller/shop/ApiUserBusinessRoleController.java

@@ -92,12 +92,14 @@ public class ApiUserBusinessRoleController extends AbstractApiController {
     /**
      * 获取会员在店铺详细信息
      */
+    @FilePathSplicing(type = FilePathSplicingType.RESPONSE)
     @ApiOperation("获取会员在店铺详细信息")
     @GetMapping("/userInfo")
     public R<UserBusinessRoleVo> userInfo() {
         Long userId = getUserId(true);
         UserBusinessRoleVo userBusinessRoleVo = iUserBusinessRoleService.queryByUser(userId);
         if (ObjectUtil.isNotNull(userBusinessRoleVo)) {
+            userBusinessRoleVo.setBusinessVo(businessService.queryById(userBusinessRoleVo.getBusinessId()));
             userBusinessRoleVo.setIsBoundMore(iUserBusinessRoleService.isBoundMore(userId));
         }
         return R.ok(userBusinessRoleVo);

+ 5 - 1
ruoyi-line/src/main/java/com/ruoyi/subsidy/domain/bo/SubsidyQueueBo.java

@@ -271,5 +271,9 @@ public class SubsidyQueueBo extends BaseTimeEntity {
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date queueEndTime;
 
-
+    /**
+     * 排序的方向desc或者asc
+     */
+    @ApiModelProperty(value = "排序的方向")
+    private String isAsc = "asc";
 }

+ 3 - 1
ruoyi-line/src/main/java/com/ruoyi/subsidy/service/impl/SubsidyQueueServiceImpl.java

@@ -194,8 +194,10 @@ public class SubsidyQueueServiceImpl implements ISubsidyQueueService {
             lqw.le(SubsidyQueue::getQueueTime, bo.getQueueEndTime());
         }
 
-        if (bo.getCurrentBusinessId() == null) {
+        if ("asc".equals(bo.getIsAsc())) {
             lqw.orderByAsc(SubsidyQueue::getQueueOrder);
+        } else {
+            lqw.orderByDesc(SubsidyQueue::getQueueOrder);
         }
         return lqw;
     }

+ 2 - 1
ruoyi-shop/src/main/java/com/ruoyi/shop/order/service/impl/ShopOrderPackageServiceImpl.java

@@ -773,7 +773,8 @@ public class ShopOrderPackageServiceImpl implements IShopOrderPackageService {
     public Long businessSimpleCount(BusinessCountBo today) {
         return this.baseMapper.selectCount(new LambdaQueryWrapper<ShopOrderPackage>()
             .eq(ShopOrderPackage::getBusinessId, today.getBusinessId())
-            .between(ShopOrderPackage::getReceiptTime, today.getStartTime(), today.getEndTime())
+            .between(ObjectUtil.isNotNull(today.getStartTime()) && ObjectUtil.isNotNull(today.getEndTime()),
+                ShopOrderPackage::getReceiptTime, today.getStartTime(), today.getEndTime())
             .eq(ShopOrderPackage::getPackageStatus, PackageStatus.RECEIPTED)
             .eq(ShopOrderPackage::getPackageType, PackageType.SELF_PICKUP)
 

+ 4 - 0
ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/domain/Withdrawal.java

@@ -86,4 +86,8 @@ public class Withdrawal extends BaseTimeEntity {
      */
     private String auditResult;
 
+    /**
+     * 第三方单号
+     */
+    private String thirdOrderId;
 }

+ 19 - 0
ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/domain/bo/WithdrawalBo.java

@@ -1,5 +1,6 @@
 package com.ruoyi.shop.withdrawal.domain.bo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
 import com.ruoyi.common.enums.AuditStatus;
@@ -17,6 +18,7 @@ import java.util.Date;
 import java.math.BigDecimal;
 
 import com.ruoyi.common.core.domain.BaseEntity;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * 提现业务对象 tb_withdrawal
@@ -78,6 +80,14 @@ public class WithdrawalBo extends BaseEntity {
      */
     @ApiModelProperty(value = "实际打款时间", required = true)
     private Date paymentTime;
+    @ApiModelProperty(value = "查询-打款开始时间", required = true)
+    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date paymentStartTime;
+    @ApiModelProperty(value = "查询-打款结束时间", required = true)
+    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date paymentEndTime;
 
     /**
      * 提现方式
@@ -127,4 +137,13 @@ public class WithdrawalBo extends BaseEntity {
     @ApiModelProperty(value = "用户密码", required = true)
     @NotBlank(message = "用户密码不能为空", groups = { AddGroup.class, EditGroup.class })
     private String payPassword;
+
+    @ApiModelProperty(value = "查询-创建开始时间", required = true)
+    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date createStartTime;
+    @ApiModelProperty(value = "查询-创建结束时间", required = true)
+    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date createEndTime;
 }

+ 7 - 1
ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/exception/WithdrawalExceptionEnum.java

@@ -13,7 +13,13 @@ public enum WithdrawalExceptionEnum implements IIntegerEnum {
     Withdrawal_IS_NOT_EXISTS(490001, "提现不存在"),
     WITHDRAWAL_AMOUNT_NOT_ENOUGH(490002, "提现金额不足"),
     WITHDRAWAL_AMOUNT_TOO_MUCH(490003, "提现金额超出最大限制"),
-    WITHDRAWAL_FEE_NOT_MATCH(490004, "提现手续费不匹配");
+    WITHDRAWAL_FEE_NOT_MATCH(490004, "提现手续费不匹配"),
+    WITHDRAWAL_STATUS_NOT_WAIT_AUDIT(490005, "提现状态不是待审核"),
+    WITHDRAWAL_AUDIT_STATUS_NOT_SUPPORT(490006, "提现审核状态错误"),
+    WITHDRAWAL_AUDIT_RESULT_NOT_EMPTY(490007, "提现审核结果不能为空"),
+    WITHDRAWAL_STATUS_SUCCESS(490008, "提现已到账 无法重复操作!"),
+    WITHDRAWAL_THIRD_ORDER_ID_EMPTY(490009, "第三方提现失败"),
+    ;
 
     private Integer code;
 

+ 9 - 0
ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/mapper/WithdrawalMapper.java

@@ -1,11 +1,14 @@
 package com.ruoyi.shop.withdrawal.mapper;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.mapper.BaseMapperPlus;
 import com.ruoyi.shop.withdrawal.domain.Withdrawal;
+import com.ruoyi.shop.withdrawal.domain.bo.WithdrawalBo;
 import com.ruoyi.shop.withdrawal.domain.vo.WithdrawalVo;
 import org.apache.ibatis.annotations.Param;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * 提现Mapper接口
@@ -17,4 +20,10 @@ public interface WithdrawalMapper extends BaseMapperPlus<WithdrawalMapper, Withd
 
     BigDecimal withdrawing(@Param("withdrawalSourceId") Long withdrawalSourceId
         , @Param("withdrawalSource") Integer withdrawalSource, @Param("auditStatus") Integer auditStatus);
+
+    Page<WithdrawalVo> selectWithdrawaPage(@Param("page") Page<Object> build, @Param("bo") WithdrawalBo bo);
+
+    List<WithdrawalVo> selectWithdrawaList(@Param("bo") WithdrawalBo bo);
+
+    WithdrawalVo statistics(@Param("bo") WithdrawalBo bo);
 }

+ 9 - 3
ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/service/IWithdrawalService.java

@@ -1,11 +1,11 @@
 package com.ruoyi.shop.withdrawal.service;
 
+import com.ruoyi.common.core.domain.PageQuery;
+import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.shop.withdrawal.domain.Withdrawal;
+import com.ruoyi.shop.withdrawal.domain.bo.WithdrawalBo;
 import com.ruoyi.shop.withdrawal.domain.vo.WithdrawalAmountVo;
 import com.ruoyi.shop.withdrawal.domain.vo.WithdrawalVo;
-import com.ruoyi.shop.withdrawal.domain.bo.WithdrawalBo;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.shop.withdrawal.enums.WithdrawalSource;
 
 import java.math.BigDecimal;
@@ -90,4 +90,10 @@ public interface IWithdrawalService {
     TableDataInfo<WithdrawalVo> queryWithdrawaPageList(WithdrawalBo bo, PageQuery pageQuery);
 
     List<WithdrawalVo> queryWithdrawaList(WithdrawalBo bo);
+
+    WithdrawalVo statistics(WithdrawalBo bo);
+
+    Boolean audit(WithdrawalBo bo);
+
+    BigDecimal auditingWithdrawalAmount();
 }

+ 142 - 3
ruoyi-shop/src/main/java/com/ruoyi/shop/withdrawal/service/impl/WithdrawalServiceImpl.java

@@ -4,10 +4,17 @@ import cn.dev33.satoken.secure.BCrypt;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.domain.AlipayFundTransUniTransferModel;
+import com.alipay.api.domain.Participant;
+import com.alipay.api.request.AlipayFundTransUniTransferRequest;
+import com.alipay.api.response.AlipayFundTransUniTransferResponse;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.agent.domain.Agent;
+import com.ruoyi.agent.domain.bo.AgentChangeBalanceBo;
 import com.ruoyi.agent.service.IAgentService;
 import com.ruoyi.base.revenue.domain.vo.RevenueSharingConfigVo;
 import com.ruoyi.base.revenue.service.IRevenueSharingConfigService;
@@ -15,6 +22,7 @@ import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.AuditStatus;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.properties.AlipayProperties;
 import com.ruoyi.common.utils.BeanCopyUtils;
 import com.ruoyi.common.utils.MathUtils;
 import com.ruoyi.common.utils.StringUtils;
@@ -22,6 +30,7 @@ import com.ruoyi.shop.withdrawal.domain.Withdrawal;
 import com.ruoyi.shop.withdrawal.domain.bo.WithdrawalBo;
 import com.ruoyi.shop.withdrawal.domain.vo.WithdrawalAmountVo;
 import com.ruoyi.shop.withdrawal.domain.vo.WithdrawalVo;
+import com.ruoyi.shop.withdrawal.enums.WithdrawalMethod;
 import com.ruoyi.shop.withdrawal.enums.WithdrawalSource;
 import com.ruoyi.shop.withdrawal.enums.WithdrawalStatus;
 import com.ruoyi.shop.withdrawal.exception.WithdrawalExceptionEnum;
@@ -30,12 +39,19 @@ import com.ruoyi.shop.withdrawal.service.IWithdrawalService;
 import com.ruoyi.system.enums.SequencePrefixEnum;
 import com.ruoyi.system.service.ISysSequenceService;
 import com.ruoyi.user.domain.User;
+import com.ruoyi.user.domain.bo.UserChangeBalanceBo;
+import com.ruoyi.user.enums.BalanceSourceType;
 import com.ruoyi.user.service.IUserService;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 提现Service业务层处理
@@ -43,6 +59,7 @@ import java.util.*;
  * @author ruoyi
  * @date 2025-12-04
  */
+@Slf4j
 @RequiredArgsConstructor
 @Service
 public class WithdrawalServiceImpl implements IWithdrawalService {
@@ -52,6 +69,7 @@ public class WithdrawalServiceImpl implements IWithdrawalService {
     private final IAgentService agentService;
     private final IRevenueSharingConfigService revenueSharingConfigService;
     private final ISysSequenceService sysSequenceService;
+    private final AlipayProperties aliPayConfig;
 
     /**
      * 查询提现分页
@@ -252,12 +270,133 @@ public class WithdrawalServiceImpl implements IWithdrawalService {
 
     @Override
     public TableDataInfo<WithdrawalVo> queryWithdrawaPageList(WithdrawalBo bo, PageQuery pageQuery) {
-        return null;
+        Page<WithdrawalVo> result = baseMapper.selectWithdrawaPage(pageQuery.build(), bo);
+        return TableDataInfo.build(result);
     }
 
     @Override
     public List<WithdrawalVo> queryWithdrawaList(WithdrawalBo bo) {
-        return Collections.emptyList();
+        return baseMapper.selectWithdrawaList(bo);
+    }
+
+    @Override
+    public WithdrawalVo statistics(WithdrawalBo bo) {
+        return baseMapper.statistics(bo);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Boolean audit(WithdrawalBo bo) {
+        Withdrawal withdrawal = loadLockById(bo.getId());
+        if (!AuditStatus.WAIT_AUDIT.equals(withdrawal.getAuditStatus())) {
+            throw new ServiceException(WithdrawalExceptionEnum.WITHDRAWAL_STATUS_NOT_WAIT_AUDIT);
+        }
+        if (WithdrawalStatus.SUCCESS.equals(withdrawal.getStatus())) {
+            throw new ServiceException(WithdrawalExceptionEnum.WITHDRAWAL_STATUS_SUCCESS);
+        }
+        if (AuditStatus.AUDIT_PASS.equals(bo.getAuditStatus())) {
+            BigDecimal amount = withdrawal.getAmount();
+            WithdrawalAmountVo amountVo = amount(withdrawal.getWithdrawalSourceId(), withdrawal.getWithdrawalSource());
+            if (amountVo.getAbleAmount().compareTo(amount) < 0) {
+                throw new ServiceException(WithdrawalExceptionEnum.WITHDRAWAL_AMOUNT_NOT_ENOUGH);
+            }
+            BigDecimal paymentAmount = amount.subtract(withdrawal.getFee());
+            //调用支付宝 转账
+            String thirdOrderId = null;
+            if (WithdrawalMethod.ALIPAY.equals(withdrawal.getWithdrawalMethod())) {
+                thirdOrderId = alipayFundTrans(withdrawal.getWithdrawalNo(), paymentAmount, "平台提现", withdrawal.getAccountInfo());
+            }
+            if (StringUtils.isEmpty(thirdOrderId)) {
+                throw new ServiceException(WithdrawalExceptionEnum.WITHDRAWAL_THIRD_ORDER_ID_EMPTY);
+            }
+            withdrawal.setThirdOrderId(thirdOrderId);
+            //扣减钱包
+            if (WithdrawalSource.USER.equals(withdrawal.getWithdrawalSource())) {
+                userService.changeUserBalance(UserChangeBalanceBo.builder()
+                    .userId(withdrawal.getWithdrawalSourceId())
+                    .entryValue(amount)
+                    .isAdd(false)
+                    .sourceType(BalanceSourceType.WITHDRAWAL)
+                    .sourceId(withdrawal.getId())
+                    .sourceCode(withdrawal.getWithdrawalNo())
+                    .remark("提现扣减")
+                    .build());
+            } else if (WithdrawalSource.AGENT.equals(withdrawal.getWithdrawalSource())) {
+                agentService.changeAgentBalance(AgentChangeBalanceBo.builder()
+                    .agentId(withdrawal.getWithdrawalSourceId())
+                    .entryValue(amount)
+                    .isAdd(false)
+                    .sourceType(com.ruoyi.agent.enums.BalanceSourceType.WITHDRAW)
+                    .sourceId(withdrawal.getId())
+                    .sourceCode(withdrawal.getWithdrawalNo())
+                    .remark("提现扣减")
+                    .build());
+            }
+            withdrawal.setStatus(WithdrawalStatus.SUCCESS);
+            withdrawal.setPaymentAmount(paymentAmount);
+            withdrawal.setPaymentTime(new Date());
+        } else if (AuditStatus.AUDIT_NOT_PASS.equals(bo.getAuditStatus())) {
+            if (StringUtils.isEmpty(bo.getAuditResult())) {
+                throw new ServiceException(WithdrawalExceptionEnum.WITHDRAWAL_AUDIT_RESULT_NOT_EMPTY);
+            }
+            withdrawal.setStatus(WithdrawalStatus.FAIL);
+        } else {
+            throw new ServiceException(WithdrawalExceptionEnum.WITHDRAWAL_AUDIT_STATUS_NOT_SUPPORT);
+        }
+        withdrawal.setAuditStatus(bo.getAuditStatus());
+        withdrawal.setAuditTime(new Date());
+        withdrawal.setAuditUserId(bo.getAuditUserId());
+        withdrawal.setAuditResult(bo.getAuditResult());
+        return baseMapper.updateById(withdrawal) > 0;
+    }
+
+    @Override
+    public BigDecimal auditingWithdrawalAmount() {
+        return null;
+    }
+
+    private String alipayFundTrans(String withdrawalNo, BigDecimal amount, String title, String identity) {
+        try {
+            AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getServerUrl(), // 支付宝网关(固定)
+                aliPayConfig.getAppId(), // APPID 即创建应用后生成
+                aliPayConfig.getAppPrivateKey(), // 开发者私钥,由开发者自己生成
+                aliPayConfig.getFormat(), // 参数返回格式,只支持json
+                aliPayConfig.getCharset(), // 编码集,支持GBK/UTF-8
+                aliPayConfig.getAlipayPublicKey(), // 支付宝公钥,由支付宝生成
+                aliPayConfig.getSignType()); // 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
+            // 构造请求参数以调用接口
+            AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
+            AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
+            // 设置商家侧唯一订单号
+            model.setOutBizNo(withdrawalNo);
+            // 设置订单总金额
+            model.setTransAmount(amount.toString());
+            // 设置描述特定的业务场景
+            model.setBizScene("DIRECT_TRANSFER");
+            // 设置业务产品码
+            model.setProductCode("TRANS_ACCOUNT_NO_PWD");
+            // 设置转账业务的标题
+            model.setOrderTitle(title);
+            // 设置收款方信息
+            Participant payeeInfo = new Participant();
+            payeeInfo.setIdentity(identity);
+            payeeInfo.setIdentityType("ALIPAY_LOGON_ID");
+            model.setPayeeInfo(payeeInfo);
+            request.setBizModel(model);
+            AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
+            if (response.isSuccess() && "SUCCESS".equals(response.getStatus())) {
+                return response.getOrderId();
+            } else {
+                log.info("支付宝转账失败{},{}", response.getMsg(), response.getSubMsg());
+            }
+        } catch (Exception e) {
+            log.error("支付宝转账异常", e);
+        }
+        return null;
+    }
+
+    private Withdrawal loadLockById(Long id) {
+        return baseMapper.selectOne(new LambdaQueryWrapper<Withdrawal>().eq(Withdrawal::getId, id).last("limit 1 for update"));
     }
 
 }

+ 69 - 0
ruoyi-shop/src/main/resources/mapper/withdrawal/WithdrawalMapper.xml

@@ -22,6 +22,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="auditResult" column="audit_result"/>
         <result property="createTime" column="create_time"/>
         <result property="updateTime" column="update_time"/>
+        <result property="thirdOrderId" column="third_order_id"/>
     </resultMap>
 
     <select id="withdrawing" resultType="java.math.BigDecimal">
@@ -31,5 +32,73 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             and audit_status = #{auditStatus}
     </select>
 
+    <select id="selectWithdrawaPage" resultType="com.ruoyi.shop.withdrawal.domain.vo.WithdrawalVo">
+        <include refid="query"/>
+    </select>
+
+    <select id="selectWithdrawaList" resultType="com.ruoyi.shop.withdrawal.domain.vo.WithdrawalVo">
+        <include refid="query"/>
+    </select>
+
+    <select id="statistics" resultType="com.ruoyi.shop.withdrawal.domain.vo.WithdrawalVo">
+        select sum(amount) amount, sum(fee) fee, sum(payment_amount) paymentAmount
+            from tb_withdrawal w
+                 left join tb_user u on w.withdrawal_source_id = u.id
+                 left join tb_agent a on w.withdrawal_source_id = a.agent_id
+        <include refid="where"/>
+    </select>
+
+    <sql id="query">
+        select w.*,
+               CASE
+                   WHEN w.withdrawal_source = 1 THEN u.nickname
+                   WHEN w.withdrawal_source = 2 THEN a.real_name
+                   ELSE NULL
+               END AS withdrawalName,
+                CASE
+                   WHEN w.withdrawal_source = 1 THEN u.mobile
+                   WHEN w.withdrawal_source = 2 THEN a.phone
+                   ELSE NULL
+               END AS withdrawalPhone
+        from tb_withdrawal w
+        left join tb_user u on w.withdrawal_source_id = u.id
+        left join tb_agent a on w.withdrawal_source_id = a.agent_id
+        <include refid="where"/>
+    </sql>
+
+    <sql id="where">
+        <where>
+            <if test="bo.withdrawalNo != null and bo.withdrawalNo != ''">
+                and w.withdrawal_no like concat('%', #{bo.withdrawalNo}, '%')
+            </if>
+            <if test="bo.withdrawalPhone != null and bo.withdrawalPhone != ''">
+                and (u.mobile like concat('%', #{bo.withdrawalPhone}, '%') or a.phone like concat('%', #{bo.withdrawalPhone}, '%'))
+            </if>
+            <if test="bo.withdrawalName != null and bo.withdrawalName != ''">
+                and (u.nickname like concat('%', #{bo.withdrawalName}, '%') or a.real_name like concat('%', #{bo.withdrawalName}, '%'))
+            </if>
+            <if test="bo.withdrawalSource != null">
+                and w.withdrawal_source = #{bo.withdrawalSource.code}
+            </if>
+            <if test="bo.status != null">
+                and w.status = #{bo.status.code}
+            </if>
+            <if test="bo.withdrawalMethod != null">
+                and w.withdrawal_method = #{bo.withdrawalMethod.code}
+            </if>
+            <if test="bo.paymentStartTime != null">
+                and w.payment_time >= #{bo.paymentStartTime}
+            </if>
+            <if test="bo.paymentEndTime != null">
+                and w.payment_time &lt;= #{bo.paymentEndTime}
+            </if>
+            <if test="bo.createStartTime != null">
+                and w.create_time >= #{bo.createStartTime}
+            </if>
+            <if test="bo.createEndTime != null">
+                and w.create_time &lt;= #{bo.createEndTime}
+            </if>
+        </where>
+    </sql>
 
 </mapper>

+ 2 - 1
ruoyi-user/src/main/java/com/ruoyi/user/enums/BalanceSourceType.java

@@ -19,7 +19,8 @@ public enum BalanceSourceType implements IIntegerEnum {
     SUBSIDY(4, "消费排队补贴"),
     SHARED_SUBSIDY(5, "消费排队均摊补贴"),
     ONLINE_ORDER_REFUND_DEDUCT(6, "在线订单退款扣除补贴"),
-    SUBSIDY_OVERFLOW_RETURN(7, "消费排队均摊补贴溢出退回")
+    SUBSIDY_OVERFLOW_RETURN(7, "消费排队均摊补贴溢出退回"),
+    WITHDRAWAL(8, "提现"),
     ;
 
     @EnumValue

+ 2 - 3
ruoyi-user/src/main/java/com/ruoyi/user/mapper/UserMapper.java

@@ -1,14 +1,12 @@
 package com.ruoyi.user.mapper;
 
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.common.core.mapper.BaseMapperPlus;
 import com.ruoyi.user.domain.User;
-import com.ruoyi.user.domain.bo.UserBo;
-import com.ruoyi.user.domain.vo.UserManagerVo;
 import com.ruoyi.user.domain.vo.UserStatisticsVo;
 import com.ruoyi.user.domain.vo.UserVo;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -21,4 +19,5 @@ public interface UserMapper extends BaseMapperPlus<UserMapper, User, UserVo> {
 
     List<UserStatisticsVo> selectUserRegister(@Param("start") String start, @Param("end") String                                                end);
 
+    Long activeUserCount(@Param("businessId") Long businessId, @Param("start") Date start);
 }

+ 2 - 0
ruoyi-user/src/main/java/com/ruoyi/user/service/IUserService.java

@@ -180,4 +180,6 @@ public interface IUserService {
     String queryHeadPhotoById(Long userId);
 
     String getPhoneByCode(String encryptedData);
+
+    Long activeUserCount(Long businessId);
 }

+ 8 - 4
ruoyi-user/src/main/java/com/ruoyi/user/service/impl/UserServiceImpl.java

@@ -31,10 +31,7 @@ import com.ruoyi.common.enums.ExceptionEnum;
 import com.ruoyi.common.enums.InviteType;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.properties.AlipayProperties;
-import com.ruoyi.common.utils.IOSToeknUtils;
-import com.ruoyi.common.utils.ShareCodeUtils;
-import com.ruoyi.common.utils.SmsSend;
-import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.*;
 import com.ruoyi.common.utils.redis.RedisUtils;
 import com.ruoyi.common.utils.rest.RestUtil;
 import com.ruoyi.user.domain.User;
@@ -697,6 +694,13 @@ public class UserServiceImpl implements IUserService {
         return null;
     }
 
+    @Override
+    public Long activeUserCount(Long businessId) {
+        //24小时内登录过的
+        Date start = DateUtils.addDays(new Date(), -1);
+        return baseMapper.activeUserCount(businessId, start);
+    }
+
     private String generateUniqueMemberCode(Long userId) {
         //生成唯一码 用户不会重复 6-8位
         String userIdPart = String.valueOf(userId);

+ 11 - 0
ruoyi-user/src/main/resources/mapper/user/UserMapper.xml

@@ -28,4 +28,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         GROUP BY create_day
     </select>
 
+    <select id="activeUserCount" resultType="java.lang.Long">
+        select count(1) from tb_user u
+        <if test="businessId != null">
+            join tb_user_business_role ub on u.id = ub.user_id
+        </if>
+        where u.last_login_time &gt;= #{start}
+        <if test="businessId != null">
+            and ub.business_id = #{businessId}
+        </if>
+    </select>
+
 </mapper>