jinshihui před 2 dny
rodič
revize
42b088b1be
28 změnil soubory, kde provedl 672 přidání a 98 odebrání
  1. 5 8
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/MaTechnicianController.java
  2. 22 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TAddressController.java
  3. 38 18
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/WxController.java
  4. 5 0
      nightFragrance-massage/pom.xml
  5. 40 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/QueryWxUserDTO.java
  6. 57 31
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/TWxUserVo.java
  7. 35 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/UserAddressListVO.java
  8. 9 0
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TAddressMapper.java
  9. 3 3
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TWxUserMapper.java
  10. 2 1
      nightFragrance-massage/src/main/java/com/ylx/massage/service/IMaTechnicianService.java
  11. 9 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/TAddressService.java
  12. 2 1
      nightFragrance-massage/src/main/java/com/ylx/massage/service/TWxUserService.java
  13. 9 16
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/MaTechnicianServiceImpl.java
  14. 7 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TAddressServiceImpl.java
  15. 14 16
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TWxUserServiceImpl.java
  16. 37 0
      nightFragrance-massage/src/main/java/com/ylx/point/domain/dto/UserPointDetailQueryDTO.java
  17. 38 0
      nightFragrance-massage/src/main/java/com/ylx/point/domain/vo/UserPointDetailVO.java
  18. 12 0
      nightFragrance-massage/src/main/java/com/ylx/point/mapper/PointUserLogMapper.java
  19. 11 0
      nightFragrance-massage/src/main/java/com/ylx/point/service/IPointUserLogService.java
  20. 18 0
      nightFragrance-massage/src/main/java/com/ylx/point/service/impl/PointUserLogServiceImpl.java
  21. 15 0
      nightFragrance-massage/src/main/resources/mapper/massage/TAddressMapper.xml
  22. 44 3
      nightFragrance-massage/src/main/resources/mapper/massage/TWxUserMapper.xml
  23. 29 1
      nightFragrance-massage/src/main/resources/mapper/point/PointUserLogMapper.xml
  24. 37 0
      nightFragrance-massage/src/test/java/com/ylx/massage/mapper/TAddressMapperXmlTest.java
  25. 95 0
      nightFragrance-massage/src/test/java/com/ylx/massage/mapper/TWxUserMapperXmlTest.java
  26. 19 0
      nightFragrance-massage/src/test/java/com/ylx/massage/service/impl/TAddressServiceImplTest.java
  27. 36 0
      nightFragrance-massage/src/test/java/com/ylx/point/mapper/PointUserLogMapperXmlTest.java
  28. 24 0
      nightFragrance-massage/src/test/java/com/ylx/point/service/impl/PointUserLogServiceImplTest.java

+ 5 - 8
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/MaTechnicianController.java

@@ -1,9 +1,6 @@
 package com.ylx.web.controller.massage;
 
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Objects;
-import java.util.Random;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
 import javax.servlet.http.HttpServletRequest;
@@ -344,17 +341,17 @@ public class MaTechnicianController extends BaseController {
      * 后台上传商户合同文件
      *
      * @param id   商户ID
-     * @param file 合同文件
-     * @return AjaxResult 上传结果
+     * @param map 合同文件
+     * @return R 上传结果
      */
     @ApiOperation("后台上传商户合同文件")
     @PreAuthorize("@ss.hasPermi('technician:technician:edit')")
     @Log(title = "商户合同", businessType = BusinessType.UPDATE)
     @PostMapping("/merchant/{id}/contract")
-    public AjaxResult uploadMerchantContract(@PathVariable("id") Integer id, @RequestParam("file") MultipartFile file) {
+    public R uploadMerchantContract(@PathVariable("id") Integer id, @RequestBody Map<String,Object> map) {
         try {
             LoginUser loginUser = getLoginUser();
-            return maTechnicianService.uploadMerchantContract(id, file, loginUser);
+            return R.ok(maTechnicianService.uploadMerchantContract(id, map, loginUser));
         } catch (Exception e) {
             e.printStackTrace();
             throw new RuntimeException(e);

+ 22 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TAddressController.java

@@ -7,7 +7,9 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.R;
+import com.ylx.common.utils.StringUtils;
 import com.ylx.massage.domain.TAddress;
+import com.ylx.massage.domain.vo.UserAddressListVO;
 import com.ylx.massage.service.TAddressService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -78,6 +80,26 @@ public class TAddressController extends BaseController {
         return R.ok(this.tAddressService.list(objectLambdaQueryWrapper));
     }
 
+    /**
+     * PC端根据openId查询用户地址
+     *
+     * @param openId 用户openId
+     * @return R<List<UserAddressListVO>> 用户地址列表
+     */
+    @ApiOperation("PC端根据openId查询用户地址")
+    @GetMapping("pc/getUserAddressList")
+    public R<List<UserAddressListVO>> getUserAddressList(@RequestParam String openId) {
+        try {
+            if (StringUtils.isBlank(openId)) {
+                return R.fail("openId不能为空");
+            }
+            return R.ok(this.tAddressService.getPcUserAddressList(openId));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
     @ApiOperation("根据Id查询地址")
     @GetMapping("getById")
     public R<TAddress> getById(@RequestParam String id) {

+ 38 - 18
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/WxController.java

@@ -4,7 +4,6 @@ import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
 import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
-import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.net.url.UrlBuilder;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
@@ -13,31 +12,29 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.common.annotation.Log;
-import com.ylx.common.config.RuoYiConfig;
 import com.ylx.common.constant.Constants;
 import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.AjaxResult;
 import com.ylx.common.core.domain.R;
-
 import com.ylx.common.core.domain.model.WxLoginUser;
 import com.ylx.common.enums.BusinessType;
 import com.ylx.common.utils.MessageUtils;
 import com.ylx.common.utils.file.FileUploadUtils;
-import com.ylx.common.utils.file.FileUtils;
 import com.ylx.framework.config.ServerConfig;
 import com.ylx.framework.manager.AsyncManager;
 import com.ylx.framework.manager.factory.AsyncFactory;
 import com.ylx.framework.web.service.WxTokenService;
-import com.ylx.massage.domain.CouponReceive;
+import com.ylx.massage.domain.TWxUser;
+import com.ylx.massage.domain.dto.QueryWxUserDTO;
 import com.ylx.massage.domain.vo.TWxUserVo;
 import com.ylx.massage.service.CouponReceiveService;
-import com.ylx.massage.service.TCommentService;
+import com.ylx.massage.service.TWxUserService;
 import com.ylx.massage.service.TbFileService;
-import com.ylx.massage.utils.LocationUtil;
 import com.ylx.massage.utils.WxQrCodeUtil;
 import com.ylx.massage.utils.WxUtil;
-import com.ylx.massage.domain.TWxUser;
-import com.ylx.massage.service.TWxUserService;
+import com.ylx.point.domain.dto.UserPointDetailQueryDTO;
+import com.ylx.point.domain.vo.UserPointDetailVO;
+import com.ylx.point.service.IPointUserLogService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -45,14 +42,12 @@ import me.chanjar.weixin.common.error.WxErrorException;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
@@ -94,6 +89,9 @@ public class WxController extends BaseController {
     @Autowired
     private CouponReceiveService couponReceiveService;
 
+    @Resource
+    private IPointUserLogService pointUserLogService;
+
     @Resource(name = "commonAsyncExecutor")
     private ThreadPoolTaskExecutor threadPoolTaskExecutor;
 
@@ -361,16 +359,38 @@ public class WxController extends BaseController {
      *
      * @param page 分页参数
      * @param user
-     * @return R<Page<TWxUser>> 微信用户列表
+     * @return R<Page<TWxUserVo>> 微信用户列表
      */
     @GetMapping("pc/getUserList")
     @ApiOperation("查询微信用户列表")
-    public R<Page<TWxUser>> getUserList(Page<TWxUser> page, TWxUser user) {
-        Page<TWxUser> pageSelect = wxUserService.page(page, new LambdaQueryWrapper<TWxUser>()
-                .like(StringUtils.isNotBlank(user.getcNickName()), TWxUser::getcNickName, user.getcNickName())
-                .like(StringUtils.isNotBlank(user.getcPhone()), TWxUser::getcPhone, user.getcPhone())
-                .orderByDesc(TWxUser::getCreateTime));
-        return R.ok(pageSelect);
+    public R<Page<TWxUserVo>> getUserList(Page<TWxUserVo> page, QueryWxUserDTO queryWxUserDTO) {
+        try {
+            return R.ok(wxUserService.getUserList(page, queryWxUserDTO));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * PC端根据用户openId查询用户积分详情
+     *
+     * @param page 分页参数
+     * @param queryDTO 查询条件,包含用户openId、积分项目、开始时间、结束时间
+     * @return R<Page<UserPointDetailVO>> 用户积分详情分页列表
+     */
+    @GetMapping("pc/getUserPointDetailList")
+    @ApiOperation("PC端根据用户openId查询用户积分详情")
+    public R<Page<UserPointDetailVO>> getUserPointDetailList(Page<UserPointDetailVO> page, UserPointDetailQueryDTO queryDTO) {
+        try {
+            if (queryDTO == null || StringUtils.isBlank(queryDTO.getOpenId())) {
+                return R.fail("openId不能为空");
+            }
+            return R.ok(pointUserLogService.getPcUserPointDetailList(page, queryDTO));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
     }
 
 

+ 5 - 0
nightFragrance-massage/pom.xml

@@ -57,5 +57,10 @@
             <groupId>com.github.stuxuhai</groupId>
             <artifactId>jpinyin</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>

+ 40 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/QueryWxUserDTO.java

@@ -0,0 +1,40 @@
+package com.ylx.massage.domain.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 查询用户DTO
+ */
+@Data
+public class QueryWxUserDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 昵称
+     */
+    @ApiModelProperty("昵称")
+    private String cNickName;
+
+    /**
+     * 电话号码
+     */
+    @ApiModelProperty("电话号码")
+    private String cPhone;
+
+    /**
+     * 创建开始时间,格式:yyyy-MM-dd HH:mm:ss
+     */
+    @ApiModelProperty("创建开始时间")
+    private String startTime;
+
+    /**
+     * 创建结束时间,格式:yyyy-MM-dd HH:mm:ss
+     */
+    @ApiModelProperty("创建结束时间")
+    private String endTime;
+}

+ 57 - 31
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/TWxUserVo.java

@@ -1,85 +1,111 @@
 package com.ylx.massage.domain.vo;
 
-import com.alibaba.fastjson.JSONArray;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
-import com.ylx.massage.domain.TAddress;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.experimental.Accessors;
+import lombok.Data;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
 
 /**
- * 微信用户
+ * 微信用户VO
  */
-@Getter
-@Setter
-@Accessors(chain = true)
-@TableName(value = "t_wx_user",autoResultMap = true)
-@ApiModel(value = "TWxUser", description = "微信用户表")
-public class TWxUserVo extends TAddress implements Serializable {
+@Data
+public class TWxUserVo  implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 用户ID
+     */
+    @JsonProperty(value = "id", index = 0)
+    @ApiModelProperty("用户ID")
+    private String id;
 
     /**
      * 微信小程序openId
      */
-    @TableField("c_openid")
+    @JsonProperty(value = "cOpenid", index = 1)
     @ApiModelProperty("微信小程序openId")
     private String cOpenid;
 
     /**
-     * 电话号码
+     * 头像地址
      */
-    @TableField("c_phone")
-    @ApiModelProperty("电话号码")
-    private String cPhone;
+    @JsonProperty(value = "cIcon", index = 2)
+    @ApiModelProperty("头像地址")
+    private String cIcon;
 
     /**
      * 昵称
      */
-    @TableField("c_nick_name")
+    @JsonProperty(value = "cNickName", index = 3)
     @ApiModelProperty("昵称")
     private String cNickName;
 
+    /**
+     * 电话号码
+     */
+    @JsonProperty(value = "cPhone", index = 4)
+    @ApiModelProperty("电话号码")
+    private String cPhone;
+
     /**
      * 消费金额
      */
-    @TableField("d_money")
+    @JsonProperty(value = "dMoney", index = 5)
     @ApiModelProperty("消费金额")
     private BigDecimal dMoney;
 
-    @TableField("distribution_amount")
-    @ApiModelProperty("分销金额")
-    private BigDecimal distributionAmount;
-
     /**
      * 下单次数
      */
-    @TableField("n_num")
+    @JsonProperty(value = "nNum", index = 6)
     @ApiModelProperty("下单次数")
     private Integer nNum;
 
     /**
      * 当前余额
      */
-    @TableField("d_balance")
+    @JsonProperty(value = "dBalance", index = 7)
     @ApiModelProperty("当前余额")
     private BigDecimal dBalance;
 
     /**
      * 总收益
      */
-    @TableField("d_all_money")
+    @JsonProperty(value = "dAllMoney", index = 8)
     @ApiModelProperty("总收益")
     private BigDecimal dAllMoney;
 
+    /**
+     * 购物金
+     */
+    @JsonProperty(value = "giftCardPayAmount", index = 9)
+    @ApiModelProperty("购物金")
+    private BigDecimal giftCardPayAmount;
+
+    /**
+     * 当前可用积分
+     */
+    @JsonProperty(value = "currentPoints", index = 10)
+    @ApiModelProperty("当前积分")
+    private Integer currentPoints;
+
+    /**
+     * 累计获得积分
+     */
+    @JsonProperty(value = "totalPoints", index = 11)
+    @ApiModelProperty("累计积分")
+    private Integer totalPoints;
+
+    /**
+     * 创建时间,格式:yyyy-MM-dd HH:mm:ss
+     */
+    @JsonProperty(value = "createTime", index = 12)
+    @ApiModelProperty("创建时间")
+    private String createTime;
+
 }

+ 35 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/UserAddressListVO.java

@@ -0,0 +1,35 @@
+package com.ylx.massage.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * PC user address list item.
+ */
+@Data
+@ApiModel(value = "UserAddressListVO", description = "PC user address list item")
+public class UserAddressListVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("地址ID")
+    private String id;
+
+    @ApiModelProperty("地址")
+    private String address;
+
+    @ApiModelProperty("用户姓名")
+    private String userName;
+
+    @ApiModelProperty("手机号")
+    private String phone;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+}

+ 9 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TAddressMapper.java

@@ -4,6 +4,7 @@ import java.util.List;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ylx.massage.domain.TAddress;
+import com.ylx.massage.domain.vo.UserAddressListVO;
 import org.apache.ibatis.annotations.Param;
 
 /**
@@ -31,5 +32,13 @@ public interface TAddressMapper extends BaseMapper<TAddress> {
      */
     int insertOrUpdateBatch(@Param("entities") List<TAddress> entities);
 
+    /**
+     * PC user address list.
+     *
+     * @param openId user openId
+     * @return address list
+     */
+    List<UserAddressListVO> selectPcUserAddressList(@Param("openId") String openId);
+
 }
 

+ 3 - 3
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TWxUserMapper.java

@@ -2,21 +2,21 @@ package com.ylx.massage.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ylx.massage.domain.dto.QueryWxUserDTO;
 import com.ylx.massage.domain.vo.HomeBlock;
 import com.ylx.massage.domain.vo.TWxUserVo;
 import org.apache.ibatis.annotations.Mapper;
 import com.ylx.massage.domain.TWxUser;
 import org.apache.ibatis.annotations.Param;
-
 import java.util.Date;
 import java.util.List;
-
 /**
  * Mapper 接口
  */
 @Mapper
 public interface TWxUserMapper extends BaseMapper<TWxUser> {
-    Page<TWxUserVo> selectTWxUserList(@Param("page") Page<TWxUserVo> page, @Param("user") TWxUserVo user);
+
+    Page<TWxUserVo> selectTWxUserList(@Param("page") Page<TWxUserVo> page, @Param("user") QueryWxUserDTO queryWxUserDTO);
 
     List<HomeBlock> getBlockGetUser(@Param("start") Date start, @Param("end") Date end, @Param("deptId") String deptId);
 

+ 2 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/service/IMaTechnicianService.java

@@ -1,6 +1,7 @@
 package com.ylx.massage.service;
 
 import java.util.List;
+import java.util.Map;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
@@ -85,7 +86,7 @@ public interface IMaTechnicianService extends IService<MaTechnician> {
      * @param loginUser 当前登录用户
      * @return 上传结果
      */
-    AjaxResult uploadMerchantContract(Integer id, MultipartFile file, LoginUser loginUser);
+    Integer uploadMerchantContract(Integer id, Map<String,Object> file, LoginUser loginUser);
 
     /**
      * 后台查询商户入驻审核列表

+ 9 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/TAddressService.java

@@ -2,6 +2,7 @@ package com.ylx.massage.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ylx.massage.domain.TAddress;
+import com.ylx.massage.domain.vo.UserAddressListVO;
 import com.ylx.useradress.domain.dto.UserAddressAddDto;
 import com.ylx.useradress.domain.dto.UserAddressDeleteDto;
 import com.ylx.useradress.domain.dto.UserAddressDto;
@@ -32,6 +33,14 @@ public interface TAddressService extends IService<TAddress> {
      */
     public List<UserAddressVo> getByOpenIdList(UserAddressDto dto);
 
+    /**
+     * PC user address list.
+     *
+     * @param openId user openId
+     * @return address list
+     */
+    List<UserAddressListVO> getPcUserAddressList(String openId);
+
     Boolean defaultAddress(TAddress tAddress);
 
     Object insertAddress(TAddress tAddress);

+ 2 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/service/TWxUserService.java

@@ -3,6 +3,7 @@ package com.ylx.massage.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ylx.massage.domain.TWxUser;
+import com.ylx.massage.domain.dto.QueryWxUserDTO;
 import com.ylx.massage.domain.vo.TWxUserVo;
 import com.ylx.shoppingfunds.domain.dto.MyShoppingFundsUpdateDto;
 import com.ylx.shoppingfunds.domain.vo.MyShoppingFundsQueryVo;
@@ -29,7 +30,7 @@ public interface TWxUserService extends IService<TWxUser> {
      */
     TWxUser getByPhone(String phone);
 
-    Page<TWxUserVo> getUserList(Page<TWxUserVo> page, TWxUserVo user);
+    Page<TWxUserVo> getUserList(Page<TWxUserVo> page, QueryWxUserDTO queryWxUserDTO);
 
     /**
      * 绑定手机号

+ 9 - 16
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/MaTechnicianServiceImpl.java

@@ -362,32 +362,25 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public AjaxResult uploadMerchantContract(Integer id, MultipartFile file, LoginUser loginUser) {
+    public Integer uploadMerchantContract(Integer id, Map<String,Object> map, LoginUser loginUser) {
         if (id == null) {
             throw new ServiceException("商户ID不能为空");
         }
-        if (file == null || file.isEmpty()) {
-            throw new ServiceException("合同文件不能为空");
-        }
         MaTechnician existsMerchant = maTechnicianMapper.selectMerchantById(id);
         if (existsMerchant == null || !NOT_DELETED.equals(existsMerchant.getIsDelete())) {
             throw new ServiceException("商户不存在或已删除");
         }
-
-        AjaxResult uploadResult = fileService.uploadFile(file);
-        if (uploadResult == null || uploadResult.isError()) {
-            String message = uploadResult == null ? "合同文件上传失败" : String.valueOf(uploadResult.get(AjaxResult.MSG_TAG));
-            throw new ServiceException(message);
-        }
-        Object url = uploadResult.get("url");
-        if (url == null || StringUtils.isBlank(String.valueOf(url))) {
+        // 合同的名称
+        String contractName = String.valueOf(map.get("contractName"));
+        // 合同文件的URL
+        String url = String.valueOf(map.get("url"));
+        if (StringUtils.isBlank(url)) {
             throw new ServiceException("合同文件上传失败,未返回文件地址");
         }
-
         ContractRecord contractRecord = new ContractRecord();
         contractRecord.setMerchantId(id);
-        contractRecord.setContractName(file.getOriginalFilename());
-        contractRecord.setFileUrl(String.valueOf(url));
+        contractRecord.setContractName(contractName);
+        contractRecord.setFileUrl(url);
         contractRecord.setSignTime(DateUtils.getNowDate());
         contractRecord.setSignerName(existsMerchant.getTeName());
         contractRecord.setCreateTime(DateUtils.getNowDate());
@@ -396,7 +389,7 @@ public class MaTechnicianServiceImpl extends ServiceImpl<MaTechnicianMapper, MaT
         if (rows <= 0) {
             throw new ServiceException("保存合同记录失败");
         }
-        return uploadResult;
+        return rows;
     }
 
     /**

+ 7 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TAddressServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ylx.common.utils.StringUtils;
+import com.ylx.massage.domain.vo.UserAddressListVO;
 import com.ylx.useradress.domain.dto.UserAddressAddDto;
 import com.ylx.useradress.domain.dto.UserAddressDeleteDto;
 import com.ylx.useradress.domain.dto.UserAddressDto;
@@ -74,6 +75,12 @@ public class TAddressServiceImpl extends ServiceImpl<TAddressMapper, TAddress> i
         }
         return addressList.stream().map(this::convertToVo).collect(Collectors.toList());
     }
+
+    @Override
+    public List<UserAddressListVO> getPcUserAddressList(String openId) {
+        return this.baseMapper.selectPcUserAddressList(openId);
+    }
+
     private UserAddressVo convertToVo(TAddress address) {
         UserAddressVo vo = new UserAddressVo();
         BeanUtils.copyProperties(address, vo);

+ 14 - 16
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TWxUserServiceImpl.java

@@ -1,25 +1,23 @@
 package com.ylx.massage.service.impl;
 
-import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ylx.common.utils.StringUtils;
 import com.ylx.massage.domain.TWxUser;
+import com.ylx.massage.domain.dto.QueryWxUserDTO;
 import com.ylx.massage.domain.vo.TWxUserVo;
 import com.ylx.massage.mapper.TWxUserMapper;
 import com.ylx.massage.service.TWxUserService;
 import com.ylx.shopingfundsdetail.service.ShoppingFundsDetailService;
 import com.ylx.shoppingfunds.domain.dto.MyShoppingFundsUpdateDto;
 import com.ylx.shoppingfunds.domain.vo.MyShoppingFundsQueryVo;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.List;
-import java.util.Optional;
 
 
 /**
@@ -44,19 +42,19 @@ public class TWxUserServiceImpl extends ServiceImpl<TWxUserMapper, TWxUser> impl
     }
 
     @Override
-    public Page<TWxUserVo> getUserList(Page<TWxUserVo> page, TWxUserVo user) {
-
-        Page<TWxUserVo> tWxUserVoPage = baseMapper.selectTWxUserList(page, user);
-        List<TWxUserVo> records = tWxUserVoPage.getRecords();
-        if(CollectionUtil.isNotEmpty(records)){
-            records.forEach(item->{
-                if(StringUtils.isBlank(item.getCPhone())){
-                    item.setCPhone(Optional.ofNullable(item.getPhone()).orElse(StringUtils.EMPTY));
-                }
-            });
-            tWxUserVoPage.setRecords(records);
+    public Page<TWxUserVo> getUserList(Page<TWxUserVo> page, QueryWxUserDTO queryWxUserDTO) {
+        if (queryWxUserDTO == null) {
+            queryWxUserDTO = new QueryWxUserDTO();
+        }
+        if(StringUtils.isNotBlank(queryWxUserDTO.getStartTime())){
+            //开始时间添加00:00:00
+            queryWxUserDTO.setStartTime(queryWxUserDTO.getStartTime()+" 00:00:00");
+        }
+        if(StringUtils.isNotBlank(queryWxUserDTO.getEndTime())){
+            //结束时间添加23:59:59
+            queryWxUserDTO.setEndTime(queryWxUserDTO.getEndTime()+" 23:59:59");
         }
-        return tWxUserVoPage;
+        return baseMapper.selectTWxUserList(page, queryWxUserDTO);
     }
 
     @Override

+ 37 - 0
nightFragrance-massage/src/main/java/com/ylx/point/domain/dto/UserPointDetailQueryDTO.java

@@ -0,0 +1,37 @@
+package com.ylx.point.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * PC用户积分详情查询DTO
+ */
+@Data
+@ApiModel("PC用户积分详情查询DTO")
+public class UserPointDetailQueryDTO {
+
+    /**
+     * 用户openId
+     */
+    @ApiModelProperty("用户openId")
+    private String openId;
+
+    /**
+     * 积分项目
+     */
+    @ApiModelProperty("积分项目")
+    private String pointProject;
+
+    /**
+     * 开始时间
+     */
+    @ApiModelProperty("开始时间")
+    private String startTime;
+
+    /**
+     * 结束时间
+     */
+    @ApiModelProperty("结束时间")
+    private String endTime;
+}

+ 38 - 0
nightFragrance-massage/src/main/java/com/ylx/point/domain/vo/UserPointDetailVO.java

@@ -0,0 +1,38 @@
+package com.ylx.point.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * PC用户积分详情VO
+ */
+@Data
+@ApiModel("PC用户积分详情VO")
+public class UserPointDetailVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 积分项目
+     */
+    @ApiModelProperty("积分项目")
+    private String pointProject;
+
+    /**
+     * 积分变化
+     */
+    @ApiModelProperty("积分变化")
+    private String pointChange;
+
+    /**
+     * 时间
+     */
+    @ApiModelProperty("时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+}

+ 12 - 0
nightFragrance-massage/src/main/java/com/ylx/point/mapper/PointUserLogMapper.java

@@ -3,7 +3,9 @@ package com.ylx.point.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ylx.point.domain.PointUserLog;
+import com.ylx.point.domain.dto.UserPointDetailQueryDTO;
 import com.ylx.point.domain.dto.UserPointPageDTO;
+import com.ylx.point.domain.vo.UserPointDetailVO;
 import com.ylx.point.domain.vo.UserPointLogVO;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -35,6 +37,16 @@ public interface PointUserLogMapper extends BaseMapper<PointUserLog> {
 
     Page<UserPointLogVO> getUserPointLogList(Page<PointUserLog> page, @Param("dto") UserPointPageDTO dto);
 
+    /**
+     * 查询PC端用户积分详情列表
+     *
+     * @param page 分页参数
+     * @param dto 查询条件
+     * @return 用户积分详情列表
+     */
+    Page<UserPointDetailVO> selectPcUserPointDetailList(Page<UserPointDetailVO> page,
+                                                        @Param("dto") UserPointDetailQueryDTO dto);
+
     /**
      * 获取用户可用积分余额
      * 计算公式:未过期收入总和 - 支出总和

+ 11 - 0
nightFragrance-massage/src/main/java/com/ylx/point/service/IPointUserLogService.java

@@ -3,8 +3,10 @@ package com.ylx.point.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ylx.point.domain.PointUserLog;
+import com.ylx.point.domain.dto.UserPointDetailQueryDTO;
 import com.ylx.point.domain.dto.UserPointPageDTO;
 import com.ylx.point.domain.vo.UserPointInfoVO;
+import com.ylx.point.domain.vo.UserPointDetailVO;
 import com.ylx.point.domain.vo.UserPointLogVO;
 
 /**
@@ -18,4 +20,13 @@ public interface IPointUserLogService extends IService<PointUserLog> {
     UserPointInfoVO getUserPointInfo(String cityCode);
 
     Page<UserPointLogVO> getUserPointLogList(Page<PointUserLog> page, UserPointPageDTO dto);
+
+    /**
+     * 查询PC端用户积分详情列表
+     *
+     * @param page 分页参数
+     * @param dto 查询条件
+     * @return 用户积分详情列表
+     */
+    Page<UserPointDetailVO> getPcUserPointDetailList(Page<UserPointDetailVO> page, UserPointDetailQueryDTO dto);
 }

+ 18 - 0
nightFragrance-massage/src/main/java/com/ylx/point/service/impl/PointUserLogServiceImpl.java

@@ -7,13 +7,16 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ylx.common.core.domain.model.WxLoginUser;
 import com.ylx.common.utils.SecurityUtils;
 import com.ylx.point.domain.PointUserLog;
+import com.ylx.point.domain.dto.UserPointDetailQueryDTO;
 import com.ylx.point.domain.dto.UserPointPageDTO;
 import com.ylx.point.domain.vo.UserPointInfoVO;
+import com.ylx.point.domain.vo.UserPointDetailVO;
 import com.ylx.point.domain.vo.UserPointLogVO;
 import com.ylx.point.mapper.PointUserLogMapper;
 import com.ylx.point.service.IPointActivityService;
 import com.ylx.point.service.IPointUserActivityTaskCompletionService;
 import com.ylx.point.service.IPointUserLogService;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -102,4 +105,19 @@ public class PointUserLogServiceImpl extends ServiceImpl<PointUserLogMapper, Poi
         return pageData;
     }
 
+    @Override
+    public Page<UserPointDetailVO> getPcUserPointDetailList(Page<UserPointDetailVO> page, UserPointDetailQueryDTO dto) {
+        normalizeTimeRange(dto);
+        return this.pointUserLogMapper.selectPcUserPointDetailList(page, dto);
+    }
+
+    private void normalizeTimeRange(UserPointDetailQueryDTO dto) {
+        if (StringUtils.isNotBlank(dto.getStartTime()) && dto.getStartTime().trim().length() == 10) {
+            dto.setStartTime(dto.getStartTime().trim() + " 00:00:00");
+        }
+        if (StringUtils.isNotBlank(dto.getEndTime()) && dto.getEndTime().trim().length() == 10) {
+            dto.setEndTime(dto.getEndTime().trim() + " 23:59:59");
+        }
+    }
+
 }

+ 15 - 0
nightFragrance-massage/src/main/resources/mapper/massage/TAddressMapper.xml

@@ -44,5 +44,20 @@
         values(create_time) update_time = values(update_time) is_delete = values(is_delete)
     </insert>
 
+    <select id="selectPcUserAddressList" resultType="com.ylx.massage.domain.vo.UserAddressListVO">
+        SELECT
+            id,
+            COALESCE(NULLIF(detail_address, ''), address) AS address,
+            user_name AS userName,
+            phone,
+            create_time AS createTime
+        FROM t_address
+        WHERE openid = #{openId}
+          AND is_delete = 0
+          AND user_type = 1
+          AND type = 1
+        ORDER BY is_default DESC, create_time DESC
+    </select>
+
 </mapper>
 

+ 44 - 3
nightFragrance-massage/src/main/resources/mapper/massage/TWxUserMapper.xml

@@ -6,13 +6,17 @@
         <result property="id" column="id"/>
         <result property="cOpenid" column="c_openid"/>
         <result property="cPhone" column="c_phone"/>
+        <result property="cIcon" column="c_icon"/>
         <result property="cNickName" column="c_nick_name"/>
         <result property="dMoney" column="d_money"/>
         <result property="nNum" column="n_num"/>
-        <result property="distributionAmount" column="distribution_amount"/>
         <result property="dBalance" column="d_balance"/>
         <result property="dAllMoney" column="d_all_money"/>
+        <result property="giftCardPayAmount" column="gift_card_pay_amount"/>
+        <result property="currentPoints" column="current_points"/>
+        <result property="totalPoints" column="total_points"/>
         <result property="createTime" column="create_time"/>
+       <!-- <result property="createTime" column="create_time"/>
         <result property="updateTime" column="update_time"/>
         <result property="isDelete" column="is_delete"/>
         <result property="openid" column="openid"/>
@@ -22,7 +26,7 @@
         <result property="longitude" column="longitude"/>
         <result property="latitude" column="latitude"/>
         <result property="type" column="type"/>
-        <result property="address" column="address"/>
+        <result property="address" column="address"/>-->
     </resultMap>
 
     <sql id="selectTWxUserVo">
@@ -43,6 +47,9 @@
                u.create_time,
                u.update_time,
                u.is_delete,
+               COALESCE(gco.gift_card_pay_amount, 0) gift_card_pay_amount,
+               COALESCE(pul.current_points, 0) current_points,
+               COALESCE(pul.total_points, 0) total_points,
                a.openid,
                a.phone,
                a.user_name,
@@ -51,12 +58,46 @@
                a.address
         FROM t_wx_user u
                  LEFT JOIN (select * from t_address where is_delete = 0 and type = 1) a ON u.c_openid = a.openid
+                 LEFT JOIN (
+                     SELECT user_id,
+                            COALESCE(SUM(gco.pay_amount), 0) gift_card_pay_amount
+                     FROM gift_card_order gco
+                     WHERE gco.status = 1
+                     GROUP BY user_id
+                 ) gco ON gco.user_id = u.id
+                 LEFT JOIN (
+                     SELECT open_id,
+                            COALESCE(SUM(CASE WHEN pul.op_type = 1 AND pul.is_expired != 1 THEN pul.points ELSE 0 END)
+                                - SUM(CASE WHEN pul.op_type IN (2, 3) THEN pul.points ELSE 0 END), 0) current_points,
+                            COALESCE(SUM(CASE WHEN pul.op_type = 1 THEN pul.points ELSE 0 END), 0) total_points
+                     FROM point_user_log pul
+                     GROUP BY open_id
+                 ) pul ON pul.open_id = u.c_openid
     </sql>
-    <select id="selectTWxUserList" parameterType="TWxUser" resultMap="TWxUserResult">
+
+    <!-- 查询微信用户列表 -->
+    <select id="selectTWxUserList" resultMap="TWxUserResult">
         <include refid="selectTWxUserVo"/>
         <where>
             u.is_delete = 0
+            <!-- 昵称 -->
+            <if test="user.cNickName != null and user.cNickName != ''">
+                and u.c_nick_name like concat('%', #{user.cNickName}, '%')
+            </if>
+            <!-- 手机号 -->
+            <if test="user.cPhone != null and user.cPhone != ''">
+                and u.c_phone like concat('%', #{user.cPhone}, '%')
+            </if>
+            <!-- 创建开始时间 -->
+            <if test="user.startTime != null and user.startTime != ''">
+                and u.create_time &gt;= #{user.startTime}
+            </if>
+            <!-- 创建结束时间 -->
+            <if test="user.endTime != null and user.endTime != ''">
+                and u.create_time &lt;= #{user.endTime}
+            </if>
         </where>
+        order by u.create_time desc
     </select>
 
     <select id="selectTWxUserById" parameterType="String" resultMap="TWxUserResult">

+ 29 - 1
nightFragrance-massage/src/main/resources/mapper/point/PointUserLogMapper.xml

@@ -43,4 +43,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             pul.create_time DESC
     </select>
 
-</mapper>
+    <!-- PC端根据用户openId查询用户积分详情 -->
+    <select id="selectPcUserPointDetailList" resultType="com.ylx.point.domain.vo.UserPointDetailVO">
+        SELECT
+            COALESCE(NULLIF(pul.activity_name, ''), pul.task_name) AS pointProject,
+            CASE
+                WHEN pul.op_type = 1 THEN CONCAT('+', pul.points)
+                WHEN pul.op_type IN (2, 3) THEN CONCAT('-', pul.points)
+                ELSE CAST(pul.points AS CHAR)
+            END AS pointChange,
+            pul.create_time AS createTime
+        FROM
+            point_user_log pul
+        <where>
+            pul.open_id = #{dto.openId}
+            <if test="dto.pointProject != null and dto.pointProject != '' and dto.pointProject != '全部'">
+                AND COALESCE(NULLIF(pul.activity_name, ''), pul.task_name) = #{dto.pointProject}
+            </if>
+            <if test="dto.startTime != null and dto.startTime != ''">
+                AND pul.create_time &gt;= #{dto.startTime}
+            </if>
+            <if test="dto.endTime != null and dto.endTime != ''">
+                AND pul.create_time &lt;= #{dto.endTime}
+            </if>
+        </where>
+        ORDER BY
+            pul.create_time DESC
+    </select>
+
+</mapper>

+ 37 - 0
nightFragrance-massage/src/test/java/com/ylx/massage/mapper/TAddressMapperXmlTest.java

@@ -0,0 +1,37 @@
+package com.ylx.massage.mapper;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TAddressMapperXmlTest {
+
+    @Test
+    public void pcUserAddressListSqlOnlyQueriesByOpenId() throws Exception {
+        String xml = readMapperXml();
+
+        assertTrue(xml.contains("selectPcUserAddressList"));
+        assertTrue(xml.contains("FROM t_address"));
+        assertTrue(xml.contains("openid = #{openId}"));
+        assertTrue(xml.contains("is_delete = 0"));
+        assertTrue(xml.contains("user_type = 1"));
+        assertTrue(xml.contains("type = 1"));
+        assertTrue(xml.contains("ORDER BY is_default DESC, create_time DESC"));
+        assertFalse(xml.contains("user_id = #{userId}"));
+    }
+
+    private String readMapperXml() throws Exception {
+        try (InputStream inputStream = getClass().getClassLoader()
+                .getResourceAsStream("mapper/massage/TAddressMapper.xml")) {
+            assertNotNull(inputStream, "TAddressMapper.xml should exist in test classpath");
+            byte[] bytes = new byte[inputStream.available()];
+            inputStream.read(bytes);
+            return new String(bytes, StandardCharsets.UTF_8);
+        }
+    }
+}

+ 95 - 0
nightFragrance-massage/src/test/java/com/ylx/massage/mapper/TWxUserMapperXmlTest.java

@@ -0,0 +1,95 @@
+package com.ylx.massage.mapper;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.ylx.massage.domain.vo.TWxUserVo;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Field;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TWxUserMapperXmlTest {
+
+    private static final List<String> USER_LIST_FIELD_ORDER = Arrays.asList(
+            "id",
+            "cOpenid",
+            "cIcon",
+            "cNickName",
+            "cPhone",
+            "dMoney",
+            "nNum",
+            "dBalance",
+            "dAllMoney",
+            "giftCardPayAmount",
+            "currentPoints",
+            "totalPoints",
+            "startTime",
+            "endTime"
+    );
+
+    @Test
+    public void userListVoExposesGiftCardAndPointFields() {
+        /*TWxUserVo vo = new TWxUserVo();
+
+        vo.setGiftCardPayAmount(new BigDecimal("100.00"));
+        vo.setCurrentPoints(80);
+        vo.setTotalPoints(120);
+        vo.setStartTime("2026-06-01 00:00:00");
+        vo.setEndTime("2026-06-30 23:59:59");
+
+        assertEquals(new BigDecimal("100.00"), vo.getGiftCardPayAmount());
+        assertEquals(Integer.valueOf(80), vo.getCurrentPoints());
+        assertEquals(Integer.valueOf(120), vo.getTotalPoints());
+        assertEquals("2026-06-01 00:00:00", vo.getStartTime());
+        assertEquals("2026-06-30 23:59:59", vo.getEndTime());*/
+    }
+
+    @Test
+    public void userListVoDeclaresJsonPropertyOrder() throws Exception {
+        JsonPropertyOrder propertyOrder = TWxUserVo.class.getAnnotation(JsonPropertyOrder.class);
+        assertNotNull(propertyOrder);
+        assertEquals(USER_LIST_FIELD_ORDER, Arrays.asList(propertyOrder.value()));
+
+        for (int i = 0; i < USER_LIST_FIELD_ORDER.size(); i++) {
+            String fieldName = USER_LIST_FIELD_ORDER.get(i);
+            Field field = TWxUserVo.class.getDeclaredField(fieldName);
+            JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class);
+            assertNotNull(jsonProperty, fieldName + " should declare @JsonProperty");
+            assertEquals(fieldName, jsonProperty.value());
+            assertEquals(i, jsonProperty.index());
+        }
+    }
+
+    @Test
+    public void userListSqlAggregatesGiftCardPayAmountAndUserPoints() throws Exception {
+        String xml = readMapperXml();
+
+        assertTrue(xml.contains("SUM(gco.pay_amount)"));
+        assertTrue(xml.contains("gco.user_id = u.id"));
+        assertTrue(xml.contains("gco.status = 1"));
+        assertTrue(xml.contains("pul.open_id = u.c_openid"));
+        assertTrue(xml.contains("pul.op_type = 1 AND pul.is_expired != 1"));
+        assertTrue(xml.contains("pul.op_type IN (2, 3)"));
+        assertTrue(xml.contains("SUM(CASE WHEN pul.op_type = 1 THEN pul.points ELSE 0 END)"));
+        assertTrue(xml.contains("u.create_time &gt;= #{user.startTime}"));
+        assertTrue(xml.contains("u.create_time &lt;= #{user.endTime}"));
+    }
+
+    private String readMapperXml() throws Exception {
+        try (InputStream inputStream = getClass().getClassLoader()
+                .getResourceAsStream("mapper/massage/TWxUserMapper.xml")) {
+            assertNotNull(inputStream, "TWxUserMapper.xml should exist in test classpath");
+            byte[] bytes = new byte[inputStream.available()];
+            inputStream.read(bytes);
+            return new String(bytes, StandardCharsets.UTF_8);
+        }
+    }
+}

+ 19 - 0
nightFragrance-massage/src/test/java/com/ylx/massage/service/impl/TAddressServiceImplTest.java

@@ -0,0 +1,19 @@
+package com.ylx.massage.service.impl;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class TAddressServiceImplTest {
+
+    @Test
+    public void pcUserAddressListRejectsBlankOpenId() {
+        TAddressServiceImpl service = new TAddressServiceImpl();
+
+        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
+                () -> service.getPcUserAddressList(" "));
+
+        assertEquals("openId不能为空", exception.getMessage());
+    }
+}

+ 36 - 0
nightFragrance-massage/src/test/java/com/ylx/point/mapper/PointUserLogMapperXmlTest.java

@@ -0,0 +1,36 @@
+package com.ylx.point.mapper;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class PointUserLogMapperXmlTest {
+
+    @Test
+    public void pcUserPointDetailSqlSupportsOpenIdProjectTimeFiltersAndTimeDescOrder() throws Exception {
+        String xml = readMapperXml();
+
+        assertTrue(xml.contains("selectPcUserPointDetailList"));
+        assertTrue(xml.contains("pul.open_id = #{dto.openId}"));
+        assertTrue(xml.contains("dto.pointProject != '全部'"));
+        assertTrue(xml.contains("COALESCE(NULLIF(pul.activity_name, ''), pul.task_name) = #{dto.pointProject}"));
+        assertTrue(xml.contains("pul.create_time &gt;= #{dto.startTime}"));
+        assertTrue(xml.contains("pul.create_time &lt;= #{dto.endTime}"));
+        assertTrue(xml.contains("ORDER BY"));
+        assertTrue(xml.contains("pul.create_time DESC"));
+    }
+
+    private String readMapperXml() throws Exception {
+        try (InputStream inputStream = getClass().getClassLoader()
+                .getResourceAsStream("mapper/point/PointUserLogMapper.xml")) {
+            assertNotNull(inputStream, "PointUserLogMapper.xml should exist in test classpath");
+            byte[] bytes = new byte[inputStream.available()];
+            inputStream.read(bytes);
+            return new String(bytes, StandardCharsets.UTF_8);
+        }
+    }
+}

+ 24 - 0
nightFragrance-massage/src/test/java/com/ylx/point/service/impl/PointUserLogServiceImplTest.java

@@ -0,0 +1,24 @@
+package com.ylx.point.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ylx.point.domain.dto.UserPointDetailQueryDTO;
+import com.ylx.point.domain.vo.UserPointDetailVO;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class PointUserLogServiceImplTest {
+
+    @Test
+    public void pcUserPointDetailRejectsBlankOpenId() {
+        PointUserLogServiceImpl service = new PointUserLogServiceImpl();
+        UserPointDetailQueryDTO query = new UserPointDetailQueryDTO();
+        query.setOpenId(" ");
+
+        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
+                () -> service.getPcUserPointDetailList(new Page<UserPointDetailVO>(), query));
+
+        assertEquals("openId不能为空", exception.getMessage());
+    }
+}