Pu Zhibing
2025-03-18 f615ec5c9239327740948501627545f8e78e2a9e
Merge remote-tracking branch 'origin/master'
58个文件已修改
13个文件已添加
2417 ■■■■ 已修改文件
a.json 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserClient.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/AppUser.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/UserPoint.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/factory/OrderClientFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/feignClient/OrderClient.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/ShopBalanceStatement.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/ShopBalanceStatementCopy.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/ShopPointCopy.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/ShopClientFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/ShopClient.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/SysUserFallbackFactory.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-auth/src/main/resources/bootstrap.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-gateway/src/main/resources/bootstrap.yml 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/resources/mapping/system/SysUserMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AgentApplicationController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserController.java 133 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserShopController.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/UserCouponController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/VipCenterController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/AppUserService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/VipCenterService.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/AppUserServiceImpl.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/BalanceChangeRecordServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserCouponServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserPointServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/VipCenterServiceImpl.java 483 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/WalletServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/util/weChat/WeChatUtil.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/bootstrap.yml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/AppUserMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/UserPointMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/CommissionController.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/JsapiServiceExample.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/OrderController.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ShoppingCartController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/ConfirmDeliveryEvent.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/ConfirmDeliveryEventListener.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEvent.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEventListener.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/CommissionServiceImpl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/ShoppingCartServiceImpl.java 77 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/OrderExport.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Contact.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Order.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/OrderKey.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Payer.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Shipping.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/bootstrap.yml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderGoodMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/CouponInfoController.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShareController.java 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShopBalanceStatementController.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShopController.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShopWithdrawController.java 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/SaveWithdrawalAccount.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/ShopBalanceStatementDetailPage.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/ShopCommission.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/ShopCommissionDetail.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/resources/bootstrap.yml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
a.json
@@ -1,26 +1,11 @@
{
  "appointStore": 2,
  "cashPayment": 1,
  "commodityAuthority": "-1",
  "delFlag": 0,
  "detail": "<p>124</p>",
  "detailPicture": "http://qijishenghuiyuan.obs.cn-southwest-2.myhuaweicloud.com/admin/ce9f63be73a64fd29449fcd1aae6ed8c.png",
  "distributionMode": "1",
  "goodsCategoryId": 21,
  "homePagePicture": "http://qijishenghuiyuan.obs.cn-southwest-2.myhuaweicloud.com/admin/9655a4f62a784daa8bd46b8881020183.png",
  "id": 71,
  "idStr": "71",
  "introduction": "1111",
  "name": "面部玫瑰精油",
  "operatingCost": 20.00,
  "originalPrice": 2.00,
  "pageCurr": 1,
  "pageSize": 10,
  "pointPayment": 0,
  "purchaseLimit": -1,
  "saleNum": 0,
  "sellingPrice": 15.00,
  "shopCost": 20.00,
  "status": 2,
  "type": 2
  "order_key": {
    "order_number_type": 2,
    "transaction_id": "4200002671202503143982490042"
  },
  "delivery_mode": 1,
  "logistics_type": 1,
  "shipping_list": "[]",
  "upload_time": "2025-03-14T22:34:59.709+08:00",
  "payer": "{\"openid\":\"ooOrs62ua63vzhaAeDZDwtH96o34\"}"
}
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java
@@ -118,6 +118,11 @@
                R.fail("检查会员等级变更失败:" + cause.getMessage());
            }
            
            @Override
            public void vipConsumption(Long appUserId) {
                R.fail("检查会员等级变更失败:" + cause.getMessage());
            }
            @Override
            public void vipDemotion(Long appUserId) {
                R.fail("检查会员等级降级失败:" + cause.getMessage());
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserClient.java
@@ -109,6 +109,12 @@
     */
    @PostMapping("/app-user/vipUpgrade")
    void vipUpgrade(@RequestParam("appUserId") Long appUserId);
    /**
     * 消费后检查会员等级变更
     */
    @PostMapping("/app-user/vipConsumption")
    void vipConsumption(@RequestParam("appUserId") Long appUserId);
    
    
    /**
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/AppUser.java
@@ -336,6 +336,9 @@
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastOrderTime;
    @TableField(exist = false)
    private Set<Long> userIds;
    public String getIdStr(){
        return String.valueOf(id);
    }
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/UserPoint.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiParam;
@@ -39,6 +40,7 @@
    @ApiModelProperty(value = "变动类型(1-消费,2-返佣,3-拉新,4-每日分享,5-每日签到,6-使用时长, 7-注册积分, 8-门店业绩," +
            "9-门店返佣,14-下级门店返佣,10-技师业绩,11-兑换商品,12-他人赠送,13-赠与他人,15-兑换券)")
    @Excel(name = "变动类型", readConverterExp = "1=消费积分,2=返佣积分,3=拉新人积分,4=每日分享,5=每日签到,6=使用时长,7=注册积分,8=门店业绩,9=门店返佣,14=下级门店返佣,10=技师业绩,11=兑换商品,12=他人赠送,13=赠与他人,15=兑换券")
    @TableField("type")
    private Integer type;
@@ -48,6 +50,7 @@
    @ApiModelProperty(value = "变动金额")
    @TableField("variable_point")
    @Excel(name = "变动金额")
    private Integer variablePoint;
    @ApiModelProperty(value = "变动后余额")
@@ -56,6 +59,7 @@
    @ApiModelProperty(value = "变动时间")
    @TableField("create_time")
    @Excel(name = "变动时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @ApiModelProperty(value = "变动用户id")
@@ -71,6 +75,7 @@
    private String extention;
    @ApiModelProperty(value = "用户名称")
    @Excel(name = "用户名称")
    @TableField(exist = false)
    private String userName;
    @ApiModelProperty(value = "变动类型 0未变化1增加2减少")
@@ -78,6 +83,7 @@
    private Integer variableType;
    @ApiModelProperty(value = "联系电话")
    @Excel(name = "联系电话")
    @TableField(exist = false)
    private String phone;
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/factory/OrderClientFallbackFactory.java
@@ -40,6 +40,11 @@
            }
            @Override
            public R<List<Order>> getRedeemedOrdersByShop(Integer shopId) {
                return R.fail("获取已核销的订单失败:" + cause.getMessage());
            }
            @Override
            public R<Order> getOrderById(Long id) {
                return R.fail("根据id获取订单详情失败:" + cause.getMessage());
            }
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/feignClient/OrderClient.java
@@ -54,6 +54,14 @@
    @PostMapping("/order/getAppUserByShoppingShop")
    R<Set<Long>> getAppUserByShoppingShop(@RequestParam("shopId") Integer shopId);
    /**
     * 获取指定门店的核销订单
     */
    @GetMapping("/order/getRedeemedOrdersByShop")
    R<List<Order>> getRedeemedOrdersByShop(@RequestParam("shopId") Integer shopId);
    /**
     * 根据id获取订单详情
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/ShopBalanceStatement.java
@@ -50,9 +50,9 @@
    @TableField(exist = false)
    @Excel(name = "联系电话")
    private String phone;
    @ApiModelProperty(value = "变动类型(1=绑定门店分佣,2=下级门店分佣,3=核销门店服务费,4=提现)")
    @ApiModelProperty(value = "变动类型(1=服务商分佣,2=高级服务商分佣,3=核销门店服务费,4=提现)")
    @TableField("type")
    @Excel(name = "变更类型",readConverterExp = "1=绑定门店分佣,2=下级门店分佣,3=核销门店服务费,4=提现")
    @Excel(name = "变更类型",readConverterExp = "1=服务商分佣,2=高级服务商分佣,3=核销门店服务费")
    private Integer type;
    @ApiModelProperty(value = "历史余额")
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/ShopBalanceStatementCopy.java
@@ -52,7 +52,7 @@
    private String phone;
    @ApiModelProperty(value = "变动类型(1=绑定门店分佣,2=下级门店分佣,3=核销门店服务费,4=提现)")
    @TableField("type")
    @Excel(name = "变更类型",readConverterExp = "1=绑定门店分佣,2=下级门店分佣,3=核销门店服务费,4=提现")
    @Excel(name = "变更类型",readConverterExp = "1=服务商分佣,2=高级服务商分佣,3=核销门店服务费,4=提现")
    private Integer type;
    @ApiModelProperty(value = "历史余额")
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/ShopPointCopy.java
@@ -25,7 +25,7 @@
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_shop_point")
@TableName("t_shop_point_copy")
@ApiModel(value="ShopPoint对象", description="")
public class ShopPointCopy implements Serializable {
@@ -117,4 +117,5 @@
    private Integer pageSize;
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/ShopClientFallbackFactory.java
@@ -44,6 +44,11 @@
            }
            @Override
            public R<Set<Long>> getManagerByManagerName(String managerName) {
                return R.fail("根据门店管理员名称获取门店id失败:" + cause.getMessage());
            }
            @Override
            public R<List<ShopBalanceStatement>> getShopBalanceStatementList(ShopBalanceStatement shopBalanceStatement) {
                return R.fail();
            }
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/ShopClient.java
@@ -50,6 +50,9 @@
    @PostMapping("/shop/getShopIdByName")
    R<Set<Integer>> getShopIdByName(@RequestParam("shopName") String shopName);
    @PostMapping("/shop/getManagerByManagerName")
    R<Set<Long>> getManagerByManagerName(@RequestParam("managerName") String managerName);
    @PostMapping("/shop-balance-statement/getList")
    R<List<ShopBalanceStatement>> getShopBalanceStatementList(@RequestBody ShopBalanceStatement shopBalanceStatement);
    
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/SysUserFallbackFactory.java
@@ -16,6 +16,7 @@
            @Override
            public R<SysUser> getSysUser(Long userId) {
                System.out.println(cause.getMessage());
                return R.fail("获取用户失败:" + cause.getMessage());
            }
ruoyi-auth/src/main/resources/bootstrap.yml
@@ -55,13 +55,13 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/HttpUtils.java
@@ -10,6 +10,10 @@
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
/**
 * 通用http发送方法
@@ -233,6 +237,21 @@
        return result.toString();
    }
    public static void main(String[] args) {
        // 获取当前时间,并指定时区偏移为 +08:00
        OffsetDateTime now = OffsetDateTime.now(ZoneOffset.of("+08:00"));
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx");
        // 将时间格式化为字符串
        String formattedDateTime = now.format(formatter);
        // 输出结果
        System.out.println(formattedDateTime);
    }
    public static String post(String strURL, String params) {
        String result = "";
        BufferedReader reader = null;
ruoyi-gateway/src/main/resources/bootstrap.yml
@@ -1,8 +1,7 @@
server:
  port: 9000
  port: 9600
  tomcat:
    basedir: /mnt/tomcat
    max-swallow-size: 100MB
# Spring
spring:
  application:
@@ -10,6 +9,7 @@
    name: ruoyi-gateway
  main:
    allow-bean-definition-overriding: true
    allow-circular-references: true
  profiles:
    # 环境配置
#    active: dev
@@ -24,41 +24,24 @@
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        service: ruoyi-gateway
        group: DEFAULT_GROUP
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        username:
        password:
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        username:
        password:
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        name: ruoyi-gateway
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - application.${spring.cloud.nacos.config.file-extension}
    sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 127.0.0.1:8718
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-ruoyi-gateway
            groupId: DEFAULT_GROUP
            username: nacos
            password: nacos
            data-type: json
            rule-type: gw-flow
---
spring:
  config:
@@ -113,33 +96,18 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        server-addr: 192.168.110.169:8848
        service: ruoyi-gateway
        group: DEFAULT_GROUP
        namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.169:8848
        namespace: 96712c7a-480b-4f40-b783-39f00f3b33ce
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        name: ruoyi-gateway
        # 配置文件格式
        file-extension: yml
        # 共享配置
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
    sentinel:
      # 取消控制台懒加载
      eager: true
      transport:
        # 控制台地址
        dashboard: 139.9.236.40:8718
      # nacos配置持久化
      datasource:
        ds1:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: sentinel-ruoyi-gateway
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: gw-flow
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.controller;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -31,6 +32,7 @@
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@@ -50,6 +52,7 @@
@RestController
@RequestMapping("/user")
@Api(tags = "用户信息")
@Slf4j
public class SysUserController extends BaseController {
    @Resource
    private ISysUserService userService;
@@ -130,7 +133,8 @@
        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) {
            return error("手机号已开通账号");
        }
        if (StringUtils.isNotEmpty(user.getUserName()) && !userService.checkUserNameUnique(user)) {
        if (StringUtils.isNotEmpty(user.getNickName()) && !userService.checkNickNameUnique(user)) {
            return error("登录账号重复");
        }
        //门店员工添加数据,需要判断账号是否存在,共用同一个账号
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -112,18 +112,19 @@
    /**
     * 校验用户名称是否唯一
     * 
     * @param userName 用户名称
     * @return 结果
     */
    SysUser checkUserNameUnique(String userName);
    SysUser checkUserNameUnique(SysUser user);
    SysUser checkNickNameUnique(SysUser sysUser);
    /**
     * 校验手机号码是否唯一
     *
     * @param phonenumber 手机号码
     * @return 结果
     */
    SysUser checkPhoneUnique(String phonenumber);
    SysUser checkPhoneUnique(SysUser sysUser);
    
    
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -81,6 +81,8 @@
     */
    boolean checkUserNameUnique(SysUser user);
    boolean checkNickNameUnique(SysUser user);
    /**
     * 校验手机号码是否唯一
     *
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.service.impl;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.api.feignClient.AppUserClient;
@@ -192,8 +193,18 @@
    @Override
    public boolean checkUserNameUnique(SysUser user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkUserNameUnique(user.getUserName());
        SysUser info = userMapper.checkUserNameUnique(user);
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }
    @Override
    public boolean checkNickNameUnique(SysUser user) {
        SysUser info = userMapper.checkNickNameUnique(user);
        System.err.println("aaaaa:"+(JSON.toJSONString(info)));
        if (StringUtils.isNotNull(info) ) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
@@ -208,7 +219,7 @@
    @Override
    public boolean checkPhoneUnique(SysUser user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
        SysUser info = userMapper.checkPhoneUnique(user);
        if (StringUtils.isNotNull(info)) {
            return UserConstants.NOT_UNIQUE;
        }
ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml
@@ -53,13 +53,13 @@
        server-addr: 127.0.0.1:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        namespace: 20c168da-8cf1-4fff-bc38-bc62df656b6a
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
ruoyi-modules/ruoyi-system/src/main/resources/mapping/system/SysUserMapper.xml
@@ -196,6 +196,10 @@
        </where>
        ORDER BY create_time DESC
    </select>
    <select id="checkNickNameUnique" resultMap="SysUserResult">
        select user_id, user_name from sys_user where nick_name = #{nickName}
        and del_flag = '0' limit 1
    </select>
    <insert id="insertUser" parameterType="com.ruoyi.system.api.domain.SysUser" useGeneratedKeys="true" keyProperty="userId">
         insert into sys_user(
ruoyi-service/ruoyi-account/pom.xml
@@ -132,6 +132,12 @@
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-modules-other</artifactId>
            <version>3.6.2</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AgentApplicationController.java
@@ -150,7 +150,7 @@
        }
        if (vipCenterService.checkReadyToBePartner(appUser.getId())){
        if (vipCenterService.isEligibleForGlobalPartner(appUser.getId())){
            return basePoint * i;
        }
        return 0;
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserController.java
@@ -1,8 +1,10 @@
package com.ruoyi.account.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
@@ -31,7 +33,6 @@
import com.ruoyi.other.api.domain.VipSetting;
import com.ruoyi.other.api.feignClient.ShopBalanceStatementClient;
import com.ruoyi.other.api.feignClient.ShopClient;
import com.ruoyi.other.api.feignClient.StoreClient;
import com.ruoyi.other.api.feignClient.VipSettingClient;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
@@ -73,8 +74,6 @@
    @Resource
    private AppUserService appUserService;
    @Resource
    private StoreClient storeClient;
    @Resource
    private UserCouponService userCouponService;
    @Resource
@@ -83,8 +82,6 @@
    private VipSettingClient vipSettingClient;
    @Resource
    private UserPointService userPointService;
    @Resource
    private VipSettingService vipSettingService;
    @Resource
    private AppUserMapper appUserMapper;
    @Resource
@@ -108,6 +105,9 @@
    @Resource
    private WeChatUtil weChatUtil;
    @Resource
    private IAppUserGiveawayTemporaryService appUserGiveawayTemporaryService;
    
    @Value("${file.upload.location}")
    private String filePath;
@@ -172,7 +172,7 @@
    @PostMapping("/getCouponCount")
    public R<Long> getCouponCount(@RequestParam("userId") Long userId, @RequestParam("couponId") Integer couponId) {
        LambdaQueryChainWrapper<UserCoupon> chainWrapper = userCouponService.lambdaQuery().eq(UserCoupon::getCouponId, couponId);
        if(null != userId && -1 == userId){
        if(null != userId && -1 != userId){
            chainWrapper.eq(UserCoupon::getAppUserId, userId);
        }
        Long count = chainWrapper.count();
@@ -291,6 +291,16 @@
            }
        }
        if (user.getShopName() == null){
            user.setShopName("");
        }
        if (user.getShopCover() == null){
            user.setShopCover("");
        }
        if (user.getShopAddress() == null){
            user.setShopAddress("");
        }
        //指导老师
        allSuperiors.stream()
                .filter(superiors -> superiors.getVipId() != null && superiors.getVipId() > 3)
@@ -300,12 +310,23 @@
                    user.setTeacherPhone(superiors.getPhone());
                });
        if (user.getTeacher() == null){
            user.setTeacher("");
        }
        if (user.getTeacherPhone() == null){
            user.setTeacherPhone("");
        }
        //获取绑定上级
        if (user.getInviteUserId() != null) {
            AppUser byId = appUserService.getById(user.getInviteUserId());
            user.setTopUser(byId);
        }else {
            AppUser topUser = new AppUser();
            user.setTopUser(topUser);
        }
        //获取绑定下级列表
        List<AppUser> list = appUserService.lambdaQuery()
@@ -534,6 +555,11 @@
        } else {
            user.setIsSign(0);
        }
        List<AppUserGiveawayTemporary> temporaryList = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>()
                .eq(AppUserGiveawayTemporary::getAppUserId, userId));
        user.setLavePoint(temporaryList.stream().mapToInt(AppUserGiveawayTemporary::getTotalPoint).sum() + user.getTotalPoint());
        return R.ok(user);
    }
@@ -663,14 +689,42 @@
        return R.ok(list);
    }
    @GetMapping("/getUserPointsPage")
    @ApiOperation(value = "用户列表", tags = {"管理后台"})
    public R<IPage<AppUser>> getUserPointsPage(@ApiParam("页码") @RequestParam Integer pageNum,
                                            @ApiParam("每一页数据大小") Integer pageSize,
                                            AppUser appUser) {
        Long userId = tokenService.getLoginUser().getUserid();
        SysUser data = sysUserClient.getSysUser(userId).getData();
        QueryWrapper<AppUser> queryWrapper = new QueryWrapper<>();
        if (data.getRoleType() == 2) {
            Integer shopId = data.getObjectId();
            List<Order> orders = orderClient.getRedeemedOrdersByShop(shopId).getData();
            List<Long> userIds = orders.stream().map(Order::getAppUserId).collect(Collectors.toList());
            queryWrapper.in(!CollectionUtils.isEmpty(userIds), "id", userIds)
                    .like(StringUtils.isNotEmpty( appUser.getName()),"name", appUser.getName());
        }
        queryWrapper.eq("del_flag", 0);
        queryWrapper.ne("status", 3);
        List<AppUser> appUserList = appUserService.list(queryWrapper);
        Page<AppUser> objectPage = Page.of(pageNum, pageSize);
        objectPage.setRecords(appUserList);
        return R.ok(objectPage);
    }
    /**
     * 获取用户列表
     */
    @GetMapping("/getAppuserPage")
    @ApiOperation(value = "用户列表", tags = {"管理后台"})
    public R<IPage<AppUser>> getAppuserPage(@ApiParam("页码") @RequestParam Integer pageNum,
                                            @ApiParam("每一页数据大小") Integer pageSize,
                                            AppUser appUser) {
        Long userid = tokenService.getLoginUser().getUserid();
        SysUser sysUser = sysUserClient.getSysUser(userid).getData();
        Integer shopId = null;
@@ -696,6 +750,8 @@
        }
        return R.ok(appuserPage);
    }
    @GetMapping("/shop/getAppuserPage")
    @ApiOperation(value = "用户列表", tags = {"门店后台"})
@@ -803,17 +859,17 @@
    }
    private void loginout(Long userId) {
        // 获取所有符合模式的缓存键
        Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        if (!CollectionUtils.isEmpty(keys)) {
        if (CollectionUtils.isEmpty(keys)) {
            return; // 如果没有匹配的键,直接返回
        }
        // 遍历所有键并删除与指定用户ID相关的登录信息
            for (String key : keys) {
                LoginUser user = redisService.getCacheObject(key);
                if (user == null || user.getUserid() == null) {
                    continue;
                }
                if (user.getUserid().equals(userId)) {
            if (user != null && userId.equals(user.getUserid())) {
                    redisService.deleteObject(key);
                    break;
                }
            }
        }
    }
@@ -1047,15 +1103,46 @@
    @GetMapping("/statistics")
    @ApiOperation(value = "用户统计", tags = {"管理后台-首页统计-用户统计"})
    public R<UserStatistics> statistics() {
        Long userid = tokenService.getLoginUser().getUserid();
        SysUser data = sysUserClient.getSysUser(userid).getData();
        Integer shopId = null;
        Set<Long> userId = null;
        Long userId = tokenService.getLoginUser().getUserid();
        SysUser data = sysUserClient.getSysUser(userId).getData();
        QueryWrapper<AppUser> queryWrapper = new QueryWrapper<>();
        if(data.getRoleType() == 2){
            shopId = data.getObjectId();
            userId = orderClient.getAppUserByShoppingShop(shopId).getData();
            Integer shopId = data.getObjectId();
            List<Order> orders = orderClient.getRedeemedOrdersByShop(shopId).getData();
            List<Long> userIds = orders.stream().map(Order::getAppUserId).collect(Collectors.toList());
            queryWrapper.in(!CollectionUtils.isEmpty(userIds), "id", userIds); // userIds 不为空时,查询 id 在 userIds 中
        }
        UserStatistics userStatistics = appUserMapper.getUserStatistics(shopId, userId);
        queryWrapper.eq("del_flag", 0);
        queryWrapper.ne("status", 3);
        List<AppUser> appUserList = appUserService.list(queryWrapper);
        Map<Integer, Long> vipIdCountMap = appUserList.stream()
                .collect(Collectors.groupingBy(AppUser::getVipId, Collectors.counting()));
        UserStatistics userStatistics = new UserStatistics();
        userStatistics.setTotalUser(appUserList.size());
        userStatistics.setConsumerUser(vipIdCountMap.getOrDefault(0, 0L).intValue() +
                vipIdCountMap.getOrDefault(1, 0L).intValue() +
                vipIdCountMap.getOrDefault(2, 0L).intValue() +
                vipIdCountMap.getOrDefault(3, 0L).intValue());
        userStatistics.setCommonUser(vipIdCountMap.getOrDefault(1, 0L).intValue());
        userStatistics.setGoldUser(vipIdCountMap.getOrDefault(2, 0L).intValue());
        userStatistics.setDiamondUser(vipIdCountMap.getOrDefault(3, 0L).intValue());
        userStatistics.setEntrepreneurUser(vipIdCountMap.getOrDefault(4, 0L).intValue() +
                vipIdCountMap.getOrDefault(5, 0L).intValue() +
                vipIdCountMap.getOrDefault(6, 0L).intValue() +
                vipIdCountMap.getOrDefault(7, 0L).intValue());
        userStatistics.setProxyUser(vipIdCountMap.getOrDefault(4, 0L).intValue());
        userStatistics.setAgentUser(vipIdCountMap.getOrDefault(5, 0L).intValue());
        userStatistics.setTotalAgentUser(vipIdCountMap.getOrDefault(6, 0L).intValue());
        userStatistics.setPartnerUser(vipIdCountMap.getOrDefault(7, 0L).intValue());
        long shopUserCount = appUserList.stream()
                .filter(appUser -> appUser.getUserType() == 2)
                .count();
        userStatistics.setShopUser((int) shopUserCount);
        return R.ok(userStatistics);
    }
@@ -1284,6 +1371,10 @@
        appUserService.vipUpgrade(appUserId);
    }
    
    @PostMapping("/vipConsumption")
    public void vipConsumption(@RequestParam("appUserId") Long appUserId){
        appUserService.vipConsumption(appUserId);
    }
    
    /**
     * 检查会员降级
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserShopController.java
@@ -7,6 +7,9 @@
import com.ruoyi.account.service.AppUserService;
import com.ruoyi.account.service.AppUserShopService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -24,6 +27,8 @@
    private AppUserShopService appUserShopService;
    @Resource
    private AppUserService appUserService;
    @Resource
    private TokenService tokenService;
@@ -75,4 +80,16 @@
    public void saveAppUserShop(@RequestBody AppUserShop appUserShop){
        appUserShopService.save(appUserShop);
    }
    /**
     * 校验登录用户是否为门店店长
     */
    @GetMapping("/checkUserIsShopManager")
    public R<Boolean> checkUserIsShopManager(){
        LoginUser loginUserApplet = tokenService.getLoginUserApplet();
        List<AppUserShop> list = appUserShopService.list(new LambdaQueryWrapper<AppUserShop>()
                .eq(AppUserShop::getAppUserId, loginUserApplet.getUserid())
                .eq(AppUserShop::getRoleType, 1));
        return R.ok(!CollectionUtils.isEmpty(list));
    }
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/UserCouponController.java
@@ -75,7 +75,8 @@
    public R<Page<UserCoupon>> minelist(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @ApiParam("1未使用2已使用3已过期") Integer status) {
        Long userid = tokenService.getLoginUserApplet().getUserid();
        LambdaQueryChainWrapper<UserCoupon> chainWrapper = userCouponService.lambdaQuery()
                .eq(UserCoupon::getAppUserId, userid);
                .eq(UserCoupon::getAppUserId, userid)
                .isNotNull(UserCoupon::getCouponInfo);
        if(null != status && 1 == status){
            chainWrapper.isNull(UserCoupon::getUseTime).gt(UserCoupon::getEndTime, LocalDateTime.now());
        }
@@ -92,7 +93,7 @@
            CouponInfoVo vo = JSON.parseObject(couponInfo, CouponInfoVo.class);
//            BeanUtils.copyProperties(data,vo);
            //如果是商品券,将商品名称返回
            if (vo.getCouponType()==4){
            if (vo != null && vo.getCouponType()==4){
                List<String> goodNames = new ArrayList<>();
                if (vo.getForGoodIds().equals("-1")){
                    List<Goods> data1 = goodsClient.getAllGoods().getData();
@@ -299,9 +300,8 @@
    @PostMapping("/getCouponInfo")
    public R<CouponInfoVo> getCouponInfo(@RequestParam("userCouponId") Long userCouponId){
        UserCoupon userCoupon = userCouponService.getById(userCouponId);
        CouponInfo data = couponClient.detail(userCoupon.getCouponId()).getData();
        CouponInfoVo couponInfoVo = new CouponInfoVo();
        BeanUtils.copyProperties(data, couponInfoVo);
        String jsonStr = userCoupon.getCouponInfo();
        CouponInfoVo couponInfoVo = JSON.parseObject(jsonStr, CouponInfoVo.class);
        return R.ok(couponInfoVo);
    }
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/VipCenterController.java
@@ -135,7 +135,7 @@
    @GetMapping("/check")
    @ApiOperation(value = "会员申请检查", tags = {"会员中心-小程序"})
    public R<Boolean> check(@ApiParam("4:准代理,5:代理,6:总代理,7:合伙人") @RequestParam Integer type) {
        return R.ok(vipCenterService.check(type));
        return R.ok(vipCenterService.checkEligibility(type));
    }
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/AppUserService.java
@@ -93,6 +93,12 @@
     * @param appUserId
     */
    void vipUpgrade(Long appUserId);
    /**
     * 消费后检查会员等级变更
     */
    void vipConsumption(Long appUserId);
    
    /**
     * 处理用户会员降级
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/VipCenterService.java
@@ -5,23 +5,23 @@
    /**
     * 校验准代理的申请条件
     */
    Boolean checkReadyToBeProxy(Long userId,Integer vipId);
    Boolean isEligibleForStorePartner(Long userId,Integer vipId);
    /**
     * 校验代理的申请条件
     */
    Boolean checkReadyToBeAgent(Long userId);
    Boolean isEligibleForCityPartner(Long userId);
    /**
     * 校验总代理的申请条件
     */
    Boolean checkReadyToBeTotalAgent(Long userId);
    Boolean isEligibleForNationalPartner(Long userId);
    /**
     * 校验合伙人的申请条件
     */
    Boolean checkReadyToBePartner(Long userId);
    Boolean isEligibleForGlobalPartner(Long userId);
    Boolean check(Integer type);
    Boolean checkEligibility(Integer type);
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/AppUserServiceImpl.java
@@ -22,18 +22,14 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.redis.annotation.DistributedLock;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.order.feignClient.OrderClient;
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.feignClient.*;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
import com.ruoyi.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.core.util.UuidUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -410,6 +406,7 @@
                    }
                    userCoupon.setStartTime(start);
                    userCoupon.setEndTime(end);
                    userCoupon.setCouponInfo(JSON.toJSONString(couponInfo));
                    userCouponService.save(userCoupon);
                }
            }
@@ -614,6 +611,130 @@
                userChangeLog.setChangeType(1);
                userChangeLogService.save(userChangeLog);
                return;
            }
        }
    }
    public void vipConsumption(Long id){
        System.out.println("1111111111111111111111");
        AppUser appUser = this.getById(id);
        System.out.println("消费积分:"+ appUser.getShopPoint());
        System.out.println("返佣积分:"+ appUser.getSharePoint() );
        Integer vipId = appUser.getVipId();
        //钻石会员
        VipSetting vipSetting3 = vipSettingClient.getVipSetting(3).getData();
        //消费积分满足升级
        if(1 == vipSetting3.getVipLevelUpShopRole() && appUser.getShopPoint() >= vipSetting3.getVipLevelUpShop() && appUser.getVipId() < 3){
            appUser.setVipId(3);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //返佣积分满足升级
        if(1 == vipSetting3.getVipLevelUpShareRole() && appUser.getSharePoint() >= vipSetting3.getVipLevelUpShare() && appUser.getVipId() < 3){
            appUser.setVipId(3);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //下级人数满足升级
        Integer vipLevelUpNumRole = vipSetting3.getVipLevelUpNumRole();
        Integer vipDirectNum = vipSetting3.getVipDirectNum();
        Integer vipTeamNum = vipSetting3.getVipTeamNum();
        if(1 == vipLevelUpNumRole && appUser.getVipId() < 3){
            //查询直推用户达到X人或者团队人数达到X人后,可升级
            //直推用户数
            long count = this.count(new LambdaQueryWrapper<AppUser>().eq(AppUser::getDelFlag, 0).eq(AppUser::getStatus, 1).eq(AppUser::getInviteUserId, id));
            //团队用户数
            List<AppUser> subordinate = getSubordinate(id);
            if(vipDirectNum <= count || vipTeamNum <= subordinate.size()){
                appUser.setVipId(3);
                this.updateById(appUser);
                //添加等级变化记录
                UserChangeLog userChangeLog = new UserChangeLog();
                userChangeLog.setDelFlag(0);
                userChangeLog.setCreateTime(LocalDateTime.now());
                userChangeLog.setAppUserId(appUser.getId());
                userChangeLog.setBeforeVipId(vipId);
                userChangeLog.setAfterVipId(appUser.getVipId());
                userChangeLog.setChangeType(1);
                userChangeLogService.save(userChangeLog);
                return;
            }
        }
        //黄金会员
        VipSetting vipSetting2 = vipSettingClient.getVipSetting(2).getData();
        //消费积分满足升级
        if(1 == vipSetting2.getVipLevelUpShopRole() && appUser.getShopPoint() >= vipSetting2.getVipLevelUpShop() && appUser.getVipId() < 2){
            appUser.setVipId(2);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //返佣积分满足升级
        if(1 == vipSetting2.getVipLevelUpShareRole() && appUser.getSharePoint() >= vipSetting2.getVipLevelUpShare() && appUser.getVipId() < 2){
            appUser.setVipId(2);
            this.updateById(appUser);
            //添加等级变化记录
            UserChangeLog userChangeLog = new UserChangeLog();
            userChangeLog.setDelFlag(0);
            userChangeLog.setCreateTime(LocalDateTime.now());
            userChangeLog.setAppUserId(appUser.getId());
            userChangeLog.setBeforeVipId(vipId);
            userChangeLog.setAfterVipId(appUser.getVipId());
            userChangeLog.setChangeType(1);
            userChangeLogService.save(userChangeLog);
            return;
        }
        //下级人数满足升级
        vipLevelUpNumRole = vipSetting2.getVipLevelUpNumRole();
        vipDirectNum = vipSetting2.getVipDirectNum();
        vipTeamNum = vipSetting2.getVipTeamNum();
        if(1 == vipLevelUpNumRole && appUser.getVipId() < 2){
            //查询直推用户达到X人或者团队人数达到X人后,可升级
            //直推用户数
            long count = this.count(new LambdaQueryWrapper<AppUser>().eq(AppUser::getDelFlag, 0).eq(AppUser::getStatus, 1).eq(AppUser::getInviteUserId, id));
            //团队用户数
            List<AppUser> subordinate = getSubordinate(id);
            if(vipDirectNum <= count || vipTeamNum <= subordinate.size()){
                appUser.setVipId(2);
                this.updateById(appUser);
                //添加等级变化记录
                UserChangeLog userChangeLog = new UserChangeLog();
                userChangeLog.setDelFlag(0);
                userChangeLog.setCreateTime(LocalDateTime.now());
                userChangeLog.setAppUserId(appUser.getId());
                userChangeLog.setBeforeVipId(vipId);
                userChangeLog.setAfterVipId(appUser.getVipId());
                userChangeLog.setChangeType(1);
                userChangeLogService.save(userChangeLog);
            }
        }
    }
@@ -922,7 +1043,7 @@
            Integer online = jsonObject.getInteger("online");
            online += 10;
            //满足一个小时,开始发放积分,计时归0
            if(time >= 3600000L && 60 <= online){
            if(time >= 60000 && 1 <= online){
                jsonObject.put("time", System.currentTimeMillis());
                jsonObject.put("online", 0);
                redisService.setCacheObject("ONLINE_" + userid, jsonObject, 1L, TimeUnit.HOURS);
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/BalanceChangeRecordServiceImpl.java
@@ -98,7 +98,7 @@
            BigDecimal beforeAmount = changeRecord.getBeforeAmount();
            BigDecimal afterAmount = changeRecord.getAfterAmount();
            if (beforeAmount.compareTo(afterAmount) < 0 && changeRecord.getChangeType().equals(2)){
            if (beforeAmount.compareTo(afterAmount) > 0){
                BigDecimal changeAmount = changeRecord.getChangeAmount();
                totalWithdraw = totalWithdraw.add(changeAmount);
                walletStatisticsDetail.setFlag(2);
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserCouponServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.account.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.api.vo.PaymentUserCouponVo;
@@ -46,11 +47,13 @@
    public List<PaymentUserCouponVo> getUserCoupon(Long userId, Integer type) {
        List<UserCoupon> list = this.list(new LambdaQueryWrapper<UserCoupon>().eq(UserCoupon::getAppUserId, userId).eq(UserCoupon::getDelFlag, 0)
                .isNull(UserCoupon::getUseTime).gt(UserCoupon::getEndTime, LocalDateTime.now()).last(" and now() between start_time and end_time"));
        List<Integer> couponIds = list.stream().map(UserCoupon::getCouponId).collect(Collectors.toList());
        if(couponIds.size() == 0){
            return null;
        List<CouponInfo> couponInfoList = new ArrayList<>();
        for (String jsonStr : list.stream().map(UserCoupon::getCouponInfo).collect(Collectors.toList())) {
            CouponInfo couponInfo = JSONObject.parseObject(jsonStr, CouponInfo.class);
            couponInfoList.add(couponInfo);
        }
        List<CouponInfo> couponInfoList = couponInfoClient.getCouponInfoList(couponIds).getData();
        //构建返回数据
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm");
        List<PaymentUserCouponVo> infoVoList = new ArrayList<>();
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/UserPointServiceImpl.java
@@ -71,7 +71,8 @@
    public UserPointVO getUserPoint(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingByUserId(userId);
        List<AppUserGiveawayTemporary> list = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>().eq(AppUserGiveawayTemporary::getAppUserId, userId));
        List<AppUserGiveawayTemporary> list = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>()
                .eq(AppUserGiveawayTemporary::getAppUserId, userId));
        int totalPoint = 0;
        int sharePoint = 0;
        int shopAchievementPoint = 0;
@@ -205,6 +206,16 @@
    @Override
    public UserPointStatistics getStatistics(UserPoint userPoint) {
        List<UserPoint> userPointList = this.baseMapper.selectUserPoint(userPoint);
        userPointList.forEach(item -> {
            int i = item.getHistoricalPoint() - item.getBalance();
            if (i>0){
                item.setVariablePoint(item.getVariablePoint() * -1);
            }else {
                item.setVariablePoint(item.getVariablePoint());
            }
        });
        Map<Integer, Integer> userBalanceMap = userPointList.stream()
                .collect(Collectors.groupingBy(
                        UserPoint::getType,
@@ -239,6 +250,15 @@
    @Override
    public IPage<UserPoint> getUserPointPage(Page<UserPoint> page, UserPoint userPoint) {
        return this.baseMapper.queryUserPointPage(page, userPoint);
        IPage<UserPoint> userPointIPage = this.baseMapper.queryUserPointPage(page, userPoint);
        userPointIPage.getRecords().forEach(item -> {
            int i = item.getHistoricalPoint() - item.getBalance();
            if (i>0){
                item.setVariablePoint(item.getVariablePoint() * -1);
            }else {
                item.setVariablePoint(item.getVariablePoint());
            }
        });
        return userPointIPage;
    }
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/VipCenterServiceImpl.java
@@ -4,7 +4,11 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.account.api.model.AgentApplication;
import com.ruoyi.account.api.model.AppUser;
import com.ruoyi.account.mapper.AgentApplicationMapper;
import com.ruoyi.account.service.AgentApplicationService;
import com.ruoyi.account.service.AppUserService;
import com.ruoyi.account.service.VipCenterService;
import com.ruoyi.account.service.VipSettingService;
@@ -22,11 +26,10 @@
import com.ruoyi.other.api.feignClient.VipGoodClient;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
@Service
@@ -36,293 +39,271 @@
    @Resource
    private RemoteOrderGoodsClient remoteOrderGoodsClient;
    @Resource
    private VipGoodClient vipGoodClient;
    @Resource
    private VipSettingService vipSettingService;
    @Resource
    private ShopClient shopClient;
    @Resource
    private TokenService tokenService;
    @Resource
    private GoodsClient goodsClient;
    private AgentApplicationMapper agentApplicationMapper;
    // 钻石会员
    private static final int VIP_ID_DIAMOND = 3;
    // 门店合伙人
    private static final int VIP_ID_STORE_PARTNER = 4;
    // 城市合伙人
    private static final int VIP_ID_CITY_PARTNER = 5;
    // 全国合伙人
    private static final int VIP_ID_NATIONAL_PARTNER = 6;
    // 全球合伙人
    private static final int VIP_ID_GLOBAL_PARTNER = 7;
    @Override
    public Boolean checkReadyToBeProxy(Long userId,Integer vipId) {
    /**
     * 判断是否满足申请门店合伙人的条件
     * @param userId 用户ID
     * @param vipId 会员等级ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForStorePartner(Long userId, Integer vipId) {
        AppUser appUser = appUserService.getById(userId);
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 准代理会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(4);
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        // 获取指定购买商品
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_STORE_PARTNER);
        // 判断是否已经购买过指定商品
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
                return true;
            }
        // 判断是否满足条件
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推钻石用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 获取用户直推钻石用户数量
            long userDiamondsCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId)
                    .eq(AppUser::getDelFlag, 0)
                    .eq(AppUser::getStatus, 1)
                    .gt(AppUser::getVipId, 2));
            // 判断是否满足直推钻石用户数量
            return userDiamondsCount >= vipDirectNum.longValue();
    /**
     * 判断是否满足申请城市合伙人的条件
     * @param userId 用户ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForCityPartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_CITY_PARTNER);
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
            return true;
        }
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
    }
    /**
     * 判断是否满足申请全国合伙人的条件
     * @param userId 用户ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForNationalPartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_NATIONAL_PARTNER);
        // 判断是否已经购买过指定商品
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
            return true;
        }
        if (vipSetting.getVipLevelUpProxyRole() == 1 && appUser.getVipId() == VIP_ID_CITY_PARTNER) {
            return true;
        }
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
    }
    /**
     * 判断是否满足申请全球合伙人的条件
     * @param userId 用户ID
     * @return 是否满足条件
     */
    public Boolean isEligibleForGlobalPartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        VipSetting vipSetting = vipSettingService.getVipSettingById(VIP_ID_GLOBAL_PARTNER);
        if (hasPurchasedGoods(userId, vipSetting.getGoodIds())) {
            return true;
        }
        return meetsPointsAndDirectUsersCriteria(appUser, vipSetting);
    }
    /**
     * 判断是否已经申请过
     * @param userId 用户ID
     * @param vipId 会员等级ID
     * @return 是否已经申请过
     */
    private boolean hasPendingApplication(Long userId, Integer vipId) {
        return agentApplicationMapper.selectCount(new QueryWrapper<AgentApplication>()
                .eq("app_user_id", userId)
                .eq("application_vip_id", vipId)
                .ne("status", 3)
                .eq("del_flag", 0)) > 0;
    }
    /**
     * 判断是否已经购买过指定商品
     * @param userId 用户ID
     * @param goodIds 商品ID列表
     * @return 是否已经购买过指定商品
     */
    private boolean hasPurchasedGoods(Long userId, String goodIds) {
        if (goodIds == null || goodIds.isEmpty()) {
        return false;
    }
        return Arrays.stream(goodIds.split(","))
                .anyMatch(goodId -> {
                    R<List<Order>> orderResponse = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(goodId));
                    return R.isSuccess(orderResponse) && !orderResponse.getData().isEmpty();
                });
    }
    @Override
    public Boolean checkReadyToBeAgent(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 代理会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(5);
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
    /**
     * 判断是否满足条件
     * @param appUser 用户信息
     * @param vipSetting 会员设置
     * @return 是否满足条件
     */
    private boolean meetsPointsAndDirectUsersCriteria(AppUser appUser, VipSetting vipSetting) {
        // 满足消费积分和返佣积分
        if (vipSetting.getVipLevelUpShopRole() == 1) {
            if (appUser.getShopPoint() >= vipSetting.getVipLevelUpShop() &&
                    appUser.getSharePoint() >= vipSetting.getVipLevelUpShare()) {
                return true;
            }
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推钻石用户数阈值
        long directDiamondUserCount = getDirectDiamondUserCount(appUser.getId()); // 直推钻石会员数量
        if (vipSetting.getId() < VIP_ID_NATIONAL_PARTNER){ // 门店合伙人、城市合伙人
            if (vipSetting.getVipLevelUpNumRole() == 1) {
                return directDiamondUserCount >= vipSetting.getVipDirectNum(); //直推钻石会员数量大于等于指定数量
            }
        }else if (vipSetting.getId() == VIP_ID_NATIONAL_PARTNER){ // 全国合伙人
            if (vipSetting.getVipLevelUpNumRole() == 1){
                List<AppUser> appUsers = appUserService.list(new LambdaQueryWrapper<AppUser>()
                        .eq(AppUser::getInviteUserId, appUser.getId())
                        .ge(AppUser::getVipId, VIP_ID_CITY_PARTNER)
                        .eq(AppUser::getDelFlag, 0));
                if (appUsers.size() >= vipSetting.getVipDirectNum()){ // 直推城市合伙人数量大于等于指定数量
                    List<Long> userIds = appUsers.stream().map(AppUser::getId).collect(Collectors.toList());
                    long directStorePartnerCount = getDirectStorePartnerCount(userIds);
                    return directStorePartnerCount >= vipSetting.getVipDirectVipNum(); // 城市合伙人下的门店合伙人数量大于等于指定数量
                }
            }
        }else if (vipSetting.getId() == VIP_ID_GLOBAL_PARTNER){ // 全球合伙人
            if (vipSetting.getVipLevelUpNumRole() == 1){
                // 城市合伙人用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 获取用户直推钻石用户数量
            long userDiamondsCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId)
                    .eq(AppUser::getVipId, 3));
            // 判断是否满足直推钻石用户数量
            return userDiamondsCount >= vipDirectNum.longValue();
        }
        return false;
    }
    @Override
    public Boolean checkReadyToBeTotalAgent(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        // 获取总代会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(6);
        // 获取指定购买商品
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        // 获取会员等级是否必须达到代理
        Integer vipLevelUpProxyRole = vipSetting.getVipLevelUpProxyRole();
        if (b && vipLevelUpProxyRole == 1 && appUser.getVipId() == 5){
            return true;
        }
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
                return true;
            }
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推代理用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 准代理用户数阈值
                // 门店合伙人用户数阈值
            Integer vipDirectVipNum = vipSetting.getVipDirectVipNum();
            // 获取用户直推代理用户数量
            List<AppUser> userAgentList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId)
                    .eq(AppUser::getVipId, 5));
            // 代理下的准代理数量
            List<Long> userQuasiAgent = userAgentList.stream().map(AppUser::getId).collect(Collectors.toList());
            long userQuasiAgentCount = 0;
            if(userQuasiAgent.size() > 0){
                userQuasiAgentCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                        .in(AppUser::getInviteUserId, userQuasiAgent)
                        .eq(AppUser::getVipId, 4));
            }
            // 判断是否满足直推代理用户数量和准代理数量
            return userAgentList.size() >= vipDirectNum && userQuasiAgentCount >= vipDirectVipNum.longValue();
        }
        return false;
    }
    @Override
    public Boolean checkReadyToBePartner(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        // 消费积分
        Integer shopPoint = appUser.getShopPoint();
        // 返佣积分
        Integer sharePoint = appUser.getSharePoint();
        // 合伙人会员设置
        VipSetting vipSetting = vipSettingService.getVipSettingById(7);
        // 获取指定购买商品
        boolean b = false;
        String[] split = vipSetting.getGoodIds().split(",");
        for (String s : split) {
            R<List<Order>> orderListByUserIdAndGoodsId = remoteOrderGoodsClient.getOrderListByUserIdAndGoodsId(userId, Integer.valueOf(s));
            if (R.isSuccess(orderListByUserIdAndGoodsId)){
                List<Order> orderList = orderListByUserIdAndGoodsId.getData();
                if (orderList.size() > 0){
                    b = true;
                    break;
                }
            }
        }
        // 获取通过消费积分达成会员等级的开关
        Integer vipLevelUpShopRole = vipSetting.getVipLevelUpShopRole();
        if (b && null != vipLevelUpShopRole && vipLevelUpShopRole == 1){
            // 消费积分阈值
            Integer vipLevelUpShop = vipSetting.getVipLevelUpShop();
            // 返佣积分阈值
            Integer vipLevelUpShare = vipSetting.getVipLevelUpShare();
            // 判断是否满足消费积分和返佣积分
            if (shopPoint.compareTo(vipLevelUpShop) >= 0 && sharePoint.compareTo(vipLevelUpShare) >= 0){
                return true;
            }
        }
        Integer vipLevelUpNumRole = vipSetting.getVipLevelUpNumRole();
        if (b && null != vipLevelUpNumRole && vipLevelUpNumRole == 1){
            // 直推代理用户数阈值
            Integer vipDirectNum = vipSetting.getVipDirectNum();
            // 准代理用户数阈值
            Integer vipDirectVipNum = vipSetting.getVipDirectVipNum();
            // 总代用户数阈值
                // 全国合伙人用户数阈值
            Integer vipTeamVipNum = vipSetting.getVipTeamVipNum();
            // 获取开店数量阈值
                // 开店数量阈值
            Integer vipOpenShopNum = vipSetting.getVipOpenShopNum();
            // 获取直推用户有超过指定门店数量的用户
            List<Long> userShopList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                    .eq(AppUser::getInviteUserId, userId))
                    .stream().map(AppUser::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(userShopList)){
                R<List<Shop>> r = shopClient.getShopByUserIds(userShopList);
                List<Shop> shopList = r.getData();
                if (CollectionUtil.isNotEmpty(shopList)){
                    Map<Long, List<Shop>> shopUserMap = shopList.stream().collect(Collectors.groupingBy(Shop::getAppUserId));
                    // 查找 list 长度大于 3 的 key
                    Set<Long> shopUserIdSet = shopUserMap.entrySet().stream()
                            .filter(entry -> entry.getValue().size() >= vipOpenShopNum)
                            .map(Map.Entry::getKey)
                            .collect(Collectors.toSet());
                    // 获取用户直推总代理数量
                    List<AppUser> userTotalAgentList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                            .in(AppUser::getId, shopUserIdSet)
                            .eq(AppUser::getVipId, 6));
                // 1.直推用户达到指定数量会员等级最低为城市合伙人
                List<AppUser> appUsers = appUserService.list(new LambdaQueryWrapper<AppUser>()
                        .eq(AppUser::getInviteUserId, appUser.getId())
                        .ge(AppUser::getVipId, VIP_ID_CITY_PARTNER)
                        .eq(AppUser::getDelFlag, 0));
                    // 获取用户直推代理用户数量
                    List<AppUser> userAgentList = appUserService.list(new LambdaQueryWrapper<AppUser>()
                            .in(AppUser::getId, userShopList)
                            .gt(AppUser::getVipId, 4));
                if (appUsers.size() >= vipDirectNum ){
                    // 2.城市合伙人下的门店合伙人数量达到指定人数
                    List<Long> userIds = appUsers.stream().map(AppUser::getId).collect(Collectors.toList());
                    long directStorePartnerCount = getDirectStorePartnerCount(userIds);
                    if (directStorePartnerCount >= vipDirectVipNum){
                    // 代理下的准代理数量
                    List<Long> userQuasiAgent = userAgentList.stream().map(AppUser::getId).collect(Collectors.toList());
                    long userQuasiAgentCount = 0;
                    if(userQuasiAgent.size() > 0){
                        userQuasiAgentCount = appUserService.count(new LambdaQueryWrapper<AppUser>()
                                .in(AppUser::getInviteUserId, userQuasiAgent)
                                .eq(AppUser::getVipId, 4));
                        // 3.直推用户达到指定数量会员等级最低为全国合伙人并且已经开了指定门店数量
                        List<AppUser> appUsers2 = appUserService.list(new LambdaQueryWrapper<AppUser>()
                                .eq(AppUser::getInviteUserId, appUser.getId())
                                .ge(AppUser::getVipId, VIP_ID_NATIONAL_PARTNER)
                                .eq(AppUser::getDelFlag, 0));
                        return appUsers2.size() >= vipTeamVipNum && appUsers2.size() >= vipOpenShopNum;
                    }
                    // 判断是否满足直推代理用户数量和准代理数量
                    return userTotalAgentList.size() >= vipTeamVipNum && userAgentList.size() >= vipDirectNum &&
                            userQuasiAgentCount >= vipDirectVipNum;
                }
                }
            }
        }
        return false;
    }
    @Override
    public Boolean check(Integer type) {
    /**
     * 获取指定用户直推钻石会员的数量
     */
    public long getDirectDiamondUserCount(Long userId) {
        AppUser appUser = appUserService.getById(userId);
        if (appUser == null) {
            return 0;
        }
        return appUserService.count(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getInviteUserId, appUser.getId())
                .eq(AppUser::getVipId, VIP_ID_DIAMOND));
    }
    /**
     * 获取指定用户下级门店合伙人的数量
     */
    public long getDirectStorePartnerCount(List<Long> userIds) {
        List<AppUser> allSubordinates = getAllSubordinates(userIds);
        return allSubordinates.stream()
                .filter(appUser -> appUser.getVipId().equals(VIP_ID_STORE_PARTNER))
                .count();
    }
    public List<AppUser> getAllSubordinates(List<Long> userIds) {
        List<AppUser> allSubordinates = new ArrayList<>();
        Set<Long> processedUsers = new HashSet<>(); // 用于避免重复添加用户
        // 遍历每个用户ID
        for (Long userId : userIds) {
            collectSubordinates(userId, allSubordinates, processedUsers);
        }
        return allSubordinates;
    }
    private void collectSubordinates(Long userId, List<AppUser> allSubordinates, Set<Long> processedUsers) {
        if (processedUsers.contains(userId)) {
            // 如果已经处理过该用户,则跳过,防止循环引用导致的无限递归
            return;
        }
        processedUsers.add(userId);
        List<AppUser> directChildren = appUserService.list(new LambdaQueryWrapper<AppUser>()
                .eq(AppUser::getInviteUserId, userId));
        for (AppUser child : directChildren) {
            if (!allSubordinates.contains(child)) { // 确保不添加重复的用户
                allSubordinates.add(child); // 添加直接下级
            }
            collectSubordinates(child.getId(), allSubordinates, processedUsers); // 递归添加间接下级
        }
    }
    public Boolean checkEligibility(Integer type) {
        LoginUser loginUser = tokenService.getLoginUserApplet();
        Long userid = loginUser.getUserid();
        if (type == 4){
            return checkReadyToBeProxy(userid, type);
        }else if (type == 5){
            return checkReadyToBeAgent(userid);
        }else if (type == 6){
            return checkReadyToBeTotalAgent(userid);
        }else if (type == 7){
            return checkReadyToBePartner(userid);
        }else {
        Long userId = loginUser.getUserid();
        switch (type) {
            case VIP_ID_STORE_PARTNER:
                return isEligibleForStorePartner(userId, type);
            case VIP_ID_CITY_PARTNER:
                return isEligibleForCityPartner(userId);
            case VIP_ID_NATIONAL_PARTNER:
                return isEligibleForNationalPartner(userId);
            case VIP_ID_GLOBAL_PARTNER:
                return isEligibleForGlobalPartner(userId);
            default:
            throw new ServiceException("参数错误");
        }
    }
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/WalletServiceImpl.java
@@ -15,6 +15,7 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
@Service
@@ -45,7 +46,7 @@
        
        List<AppUserGiveawayTemporary> list = appUserGiveawayTemporaryService.list(new LambdaQueryWrapper<AppUserGiveawayTemporary>().eq(AppUserGiveawayTemporary::getAppUserId, userId));
        BigDecimal commissionAmount = BigDecimal.ZERO;
        if(list.size() > 0){
        if(!list.isEmpty()){
            commissionAmount = list.stream().map(AppUserGiveawayTemporary::getTotalDistributionAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
@@ -58,13 +59,13 @@
        WalletVO walletVO = new WalletVO();
        BigDecimal balance = appUser.getBalance();
        walletVO.setCommissionAmount(appUser.getTotalDistributionAmount().add(commissionAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
        walletVO.setCommissionAmount(appUser.getTotalDistributionAmount().add(commissionAmount).setScale(2, RoundingMode.HALF_UP));
        walletVO.setWithdrawalAmount(appUser.getWithdrawableAmount());
        walletVO.setWithdrawnAmount(appUser.getWithdrawnAmount().subtract(reduce));
        walletVO.setVipWithdrawalMinAmount(data.getVipWithdrawalMinAmount());
        walletVO.setTotalRechargeAmount(appUser.getTotalRechargeAmount());
        walletVO.setTotalRedPacketAmount(appUser.getTotalRedPacketAmount());
        walletVO.setTotalDistributionAmount(appUser.getTotalDistributionAmount());
        walletVO.setTotalDistributionAmount(appUser.getTotalDistributionAmount().add(commissionAmount).setScale(2, RoundingMode.HALF_UP));
        walletVO.setAuditAmount(reduce);
        walletVO.setBalance(balance);
        return walletVO;
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/util/weChat/WeChatUtil.java
@@ -222,8 +222,6 @@
            HttpResponse execute = post.execute();
            byte[] bytes = execute.bodyBytes();
            String body1 = execute.body();
            System.err.println(body1);
            System.err.println(Base64.encodeBase64String(bytes));
            return new ByteArrayInputStream(bytes);
        }catch (Exception e){
            e.printStackTrace();
ruoyi-service/ruoyi-account/src/main/resources/bootstrap.yml
@@ -23,7 +23,7 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.106:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
@@ -31,12 +31,12 @@
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.106:8848
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        # 配置文件格式
        file-extension: yml
        # 共享配置
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/AppUserMapper.xml
@@ -54,9 +54,11 @@
        FROM t_app_user ta
        <where>
            ta.del_flag = 0 and ta.status != 3
            <if test="null != appUser.name and '' != appUser.name">
            <if test="appUser.name != null and appUser.name != ''">
                and ta.`name` like CONCAT('%',#{appUser.name},'%')
            </if>
            <if test="null != appUser.phone and '' != appUser.phone">
                and ta.phone like CONCAT('%',#{appUser.phone},'%')
            </if>
@@ -72,12 +74,13 @@
                    #{shopId}
                </foreach>
            </if>
            <if test="null != shopId">
            <if test="null != shopId and userId !=null and userId.size > 0">
                and ta.shop_id = #{shopId} or ta.id in
                <foreach collection="userId" item="item" index="index" open="(" separator="," close=")">
                    #{item}
                </foreach>
            </if>
        </where>
        order by ta.is_danger desc , ta.create_time desc
@@ -116,7 +119,6 @@
    <select id="getUserStatistics" resultType="com.ruoyi.account.vo.UserStatistics">
        SELECT
        COUNT(*) AS totalUser,
        SUM(CASE WHEN tau.user_type = 2 THEN 1 ELSE 0 END) AS shopUser,
        SUM(CASE WHEN tau.vip_id <![CDATA[<]]> 4 THEN 1 ELSE 0 END) AS consumerUser,
        SUM(CASE WHEN tau.vip_id = 1 THEN 1 ELSE 0 END) AS commonUser,
        SUM(CASE WHEN tau.vip_id = 2 THEN 1 ELSE 0 END) AS goldUser,
@@ -131,7 +133,7 @@
        <where>
            <if test="null != shopId">
                tau.shop_id = #{shopId}
                <if test="null != userId">
                <if test="null != userId and userId.size>0">
                    or tau.id in
                    <foreach collection="userId" item="item" index="index" open="(" separator="," close=")">
                        #{item}
@@ -139,7 +141,6 @@
                </if>
            </if>
        and  tau.del_flag = 0
        and tau.`status` !=3
        </where>
    </select>
    <select id="getUserStatisticsDetail" resultType="com.ruoyi.account.vo.UserStatisticsDetail">
@@ -158,7 +159,10 @@
            t_app_user tau
        <where>
            <if test="null != shopId">
                tau.shop_id = #{shopId} or
                tau.shop_id = #{shopId}
            </if>
            <if test="null != shopId and null != userId and userId.size() > 0">
                or
            </if>
            <if test="null != userId and userId.size() > 0">
                tau.id in
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/UserPointMapper.xml
@@ -24,12 +24,14 @@
        tau.phone,
        tup.type,
        tup.create_time,
        tup.variable_point
        tup.variable_point,
        tup.historical_point,
        tup.balance
        FROM
        t_user_point tup
        LEFT JOIN t_app_user tau ON tup.app_user_id = tau.id
        <where>
            tup.type not in (8, 9, 14)
            tup.type not in (8, 9, 14) and tau.status != 3 and tau.del_flag = 0
            <if test="userPoint.userName != null and userPoint.userName != ''">
                AND tau.`name` LIKE concat('%',#{userPoint.userName},'%')
            </if>
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/CommissionController.java
@@ -2,6 +2,10 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.order.service.CommissionService;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiService;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.QueryOrderByIdRequest;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -12,6 +16,5 @@
public class CommissionController {
    @Resource
    private CommissionService commissionService;
    public static JsapiService service;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/JsapiServiceExample.java
New file
@@ -0,0 +1,93 @@
package com.ruoyi.order.controller;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiService;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.CloseOrderRequest;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.QueryOrderByIdRequest;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
/** JsapiService使用示例 */
public class JsapiServiceExample {
    /** 商户号 */
    public static String merchantId = "190000****";
    /** 商户API私钥路径 */
    public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem";
    /** 商户证书序列号 */
    public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********";
    /** 商户APIV3密钥 */
    public static String apiV3Key = "...";
    public static JsapiService service;
    public static void main(String[] args) {
        // 初始化商户配置
        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(merchantId)
                        // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
                        .privateKeyFromPath(privateKeyPath)
                        .merchantSerialNumber(merchantSerialNumber)
                        .apiV3Key(apiV3Key)
                        .build();
        // 初始化服务
        service = new JsapiService.Builder().config(config).build();
        // ... 调用接口
        try {
            closeOrder();
        } catch (HttpException e) { // 发送HTTP请求失败
            // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
            // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
        } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
            // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
        }
    }
    /** 关闭订单 */
    public static void closeOrder() {
        CloseOrderRequest request = new CloseOrderRequest();
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        service.closeOrder(request);
    }
    /** JSAPI支付下单 */
    public static PrepayResponse prepay() {
        PrepayRequest request = new PrepayRequest();
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        return service.prepay(request);
    }
    /** 微信支付订单号查询订单 */
    public static Transaction queryOrderById() {
        QueryOrderByIdRequest request = new QueryOrderByIdRequest();
        request.setTransactionId("4208450740201411110007820472");
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        return service.queryOrderById(request);
    }
    /** 商户订单号查询订单 */
    public static Transaction queryOrderByOutTradeNo() {
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        return service.queryOrderByOutTradeNo(request);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/OrderController.java
@@ -34,6 +34,7 @@
import com.ruoyi.system.api.feignClient.SysUserClient;
import com.ruoyi.system.api.model.LoginUser;
import io.swagger.annotations.*;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -482,6 +483,16 @@
        return R.ok(collect);
    }
    /**
     * 获取指定门店的核销订单
     */
    @GetMapping("/getRedeemedOrdersByShop")
    public R<List<Order>> getRedeemedOrdersByShop(@RequestParam("shopId") Integer shopId) {
        return R.ok(orderService.list(new LambdaQueryWrapper<Order>()
                .isNotNull(Order::getEndTime)
                .eq(Order::getShopId, shopId)));
    }
    /**
     * 获取订单快递明细
@@ -545,6 +556,50 @@
    @GetMapping("/exportExpress")
    public void exportExpress(HttpServletResponse response, OrderPageList orderPage) {
        //搜索条件,用户姓名
        if (StringUtils.isNotEmpty(orderPage.getUserName())) {
            List<AppUser> data = appUserClient.getAppUserByNameNoFilter(orderPage.getUserName()).getData();
            List<Long> collect = data.stream().map(AppUser::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(collect)) {
                return;
            }
            if (null != orderPage.getAppUserIds()) {
                List<Long> appUserIds = orderPage.getAppUserIds();
                appUserIds.addAll(collect);
                orderPage.setAppUserIds(appUserIds);
            } else {
                orderPage.setAppUserIds(collect);
            }
        }
        //搜索条件,用户电话
        if (StringUtils.isNotEmpty(orderPage.getPhone())) {
            List<AppUser> data = appUserClient.getAppUserByPhoneNoFilter(orderPage.getPhone()).getData();
            List<Long> collect = data.stream().map(AppUser::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(collect)) {
                return;
            }
            if (null != orderPage.getAppUserIds()) {
                List<Long> appUserIds = orderPage.getAppUserIds();
                if (!containsAny(appUserIds, collect)) {
                    return;
                }
                appUserIds.addAll(collect);
                orderPage.setAppUserIds(appUserIds);
            } else {
                orderPage.setAppUserIds(collect);
            }
        }
        if (null != orderPage.getAppUserIds()) {
            orderPage.setAppUserIds(orderPage.getAppUserIds().stream().distinct().collect(Collectors.toList()));
        }
//        UserAddress userAddress = JSON.parseObject(order.getAddressJson(), UserAddress.class);
//        orderInfo.setRecipient(userAddress.getRecieveName() + "-" + userAddress.getRecievePhone());
//        userAddress.setRecieveAddress(userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getRecieveAddress());
//        orderInfo.setAddress(userAddress.getRecieveAddress());
        List<OrderExport> orderExportList = orderMapper.getOrderExportList(orderPage);
        orderExportList.forEach(orderExport -> {
            Long appUserId = orderExport.getAppUserId();
@@ -557,7 +612,8 @@
            if (StringUtils.isNotEmpty(goodJson) && !"NULL".equals(goodJson)) {
                Goods goods = JSONObject.parseObject(goodJson, Goods.class);
                orderExport.setGoodsName(goods.getName());
                orderExport.setCostPrice(goods.getShopCost().add(goods.getOperatingCost()));
                orderExport.setCompanyCostPrice(goods.getOperatingCost());
                orderExport.setSupplierCostPrice(goods.getShopCost());
            }
            String expressJson = orderExport.getExpressJson();
@@ -566,6 +622,17 @@
                orderExport.setExpressNum(jsonObject.getString("num"));
                orderExport.setExpressName(ExpressCompanyMap.getCompanyNameByCode(jsonObject.getString("com")));
            }
            String addressJson = orderExport.getAddressJson();
            if (StringUtils.isNotEmpty(addressJson)) {
                UserAddress userAddress = JSON.parseObject(addressJson, UserAddress.class);
                orderExport.setAddress(
                                userAddress.getProvince() +
                                userAddress.getCity() +
                                userAddress.getDistrict() +
                                userAddress.getRecieveAddress()
                );
            }
        });
@@ -576,6 +643,29 @@
    /**
     * 判断 list1 是否包含 list2 中的至少一个元素
     *
     * @param list1 第一个列表
     * @param list2 第二个列表
     * @return 如果 list1 包含 list2 中的至少一个元素,返回 true;否则返回 false
     */
    private boolean containsAny(List<Long> list1, List<Long> list2) {
        // 将 list1 转换为 HashSet 以提高查询效率
        Set<Long> set1 = new HashSet<>(list1);
        // 遍历 list2,检查是否有元素存在于 set1 中
        for (Long element : list2) {
            if (set1.contains(element)) {
                return true;
            }
        }
        // 如果没有找到共同元素,返回 false
        return false;
    }
    /**
     * 获取用户订单数量
     *
     * @param appUserId
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ShoppingCartController.java
@@ -1,6 +1,7 @@
package com.ruoyi.order.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.model.AppUser;
@@ -118,6 +119,9 @@
    @ResponseBody
    @GetMapping("/shoppingCartPaymentCallback")
    public void shoppingCartPaymentCallback(UniPayCallbackResult uniPayCallbackResult, HttpServletResponse response){
        String jsonString = JSONObject.toJSONString(uniPayCallbackResult);
        System.out.println("1111111111111111111111");
        System.out.println(jsonString);
        R callback = shoppingCartService.shoppingCartPaymentCallback(uniPayCallbackResult);
        if(callback.getCode() == 200){
            response.setStatus(200);
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/ConfirmDeliveryEvent.java
New file
@@ -0,0 +1,11 @@
package com.ruoyi.order.event;
import org.springframework.context.ApplicationEvent;
public class ConfirmDeliveryEvent extends ApplicationEvent {
    public ConfirmDeliveryEvent(Object source) {
        super(source);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/ConfirmDeliveryEventListener.java
New file
@@ -0,0 +1,160 @@
package com.ruoyi.order.event;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.model.AppUser;
import com.ruoyi.order.model.OrderGood;
import com.ruoyi.order.service.OrderGoodService;
import com.ruoyi.order.service.OrderService;
import com.ruoyi.order.vo.delivery.*;
import com.ruoyi.other.api.domain.Goods;
import com.ruoyi.other.api.domain.Shop;
import com.ruoyi.other.api.feignClient.ShopClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor
@Component
@Slf4j
public class ConfirmDeliveryEventListener {
    private final OrderService orderService;
    private final OrderGoodService orderGoodService;
    @Resource
    private ShopClient shopClient;
    @Resource
    private AppUserClient appUserClient;
    /**
     * 发货信息同步至微信
     */
    @Async
    @EventListener(ConfirmDeliveryEvent.class)
    public synchronized void confirmDelivery(ConfirmDeliveryEvent event) {
        Long orderId = (Long) event.getSource();
        Order order = buildOrder(orderId);
        log.info("发货信息同步至微信");
        // 1. 获取access_token(GET请求)
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"
                + "&appid=wxdeed472c98e42a54"
                + "&secret=c89c697c981452480e0781fb82d4284c";
        // 发送GET请求[1](@ref)
        String tokenResponse = HttpUtil.get(tokenUrl);
        cn.hutool.json.JSONObject tokenJson = JSONUtil.parseObj(tokenResponse);
        String accessToken = tokenJson.getStr("access_token");
        // 构建请求体(使用Hutool的JSONObject)
        JSONObject requestBody = new JSONObject();
        requestBody.put("order_key", order.getOrder_key());
        requestBody.put("delivery_mode", order.getDelivery_mode());
        requestBody.put("logistics_type", order.getLogistics_type());
        requestBody.put("shipping_list", JSON.parseArray(JSONObject.toJSONString(order.getShipping_list())));
        requestBody.put("upload_time", order.getUpload_time());
        requestBody.put("payer", JSONObject.parseObject(JSONObject.toJSONString(order.getPayer())));
        log.info("请求体:" + requestBody);
        // 2. 上传物流信息(POST请求)
        String logisticsUrl = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=" + accessToken;
        // 发送POST请求[3](@ref)
        String result = HttpRequest.post(logisticsUrl)
                .header("Content-Type", "application/json;charset=UTF-8") // 设置请求头[1](@ref)
                .body(requestBody.toString()) // 设置JSON请求体[3](@ref)
                .timeout(5000) // 设置超时时间
                .execute()
                .body();
        System.out.println("接口返回结果:" + result);
    }
    public Order buildOrder(Long orderId) {
        com.ruoyi.order.model.Order tOrder = orderService.getById(orderId);
        Shop shop = shopClient.getShopById(tOrder.getShopId()).getData();
        List<OrderGood> orderGoods = orderGoodService.list(new LambdaQueryWrapper<OrderGood>()
                .eq(OrderGood::getOrderId, orderId));
        String expressJson = tOrder.getExpressJson();
        JSONObject jsonObject = JSONObject.parseObject(expressJson);
        String com = jsonObject.getString("com");
        String num = jsonObject.getString("num");
        Order order = new Order();
        order.setDelivery_mode(1);
        order.setLogistics_type(1);
        order.setUpload_time(dateToString(OffsetDateTime.now(ZoneOffset.of("+08:00"))));
        OrderKey orderKey = new OrderKey();
        orderKey.setOrder_number_type(2);
        orderKey.setTransaction_id(tOrder.getSerialNumber());
        order.setOrder_key(orderKey);
        List<Shipping> shippingList = new ArrayList<>();
        for (OrderGood orderGood : orderGoods) {
            Integer orderGoodNum = orderGood.getNum();
            String goodJson = orderGood.getGoodJson();
            Goods goods = JSONObject.parseObject(goodJson, Goods.class);
            String name = goods.getName();
            Shipping shipping = new Shipping();
            shipping.setTracking_no(num);
            shipping.setExpress_company(com);
            shipping.setItem_desc(name + "*" + orderGoodNum);
            String phone = maskPhoneNumber(shop.getPhone());
            Contact contact = new Contact();
            contact.setConsignor_contact(phone);
            shipping.setContact(contact);
            shippingList.add(shipping);
        }
        order.setShipping_list(shippingList);
        AppUser appUser = appUserClient.getAppUserById(tOrder.getAppUserId());
        Payer payer = new Payer();
        payer.setOpenid(appUser.getWxOpenid());
        order.setPayer(payer);
        return order;
    }
    /**
     * 将手机号码中间四位替换为掩码
     * @param phoneNumber 原始手机号码
     * @return 掩码后的手机号码
     */
    public static String maskPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.length() != 11) {
            throw new IllegalArgumentException("手机号码必须为11位数字");
        }
        // 使用正则表达式替换中间四位为****
        return phoneNumber.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }
    /**
     * 将时间类型转换成字符串
     */
    public static String dateToString(OffsetDateTime now) {
        // 获取当前时间,并指定时区偏移为 +08:00
//        OffsetDateTime now = OffsetDateTime.now(ZoneOffset.of("+08:00"));
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx");
        // 将时间格式化为字符串
        return now.format(formatter);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEvent.java
New file
@@ -0,0 +1,10 @@
package com.ruoyi.order.event;
import org.springframework.context.ApplicationEvent;
public class PayEvent extends ApplicationEvent {
    public PayEvent(Object source) {
        super(source);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/event/PayEventListener.java
New file
@@ -0,0 +1,38 @@
package com.ruoyi.order.event;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.model.AppUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
@Component
@Slf4j
public class PayEventListener {
    private final AppUserClient appUserClient;
    /**
     * 检查会员等级变更
     */
    @Async
    @EventListener(PayEvent.class)
    public void checkVipChange(PayEvent event) {
        String source = (String) event.getSource();
        AppUser appUsers = JSONObject.parseObject(source, AppUser.class);
        appUserClient.vipConsumption(appUsers.getId());
    }
    /**
     * 积分变更
     */
    @Async
    @EventListener(PayEvent.class)
    public void checkCouponChange(PayEvent event) {
        // TODO
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/CommissionServiceImpl.java
@@ -1,31 +1,29 @@
package com.ruoyi.order.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.account.api.feignClient.*;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.feignClient.AppUserGiveawayTemporaryClient;
import com.ruoyi.account.api.feignClient.BalanceChangeRecordClient;
import com.ruoyi.account.api.feignClient.UserPointClient;
import com.ruoyi.account.api.model.*;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.order.model.Order;
import com.ruoyi.order.model.OrderGood;
import com.ruoyi.order.service.CommissionService;
import com.ruoyi.order.service.OrderGoodService;
import com.ruoyi.order.service.OrderService;
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.feignClient.*;
import com.ruoyi.order.model.Order;
import com.ruoyi.order.model.OrderGood;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@@ -64,7 +62,7 @@
        List<Order> list = orderService.list(new LambdaQueryWrapper<Order>().eq(Order::getIsCommission, 2).isNotNull(Order::getAfterSaleTime)
                .eq(Order::getDelFlag, 0).ne(Order::getPayMethod, 3).last(" and after_sale_time <= now()"));
        List<Long> collect = list.stream().map(Order::getId).collect(Collectors.toList());
        if(collect.size() == 0){
        if(collect.isEmpty()){
            return;
        }
    
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java
@@ -1,5 +1,8 @@
package com.ruoyi.order.service.impl;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -9,11 +12,13 @@
import com.ruoyi.common.core.constant.ExpressCompanyMap;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.HttpUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.uuid.QRCodeGenerator;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.order.enums.OrderStatus;
import com.ruoyi.order.event.ConfirmDeliveryEvent;
import com.ruoyi.order.mapper.OrderGoodMapper;
import com.ruoyi.order.mapper.OrderMapper;
import com.ruoyi.order.model.Order;
@@ -44,6 +49,7 @@
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.Nullable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -58,6 +64,7 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -137,6 +144,8 @@
    private AppUserGiveawayTemporaryClient appUserGiveawayTemporaryClient;
    @Resource
    private ShopGiveawayTemporaryClient shopGiveawayTemporaryClient;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
    @Override
@@ -183,9 +192,9 @@
        }
        // 优惠券
        String couponJson = order.getCouponJson();
        CouponInfo couponInfo = new CouponInfo();
        JSONObject jsonObject = new JSONObject();
        if (StringUtils.isNotEmpty(couponJson)) {
            couponInfo = JSONObject.parseObject(couponJson, CouponInfo.class);
            jsonObject = JSONObject.parseObject(couponJson);
        }
        // 参与活动
@@ -208,7 +217,7 @@
        orderDetailVO.setOrderNumber(order.getOrderNumber());
        orderDetailVO.setCreateTime(order.getCreateTime());
        orderDetailVO.setTotalAmount(order.getTotalAmount());
        orderDetailVO.setCouponName(couponInfo.getCouponName());
        orderDetailVO.setCouponName(jsonObject.getString("couponName"));
        orderDetailVO.setActivityName(orderActivityInfo.getActivityName());
        orderDetailVO.setCouponAmount(order.getDiscountTotalAmount());
        orderDetailVO.setExpressAmount(order.getExpressAmount());
@@ -246,6 +255,7 @@
        }
        return orderDetailVO;
    }
    @Override
    public boolean check(Order order, Integer shopId, Long userId) {
@@ -464,49 +474,7 @@
        return r;
    }
    /**
     * 确认发货操作
     *
     * @return
     */
    @Override
    public R confirmDelivery(ConfirmDelivery confirmDelivery) {
        Order order = this.getById(confirmDelivery.getOrderId());
        if (1 == order.getPayStatus()) {
            return R.fail("订单还未完成支付");
        }
        if (1 == order.getOrderType() || null == order.getAddressJson()) {
            return R.fail("该订单不支付快递配送");
        }
        if (1 != order.getOrderStatus()) {
            return R.fail("无效的操作");
        }
        //添加快递号和修改订单状态
        order.setExpressJson(confirmDelivery.getCode());
        order.setDeliverProvince(confirmDelivery.getDeliverProvince());
        order.setDeliverProvinceCode(confirmDelivery.getDeliverProvinceCode());
        order.setDeliverCity(confirmDelivery.getDeliverCity());
        order.setDeliverCityCode(confirmDelivery.getDeliverCityCode());
        order.setDeliverDistrict(confirmDelivery.getDeliverDistrict());
        order.setDeliverDistrictCode(confirmDelivery.getDeliverDistrictCode());
        order.setOrderStatus(2);
        //添加查询快递信息队列
        //一小时后定时查询快递信息
        SystemConfig systemConfig = systemConfigClient.getSystemConfig(3).getData();
        JSONObject jsonObject = JSON.parseObject(systemConfig.getContent());
        Integer waitTime = jsonObject.getInteger("waitTime");
        redisTemplate.opsForZSet().add("order_express", order.getId(), LocalDateTime.now().plusHours(waitTime).toEpochSecond(ZoneOffset.UTC));
        JSONObject jsonObject1 = JSON.parseObject(confirmDelivery.getCode());
        String com = jsonObject1.getString("com");
        String num = jsonObject1.getString("num");
        UserAddress userAddress = JSON.parseObject(order.getAddressJson(), UserAddress.class);
        MapTrackKD100Vo mapTrackKD100Vo = ExpressDeliveryUtil.kd100MapTrack(com, num, order.getDeliverProvince() + order.getDeliverCity(),
                userAddress.getProvince() + userAddress.getCity());
        order.setExpressResult(JSON.toJSONString(mapTrackKD100Vo));
        this.updateById(order);
        return R.ok();
    }
    /**
@@ -541,7 +509,8 @@
    public R refundPayMoney(Order order) {
        //开始退款
        Integer payMethod = order.getPayMethod();
        BigDecimal paymentAmount = order.getPaymentAmount();
        BigDecimal expressAmount = order.getExpressAmount() == null ? BigDecimal.ZERO : order.getExpressAmount();
        BigDecimal paymentAmount = order.getPaymentAmount().add(expressAmount);
        AppUser appUser = appUserClient.getAppUserById(order.getAppUserId());
        if (1 == payMethod) {
            //微信退款
@@ -584,6 +553,7 @@
            balanceChangeRecord.setDelFlag(0);
            balanceChangeRecord.setCreateTime(LocalDateTime.now());
            balanceChangeRecordClient.saveBalanceChangeRecord(balanceChangeRecord);
            //退回获得的消费积分
            //需要先检查会员等级时候回回退,使用回退后的会员等级查询配置
@@ -635,7 +605,6 @@
        if (3 == payMethod) {
            //开始运费退款,积分支付,运费是单独进行支付的,所以需要单独退款
            if (null != order.getExpressAmount() && BigDecimal.ZERO.compareTo(order.getExpressAmount()) < 0) {
                BigDecimal expressAmount = order.getExpressAmount();
                if (1 == order.getExpressPayMethod()) {
                    //微信退款
                    RefundResult refund = PaymentUtil.refund(order.getOrderNumber(), "R" + order.getOrderNumber(), expressAmount.doubleValue(), "/order/order/refundExpressPayMoneyCallback");
@@ -702,6 +671,11 @@
        order.setRefundStatus(2);
        order.setRefundTime(LocalDateTime.now());
        shopPointClient.deleteShopPointCopy(order.getId(), Arrays.asList(1,2,3));
        shopBalanceStatementClient.deleteShopBalanceStatementCopy(order.getId(), Arrays.asList(1,2,3));
        appUserGiveawayTemporaryClient.delAppUserGiveawayTemporary(order.getId());
        shopGiveawayTemporaryClient.delShopGiveawayTemporary(order.getId());
        return R.ok();
    }
@@ -848,6 +822,7 @@
        Long days = jsonObject.getLong("days");
        order.setAfterSaleTime(LocalDateTime.now().plusDays(days));
        this.updateById(order);
        commissionService.calculationCommissionShop(order.getId());
        return R.ok();
    }
@@ -975,6 +950,10 @@
        if (order_express.size() > 0) {
            for (Long id : order_express) {
                Order order = this.getById(id);
                if (order == null){
                    redisTemplate.opsForZSet().remove("order_express", id);
                    continue;
                }
                if (order.getOrderStatus() != 2) {
                    redisTemplate.opsForZSet().remove("order_express", id);
                    continue;
@@ -1002,11 +981,15 @@
        }
    }
    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importExpress(String url) {
        URL url1 = new URL(url);
        URL url1 = null;
        try {
            url1 = new URL(url);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
        try (InputStream fileInputStream = url1.openStream()) {
            Workbook workbook = new XSSFWorkbook(fileInputStream);
            Sheet sheet = workbook.getSheetAt(0); // 获取第一个Sheet
@@ -1014,18 +997,33 @@
            for (int i = 1; i <= lastRowNum; i++) {
                Row row = sheet.getRow(i);
                // 订单编号
                if (row.getCell(0) == null){
                    throw new ServiceException("第" + i + "行订单编号为空", 500);
                }
                row.getCell(0).setCellType(CellType.STRING);
                String orderNum = row.getCell(0).getStringCellValue();
                // 快递单号
                if (row.getCell(1) == null){
                    throw new ServiceException("第" + i + "行快递单号为空", 500);
                }
                row.getCell(1).setCellType(CellType.STRING);
                String expressNum = row.getCell(1).getStringCellValue();
                // 快递公司名称
                if (row.getCell(2) == null){
                    throw new ServiceException("第" + i + "行快递公司为空", 500);
                }
                row.getCell(2).setCellType(CellType.STRING);
                String expressName = row.getCell(2).getStringCellValue();
                // 省区划代码
                if (row.getCell(3) == null){
                    throw new ServiceException("第" + i + "行省区划代码为空", 500);
                }
                row.getCell(3).setCellType(CellType.STRING);
                String provinceCode = row.getCell(3).getStringCellValue();
                // 市区划代码
                if (row.getCell(4) == null){
                    throw new ServiceException("第" + i + "行市区划代码为空", 500);
                }
                row.getCell(4).setCellType(CellType.STRING);
                String cityCode = row.getCell(4).getStringCellValue();
                Order order = this.getOne(new LambdaQueryWrapper<Order>()
@@ -1070,7 +1068,10 @@
                confirmDelivery.setDeliverProvinceCode(regionBiCode.getData().getCode());
                confirmDelivery.setDeliverCity(regionBiCode1.getData().getName());
                confirmDelivery.setDeliverCityCode(regionBiCode1.getData().getCode());
                confirmDelivery(confirmDelivery);
                R r = confirmDelivery(confirmDelivery);
                if (R.isError(r)) {
                    throw new ServiceException(r.getMsg(), 500);
                }
            }
        } catch (IOException e) {
@@ -1081,6 +1082,54 @@
    }
    /**
     * 确认发货操作
     *
     * @return
     */
    @Override
    public R confirmDelivery(ConfirmDelivery confirmDelivery) {
        Order order = this.getById(confirmDelivery.getOrderId());
        if (1 == order.getPayStatus()) {
            return R.fail("订单还未完成支付");
        }
        if (1 == order.getOrderType() || null == order.getAddressJson()) {
            return R.fail("该订单不支付快递配送");
        }
        if (1 != order.getOrderStatus()) {
            return R.fail("无效的操作");
        }
        //添加快递号和修改订单状态
        order.setExpressJson(confirmDelivery.getCode());
        order.setDeliverProvince(confirmDelivery.getDeliverProvince());
        order.setDeliverProvinceCode(confirmDelivery.getDeliverProvinceCode());
        order.setDeliverCity(confirmDelivery.getDeliverCity());
        order.setDeliverCityCode(confirmDelivery.getDeliverCityCode());
        order.setDeliverDistrict(confirmDelivery.getDeliverDistrict());
        order.setDeliverDistrictCode(confirmDelivery.getDeliverDistrictCode());
        order.setOrderStatus(2);
        //添加查询快递信息队列
        //一小时后定时查询快递信息
        SystemConfig systemConfig = systemConfigClient.getSystemConfig(3).getData();
        JSONObject jsonObject = JSON.parseObject(systemConfig.getContent());
        Integer waitTime = jsonObject.getInteger("waitTime");
        redisTemplate.opsForZSet().add("order_express", order.getId(), LocalDateTime.now().plusHours(waitTime).toEpochSecond(ZoneOffset.UTC));
        JSONObject jsonObject1 = JSON.parseObject(confirmDelivery.getCode());
        String com = jsonObject1.getString("com");
        String num = jsonObject1.getString("num");
        UserAddress userAddress = JSON.parseObject(order.getAddressJson(), UserAddress.class);
        MapTrackKD100Vo mapTrackKD100Vo = ExpressDeliveryUtil.kd100MapTrack(com, num, order.getDeliverProvince() + order.getDeliverCity(),
                userAddress.getProvince() + userAddress.getCity());
        order.setExpressResult(JSON.toJSONString(mapTrackKD100Vo));
        this.updateById(order);
        // 发布事件
        applicationEventPublisher.publishEvent(new ConfirmDeliveryEvent(order.getId()));
        return R.ok();
    }
    public static void importExpress2(String filePath) throws MalformedURLException {
        // 从网络地址读取
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/ShoppingCartServiceImpl.java
@@ -14,6 +14,7 @@
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.order.event.PayEvent;
import com.ruoyi.order.mapper.ShoppingCartMapper;
import com.ruoyi.order.model.Order;
import com.ruoyi.order.model.OrderBalancePayment;
@@ -31,6 +32,7 @@
import com.ruoyi.other.api.vo.GetGoodsShopByGoodsIds;
import com.ruoyi.other.api.vo.GetSeckillActivityInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -108,12 +110,6 @@
    private CommissionService commissionService;
    @Resource
    private VipSettingClient vipSettingClient;
    @Resource
    private UserChangeLogClient userChangeLogClient;
    @Resource
    private PointSettingClient pointSettingClient;
    
    @Resource
@@ -121,6 +117,9 @@
    
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private ApplicationEventPublisher applicationEventPublisher;
    
    
    
@@ -1167,7 +1166,7 @@
                appUser.setLastShopTime(LocalDateTime.now());
                appUserClient.editAppUserById(appUser);
                //变更等级
                appUserClient.vipUpgrade(appUser.getId());
                applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
                //修改订支付状态
                order.setPayStatus(2);
                //自提
@@ -1204,33 +1203,36 @@
            BigDecimal balance = appUser.getBalance();
            //红包金额满足支付
            BigDecimal paymentMoney1 = paymentMoney;
            if(paymentMoney1.compareTo(totalRedPacketAmount) <= 0){
                totalRedPacketAmount = totalRedPacketAmount.subtract(paymentMoney1);
                balance = balance.subtract(paymentMoney1);
                appUser.setTotalRedPacketAmount(totalRedPacketAmount);
                appUser.setBalance(balance);
                redPacketAmount = paymentMoney1;
            }else{
                paymentMoney1 = paymentMoney1.subtract(totalRedPacketAmount);
                redPacketAmount = totalRedPacketAmount;
                totalRedPacketAmount = BigDecimal.ZERO;
                if(paymentMoney1.compareTo(totalDistributionAmount) <= 0){
                    totalDistributionAmount = totalDistributionAmount.subtract(paymentMoney1);
                    balance = balance.subtract(paymentMoney1);
                    appUser.setTotalRedPacketAmount(totalRedPacketAmount);
//                    appUser.setTotalDistributionAmount(totalDistributionAmount);
                    appUser.setBalance(balance);
                    distributionAmount = paymentMoney1;
                }else{
                    paymentMoney1 = paymentMoney1.subtract(totalDistributionAmount);
                    totalDistributionAmount = BigDecimal.ZERO;
                    balance = balance.subtract(paymentMoney1);
                    appUser.setTotalRedPacketAmount(totalRedPacketAmount);
//                    appUser.setTotalDistributionAmount(totalDistributionAmount);
                    appUser.setBalance(balance);
                    distributionAmount = totalDistributionAmount;
                }
            }
//            if(paymentMoney1.compareTo(totalRedPacketAmount) <= 0){
//                totalRedPacketAmount = totalRedPacketAmount.subtract(paymentMoney1);
//                balance = balance.subtract(paymentMoney1);
//                appUser.setTotalRedPacketAmount(totalRedPacketAmount);
//                appUser.setBalance(balance);
//                redPacketAmount = paymentMoney1;
//            }else{
//                paymentMoney1 = paymentMoney1.subtract(totalRedPacketAmount);
//                redPacketAmount = totalRedPacketAmount;
//                totalRedPacketAmount = BigDecimal.ZERO;
//                if(paymentMoney1.compareTo(totalDistributionAmount) <= 0){
////                    totalDistributionAmount = totalDistributionAmount.subtract(paymentMoney1);
//                    balance = balance.subtract(paymentMoney1);
//                    appUser.setTotalRedPacketAmount(totalRedPacketAmount);
////                    appUser.setTotalDistributionAmount(totalDistributionAmount);
//                    appUser.setBalance(balance);
//                    distributionAmount = paymentMoney1;
//                }else{
//                    paymentMoney1 = paymentMoney1.subtract(totalDistributionAmount);
//                    totalDistributionAmount = BigDecimal.ZERO;
//                    balance = balance.subtract(paymentMoney1);
//                    appUser.setTotalRedPacketAmount(totalRedPacketAmount);
////                    appUser.setTotalDistributionAmount(totalDistributionAmount);
//                    appUser.setBalance(balance);
//                    distributionAmount = totalDistributionAmount;
//                }
//            }
            //构建积分流水记录
            if(earnPoint > 0){
                PointSetting pointSetting = pointSettingClient.getPointSetting(appUser.getVipId()).getData();
@@ -1269,7 +1271,7 @@
            appUser.setLastShopTime(LocalDateTime.now());
            appUserClient.editAppUserById(appUser);
            //变更等级
            appUserClient.vipUpgrade(appUser.getId());
            applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
            //构建余额明细变动记录
            BalanceChangeRecord balanceChangeRecord = new BalanceChangeRecord();
            balanceChangeRecord.setAppUserId(appUser.getId());
@@ -1352,7 +1354,7 @@
            appUser.setLastShopTime(LocalDateTime.now());
            appUserClient.editAppUserById(appUser);
            //变更等级
            appUserClient.vipUpgrade(appUser.getId());
            applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
            //积分支付不返佣
@@ -1510,13 +1512,16 @@
        appUser.setLastShopTime(LocalDateTime.now());
        appUserClient.editAppUserById(appUser);
        //变更等级
        appUserClient.vipUpgrade(appUser.getId());
        applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
        //修改订支付状态
        order.setPayStatus(2);
        //自提
        if(order.getOrderType() == 1 && StringUtils.isEmpty(order.getAddressJson())){
            order.setOrderStatus(2);
        }
        String r7TrxNo = uniPayCallbackResult.getR9_BankTrxNo();
        order.setSerialNumber(r7TrxNo);
        orderService.updateById(order);
        //处理优惠券
@@ -1594,7 +1599,7 @@
        appUser.setLastShopTime(LocalDateTime.now());
        appUserClient.editAppUserById(appUser);
        //变更等级
        appUserClient.vipUpgrade(appUser.getId());
        applicationEventPublisher.publishEvent(new PayEvent(JSON.toJSONString(appUser)));
        //修改订支付状态
        order.setPayStatus(2);
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/OrderExport.java
@@ -14,17 +14,64 @@
    @Excel(name = "订单状态" , readConverterExp = "1=待发货,2=待收货,3=待使用,4=已完成,5=已取消,6=已退款,7=售后中,8=已评价")
    private String orderStatus;
    /**
     * 订单编号
     * 交易单号
     */
    @Excel(name = "订单编号")
    @Excel(name = "交易单号")
    private String serialNumber;
    /**
     * 商户单号
     */
    @Excel(name = "商户单号")
    private String orderNumber;
    /**
     * 商户号
     */
    @Excel(name = "商户号")
    private String tradeMerchantNo = "729677708";
    /**
     * 发货方式
     */
    @Excel(name = "发货方式", readConverterExp = "1=快递,2=自提")
    private String distributionMode;
    /**
     * 发货模式
     */
    @Excel(name = "发货模式")
    private String deliveryMode = "统一发货";
    /**
     * 是否完成发货
     */
    @Excel(name = "是否完成发货")
    private String isDelivery;
    /**
     * 是否重新发货
     */
    @Excel(name = "是否重新发货")
    private String isReDelivery;
    /**
     * 订单类型
     */
    @Excel(name = "订单类型", readConverterExp = "1=服务,2=单品")
    private String orderType;
    /**
     * 收货地址
     */
    @Excel(name = "收货地址")
    private String address;
    /**
     * 下单时间
@@ -61,8 +108,14 @@
    /**
     * 成本价
     */
    @Excel(name = "成本价")
    private BigDecimal costPrice;
    @Excel(name = "公司运营成本")
    private BigDecimal companyCostPrice;
    /**
     * 成本价
     */
    @Excel(name = "门店、供应商成本")
    private BigDecimal supplierCostPrice;
    /**
     * 支付金额
@@ -109,4 +162,10 @@
     */
    @Excel(name = "市区划代码")
    private String cityCode;
    private String addressJson;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Contact.java
New file
@@ -0,0 +1,12 @@
package com.ruoyi.order.vo.delivery;
import lombok.Data;
@Data
public class Contact {
    /**
     * 寄件人联系方式,寄件人联系方式,采用掩码传输,最后4位数字不能打掩码
     * 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
     */
    private String consignor_contact;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Order.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.order.vo.delivery;
import lombok.Data;
import java.util.List;
@Data
public class Order {
    //订单,需要上传物流信息的订单
    private OrderKey order_key;
    //发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY
    private int delivery_mode;
    // 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
    private int logistics_type;
    /**
     * 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10]
     * 属性    类型    必填    说明
     * tracking_no    string    否    物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]
     * express_company    string    否    物流公司编码,快递公司ID,参见「查询物流公司编码列表」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]
     * item_desc    string    是    商品信息,例如:微信红包抱枕*1个,限120个字以内
     * contact    object    否    联系方式,当发货的物流公司为顺丰时,联系方式为必填,收件人或寄件人联系方式二选一
     * 属性    类型    必填    说明
     * consignor_contact    string    否    寄件人联系方式,寄件人联系方式,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
     * receiver_contact    string    否    收件人联系方式,收件人联系方式为,采用掩码传输,最后4位数字不能打掩码 示例值: `189****1234, 021-****1234, ****1234, 0**2-***1234, 0**2-******23-10, ****123-8008` 值限制: 0 ≤ value ≤ 1024
     * upload_time    string    是    上传时间,用于标识请求的先后顺序 示例值: `2022-12-15T13:29:35.120+08:00`
     * payer    object    是    支付者,支付者信息
     * 属性    类型    必填    说明
     * openid    string    是    用户标识,用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]
     */
    private List<Shipping> shipping_list;
    // 上传时间,用于标识请求的先后顺序 示例值: `2022-12-15T13:29:35.120+08:00`
    private String upload_time;
    // 支付者,支付者信息
    private Payer payer;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/OrderKey.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.order.vo.delivery;
import lombok.Data;
@Data
public class OrderKey {
    /**
     * 订单单号类型,用于确认需要上传详情的订单。枚举值1,使用下单商户号和商户侧单号;枚举值2,使用微信支付单号。
     */
    private int order_number_type;
    /**
     * 原支付交易对应的微信订单号
     */
    private String transaction_id;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Payer.java
New file
@@ -0,0 +1,11 @@
package com.ruoyi.order.vo.delivery;
import lombok.Data;
@Data
public class Payer {
    /**
     * 用户标识,用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]
     */
    private String openid;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/vo/delivery/Shipping.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.order.vo.delivery;
import lombok.Data;
@Data
public class Shipping {
    /**
     * 物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]
     */
    private String tracking_no;
    /**
     * 物流公司编码,快递公司ID,参见「查询物流公司编码列表」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]
     */
    private String express_company;
    /**
     * 商品信息,例如:微信红包抱枕*1个,限120个字以内
     */
    private String item_desc;
    /**
     * 联系方式,当发货的物流公司为顺丰时,联系方式为必填,收件人或寄件人联系方式二选一
     */
    private Contact contact;
}
ruoyi-service/ruoyi-order/src/main/resources/bootstrap.yml
@@ -23,7 +23,7 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.106:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
@@ -31,12 +31,12 @@
        password: nacos
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.106:8848
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        # 配置文件格式
        file-extension: yml
        # 共享配置
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderGoodMapper.xml
@@ -8,6 +8,6 @@
        FROM
            t_order_good og
                LEFT JOIN t_order o ON og.order_id = o.id
        WHERE og.goods_id = #{goodsId} and o.app_user_id = #{userId}
        WHERE og.goods_id = #{goodsId} and o.app_user_id = #{userId} and o.order_status != 5 and o.order_status != 6
    </select>
</mapper>
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml
@@ -69,7 +69,7 @@
            deliver_province_code,
            deliver_city,
            deliver_city_code
        from t_order where del_flag = 0 and pay_status = 2
        from t_order where del_flag = 0
        <if test="null != item.code and '' != item.code">
            and order_number like CONCAT('%', #{item.code}, '%')
        </if>
@@ -101,18 +101,19 @@
    </select>
    <select id="getOrderStatistics" resultType="com.ruoyi.order.vo.OrderStatistics">
        SELECT
            SUM( CASE WHEN tor.order_status!=5 THEN 1 ELSE 0 END ) as total,
            SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN 1 ELSE 0 END ) as serviceTotal,
            SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN 1 ELSE 0 END ) as singleTotal,
            SUM( tor.total_amount ) as totalMoney,
            SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ) as serviceTotalMoney,
            SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ) as singleTotalMoney
        coalesce(SUM( CASE WHEN tor.order_status!=5 THEN 1 ELSE 0 END ), 0) as total,
        coalesce(SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN 1 ELSE 0 END ),0) as serviceTotal,
        coalesce(SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN 1 ELSE 0 END ),0) as singleTotal,
        coalesce(SUM( CASE WHEN tor.order_status!=5 THEN tor.total_amount ELSE 0 END ),0) as totalMoney,
        coalesce(SUM( CASE WHEN tor.order_type = 1 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ),0) as
        serviceTotalMoney,
        coalesce( SUM( CASE WHEN tor.order_type = 2 and tor.order_status!=5 THEN tor.total_amount ELSE 0 END ),0) as
        singleTotalMoney
        FROM
        t_order tor where 1 = 1
        t_order tor where 1 = 1 AND tor.del_flag = 0
        <if test="null != shopId">
            and tor.shop_id = #{shopId}
        </if>
        and tor.order_status!=5
    </select>
@@ -161,6 +162,8 @@
            o.order_status,
            o.order_number,
            o.order_type,
            case when o.order_type = 1 then 1 else o.distribution_mode end as distributionMode,
            o.address_Json,
            o.create_time,
            o.app_user_id,
            og.goods_id,
@@ -168,6 +171,7 @@
            og.good_json,
            og.selling_price orderMoney,
            o.express_json,
            o.serial_number,
            o.deliver_province province,
            o.deliver_province_code provinceCode,
            o.deliver_city city,
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/CouponInfoController.java
@@ -161,37 +161,62 @@
        Long userid = tokenService.getLoginUserApplet().getUserid();
        AppUser appUserById = appUserClient.getAppUserById(userid);
        LocalDateTime now = LocalDateTime.now();
        //查出全部可领取的优惠劵
        List<CouponInfo> list = couponInfoService.lambdaQuery().le(CouponInfo::getSendStartTime, now).ge(CouponInfo::getSendEndTime, now).eq(CouponInfo::getPersonType, 1).list();
        List<CouponInfo> list = couponInfoService.lambdaQuery()
                .le(CouponInfo::getSendStartTime, now)
                .ge(CouponInfo::getSendEndTime, now)
                .eq(CouponInfo::getPersonType, 1)
                .list();
        //查出指定人员可领取优惠券
        List<CouponInfo> list1 = couponInfoService.lambdaQuery().le(CouponInfo::getSendStartTime, now).ge(CouponInfo::getSendEndTime, now).eq(CouponInfo::getPersonType, 2).apply("FIND_IN_SET('" + appUserById.getId() + "', person_ids)").list();
        List<CouponInfo> list1 = couponInfoService.lambdaQuery()
                .le(CouponInfo::getSendStartTime, now)
                .ge(CouponInfo::getSendEndTime, now)
                .eq(CouponInfo::getPersonType, 2)
                .apply("FIND_IN_SET('" + appUserById.getId() + "', person_ids)")
                .list();
        //查出指定会员可领取优惠劵
        List<CouponInfo> list2 = couponInfoService.lambdaQuery().le(CouponInfo::getSendStartTime, now).ge(CouponInfo::getSendEndTime, now).eq(CouponInfo::getPersonType, 3).apply("FIND_IN_SET('" + appUserById.getVipId() + "', vip_ids)").list();
        List<CouponInfo> list2 = couponInfoService.lambdaQuery()
                .le(CouponInfo::getSendStartTime, now)
                .ge(CouponInfo::getSendEndTime, now)
                .eq(CouponInfo::getPersonType, 3)
                .apply("FIND_IN_SET('" + appUserById.getVipId() + "', vip_ids)").list();
        List<CouponInfo> returnList = new ArrayList<>();
        count(userid, list, returnList);
        count(userid, list1, returnList);
        count(userid, list2, returnList);
        return R.ok(returnList);
        returnList.addAll(list);
        returnList.addAll(list1);
        returnList.addAll(list2);
        List<CouponInfo> collect = returnList.stream().filter(couponInfo -> {
            Integer couponInfoId = couponInfo.getId();
            Integer sendNum = couponInfo.getSendNum();
            Integer maxNum = couponInfo.getMaxNum();
            Long count = appUserClient.getCouponCount(-1L, couponInfoId).getData();
            Long count2 = appUserClient.getCouponCount(userid, couponInfoId).getData();
            return count < sendNum && count2 < maxNum;
        }).collect(Collectors.toList());
        return R.ok(collect);
    }
    private void count(Long userid, List<CouponInfo> list1, List<CouponInfo> returnList) {
        for (CouponInfo couponInfo : list1) {
            Long count = appUserClient.getCouponCount(-1L, couponInfo.getId()).getData();
            if(count >= couponInfo.getSendNum()){
            Integer couponInfoId = couponInfo.getId();
            Integer sendNum = couponInfo.getSendNum();
            Integer maxNum = couponInfo.getMaxNum();
            Long count = appUserClient.getCouponCount(-1L, couponInfoId).getData();
            if(count >= sendNum){
                continue;
            }
            count = appUserClient.getCouponCount(userid, couponInfo.getId()).getData();
            couponInfo.setMaxNum(couponInfo.getMaxNum() - count.intValue());
            if((couponInfo.getSendNum() - count) >= couponInfo.getMaxNum()){
                for (int i = 0; i < couponInfo.getMaxNum(); i++) {
                    returnList.add(couponInfo);
                }
            }else{
                for (int i = 0; i < (couponInfo.getSendNum() - count); i++) {
                    returnList.add(couponInfo);
                }
            }
            
            count = appUserClient.getCouponCount(userid, couponInfoId).getData();
            couponInfo.setMaxNum(maxNum - count.intValue());
            if(count < maxNum){
                continue;
            }
            for (int i = 0; i < maxNum; i++) {
                returnList.add(couponInfo);
            }
        }
    }
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShareController.java
@@ -324,7 +324,8 @@
            Boolean data = userPointClient.judgmentDailyShare(userid).getData();
            if(!data){
                AppUser appUser = appUserClient.getAppUserById(userid);
                PointSetting pointSetting = pointSettingService.getOne(new LambdaQueryWrapper<PointSetting>().eq(PointSetting::getId, appUser.getVipId()).eq(PointSetting::getDelFlag, 0));
                PointSetting pointSetting = pointSettingService.getOne(new LambdaQueryWrapper<PointSetting>()
                        .eq(PointSetting::getId, appUser.getVipId()).eq(PointSetting::getDelFlag, 0));
                if(null != pointSetting){
                    Integer everySharePoint = pointSetting.getEverySharePoint();
                    Integer lavePoint = appUser.getLavePoint();
@@ -336,7 +337,6 @@
                    appUser.setTotalPoint(appUser.getTotalPoint() + everySharePoint);
                    appUserClient.editAppUserById(appUser);
                    //添加积分流水
                    if(everySharePoint > 0){
                        UserPoint userPoint = new UserPoint();
                        userPoint.setAppUserId(userid);
                        userPoint.setType(4);
@@ -347,12 +347,18 @@
                        userPoint.setAppUserId(appUser.getId());
                        userPointClient.saveUserPoint(userPoint);
                    }
                }
            }
        }
        return R.ok(one);
    }
    
    //appUserShare/
    @GetMapping("/saveAppUserShare")
    public R<Share> saveAppUserShare() {
        return getAppletShare();
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShopBalanceStatementController.java
@@ -1,27 +1,37 @@
package com.ruoyi.other.controller;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.other.api.domain.Shop;
import com.ruoyi.other.api.domain.ShopBalanceStatement;
import com.ruoyi.other.api.domain.ShopBalanceStatementCopy;
import com.ruoyi.other.api.domain.ShopWithdraw;
import com.ruoyi.other.dto.ShopBalanceDto;
import com.ruoyi.other.mapper.ShopBalanceStatementCopyMapper;
import com.ruoyi.other.mapper.ShopBalanceStatementMapper;
import com.ruoyi.other.service.ShopBalanceStatementService;
import com.ruoyi.other.service.ShopService;
import com.ruoyi.other.service.ShopWithdrawService;
import com.ruoyi.other.vo.ShopBalanceStatementDetailPage;
import com.ruoyi.other.vo.ShopCommission;
import com.ruoyi.other.vo.ShopCommissionDetail;
import com.ruoyi.other.vo.ShopCommissionStatisticsVO;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -29,9 +39,11 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Collection;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * <p>
@@ -57,9 +69,8 @@
    private SysUserClient sysUserClient;
    @Resource
    private ShopBalanceStatementCopyMapper shopBalanceStatementCopyMapper;
    @Resource
    private ShopWithdrawService shopWithdrawService;
    
    /**
@@ -73,6 +84,7 @@
        ShopCommissionStatisticsVO shopCommissionStatisticsVO = shopBalanceStatementService.shopCommissionStatistics(Page.of(pageNum, pageSize), shopBalanceStatement);
        return R.ok(shopCommissionStatisticsVO);
    }
    /**
     * 导出门店分佣统计
     */
@@ -84,6 +96,7 @@
        ExcelUtil<ShopBalanceStatement> util = new ExcelUtil<>(ShopBalanceStatement.class);
        util.exportExcel(response, statementIPage.getRecords(), "用户积分统计");
    }
    @GetMapping("/commissionStatistics/list")
    @ApiOperation(value = "门店余额明细", notes = "门店余额明细", tags = {"门店后台"})
    public R<Page<ShopBalanceStatement>> shopCommissionStatisticslist(@ApiParam("页码") @RequestParam Integer pageNum,
@@ -186,10 +199,6 @@
    }
    @PostMapping("/getList")
    public R<List<ShopBalanceStatement>> getList(@RequestBody ShopBalanceStatement shopBalanceStatement){
        return R.ok(shopBalanceStatementMapper.selectShopBalanceStatementList(shopBalanceStatement));
@@ -198,6 +207,7 @@
    
    /**
     * 保存门店余额流水
     *
     * @param shopBalanceStatement
     */
    @PostMapping("/saveShopBalanceStatement")
@@ -226,9 +236,9 @@
    }
    
    /**
     * 获取门店流水数据
     *
     * @param types
     * @param objectId
     * @return
@@ -253,5 +263,158 @@
        List<ShopBalanceStatement> list = shopBalanceStatementService.list(queryWrapper);
        return R.ok(list);
    }
    /**
     * 获取门店佣金
     *
     * @param shopId
     * @return
     */
    @GetMapping("getShopCommission")
    @ApiOperation(value = "获取门店佣金", notes = "获取门店佣金", tags = {"小程序-个人中心-门店管理-门店钱包"})
    @Transactional
    public R<ShopCommission> getShopCommission(@RequestParam("shopId") Integer shopId) {
        // 合并查询逻辑
        List<ShopBalanceStatementCopy> copies = shopBalanceStatementCopyMapper.selectList(
                new LambdaQueryWrapper<ShopBalanceStatementCopy>()
                        .eq(ShopBalanceStatementCopy::getShopId, shopId));
        List<ShopBalanceStatement> statements = shopBalanceStatementService.list(
                new LambdaQueryWrapper<ShopBalanceStatement>()
                        .eq(ShopBalanceStatement::getShopId, shopId));
        // 合并计算
        Map<Integer, BigDecimal> result = Stream.concat(
                copies.stream().map(e -> Pair.of(e.getType(), e.getVariableAmount())),
                statements.stream().map(e -> Pair.of(e.getType(), e.getVariableAmount()))
        ).collect(Collectors.groupingBy(
                Pair::getKey,
                Collectors.mapping(Pair::getValue, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
        ));
        // 待审核佣金
        BigDecimal waitingAudit = shopWithdrawService.list(new LambdaQueryWrapper<ShopWithdraw>()
                        .eq(ShopWithdraw::getShopId, shopId)
                        .eq(ShopWithdraw::getAuditStatus, 0))
                .stream()
                .map(ShopWithdraw::getMoney)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // 店铺信息校验
        Shop shop = shopService.getById(shopId);
        if (shop == null) {
            throw new ServiceException("店铺不存在");
        }
        // 构建结果
        List<ShopWithdraw> list = shopWithdrawService.lambdaQuery().eq(ShopWithdraw::getShopId, shopId)
                .eq(ShopWithdraw::getAuditStatus, 0).list();
        BigDecimal withdrawAuditMoney = list.stream().map(ShopWithdraw::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        ShopCommission commission = new ShopCommission();
        commission.setCanWithdrawCommission(shop.getCanWithdrawMoney());
        commission.setWithdrawnCommission(shop.getWithdrawMoney().subtract(withdrawAuditMoney));
        commission.setCommissionAmount(
                result.getOrDefault(1, BigDecimal.ZERO)
                        .add(result.getOrDefault(2, BigDecimal.ZERO)
                                .add(result.getOrDefault(3, BigDecimal.ZERO))
                        ));
        commission.setWaitingAuditCommission(waitingAudit);
        commission.setTotalAmount(commission.getCommissionAmount());
        return R.ok(commission);
    }
    /**
     * 获取门店佣金明细
     */
    @GetMapping("/getshopCommissionStatisticsDetail")
    @ApiOperation(value = "门店返佣明细", notes = "门店返佣明细", tags = {"小程序-个人中心-门店管理-门店钱包"})
    public R<ShopBalanceStatementDetailPage> shopCommissionStatisticsDetail(@ApiParam("店铺id") Integer shopId,
                                                                            @ApiParam("类型") Integer type,
                                                                            @ApiParam("开始时间") String createTime,
                                                                            @ApiParam("页码") Integer pageNum,
                                                                            @ApiParam("每一页数据大小") Integer pageSize) {
        LocalDateTime startDate = null;
        LocalDateTime endDate = null;
        if (StringUtils.isNotEmpty(createTime)){
            startDate = LocalDateTime.parse(createTime + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            endDate = LocalDateTime.parse(createTime + " 23:59:59", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }
        List<ShopBalanceStatementCopy> copies = shopBalanceStatementCopyMapper.selectList(
                new LambdaQueryWrapper<ShopBalanceStatementCopy>()
                        .eq(ShopBalanceStatementCopy::getShopId, shopId)
                        .eq(type != null, ShopBalanceStatementCopy::getType, type)
                        .between(startDate != null && endDate != null, ShopBalanceStatementCopy::getCreateTime,
                                startDate, endDate));
        List<ShopBalanceStatement> statements = shopBalanceStatementService.list(
                new LambdaQueryWrapper<ShopBalanceStatement>()
                        .eq(ShopBalanceStatement::getShopId, shopId)
                        .eq(type != null, ShopBalanceStatement::getType, type)
                        .between(startDate != null && endDate != null, ShopBalanceStatement::getCreateTime,
                                startDate, endDate));
        Map<Integer, String> itemMap = new HashMap<>();
        itemMap.put(1, "服务商分佣");
        itemMap.put(2, "高级服务商分佣");
        itemMap.put(3, "核销门店服务费");
        itemMap.put(4, "提现");
        List<ShopCommissionDetail> list = new ArrayList<>();
        for (ShopBalanceStatementCopy copy : copies) {
            ShopCommissionDetail detail = new ShopCommissionDetail();
            detail.setItem(itemMap.get(copy.getType()));
            detail.setTime(copy.getCreateTime());
            detail.setAmount(copy.getVariableAmount());
            BigDecimal beforeAmount = copy.getHistoricalBalance();
            BigDecimal afterAmount = copy.getBalance();
            if (beforeAmount.compareTo(afterAmount) > 0) {
                detail.setType(2);
            } else {
                detail.setType(1);
            }
            list.add(detail);
        }
        for (ShopBalanceStatement statement : statements) {
            ShopCommissionDetail detail = new ShopCommissionDetail();
            detail.setItem(itemMap.get(statement.getType()));
            detail.setTime(statement.getCreateTime());
            detail.setAmount(statement.getVariableAmount());
            BigDecimal beforeAmount = statement.getHistoricalBalance();
            BigDecimal afterAmount = statement.getBalance();
            if (beforeAmount.compareTo(afterAmount) > 0) {
                detail.setType(2);
            } else {
                detail.setType(1);
            }
            list.add(detail);
        }
        // 按时间排序加手动分页
        Integer total = list.size();
        list.sort(Comparator.comparing(ShopCommissionDetail::getTime).reversed());
        if (pageNum != null && pageSize != null) {
            int fromIndex = (pageNum - 1) * pageSize;
            int toIndex = Math.min(fromIndex + pageSize, list.size());
            list = list.subList(fromIndex, toIndex);
        }
        ShopBalanceStatementDetailPage page = new ShopBalanceStatementDetailPage();
        page.setRecords(list);
        page.setTotal(total);
        page.setPageSize(pageSize);
        page.setPageNum(pageNum);
        return R.ok(page);
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShopController.java
@@ -408,6 +408,10 @@
        return R.ok();
    }
    public static void main(String[] args) {
        System.out.println("17780483325".substring(5));
    }
    @PutMapping("/freezingOrThawing")
    @ApiOperation(value = "门店管理-冻结/解冻门店", tags = {"管理后台-门店管理"})
@@ -678,8 +682,17 @@
    @PostMapping("/getShopIdByName")
    public R<Set<Integer>> getShopIdByName(@RequestParam("shopName") String shopName){
        List<Shop> list = shopService.list(new LambdaQueryWrapper<Shop>()
                .like(Shop::getName, shopName));
                .like(Shop::getName, shopName)
                .eq(Shop::getDelFlag, 0));
        return R.ok(list.stream().map(Shop::getId).collect(Collectors.toSet()));
    }
    @PostMapping("/getManagerByManagerName")
    public R<Set<Long>> getManagerByManagerName(@RequestParam("managerName") String managerName){
        List<Shop> list = shopService.list(new LambdaQueryWrapper<Shop>()
                .like(Shop::getShopManager, managerName)
                .eq(Shop::getDelFlag, 0));
        return R.ok(list.stream().map(Shop::getAppUserId).collect(Collectors.toSet()));
    }
    /**
@@ -808,6 +821,21 @@
        return R.ok();
    }
    @PostMapping("/saveWithdrawalAppletAccount")
    @ApiOperation(value = "保存提现账户", tags = {"小程序-个人中心-门店管理-门店钱包"})
    public R saveWithdrawalAppletAccount(@RequestBody SaveWithdrawalAccount saveWithdrawalAccount){
        Shop shop = shopService.getById(saveWithdrawalAccount.getShopId());
        if(null != shop){
            shop.setReceiverAccountNoEnc(saveWithdrawalAccount.getReceiverAccountNoEnc());
            shop.setReceiverNameEnc(saveWithdrawalAccount.getReceiverNameEnc());
            shop.setReceiverAccountType(saveWithdrawalAccount.getReceiverAccountType());
            shop.setReceiverBankChannelNo(saveWithdrawalAccount.getReceiverBankChannelNo());
            shopService.updateById(shop);
        }
        return R.ok();
    }
    /**
     * 获取所有门店
@@ -831,6 +859,21 @@
        }
        return R.fail("请先配置收款账户");
    }
    @ResponseBody
    @GetMapping("/verifyAppletConfiguration")
    @ApiOperation(value = "判断是否有提现账户", tags = {"门店后台-财务管理-提现明细","小程序-个人中心-门店管理-门店钱包"})
    public R verifyAppletConfiguration(Integer shopId){
        Shop shop = shopService.getById(shopId);
        if(StringUtils.hasLength(shop.getReceiverAccountNoEnc())){
            return R.ok(true);
        }
        return R.ok(false);
    }
@@ -865,7 +908,6 @@
    /**
     * 获取指定用户的服务商
     * @param userId
     * @return
     */
    @GetMapping("/getServiceProvider")
@@ -908,6 +950,8 @@
    
    
    /**
     * 获取指定用户的高级服务商
     * @return
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/ShopWithdrawController.java
@@ -7,16 +7,13 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.model.AppUser;
import com.ruoyi.account.api.model.BalanceChangeRecord;
import com.ruoyi.account.api.model.WithdrawalRequests;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.other.api.domain.Shop;
import com.ruoyi.other.api.domain.ShopBalanceStatement;
import com.ruoyi.other.api.domain.ShopWithdraw;
import com.ruoyi.other.dto.ShopBalanceDto;
import com.ruoyi.other.service.ShopBalanceStatementService;
import com.ruoyi.other.service.ShopService;
import com.ruoyi.other.service.ShopWithdrawService;
@@ -134,36 +131,66 @@
        LoginUser loginUser = tokenService.getLoginUser();
        SysUser sysUser = sysUserClient.getSysUser(loginUser.getUserid()).getData();
        Shop byId = shopService.getById(sysUser.getObjectId());
        List<ShopWithdraw> list = shopWithdrawService.lambdaQuery().eq(ShopWithdraw::getShopId, sysUser.getObjectId())
                .eq(ShopWithdraw::getAuditStatus, 0).list();
        List<ShopWithdraw> list = shopWithdrawService.lambdaQuery()
                .eq(ShopWithdraw::getShopId, sysUser.getObjectId())
                .list();
        if (!list.isEmpty()){
            BigDecimal bigDecimal = list.stream().map(ShopWithdraw::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            // 待审核列表
            List<ShopWithdraw> toBeReviewList = list.stream()
                    .filter(s -> s.getAuditStatus() == 0)
                    .collect(Collectors.toList());
            // 审核通过列表
            List<ShopWithdraw> passedReviewList = list.stream()
                    .filter(s -> s.getAuditStatus() == 1)
                    .collect(Collectors.toList());
            BigDecimal bigDecimal = toBeReviewList.stream().map(ShopWithdraw::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            byId.setWithdrawAuditMoney(bigDecimal);
            BigDecimal bigDecimal1 = passedReviewList.stream().map(ShopWithdraw::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
            byId.setWithdrawMoney(bigDecimal1);
        }else {
            byId.setWithdrawAuditMoney(BigDecimal.ZERO);
        }
        byId.setWithdrawMoney(byId.getWithdrawMoney().subtract(byId.getWithdrawAuditMoney()));
        return R.ok(byId);
    }
    
    @GetMapping("/shop/with")
    @ApiOperation(value = "提现申请", notes = "提现申请列表", tags = {"门店后台"})
    public R shopwith(@RequestParam BigDecimal money){
        Long userid = tokenService.getLoginUser().getUserid();
        SysUser sysUser = sysUserClient.getSysUser(userid).getData();
        Integer objectId = sysUser.getObjectId();
        Shop shop = shopService.getById(objectId);
        LoginUser loginUser = tokenService.getLoginUser();
        SysUser sysUser = sysUserClient.getSysUser(loginUser.getUserid()).getData();
        baseWithdrawalApplication(money, sysUser.getUserId(), sysUser.getObjectId());
        return R.ok();
    }
    /**
     * 小程序端提现申请
     */
    @ApiOperation(value = "提现申请", notes = "提现申请", tags = {"小程序-个人中心-门店管理-门店钱包"})
    @GetMapping("/withdrawalApplication")
    @ResponseBody
    public R withdrawalApplication(@RequestParam BigDecimal money, @RequestParam Integer shopId) {
        LoginUser loginUser = tokenService.getLoginUserApplet();
        baseWithdrawalApplication(money, loginUser.getUserid(), shopId);
        return R.ok();
    }
    private void baseWithdrawalApplication(BigDecimal money, Long userId, Integer shopId) {
        Shop shop = shopService.getById(shopId);
        if (money.compareTo(BigDecimal.ZERO)==0){
            return R.fail("提现金额必须大于零");
            throw new ServiceException("提现金额必须大于零");
        }
        if (money.compareTo(shop.getCanWithdrawMoney())>0){
            return R.fail("提现金额不能大于可提现金额");
            throw new ServiceException("提现金额不能大于可提现金额");
        }
        if(StringUtils.isEmpty(shop.getReceiverAccountNoEnc())){
            return R.fail("请完善账户信息后再申请提现!");
            throw new ServiceException("请完善账户信息后再申请提现!");
        }
        ShopWithdraw shopWithdraw = new ShopWithdraw();
        shopWithdraw.setShopId(objectId);
        shopWithdraw.setShopId(shopId);
        shopWithdraw.setMoney(money);
        shopWithdraw.setAuditStatus(0);
        shopWithdraw.setStatus(1);
@@ -184,14 +211,14 @@
        shopBalanceStatement.setHistoricalBalance(balance);
        shopBalanceStatement.setVariableAmount(money);
        shopBalanceStatement.setBalance(shop.getBalance());
        shopBalanceStatement.setCreateUserId(sysUser.getUserId());
        shopBalanceStatement.setCreateUserId(userId);
        shopBalanceStatement.setCreateTime(LocalDateTime.now());
        shopBalanceStatement.setObjectId(shopWithdraw.getId());
        shopBalanceStatementService.save(shopBalanceStatement);
        return R.ok();
    }
    /**
     * 审核
     */
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/ShopServiceImpl.java
@@ -134,7 +134,13 @@
                }
            }
        });
        return nearbyShopVOS;
        return sortByDistance(nearbyShopVOS);
    }
    public static List<NearbyShopVO> sortByDistance(List<NearbyShopVO> nearbyShopVOS) {
        return nearbyShopVOS.stream()
                .sorted(Comparator.comparingDouble(NearbyShopVO::getDistance))
                .collect(Collectors.toList());
    }
    @Override
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/SaveWithdrawalAccount.java
@@ -9,6 +9,7 @@
 */
@Data
public class SaveWithdrawalAccount {
    private Integer shopId;
    
    @ApiModelProperty("收款银行卡号")
    private String receiverAccountNoEnc;
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/ShopBalanceStatementDetailPage.java
New file
@@ -0,0 +1,13 @@
package com.ruoyi.other.vo;
import lombok.Data;
import java.util.List;
@Data
public class ShopBalanceStatementDetailPage {
    private List<ShopCommissionDetail> records;
    private Integer total;
    private Integer pageSize;
    private Integer pageNum;
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/ShopCommission.java
New file
@@ -0,0 +1,42 @@
package com.ruoyi.other.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@ApiModel(value = "门店分佣统计")
public class ShopCommission {
    /**
     * 总金额
     */
    @ApiModelProperty(value = "总金额")
    private BigDecimal totalAmount;
    /**
     * 可提现金额
     */
    @ApiModelProperty(value = "可提现金额")
    private BigDecimal canWithdrawCommission;
    /**
     *  分佣金额
     */
    @ApiModelProperty(value = "分佣金额")
    private BigDecimal commissionAmount;
    /**
     * 已提现金额
     */
    @ApiModelProperty(value = "已提现金额")
    private BigDecimal withdrawnCommission;
    /**
     * 提现审核中金额
     */
    @ApiModelProperty(value = "提现审核中金额")
    private BigDecimal waitingAuditCommission;
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/ShopCommissionDetail.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.other.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
@Data
public class ShopCommissionDetail {
    /**
     * 明细名称
     */
    private String item;
    /**
     * 时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime time;
    /**
     * 变动金额
     */
    private BigDecimal amount;
    /**
     * 加或减标记: 1 加 2 减
     */
    private Integer type;
}
ruoyi-service/ruoyi-other/src/main/resources/bootstrap.yml
@@ -23,20 +23,20 @@
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.106:8848
        service: ${spring.application.name}
        group: DEFAULT_GROUP
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username: nacos
        password: nacos
        username:
        password:
      config:
        # 配置中心地址
        server-addr: 127.0.0.1:8848
        server-addr: 192.168.110.106:8848
        namespace: cdf47c5f-2bf9-4dec-a616-a8dc653aceb9
        username:
        password:
        group: DEFAULT_GROUP
        name: ${spring.application.name}
        username: nacos
        password: nacos
        # 配置文件格式
        file-extension: yml
        # 共享配置