Просмотр исходного кода

【feat】【v3】
1.完善表设计
2.增加和修改奖励相关逻辑
3.增加账户相关逻辑

ChenYL 11 месяцев назад
Родитель
Сommit
71c09f145b
35 измененных файлов с 1048 добавлено и 186 удалено
  1. 8 2
      doc/sql/update-v3.sql
  2. 21 17
      doc/技术文档.md
  3. 3 4
      src/main/java/com/punchsettle/server/atomic/entity/PiMultiTask.java
  4. 3 3
      src/main/java/com/punchsettle/server/atomic/entity/PiTask.java
  5. 4 2
      src/main/java/com/punchsettle/server/atomic/entity/Reward.java
  6. 27 1
      src/main/java/com/punchsettle/server/atomic/entity/RewardExchangeHistory.java
  7. 21 2
      src/main/java/com/punchsettle/server/atomic/service/IAccountService.java
  8. 18 0
      src/main/java/com/punchsettle/server/atomic/service/IRewardExchangeHistoryService.java
  9. 0 10
      src/main/java/com/punchsettle/server/atomic/service/IRewardHistoryService.java
  10. 31 0
      src/main/java/com/punchsettle/server/atomic/service/IRewardService.java
  11. 21 0
      src/main/java/com/punchsettle/server/atomic/service/impl/AccountServiceImpl.java
  12. 3 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java
  13. 27 0
      src/main/java/com/punchsettle/server/atomic/service/impl/RewardExchangeHistoryServiceImpl.java
  14. 0 14
      src/main/java/com/punchsettle/server/atomic/service/impl/RewardHistoryServiceImpl.java
  15. 51 0
      src/main/java/com/punchsettle/server/atomic/service/impl/RewardServiceImpl.java
  16. 23 0
      src/main/java/com/punchsettle/server/constant/RewardExchangeMethodEnum.java
  17. 2 2
      src/main/java/com/punchsettle/server/constant/VersionStatusEnum.java
  18. 25 0
      src/main/java/com/punchsettle/server/pojo/account/AccountRequest.java
  19. 29 0
      src/main/java/com/punchsettle/server/pojo/account/AccountVO.java
  20. 34 0
      src/main/java/com/punchsettle/server/pojo/account/TransferRequest.java
  21. 3 3
      src/main/java/com/punchsettle/server/pojo/punchIn/PiMultiTaskQuery.java
  22. 8 3
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskQuery.java
  23. 34 0
      src/main/java/com/punchsettle/server/pojo/reward/RewardExchangeRequest.java
  24. 26 0
      src/main/java/com/punchsettle/server/pojo/reward/RewardQuery.java
  25. 49 0
      src/main/java/com/punchsettle/server/pojo/reward/RewardRequest.java
  26. 41 0
      src/main/java/com/punchsettle/server/pojo/reward/RewardVO.java
  27. 66 0
      src/main/java/com/punchsettle/server/service/controller/AccountController.java
  28. 39 12
      src/main/java/com/punchsettle/server/service/controller/RewardController.java
  29. 40 0
      src/main/java/com/punchsettle/server/service/manager/IAccountManager.java
  30. 27 8
      src/main/java/com/punchsettle/server/service/manager/IRewardManager.java
  31. 138 0
      src/main/java/com/punchsettle/server/service/manager/impl/AccountManagerImpl.java
  32. 8 15
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java
  33. 3 3
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInSettleManagerImpl.java
  34. 215 0
      src/main/java/com/punchsettle/server/service/manager/impl/RewardManagerImpl.java
  35. 0 85
      src/main/java/com/punchsettle/server/service/manager/impl/RewardManagerV1Impl.java

+ 8 - 2
doc/sql/update-v3.sql

@@ -76,6 +76,10 @@ CREATE TABLE `reward_history` (
   `account_name` varchar(100) NOT NULL COMMENT '账户名称',
   `account_points_before_exchange` int NOT NULL COMMENT '兑换前账户中的积分',
   `account_points_after_exchange` int NOT NULL COMMENT '兑换后账户中的积分',
+  `unused_points_before_exchange` int NOT NULL COMMENT '兑换前用户的未使用积分',
+  `unused_points_after_exchange` int NOT NULL COMMENT '兑换后用户的未使用积分',
+  `used_points_before_exchange` int NOT NULL COMMENT '兑换前用户的已使用积分',
+  `used_points_after_exchange` int NOT NULL COMMENT '兑换后用户的已使用积分',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
   `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
@@ -668,12 +672,14 @@ ALTER TABLE punch_settle.reward MODIFY COLUMN reward_status varchar(10) CHARACTE
 ALTER TABLE punch_settle.reward MODIFY COLUMN reward_version int NOT NULL COMMENT '奖励修改版本';
 
 ALTER TABLE punch_settle.reward_history DROP COLUMN account_name;
-insert into reward_history(user_id, reward_id, exchange_method, exchange_count, exchange_total_points, account_id, account_points_before_exchange, account_points_after_exchange, created_by, creation_time, last_updated_by, last_update_time, version, delete_flag)
+insert into reward_history(user_id, reward_id, exchange_method, exchange_count, exchange_total_points, account_id, account_points_before_exchange, account_points_after_exchange,
+unused_points_before_exchange, unused_points_after_exchange, userd_points_before_exchange, userd_points_after_exchange,
+created_by, creation_time, last_updated_by, last_update_time, version, delete_flag)
 select created_by,
 (select id from reward r where r.user_id = rr.created_by and r.reward_name = '刮一次刮刮乐'),
 'MANUAL', claim_reward_num, claim_reward_num,
 (SELECT ID FROM account a where a.user_id = rr.created_by and a.account_type = 'BASIC'),
-rr.before_claim_reward_num , rr.after_claim_reward_num ,
+rr.before_claim_reward_num , rr.after_claim_reward_num , rr.before_claim_reward_num , rr.after_claim_reward_num , rr.before_claim_reward_num , rr.after_claim_reward_num ,
 created_by, creation_time, last_updated_by, last_update_time, version, delete_flag
 from user_claim_reward_record rr;
 DROP TABLE IF EXISTS user_claim_reward_record;

+ 21 - 17
doc/技术文档.md

@@ -1116,23 +1116,23 @@ ui设计工具:即时设计
 
 表名:reward
 
-| 字段                | 类型         | 描述                                          | 索引     |
-| ------------------- | ------------ | --------------------------------------------- | -------- |
-| id                  | bigint       | 主键                                          | 主键索引 |
-| user_id             | bigint       | 用户id                                        | 普通索引 |
-| reward_unique_id    | bigint       | 奖励唯一ID                                    |          |
-| reward_status       | varchar(10)  | 奖励状态(活跃-ACTIVE,归档-ARCHIVE)           |          |
-| reward_version      | int          | 奖励修改版本                                  |          |
-| reward_name         | varchar(100) | 奖励名称                                      |          |
-| exchange_points     | int          | 兑换所需积分                                  |          |
-| auto_status         | varchar(10)  | 是否启用自动兑换(ENABLED-启用,DISABLED-关闭) |          |
-| auto_exchange_count | int          | 自动兑换数量                                  |          |
-| created_by          | bigint       | 创建人                                        |          |
-| creation_time       | timestamp    | 创建时间                                      |          |
-| last_updated_by     | bigint       | 最后更新人                                    |          |
-| last_update_time    | timestamp    | 最后更新时间                                  |          |
-| version             | bigint       | 版本号                                        |          |
-| delete_flag         | tinyint      | 逻辑删除标志(0-未删除,1-已删除)            |          |
+| 字段                | 类型         | 描述                                             | 索引     |
+| ------------------- | ------------ | ------------------------------------------------ | -------- |
+| id                  | bigint       | 主键                                             | 主键索引 |
+| user_id             | bigint       | 用户id                                           | 普通索引 |
+| reward_unique_id    | bigint       | 奖励唯一ID                                       |          |
+| reward_status       | varchar(10)  | 奖励状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE) |          |
+| reward_version      | int          | 奖励修改版本                                     |          |
+| reward_name         | varchar(100) | 奖励名称                                         |          |
+| exchange_points     | int          | 兑换所需积分                                     |          |
+| auto_status         | varchar(10)  | 是否启用自动兑换(ENABLED-启用,DISABLED-关闭)    |          |
+| auto_exchange_count | int          | 自动兑换数量                                     |          |
+| created_by          | bigint       | 创建人                                           |          |
+| creation_time       | timestamp    | 创建时间                                         |          |
+| last_updated_by     | bigint       | 最后更新人                                       |          |
+| last_update_time    | timestamp    | 最后更新时间                                     |          |
+| version             | bigint       | 版本号                                           |          |
+| delete_flag         | tinyint      | 逻辑删除标志(0-未删除,1-已删除)               |          |
 
 
 
@@ -1170,6 +1170,10 @@ ui设计工具:即时设计
 | account_id                     | bigint      | 兑换使用的账户id                         |          |
 | account_points_before_exchange | int         | 兑换前账户中的积分                       |          |
 | account_points_after_exchange  | int         | 兑换后账户中的积分                       |          |
+| unused_points_before_exchange  | int         | 兑换前用户未使用的积分                   |          |
+| unused_points_after_exchange   | int         | 兑换后用户未使用的积分                   |          |
+| used_points_before_exchange    | int         | 兑换前用户已使用的积分                   |          |
+| used_points_after_exchange     | int         | 兑换后用户已使用的积分                   |          |
 | created_by                     | bigint      | 创建人                                   |          |
 | creation_time                  | timestamp   | 创建时间                                 | 普通索引 |
 | last_updated_by                | bigint      | 最后更新人                               |          |

+ 3 - 4
src/main/java/com/punchsettle/server/atomic/entity/PiMultiTask.java

@@ -6,10 +6,9 @@ import java.io.Serializable;
 import com.punchsettle.server.atomic.ContinueTask;
 import com.punchsettle.server.common.pojo.BaseEntity;
 
-import com.punchsettle.server.constant.ArchiveStatusEnum;
 import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
 import com.punchsettle.server.constant.PunchInExtraMethodEnum;
-import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -37,10 +36,10 @@ public class PiMultiTask extends BaseEntity implements Serializable, ContinueTas
 
     /**
      * 任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
-     * @see PunchInTaskStatusEnum
+     * @see VersionStatusEnum
      */
     @Column(name = "task_status")
-    private PunchInTaskStatusEnum taskStatus;
+    private VersionStatusEnum taskStatus;
 
     /**
      * 任务修改版本

+ 3 - 3
src/main/java/com/punchsettle/server/atomic/entity/PiTask.java

@@ -13,7 +13,7 @@ import com.punchsettle.server.constant.CompareRuleEnum;
 import com.punchsettle.server.constant.PunchInExtraMethodEnum;
 import com.punchsettle.server.constant.FullAttendancePeriodEnum;
 import com.punchsettle.server.constant.PunchInMethodEnum;
-import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 import com.punchsettle.server.constant.RepeatCategoryEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
@@ -42,10 +42,10 @@ public class PiTask extends BaseEntity implements Serializable, ContinueTask {
 
     /**
      * 任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
-     * @see PunchInTaskStatusEnum
+     * @see VersionStatusEnum
      */
     @Column(name = "task_status")
-    private PunchInTaskStatusEnum taskStatus;
+    private VersionStatusEnum taskStatus;
 
     /**
      * 任务修改版本

+ 4 - 2
src/main/java/com/punchsettle/server/atomic/entity/Reward.java

@@ -5,6 +5,7 @@ import java.io.Serializable;
 
 import com.punchsettle.server.common.pojo.BaseEntity;
 
+import com.punchsettle.server.constant.VersionStatusEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -37,10 +38,11 @@ public class Reward extends BaseEntity implements Serializable {
     private Long rewardUniqueId;
 
     /**
-     * 奖励状态(活跃-ACTIVE,归档-ARCHIVE)
+     * 奖励状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
+     * @see VersionStatusEnum
      */
     @Column(name = "reward_status")
-    private String rewardStatus;
+    private VersionStatusEnum rewardStatus;
 
     /**
      * 奖励修改版本

+ 27 - 1
src/main/java/com/punchsettle/server/atomic/entity/RewardExchangeHistory.java

@@ -4,6 +4,7 @@ import java.io.Serial;
 import java.io.Serializable;
 
 import com.punchsettle.server.common.pojo.BaseEntity;
+import com.punchsettle.server.constant.RewardExchangeMethodEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -37,9 +38,10 @@ public class RewardExchangeHistory extends BaseEntity implements Serializable {
 
     /**
      * 兑换类型(手动兑换-MANUAL,自动兑换-AUTO)
+     * @see RewardExchangeMethodEnum
      */
     @Column(name = "exchange_method")
-    private String exchangeMethod;
+    private RewardExchangeMethodEnum exchangeMethod;
 
     /**
      * 兑换次数
@@ -71,4 +73,28 @@ public class RewardExchangeHistory extends BaseEntity implements Serializable {
     @Column(name = "account_points_after_exchange")
     private Integer accountPointsAfterExchange;
 
+    /**
+     * 兑换前用户的未使用积分
+     */
+    @Column(name = "unused_points_before_exchange")
+    private Integer unusedPointsBeforeExchange;
+
+    /**
+     * 兑换后用户的未使用积分
+     */
+    @Column(name = "unused_points_after_exchange")
+    private Integer unusedPointsAfterExchange;
+
+    /**
+     * 兑换前用户的已使用积分
+     */
+    @Column(name = "used_points_before_exchange")
+    private Integer usedPointsBeforeExchange;
+
+    /**
+     * 兑换后用户的已使用积分
+     */
+    @Column(name = "used_points_after_exchange")
+    private Integer usedPointsAfterExchange;
+
 }

+ 21 - 2
src/main/java/com/punchsettle/server/atomic/service/IAccountService.java

@@ -1,10 +1,10 @@
 package com.punchsettle.server.atomic.service;
 
+import java.util.List;
+
 import com.punchsettle.server.atomic.entity.Account;
 import com.punchsettle.server.pojo.punchIn.AccountQuery;
 
-import java.util.List;
-
 /**
  * @author tyuio
  * @version 1.0.0
@@ -25,4 +25,23 @@ public interface IAccountService {
      * @param accounts
      */
     void batchUpdate(List<Account> accounts);
+
+    /**
+     * 新增数据
+     * @param account
+     */
+    void insert(Account account);
+
+    /**
+     * 根据主键删除数据
+     * @param id
+     */
+    void deleteById(Long id);
+
+    /**
+     * 根据主键查询数据
+     * @param id
+     * @return
+     */
+    Account getById(Long id);
 }

+ 18 - 0
src/main/java/com/punchsettle/server/atomic/service/IRewardExchangeHistoryService.java

@@ -0,0 +1,18 @@
+package com.punchsettle.server.atomic.service;
+
+import com.punchsettle.server.atomic.entity.RewardExchangeHistory;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/8 10:38
+ * @description 奖励兑换记录 service
+ */
+public interface IRewardExchangeHistoryService {
+
+    /**
+     * 新增
+     * @param rewardExchangeHistory
+     */
+    void insert(RewardExchangeHistory rewardExchangeHistory);
+}

+ 0 - 10
src/main/java/com/punchsettle/server/atomic/service/IRewardHistoryService.java

@@ -1,10 +0,0 @@
-package com.punchsettle.server.atomic.service;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/4/8 10:38
- * @description 奖励兑换记录 service
- */
-public interface IRewardHistoryService {
-}

+ 31 - 0
src/main/java/com/punchsettle/server/atomic/service/IRewardService.java

@@ -1,5 +1,10 @@
 package com.punchsettle.server.atomic.service;
 
+import com.punchsettle.server.atomic.entity.Reward;
+import com.punchsettle.server.pojo.reward.RewardQuery;
+
+import java.util.List;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -7,4 +12,30 @@ package com.punchsettle.server.atomic.service;
  * @description 奖励 service
  */
 public interface IRewardService {
+
+    /**
+     * 按条件查询奖励
+     * @param query
+     * @return
+     */
+    List<Reward> queryByCondition(RewardQuery query);
+
+    /**
+     * 根据 id 查询奖励
+     * @param id
+     * @return
+     */
+    Reward getById(Long id);
+
+    /**
+     * 新增
+     * @param reward
+     */
+    void insert(Reward reward);
+
+    /**
+     * 更新
+     * @param reward
+     */
+    void update(Reward reward);
 }

+ 21 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/AccountServiceImpl.java

@@ -48,4 +48,25 @@ public class AccountServiceImpl implements IAccountService {
         Assert.notEmpty(accounts);
         accountMapper.batchUpdateSelective(accounts);
     }
+
+    @Override
+    public void insert(Account account) {
+        Assert.isNull(account);
+        accountMapper.insertSelective(account);
+    }
+
+    @Override
+    public void deleteById(Long id) {
+        Assert.isNull(id);
+        accountMapper.deleteByPrimaryKey(id);
+    }
+
+    @Override
+    public Account getById(Long id) {
+        if (Objects.isNull(id)) {
+            return null;
+        }
+
+        return accountMapper.selectByPrimaryKey(id);
+    }
 }

+ 3 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java

@@ -43,6 +43,9 @@ public class PiTaskServiceImpl implements IPiTaskService {
         if (Objects.nonNull(piTaskQuery.getArchiveStatus())) {
             criteria.andEqualTo(PiTask::getArchiveStatus, piTaskQuery.getArchiveStatus());
         }
+        if (!CollectionUtils.isEmpty(piTaskQuery.getIds())) {
+            criteria.andIn(PiTask::getId, piTaskQuery.getIds());
+        }
 
         weekend.excludeProperties(BaseEntity::getLastUpdatedBy,
                 BaseEntity::getLastUpdateTime,

+ 27 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/RewardExchangeHistoryServiceImpl.java

@@ -0,0 +1,27 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import com.punchsettle.server.atomic.entity.RewardExchangeHistory;
+import com.punchsettle.server.atomic.mapper.RewardExchangeHistoryMapper;
+import com.punchsettle.server.atomic.service.IRewardExchangeHistoryService;
+import com.punchsettle.server.common.utils.Assert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/8 10:54
+ * @description 奖励兑换记录 service
+ */
+@Service
+public class RewardExchangeHistoryServiceImpl implements IRewardExchangeHistoryService {
+
+    @Autowired
+    private RewardExchangeHistoryMapper rewardExchangeHistoryMapper;
+
+    @Override
+    public void insert(RewardExchangeHistory rewardExchangeHistory) {
+        Assert.isNull(rewardExchangeHistory);
+        rewardExchangeHistoryMapper.insertSelective(rewardExchangeHistory);
+    }
+}

+ 0 - 14
src/main/java/com/punchsettle/server/atomic/service/impl/RewardHistoryServiceImpl.java

@@ -1,14 +0,0 @@
-package com.punchsettle.server.atomic.service.impl;
-
-import com.punchsettle.server.atomic.service.IRewardHistoryService;
-import org.springframework.stereotype.Service;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/4/8 10:54
- * @description 奖励兑换记录 service
- */
-@Service
-public class RewardHistoryServiceImpl implements IRewardHistoryService {
-}

+ 51 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/RewardServiceImpl.java

@@ -1,7 +1,18 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import com.punchsettle.server.atomic.entity.Reward;
+import com.punchsettle.server.atomic.mapper.RewardMapper;
 import com.punchsettle.server.atomic.service.IRewardService;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.pojo.reward.RewardQuery;
+import com.punchsettle.server.utiis.WeekendUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+
+import java.util.List;
+import java.util.Objects;
 
 /**
  * @author tyuio
@@ -11,4 +22,44 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class RewardServiceImpl implements IRewardService {
+
+    @Autowired
+    private RewardMapper rewardMapper;
+
+    @Override
+    public List<Reward> queryByCondition(RewardQuery query) {
+        if (Objects.isNull(query)) {
+            return List.of();
+        }
+
+        Weekend<Reward> weekend = WeekendUtils.createExcludeAuditFields(Reward.class);
+        WeekendCriteria<Reward, Object> criteria = weekend.weekendCriteria();
+        if (Objects.nonNull(query.getRewardStatus())) {
+            criteria.andEqualTo(Reward::getRewardStatus, query.getRewardStatus());
+        }
+        if (Objects.nonNull(query.getUserId())) {
+            criteria.andEqualTo(Reward::getUserId, query.getUserId());
+        }
+        return rewardMapper.selectByExample(weekend);
+    }
+
+    @Override
+    public Reward getById(Long id) {
+        if (Objects.isNull(id)) {
+            return null;
+        }
+        return rewardMapper.selectByPrimaryKey(id);
+    }
+
+    @Override
+    public void insert(Reward reward) {
+        Assert.isNull(reward);
+        rewardMapper.insertSelective(reward);
+    }
+
+    @Override
+    public void update(Reward reward) {
+        Assert.isNull(reward);
+        rewardMapper.updateByPrimaryKeySelective(reward);
+    }
 }

+ 23 - 0
src/main/java/com/punchsettle/server/constant/RewardExchangeMethodEnum.java

@@ -0,0 +1,23 @@
+package com.punchsettle.server.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 21:25
+ * @description 奖励兑换类型枚举(手动兑换-MANUAL,自动兑换-AUTO)
+ */
+@Getter
+@AllArgsConstructor
+public enum RewardExchangeMethodEnum {
+
+    MANUAL("手动兑换"),
+    AUTO("自动兑换");
+
+    /**
+     * 名称
+     */
+    private String name;
+}

+ 2 - 2
src/main/java/com/punchsettle/server/constant/PunchInTaskStatusEnum.java → src/main/java/com/punchsettle/server/constant/VersionStatusEnum.java

@@ -7,11 +7,11 @@ import lombok.Getter;
  * @author tyuio
  * @version 1.0.0
  * @date 2025/4/24 12:11
- * @description 任务状态枚举(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
+ * @description 版本状态枚举(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
  */
 @Getter
 @AllArgsConstructor
-public enum PunchInTaskStatusEnum {
+public enum VersionStatusEnum {
 
     ACTIVE("活跃"),
     ARCHIVE("归档"),

+ 25 - 0
src/main/java/com/punchsettle/server/pojo/account/AccountRequest.java

@@ -0,0 +1,25 @@
+package com.punchsettle.server.pojo.account;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 17:03
+ * @description 账户操作请求
+ */
+@Data
+public class AccountRequest {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 账户名称
+     */
+    @NotBlank(message = "账户名称不能为空")
+    private String accountName;
+}

+ 29 - 0
src/main/java/com/punchsettle/server/pojo/account/AccountVO.java

@@ -0,0 +1,29 @@
+package com.punchsettle.server.pojo.account;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 17:02
+ * @description 账户 VO
+ */
+@Data
+public class AccountVO {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 账户名称
+     */
+    private String accountName;
+
+    /**
+     * 奖励积分
+     */
+    private Integer points;
+
+}

+ 34 - 0
src/main/java/com/punchsettle/server/pojo/account/TransferRequest.java

@@ -0,0 +1,34 @@
+package com.punchsettle.server.pojo.account;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 17:05
+ * @description 转账请求
+ */
+@Data
+public class TransferRequest {
+
+    /**
+     * 转出账户id
+     */
+    @NotNull(message = "转出账户id不能为空")
+    private Long senderAccountId;
+
+    /**
+     * 转入账户id
+     */
+    @NotNull(message = "转入账户id不能为空")
+    private Long recipientAccountId;
+
+    /**
+     * 转账积分
+     */
+    @NotNull(message = "转账积分不能为空")
+    @Positive(message = "转账积分必须大于0")
+    private Integer transferPoints;
+}

+ 3 - 3
src/main/java/com/punchsettle/server/pojo/punchIn/PiMultiTaskQuery.java

@@ -2,7 +2,7 @@ package com.punchsettle.server.pojo.punchIn;
 
 import java.util.Collection;
 
-import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 
 import lombok.Data;
 
@@ -22,7 +22,7 @@ public class PiMultiTaskQuery {
 
     /**
      * 任务状态
-     * @see PunchInTaskStatusEnum
+     * @see VersionStatusEnum
      */
-    private PunchInTaskStatusEnum multiTaskTaskStatus;
+    private VersionStatusEnum multiTaskTaskStatus;
 }

+ 8 - 3
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskQuery.java

@@ -3,7 +3,7 @@ package com.punchsettle.server.pojo.punchIn;
 import java.util.Collection;
 
 import com.punchsettle.server.constant.ArchiveStatusEnum;
-import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 import lombok.Data;
 
 /**
@@ -15,6 +15,11 @@ import lombok.Data;
 @Data
 public class PiTaskQuery {
 
+    /**
+     * 打卡任务ID列表
+     */
+    private Collection<Long> ids;
+
     /**
      * 用户ID列表
      */
@@ -22,9 +27,9 @@ public class PiTaskQuery {
 
     /**
      * 任务状态(活跃-ACTIVE,归档-ARCHIVE)
-     * @see PunchInTaskStatusEnum
+     * @see VersionStatusEnum
      */
-    private PunchInTaskStatusEnum taskStatus;
+    private VersionStatusEnum taskStatus;
 
     /**
      * 归档状态(活跃-ACTIVE,归档-ARCHIVE)

+ 34 - 0
src/main/java/com/punchsettle/server/pojo/reward/RewardExchangeRequest.java

@@ -0,0 +1,34 @@
+package com.punchsettle.server.pojo.reward;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 21:15
+ * @description 奖励兑换请求
+ */
+@Data
+public class RewardExchangeRequest {
+
+    /**
+     * 奖励ID
+     */
+    @NotNull(message = "奖励ID不能为空")
+    private Long rewardId;
+
+    /**
+     * 兑换数量
+     */
+    @NotNull(message = "兑换数量不能为空")
+    @Positive(message = "兑换数量必须大于0")
+    private Integer exchangeCount;
+
+    /**
+     * 兑换使用的账户id
+     */
+    @NotNull(message = "兑换使用的账户id不能为空")
+    private Long accountId;
+}

+ 26 - 0
src/main/java/com/punchsettle/server/pojo/reward/RewardQuery.java

@@ -0,0 +1,26 @@
+package com.punchsettle.server.pojo.reward;
+
+import com.punchsettle.server.constant.VersionStatusEnum;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 18:49
+ * @description 奖励 查询
+ */
+@Data
+public class RewardQuery {
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 奖励状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
+     * @see VersionStatusEnum
+     */
+    private VersionStatusEnum rewardStatus;
+}

+ 49 - 0
src/main/java/com/punchsettle/server/pojo/reward/RewardRequest.java

@@ -0,0 +1,49 @@
+package com.punchsettle.server.pojo.reward;
+
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 20:51
+ * @description 奖励 请求
+ */
+@Data
+public class RewardRequest {
+
+    /**
+     * 奖励唯一id
+     */
+    private Long id;
+
+    /**
+     * 奖励名称
+     */
+    @NotBlank(message = "奖励名称不能为空")
+    @Length(max = 30, message = "奖励名称不能超过30个字符")
+    private String rewardName;
+
+    /**
+     * 兑换所需积分
+     */
+    @NotNull(message = "兑换所需积分不能为空")
+    @Positive(message = "兑换所需积分必须大于0")
+    private Integer exchangePoints;
+
+    /**
+     * 是否启用自动兑换(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    @NotNull(message = "是否启用自动兑换不能为空")
+    private CommonEnableStatusEnum autoStatus;
+
+    /**
+     * 自动兑换数量
+     */
+    private Integer autoExchangeCount;
+}

+ 41 - 0
src/main/java/com/punchsettle/server/pojo/reward/RewardVO.java

@@ -0,0 +1,41 @@
+package com.punchsettle.server.pojo.reward;
+
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 18:42
+ * @description 奖励 VO
+ */
+@Data
+public class RewardVO {
+
+    /**
+     * 奖励唯一id
+     */
+    private Long id;
+
+    /**
+     * 奖励名称
+     */
+    private String rewardName;
+
+    /**
+     * 兑换所需积分
+     */
+    private Integer exchangePoints;
+
+    /**
+     * 是否启用自动兑换(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum autoStatus;
+
+    /**
+     * 自动兑换数量
+     */
+    private Integer autoExchangeCount;
+}

+ 66 - 0
src/main/java/com/punchsettle/server/service/controller/AccountController.java

@@ -0,0 +1,66 @@
+package com.punchsettle.server.service.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.punchsettle.server.pojo.account.AccountRequest;
+import com.punchsettle.server.pojo.account.AccountVO;
+import com.punchsettle.server.pojo.account.TransferRequest;
+import com.punchsettle.server.service.manager.IAccountManager;
+
+import jakarta.validation.constraints.NotNull;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 17:00
+ * @description 账户 控制器
+ */
+@RestController
+@RequestMapping("/account")
+public class AccountController {
+
+    @Autowired
+    private IAccountManager accountManager;
+
+    /**
+     * 查询账户列表
+     * @return
+     */
+    @GetMapping("/queryAccount")
+    public List<AccountVO> queryAccount() {
+        return accountManager.queryAccount();
+    }
+
+    /**
+     * 新增或更新账户信息
+     * @param request
+     */
+    @PostMapping("/saveAccount")
+    public void saveAccount(@RequestBody AccountRequest request) {
+        accountManager.saveAccount(request);
+    }
+
+    /**
+     * 删除账户
+     */
+    @DeleteMapping("/deleteAccount")
+    public void deleteAccount(@NotNull(message = "账户ID不能为空") Long id) {
+        accountManager.deleteAccount(id);
+    }
+
+    /**
+     * 转账
+     */
+    @PostMapping("/transfer")
+    public void transfer(@RequestBody TransferRequest request) {
+        accountManager.transfer(request);
+    }
+}

+ 39 - 12
src/main/java/com/punchsettle/server/service/controller/RewardController.java

@@ -2,16 +2,18 @@ package com.punchsettle.server.service.controller;
 
 import java.util.List;
 
+import com.punchsettle.server.pojo.reward.RewardExchangeRequest;
+import com.punchsettle.server.pojo.reward.RewardRequest;
+import jakarta.validation.constraints.NotNull;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import com.punchsettle.server.pojo.reward.ClaimRewardRecordQuery;
-import com.punchsettle.server.pojo.reward.ClaimRewardRecordVO;
-import com.punchsettle.server.pojo.reward.ClaimRewardRequest;
+import com.punchsettle.server.pojo.reward.RewardVO;
 import com.punchsettle.server.service.manager.IRewardManager;
 
 /**
@@ -28,20 +30,45 @@ public class RewardController {
     private IRewardManager rewardManager;
 
     /**
-     * 查询领取奖励记录
+     * 查询奖励列表
      * @return
      */
-    @PostMapping("/queryClaimRewardRecords")
-    public List<ClaimRewardRecordVO> queryClaimRewardRecords(@RequestBody @Validated ClaimRewardRecordQuery query) {
-        return rewardManager.queryClaimRewardRecords(query);
+    @GetMapping("/queryRewardList")
+    public List<RewardVO> queryRewardList() {
+        return rewardManager.queryRewardList();
     }
 
     /**
-     * 领取奖励
+     * 根据ID查询奖励
+     */
+    @GetMapping("/queryReward")
+    public RewardVO queryReward(@NotNull(message = "奖励ID不能为空") Long id) {
+        return rewardManager.queryReward(id);
+    }
+
+    /**
+     * 保存奖励
      * @param request
      */
-    @PostMapping("/claimReward")
-    public void claimReward(@RequestBody @Validated ClaimRewardRequest request) {
-        rewardManager.claimReward(request);
+    @PostMapping("/saveReward")
+    public void saveReward(@RequestBody RewardRequest request) {
+        rewardManager.saveReward(request);
+    }
+
+    /**
+     * 删除奖励
+     * @param id
+     */
+    @DeleteMapping("/deleteReward")
+    public void deleteReward(@NotNull(message = "奖励ID不能为空") Long id) {
+        rewardManager.deleteReward(id);
+    }
+
+    /**
+     * 兑换奖励
+     */
+    @PostMapping("/exchangeReward")
+    public void exchangeReward(@RequestBody RewardExchangeRequest request) {
+        rewardManager.exchangeReward(request);
     }
 }

+ 40 - 0
src/main/java/com/punchsettle/server/service/manager/IAccountManager.java

@@ -0,0 +1,40 @@
+package com.punchsettle.server.service.manager;
+
+import com.punchsettle.server.pojo.account.AccountRequest;
+import com.punchsettle.server.pojo.account.AccountVO;
+import com.punchsettle.server.pojo.account.TransferRequest;
+
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 17:01
+ * @description 账户 服务类
+ */
+public interface IAccountManager {
+
+    /**
+     * 查询账户
+     * @return
+     */
+    List<AccountVO> queryAccount();
+
+    /**
+     * 创建或者修改账户信息
+     * @param request
+     */
+    void saveAccount(AccountRequest request);
+
+    /**
+     * 删除账户
+     * @param id
+     */
+    void deleteAccount(Long id);
+
+    /**
+     * 转账
+     * @param request
+     */
+    void transfer(TransferRequest request);
+}

+ 27 - 8
src/main/java/com/punchsettle/server/service/manager/IRewardManager.java

@@ -2,9 +2,9 @@ package com.punchsettle.server.service.manager;
 
 import java.util.List;
 
-import com.punchsettle.server.pojo.reward.ClaimRewardRecordQuery;
-import com.punchsettle.server.pojo.reward.ClaimRewardRecordVO;
-import com.punchsettle.server.pojo.reward.ClaimRewardRequest;
+import com.punchsettle.server.pojo.reward.RewardExchangeRequest;
+import com.punchsettle.server.pojo.reward.RewardRequest;
+import com.punchsettle.server.pojo.reward.RewardVO;
 
 /**
  * @author tyuio
@@ -15,14 +15,33 @@ import com.punchsettle.server.pojo.reward.ClaimRewardRequest;
 public interface IRewardManager {
 
     /**
-     * 领取奖励
-     * @param request
+     * 查询奖励列表
+     * @return
      */
-    void claimReward(ClaimRewardRequest request);
+    List<RewardVO> queryRewardList();
 
     /**
-     * 查询当前用户拥有的奖励数
+     * 根据id查询奖励
+     * @param id
      * @return
      */
-    List<ClaimRewardRecordVO> queryClaimRewardRecords(ClaimRewardRecordQuery query);
+    RewardVO queryReward(Long id);
+
+    /**
+     * 保存奖励
+     * @param request
+     */
+    void saveReward(RewardRequest request);
+
+    /**
+     * 删除奖励
+     * @param id
+     */
+    void deleteReward(Long id);
+
+    /**
+     * 兑换奖励
+     * @param request
+     */
+    void exchangeReward(RewardExchangeRequest request);
 }

+ 138 - 0
src/main/java/com/punchsettle/server/service/manager/impl/AccountManagerImpl.java

@@ -0,0 +1,138 @@
+package com.punchsettle.server.service.manager.impl;
+
+import com.punchsettle.server.atomic.entity.Account;
+import com.punchsettle.server.atomic.entity.AccountTransferHistory;
+import com.punchsettle.server.atomic.service.IAccountService;
+import com.punchsettle.server.atomic.service.IAccountTransferHistoryService;
+import com.punchsettle.server.common.exception.BusinessException;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.constant.AccountCategoryEnum;
+import com.punchsettle.server.constant.TransferCategoryEnum;
+import com.punchsettle.server.pojo.account.AccountRequest;
+import com.punchsettle.server.pojo.account.AccountVO;
+import com.punchsettle.server.pojo.account.TransferRequest;
+import com.punchsettle.server.pojo.punchIn.AccountQuery;
+import com.punchsettle.server.service.manager.IAccountManager;
+import com.punchsettle.server.utiis.UserUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 17:40
+ * @description 账户 服务类
+ */
+public class AccountManagerImpl implements IAccountManager {
+
+    @Autowired
+    private IAccountService accountService;
+
+    @Autowired
+    private IAccountTransferHistoryService accountTransferHistoryService;
+
+    @Override
+    public List<AccountVO> queryAccount() {
+        AccountQuery accountQuery = new AccountQuery();
+        accountQuery.setUserIds(Arrays.asList(UserUtils.getCurrentUserId()));
+        List<Account> accounts = accountService.getAccountByCondition(accountQuery);
+        if (CollectionUtils.isEmpty(accounts)) {
+            return List.of();
+        }
+
+        return accounts.stream().map(account -> {
+            AccountVO accountVO = new AccountVO();
+            BeanUtils.copyProperties(account, accountVO);
+            return accountVO;
+        }).collect(Collectors.toList());
+    }
+
+    @Override
+    public void saveAccount(AccountRequest request) {
+        Assert.isNullInBusiness(request, "账户名称不能为空");
+
+        // 新账户则创建
+        if (Objects.isNull(request.getId())) {
+            Account addAccount = new Account();
+            addAccount.setAccountCategory(AccountCategoryEnum.GENERAL);
+            addAccount.setUserId(UserUtils.getCurrentUserId());
+            addAccount.setPoints(0);
+            addAccount.setAccountName(request.getAccountName());
+            accountService.insert(addAccount);
+            return;
+        }
+
+        // 否则更新
+        Account account = Optional.ofNullable(accountService.getById(request.getId())).orElseThrow(() -> BusinessException.fail("待更新账户不存在"));
+        Account updateAccount = new Account();
+        updateAccount.setId(account.getId());
+        updateAccount.setAccountName(request.getAccountName());
+        accountService.batchUpdate(Arrays.asList(updateAccount));
+    }
+
+    @Override
+    public void deleteAccount(Long id) {
+        Assert.isNullInBusiness(id, "待删除账户ID不能为空");
+        // 获取账户信息
+        Account account = Optional.ofNullable(accountService.getById(id)).orElseThrow(() -> BusinessException.fail("待删除账户不存在"));
+        // 账户中还有积分则不允许删除
+        Integer points = Optional.ofNullable(account.getPoints()).orElse(0);
+        if (points > 0) {
+            throw BusinessException.fail("请先清空积分后再删除");
+        }
+        accountService.deleteById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void transfer(TransferRequest request) {
+        Assert.isNullInBusiness(request, "请传入转账信息");
+
+        // 获取转出账户
+        Account senderAccount = Optional.ofNullable(accountService.getById(request.getSenderAccountId())).orElseThrow(() -> BusinessException.fail("转出账户不存在"));
+        // 转出账户的积分小于转账积分则不允许转出
+        Integer beforeSenderAccountPoints = Optional.ofNullable(senderAccount.getPoints()).orElse(0);
+        if (beforeSenderAccountPoints.compareTo(request.getTransferPoints()) < 0) {
+            BusinessException.throwFail("转出账户积分不足");
+        }
+        // 转出后积分
+        Integer afterSenderAccountPoints = beforeSenderAccountPoints - request.getTransferPoints();
+
+        // 获取转入账户
+        Account recipientAccount = Optional.ofNullable(accountService.getById(request.getRecipientAccountId())).orElseThrow(() -> BusinessException.fail("转入账户不存在"));
+        Integer beforeRecipientAccountPoints = Optional.ofNullable(recipientAccount.getPoints()).orElse(0);
+        Integer afterRecipientAccountPoints = beforeRecipientAccountPoints + request.getTransferPoints();
+
+        // 转账记录 新增
+        AccountTransferHistory accountTransferHistory = new AccountTransferHistory();
+        accountTransferHistory.setUserId(UserUtils.getCurrentUserId());
+        accountTransferHistory.setSenderAccountId(request.getSenderAccountId());
+        accountTransferHistory.setRecipientAccountId(request.getRecipientAccountId());
+        accountTransferHistory.setTransferCategory(TransferCategoryEnum.TRANSFER);
+        accountTransferHistory.setTransferPoints(request.getTransferPoints());
+        accountTransferHistory.setSaPointsBeforeTransfer(beforeSenderAccountPoints);
+        accountTransferHistory.setSaPointsAfterTransfer(afterSenderAccountPoints);
+        accountTransferHistory.setRaPointsBeforeTransfer(beforeRecipientAccountPoints);
+        accountTransferHistory.setRaPointsAfterTransfer(afterRecipientAccountPoints);
+        accountTransferHistoryService.batchInsert(Arrays.asList(accountTransferHistory));
+
+        // 转出账户和转入账户 更新
+        Account updateSenderAccount = new Account();
+        updateSenderAccount.setId(senderAccount.getId());
+        updateSenderAccount.setPoints(afterSenderAccountPoints);
+
+        Account updateRecipientAccount = new Account();
+        updateRecipientAccount.setId(recipientAccount.getId());
+        updateRecipientAccount.setPoints(afterRecipientAccountPoints);
+
+        accountService.batchUpdate(Arrays.asList(updateSenderAccount, updateRecipientAccount));
+    }
+}

+ 8 - 15
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -46,7 +46,7 @@ import com.punchsettle.server.constant.PunchInResultEnum;
 import com.punchsettle.server.constant.PunchInResultViewEnum;
 import com.punchsettle.server.constant.PunchInSettleTypeEnum;
 import com.punchsettle.server.constant.PunchInStatusV1Enum;
-import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 import com.punchsettle.server.constant.RepeatCategoryEnum;
 import com.punchsettle.server.constant.StatPeriodEnum;
 import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
@@ -124,7 +124,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         // 查询打卡任务
         PiTaskQuery piTaskQuery = new PiTaskQuery();
         piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
-        piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
         piTaskQuery.setUserIds(Arrays.asList(currentUserId));
         List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
 
@@ -177,7 +177,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         // 查询打卡任务
         PiTaskQuery piTaskQuery = new PiTaskQuery();
         piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
-        piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
         piTaskQuery.setUserIds(Arrays.asList(currentUserId));
         List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
 
@@ -341,7 +341,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         PiTask addPiTask = new PiTask();
         BeanUtils.copyProperties(request, addPiTask);
         addPiTask.setId(null);
-        addPiTask.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        addPiTask.setTaskStatus(VersionStatusEnum.ACTIVE);
         addPiTask.setTaskVersion(0);
         addPiTask.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
 
@@ -354,7 +354,7 @@ public class PunchInManagerImpl implements IPunchInManager {
             // 旧数据归档
             PiTask updatePiTask = new PiTask();
             updatePiTask.setId(piTask.getId());
-            updatePiTask.setTaskStatus(PunchInTaskStatusEnum.ARCHIVE);
+            updatePiTask.setTaskStatus(VersionStatusEnum.ARCHIVE);
             piTaskService.update(updatePiTask);
         }
 
@@ -376,7 +376,7 @@ public class PunchInManagerImpl implements IPunchInManager {
 
         // 新增打卡任务记录
         PiTask addPiTask = copyAndArchivePiTask(id);
-        addPiTask.setTaskStatus(PunchInTaskStatusEnum.DELETE);
+        addPiTask.setTaskStatus(VersionStatusEnum.DELETE);
 
         piTaskService.insert(addPiTask);
     }
@@ -624,20 +624,13 @@ public class PunchInManagerImpl implements IPunchInManager {
         // 旧的打卡任务信息归档
         PiTask updatePiTask = new PiTask();
         updatePiTask.setId(oldPiTask.getId());
-        updatePiTask.setTaskStatus(PunchInTaskStatusEnum.ARCHIVE);
+        updatePiTask.setTaskStatus(VersionStatusEnum.ARCHIVE);
         piTaskService.update(updatePiTask);
 
         // 新的打卡任务信息
         PiTask piTask = new PiTask();
         BeanUtils.copyProperties(oldPiTask, piTask);
-        piTask.setId(null);
-        piTask.setCreatedBy(null);
-        piTask.setCreationTime(null);
-        piTask.setLastUpdatedBy(null);
-        piTask.setLastUpdateTime(null);
-        piTask.setVersion(1);
-        piTask.setDeleteFlag(false);
-        piTask.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTask.setTaskStatus(VersionStatusEnum.ACTIVE);
         piTask.setTaskVersion(Optional.ofNullable(oldPiTask.getTaskVersion()).orElse(0) + 1);
         return piTask;
     }

+ 3 - 3
src/main/java/com/punchsettle/server/service/manager/impl/PunchInSettleManagerImpl.java

@@ -19,7 +19,7 @@ import com.punchsettle.server.atomic.entity.AccountTransferHistory;
 import com.punchsettle.server.atomic.service.IAccountService;
 import com.punchsettle.server.atomic.service.IAccountTransferHistoryService;
 import com.punchsettle.server.constant.AccountCategoryEnum;
-import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 import com.punchsettle.server.constant.TransferCategoryEnum;
 import com.punchsettle.server.pojo.punchIn.AccountQuery;
 import org.springframework.beans.BeanUtils;
@@ -394,7 +394,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
 
         // 获取多任务信息,用户ID-多任务关联
         PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery();
-        piMultiTaskQuery.setMultiTaskTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piMultiTaskQuery.setMultiTaskTaskStatus(VersionStatusEnum.ACTIVE);
         piMultiTaskQuery.setUserIds(userIds);
         List<PiMultiTask> piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery);
         Map<Long, PiMultiTask> piMultiTaskMap = piMultiTasks.stream()
@@ -437,7 +437,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
 
         // 获取打卡任务信息,打卡任务唯一ID-打卡任务关联
         PiTaskQuery piTaskQuery = new PiTaskQuery();
-        piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
         piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
         piTaskQuery.setUserIds(userIds);
         List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);

+ 215 - 0
src/main/java/com/punchsettle/server/service/manager/impl/RewardManagerImpl.java

@@ -0,0 +1,215 @@
+package com.punchsettle.server.service.manager.impl;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+import com.punchsettle.server.atomic.entity.Account;
+import com.punchsettle.server.atomic.entity.Reward;
+import com.punchsettle.server.atomic.entity.RewardExchangeHistory;
+import com.punchsettle.server.atomic.entity.User;
+import com.punchsettle.server.atomic.service.IAccountService;
+import com.punchsettle.server.atomic.service.IRewardExchangeHistoryService;
+import com.punchsettle.server.atomic.service.IUserService;
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+import com.punchsettle.server.common.exception.BusinessException;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.constant.RewardExchangeMethodEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
+import com.punchsettle.server.pojo.reward.RewardExchangeRequest;
+import com.punchsettle.server.pojo.reward.RewardQuery;
+import com.punchsettle.server.pojo.reward.RewardRequest;
+import com.punchsettle.server.utiis.UserUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.BeanFactoryUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.punchsettle.server.atomic.service.IRewardService;
+import com.punchsettle.server.pojo.reward.RewardVO;
+import com.punchsettle.server.service.manager.IRewardManager;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 奖励 服务类
+ * @date 2024/11/25 20:59
+ */
+@Service
+public class RewardManagerImpl implements IRewardManager {
+
+    @Autowired
+    private IRewardService rewardService;
+
+    @Autowired
+    private IAccountService accountService;
+
+    @Autowired
+    private IRewardExchangeHistoryService rewardExchangeHistoryService;
+
+    @Autowired
+    private IUserService userService;
+
+    @Override
+    public List<RewardVO> queryRewardList() {
+        // 查询奖励列表
+        RewardQuery rewardQuery = new RewardQuery();
+        rewardQuery.setUserId(UserUtils.getCurrentUserId());
+        rewardQuery.setRewardStatus(VersionStatusEnum.ACTIVE);
+        List<Reward> rewards = rewardService.queryByCondition(rewardQuery);
+
+        if (CollectionUtils.isEmpty(rewards)) {
+            return List.of();
+        }
+
+        return rewards.stream().map(reward -> {
+            RewardVO rewardVO = new RewardVO();
+            rewardVO.setId(reward.getId());
+            rewardVO.setRewardName(reward.getRewardName());
+            rewardVO.setExchangePoints(reward.getExchangePoints());
+            return rewardVO;
+        }).toList();
+    }
+
+    @Override
+    public RewardVO queryReward(Long id) {
+        Assert.isNullInBusiness(id, "请传入奖励ID");
+
+        Reward reward = Optional.ofNullable(rewardService.getById(id)).orElseThrow(() -> BusinessException.fail("无法查询到该奖励"));
+        RewardVO rewardVO = new RewardVO();
+        BeanUtils.copyProperties(reward, rewardVO);
+        return rewardVO;
+    }
+
+    @Override
+    public void saveReward(RewardRequest request) {
+        Assert.isNullInBusiness(request, "请传入奖励信息");
+
+        if (CommonEnableStatusEnum.ENABLED.equals(request.getAutoStatus()) && Objects.isNull(request.getAutoExchangeCount())) {
+            BusinessException.throwFail("启用了自动兑换,自动兑换次数不能为空");
+        }
+
+        // 新增奖励数据
+        Reward addReward = new Reward();
+        BeanUtils.copyProperties(request, addReward);
+        addReward.setUserId(UserUtils.getCurrentUserId());
+        addReward.setRewardStatus(VersionStatusEnum.ACTIVE);
+        addReward.setRewardVersion(1);
+
+        // 如果奖励已存在,则更新任务版本号、设置唯一ID、旧数据归档
+        if (Objects.nonNull(request.getId())) {
+            Reward oldReward = Optional.ofNullable(rewardService.getById(request.getId())).orElseThrow(() -> BusinessException.fail("无法查询到该奖励"));
+            addReward.setRewardVersion(oldReward.getRewardVersion() + 1);
+            addReward.setRewardUniqueId(oldReward.getRewardUniqueId());
+
+            Reward updateReward = new Reward();
+            updateReward.setId(oldReward.getId());
+            updateReward.setRewardStatus(VersionStatusEnum.ARCHIVE);
+            rewardService.update(updateReward);
+        }
+
+        rewardService.insert(addReward);
+        if (Objects.isNull(addReward.getRewardUniqueId())) {
+            Reward updateReward = new Reward();
+            updateReward.setId(addReward.getId());
+            updateReward.setRewardUniqueId(addReward.getId());
+            rewardService.update(updateReward);
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteReward(Long id) {
+        Assert.isNullInBusiness(id, "请传入奖励ID");
+
+        // 新增奖励数据
+        Reward addReward = copyAndArchive(id);
+        addReward.setRewardStatus(VersionStatusEnum.DELETE);
+        rewardService.insert(addReward);
+    }
+
+    private Reward copyAndArchive(Long id) {
+        // 获取旧数据
+        Reward oldReward = Optional.ofNullable(rewardService.getById(id)).orElseThrow(() -> BusinessException.fail("无法查询到该奖励"));
+
+        // 旧数据归档
+        Reward updateReward = new Reward();
+        updateReward.setId(oldReward.getId());
+        updateReward.setRewardStatus(VersionStatusEnum.ARCHIVE);
+        rewardService.update(updateReward);
+
+        // 新的奖励信息
+        Reward reward = new Reward();
+        BeanUtils.copyProperties(oldReward, reward);
+        reward.setRewardStatus(VersionStatusEnum.ACTIVE);
+        reward.setRewardVersion(Optional.ofNullable(oldReward.getRewardVersion()).orElse(0) + 1);
+        return reward;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void exchangeReward(RewardExchangeRequest request) {
+        Assert.isNullInBusiness(request, "请传入奖励兑换信息");
+
+        // 获取奖励信息
+        Reward reward = Optional.ofNullable(rewardService.getById(request.getRewardId())).orElseThrow(() -> BusinessException.fail("无法查询到该奖励"));
+        // 获取账户信息
+        Account account = Optional.ofNullable(accountService.getById(request.getAccountId())).orElseThrow(() -> BusinessException.fail("无法查询到该账户"));
+
+        // 兑换所需积分
+        Integer exchangePoints = Optional.ofNullable(reward.getExchangePoints()).orElse(0);
+        // 兑换所需总积分
+        Integer exchangeTotalPoints = exchangePoints * request.getExchangeCount();
+        // 兑换前账户中的积分
+        Integer accountPointsBeforeExchange = Optional.ofNullable(account.getPoints()).orElse(0);
+        if (accountPointsBeforeExchange.compareTo(exchangeTotalPoints) < 0) {
+            BusinessException.throwFail("账户积分不足,无法兑换");
+        }
+        // 兑换后账户中的积分
+        Integer accountPointsAfterExchange = accountPointsBeforeExchange - exchangeTotalPoints;
+
+        // 获取用户信息
+        User user = Optional.ofNullable(userService.getById(UserUtils.getCurrentUserId())).orElseThrow(() -> BusinessException.fail("无法查询到当前用户信息"));
+        // 兑换前未使用积分
+        Integer unusedPointsBeforeExchange = Optional.ofNullable(user.getUnusedPoints()).orElse(0);
+        if (exchangeTotalPoints.compareTo(unusedPointsBeforeExchange) < 0) {
+            BusinessException.throwFail("用户积分不足,无法兑换");
+        }
+        // 兑换前已使用积分
+        Integer usedPointsBeforeExchange = Optional.ofNullable(user.getUsedPoints()).orElse(0);
+        // 兑换后未使用积分
+        Integer unusedPointsAfterExchange = unusedPointsBeforeExchange - exchangeTotalPoints;
+        // 兑换后已使用积分
+        Integer usedPointsAfterExchange = usedPointsBeforeExchange + exchangeTotalPoints;
+
+        // 新增兑换记录
+        RewardExchangeHistory addRewardExchangeHistory = new RewardExchangeHistory();
+        addRewardExchangeHistory.setUserId(UserUtils.getCurrentUserId());
+        addRewardExchangeHistory.setRewardId(reward.getId());
+        addRewardExchangeHistory.setExchangeMethod(RewardExchangeMethodEnum.AUTO);
+        addRewardExchangeHistory.setExchangeCount(request.getExchangeCount());
+        addRewardExchangeHistory.setExchangeTotalPoints(exchangeTotalPoints);
+        addRewardExchangeHistory.setAccountId(account.getId());
+        addRewardExchangeHistory.setAccountPointsBeforeExchange(accountPointsBeforeExchange);
+        addRewardExchangeHistory.setAccountPointsAfterExchange(accountPointsAfterExchange);
+        addRewardExchangeHistory.setUnusedPointsBeforeExchange(unusedPointsBeforeExchange);
+        addRewardExchangeHistory.setUnusedPointsAfterExchange(unusedPointsAfterExchange);
+        addRewardExchangeHistory.setUsedPointsBeforeExchange(usedPointsBeforeExchange);
+        addRewardExchangeHistory.setUsedPointsAfterExchange(usedPointsAfterExchange);
+        rewardExchangeHistoryService.insert(addRewardExchangeHistory);
+
+        User updateUser = new User();
+        updateUser.setId(user.getId());
+        updateUser.setUnusedPoints(unusedPointsAfterExchange);
+        updateUser.setUsedPoints(usedPointsAfterExchange);
+        userService.updateById(updateUser);
+
+        Account updateAccount = new Account();
+        updateAccount.setId(account.getId());
+        updateAccount.setPoints(accountPointsAfterExchange);
+        accountService.batchUpdate(Arrays.asList(updateAccount));
+    }
+}

+ 0 - 85
src/main/java/com/punchsettle/server/service/manager/impl/RewardManagerV1Impl.java

@@ -1,85 +0,0 @@
-package com.punchsettle.server.service.manager.impl;
-
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.util.List;
-import java.util.Optional;
-
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import com.punchsettle.server.atomic.entity.User;
-import com.punchsettle.server.atomic.entity.UserClaimRewardRecord;
-import com.punchsettle.server.atomic.service.IUserClaimRewardRecordService;
-import com.punchsettle.server.atomic.service.IUserService;
-import com.punchsettle.server.common.exception.BusinessException;
-import com.punchsettle.server.pojo.reward.ClaimRewardRecordQuery;
-import com.punchsettle.server.pojo.reward.ClaimRewardRecordVO;
-import com.punchsettle.server.pojo.reward.ClaimRewardRequest;
-import com.punchsettle.server.service.manager.IRewardManager;
-import com.punchsettle.server.utiis.DateUtils;
-import com.punchsettle.server.utiis.UserUtils;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @description 奖励 服务类
- * @date 2024/11/25 20:59
- */
-@Service
-public class RewardManagerV1Impl implements IRewardManager {
-
-    @Autowired
-    private IUserClaimRewardRecordService userClaimRewardRecordService;
-
-    @Autowired
-    private IUserService userService;
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void claimReward(ClaimRewardRequest request) {
-        // 获取用户信息
-        Long currentUserId =
-            Optional.ofNullable(UserUtils.getCurrentUserId()).orElseThrow(() -> BusinessException.fail("无法获取当前用户ID"));
-        User user = Optional.ofNullable(userService.getById(currentUserId)).orElseThrow(() -> BusinessException.fail("无法获取当前用户的奖励信息"));
-
-        // 计算未领取奖励数、已领取奖励数
-//        if (user.getUnclaimedRewardNum() < request.getClaimRewardNum()) {
-//            throw BusinessException.fail("当前用户奖励不足,无法领取");
-//        }
-//        int unclaimedRewardNum = user.getUnclaimedRewardNum() - request.getClaimRewardNum();
-//        int claimedRewardNum = user.getClaimedRewardNum() + request.getClaimRewardNum();
-        int unclaimedRewardNum = 0;
-        int claimedRewardNum = 0;
-
-                // 构建打卡记录
-        UserClaimRewardRecord userClaimRewardRecord = new UserClaimRewardRecord();
-        userClaimRewardRecord.setClaimRewardNum(request.getClaimRewardNum());
-        userClaimRewardRecord.setClaimRewardTime(new Timestamp(System.currentTimeMillis()));
-//        userClaimRewardRecord.setBeforeClaimRewardNum(user.getUnclaimedRewardNum());
-        userClaimRewardRecord.setAfterClaimRewardNum(unclaimedRewardNum);
-        userClaimRewardRecordService.insert(userClaimRewardRecord);
-
-        // 更新用户奖励信息
-        User updateUser = new User();
-        updateUser.setId(user.getId());
-//        updateUser.setUnclaimedRewardNum(unclaimedRewardNum);
-//        updateUser.setClaimedRewardNum(claimedRewardNum);
-        userService.updateById(updateUser);
-    }
-
-    @Override
-    public List<ClaimRewardRecordVO> queryClaimRewardRecords(ClaimRewardRecordQuery query) {
-        SimpleDateFormat sdf = DateUtils.buildDateTimeFormat();
-
-        List<UserClaimRewardRecord> userClaimRewardRecords = userClaimRewardRecordService.listByCondition(query);
-        return userClaimRewardRecords.stream().map(record -> {
-            ClaimRewardRecordVO claimRewardRecordVO = new ClaimRewardRecordVO();
-            BeanUtils.copyProperties(record, claimRewardRecordVO);
-            claimRewardRecordVO.setClaimRewardTime(sdf.format(record.getClaimRewardTime()));
-            return claimRewardRecordVO;
-        }).toList();
-    }
-}