diff --git a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/task/RoomDailyTaskRestController.java b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/task/RoomDailyTaskRestController.java new file mode 100644 index 00000000..1a2148e8 --- /dev/null +++ b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/task/RoomDailyTaskRestController.java @@ -0,0 +1,46 @@ +package com.red.circle.other.adapter.app.task; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskCO; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskClaimCO; +import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskClaimCmd; +import com.red.circle.other.app.service.task.RoomDailyTaskService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 每日任务接口 + */ +@RestController +@RequestMapping("/room-task") +@RequiredArgsConstructor +public class RoomDailyTaskRestController { + + private final RoomDailyTaskService roomDailyTaskService; + + /** + * 获取任务列表 + * @eo.name 获取每日任务列表 + * @eo.url /list + * @eo.method get + */ + @GetMapping("/list") + public List getTaskList(AppExtCommand cmd) { + return roomDailyTaskService.getTaskList(cmd.getReqUserId()); + } + + /** + * 领取任务奖励 + * @eo.name 领取任务奖励 + * @eo.url /claim + * @eo.method post + * @eo.request-type json + */ + @PostMapping("/claim") + public RoomDailyTaskClaimCO claimReward(@RequestBody @Validated RoomDailyTaskClaimCmd cmd) { + return roomDailyTaskService.claimReward(cmd); + } +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/task/RoomDailyTaskClaimExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/task/RoomDailyTaskClaimExe.java new file mode 100644 index 00000000..0ef0d484 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/task/RoomDailyTaskClaimExe.java @@ -0,0 +1,93 @@ +package com.red.circle.other.app.command.task; + +import com.red.circle.common.business.exception.BusinessException; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskClaimCO; +import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskClaimCmd; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskClaimRecord; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskConfig; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskProgress; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskTier; +import com.red.circle.other.infra.database.rds.service.RoomDailyTaskDatabaseService; +import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 领取任务奖励 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class RoomDailyTaskClaimExe { + + private final RoomDailyTaskDatabaseService taskDatabaseService; + + @Transactional(rollbackFor = Exception.class) + public RoomDailyTaskClaimCO execute(RoomDailyTaskClaimCmd cmd) { + Long userId = cmd.getReqUserId(); + String taskCode = cmd.getTaskCode(); + Integer tierIndex = cmd.getTierIndex(); + + LocalDate today = ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate(); + String bizNo = userId + ":" + taskCode + ":" + today + ":" + tierIndex; + + // 幂等校验 + if (taskDatabaseService.existsClaimRecord(bizNo)) { + throw new BusinessException("该档位奖励已领取"); + } + + RoomDailyTaskConfig config = taskDatabaseService.getConfigByCode(taskCode); + if (config == null) { + throw new BusinessException("任务不存在"); + } + + RoomDailyTaskTier tier = taskDatabaseService.getTier(taskCode, tierIndex); + if (tier == null) { + throw new BusinessException("任务档位不存在"); + } + + RoomDailyTaskProgress progress = taskDatabaseService.getProgress(userId, taskCode, today); + if (progress == null || progress.getMaxTierCompleted() < tierIndex) { + throw new BusinessException("该档位任务未完成"); + } + if (progress.getMaxTierClaimed() >= tierIndex) { + throw new BusinessException("该档位奖励已领取"); + } + + // 更新领取状态 + progress.setMaxTierClaimed(tierIndex); + progress.setUpdateTime(LocalDateTime.now()); + taskDatabaseService.saveOrUpdateProgress(progress); + + // 保存领取记录 + RoomDailyTaskClaimRecord record = new RoomDailyTaskClaimRecord(); + record.setUserId(userId); + record.setTaskId(config.getId()); + record.setTaskCode(taskCode); + record.setTierIndex(tierIndex); + record.setRewardType(tier.getRewardType()); + record.setRewardValue(tier.getRewardValue()); + record.setCycleDate(today); + record.setBizNo(bizNo); + record.setClaimTime(LocalDateTime.now()); + record.setCreateTime(LocalDateTime.now()); + taskDatabaseService.saveClaimRecord(record); + + // TODO: 调用钱包服务发放金币 + + log.info("任务奖励领取成功, userId={}, taskCode={}, tierIndex={}, rewardValue={}", userId, taskCode, tierIndex, tier.getRewardValue()); + + RoomDailyTaskClaimCO co = new RoomDailyTaskClaimCO(); + co.setTaskCode(taskCode); + co.setTaskName(config.getTaskName()); + co.setTierIndex(tierIndex); + co.setRewardValue(tier.getRewardValue()); + co.setClaimTime(LocalDateTime.now()); + return co; + } +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/task/RoomDailyTaskQueryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/task/RoomDailyTaskQueryExe.java new file mode 100644 index 00000000..baab4ceb --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/task/RoomDailyTaskQueryExe.java @@ -0,0 +1,77 @@ +package com.red.circle.other.app.command.task; + +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskCO; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskTierCO; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskConfig; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskProgress; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskTier; +import com.red.circle.other.infra.database.rds.service.RoomDailyTaskDatabaseService; +import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 查询用户每日任务列表 + */ +@Component +@RequiredArgsConstructor +public class RoomDailyTaskQueryExe { + + private final RoomDailyTaskDatabaseService taskDatabaseService; + + public List execute(Long userId) { + List configs = taskDatabaseService.listEnabledConfigs(); + if (CollectionUtils.isEmpty(configs)) { + return new ArrayList<>(); + } + + List taskCodes = configs.stream().map(RoomDailyTaskConfig::getTaskCode).collect(Collectors.toList()); + List allTiers = taskDatabaseService.listTiersByTaskCodes(taskCodes); + + LocalDate today = ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate(); + List progressList = taskDatabaseService.listProgressByUser(userId, today); + + Map> tierMap = allTiers.stream() + .collect(Collectors.groupingBy(RoomDailyTaskTier::getTaskCode)); + Map progressMap = progressList.stream() + .collect(Collectors.toMap(RoomDailyTaskProgress::getTaskCode, p -> p, (a, b) -> a)); + + return configs.stream() + .map(config -> buildTaskCO(config, tierMap.getOrDefault(config.getTaskCode(), new ArrayList<>()), progressMap.get(config.getTaskCode()))) + .collect(Collectors.toList()); + } + + private RoomDailyTaskCO buildTaskCO(RoomDailyTaskConfig config, List tiers, RoomDailyTaskProgress progress) { + int currentValue = progress != null ? progress.getCurrentValue() : 0; + int maxTierCompleted = progress != null ? progress.getMaxTierCompleted() : 0; + int maxTierClaimed = progress != null ? progress.getMaxTierClaimed() : 0; + + List tierCOs = tiers.stream().map(tier -> { + RoomDailyTaskTierCO co = new RoomDailyTaskTierCO(); + co.setTierIndex(tier.getTierIndex()); + co.setTargetValue(tier.getTargetValue()); + co.setTargetUnit(tier.getTargetUnit()); + co.setRewardValue(tier.getRewardValue()); + co.setIsCompleted(tier.getTierIndex() <= maxTierCompleted); + co.setIsClaimed(tier.getTierIndex() <= maxTierClaimed); + return co; + }).collect(Collectors.toList()); + + RoomDailyTaskCO co = new RoomDailyTaskCO(); + co.setTaskId(config.getId()); + co.setTaskCode(config.getTaskCode()); + co.setTaskName(config.getTaskName()); + co.setTaskCategory(config.getTaskCategory()); + co.setIconUrl(config.getIconUrl()); + co.setCurrentValue(currentValue); + co.setTiers(tierCOs); + return co; + } +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/task/RoomDailyTaskServiceImpl.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/task/RoomDailyTaskServiceImpl.java new file mode 100644 index 00000000..92eb92d6 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/task/RoomDailyTaskServiceImpl.java @@ -0,0 +1,29 @@ +package com.red.circle.other.app.service.task; + +import com.red.circle.other.app.command.task.RoomDailyTaskClaimExe; +import com.red.circle.other.app.command.task.RoomDailyTaskQueryExe; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskCO; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskClaimCO; +import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskClaimCmd; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class RoomDailyTaskServiceImpl implements RoomDailyTaskService { + + private final RoomDailyTaskQueryExe queryExe; + private final RoomDailyTaskClaimExe claimExe; + + @Override + public List getTaskList(Long userId) { + return queryExe.execute(userId); + } + + @Override + public RoomDailyTaskClaimCO claimReward(RoomDailyTaskClaimCmd cmd) { + return claimExe.execute(cmd); + } +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskCO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskCO.java new file mode 100644 index 00000000..c0e9648c --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskCO.java @@ -0,0 +1,33 @@ +package com.red.circle.other.app.dto.clientobject.task; + +import lombok.Data; + +import java.util.List; + +/** + * 每日任务信息 + */ +@Data +public class RoomDailyTaskCO { + + /** 任务ID */ + private Long taskId; + + /** 任务编码 */ + private String taskCode; + + /** 任务名称 */ + private String taskName; + + /** 任务分类:1-Personal 2-Room Owner */ + private Integer taskCategory; + + /** 任务图标 */ + private String iconUrl; + + /** 当前进度值 */ + private Integer currentValue; + + /** 档位列表 */ + private List tiers; +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskClaimCO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskClaimCO.java new file mode 100644 index 00000000..ac9a4ba3 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskClaimCO.java @@ -0,0 +1,27 @@ +package com.red.circle.other.app.dto.clientobject.task; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 任务奖励领取结果 + */ +@Data +public class RoomDailyTaskClaimCO { + + /** 任务编码 */ + private String taskCode; + + /** 任务名称 */ + private String taskName; + + /** 领取的档位序号 */ + private Integer tierIndex; + + /** 奖励金币数 */ + private Integer rewardValue; + + /** 领取时间 */ + private LocalDateTime claimTime; +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskTierCO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskTierCO.java new file mode 100644 index 00000000..e8ded420 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/task/RoomDailyTaskTierCO.java @@ -0,0 +1,28 @@ +package com.red.circle.other.app.dto.clientobject.task; + +import lombok.Data; + +/** + * 任务档位信息 + */ +@Data +public class RoomDailyTaskTierCO { + + /** 档位序号 */ + private Integer tierIndex; + + /** 目标值 */ + private Integer targetValue; + + /** 目标单位:MINUTES/COUNT/GOLD */ + private String targetUnit; + + /** 奖励金币数 */ + private Integer rewardValue; + + /** 是否已完成 */ + private Boolean isCompleted; + + /** 是否已领取 */ + private Boolean isClaimed; +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/task/RoomDailyTaskClaimCmd.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/task/RoomDailyTaskClaimCmd.java new file mode 100644 index 00000000..88485295 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/task/RoomDailyTaskClaimCmd.java @@ -0,0 +1,21 @@ +package com.red.circle.other.app.dto.cmd.task; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 领取任务奖励命令 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class RoomDailyTaskClaimCmd extends AppExtCommand { + + @NotBlank(message = "任务编码不能为空") + private String taskCode; + + @NotNull(message = "档位序号不能为空") + private Integer tierIndex; +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/task/RoomDailyTaskService.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/task/RoomDailyTaskService.java new file mode 100644 index 00000000..19869f8d --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/task/RoomDailyTaskService.java @@ -0,0 +1,14 @@ +package com.red.circle.other.app.service.task; + +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskCO; +import com.red.circle.other.app.dto.clientobject.task.RoomDailyTaskClaimCO; +import com.red.circle.other.app.dto.cmd.task.RoomDailyTaskClaimCmd; + +import java.util.List; + +public interface RoomDailyTaskService { + + List getTaskList(Long userId); + + RoomDailyTaskClaimCO claimReward(RoomDailyTaskClaimCmd cmd); +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskClaimRecordDAO.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskClaimRecordDAO.java new file mode 100644 index 00000000..8fe5aff8 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskClaimRecordDAO.java @@ -0,0 +1,7 @@ +package com.red.circle.other.infra.database.rds.dao.task; + +import com.red.circle.framework.mybatis.dao.BaseDAO; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskClaimRecord; + +public interface RoomDailyTaskClaimRecordDAO extends BaseDAO { +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskConfigDAO.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskConfigDAO.java new file mode 100644 index 00000000..6a2d7820 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskConfigDAO.java @@ -0,0 +1,7 @@ +package com.red.circle.other.infra.database.rds.dao.task; + +import com.red.circle.framework.mybatis.dao.BaseDAO; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskConfig; + +public interface RoomDailyTaskConfigDAO extends BaseDAO { +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskProgressDAO.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskProgressDAO.java new file mode 100644 index 00000000..12d65cc9 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskProgressDAO.java @@ -0,0 +1,7 @@ +package com.red.circle.other.infra.database.rds.dao.task; + +import com.red.circle.framework.mybatis.dao.BaseDAO; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskProgress; + +public interface RoomDailyTaskProgressDAO extends BaseDAO { +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskTierDAO.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskTierDAO.java new file mode 100644 index 00000000..67dd673b --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/dao/task/RoomDailyTaskTierDAO.java @@ -0,0 +1,7 @@ +package com.red.circle.other.infra.database.rds.dao.task; + +import com.red.circle.framework.mybatis.dao.BaseDAO; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskTier; + +public interface RoomDailyTaskTierDAO extends BaseDAO { +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskClaimRecord.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskClaimRecord.java new file mode 100644 index 00000000..f0e45d42 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskClaimRecord.java @@ -0,0 +1,44 @@ +package com.red.circle.other.infra.database.rds.entity.task; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 任务奖励领取记录 + */ +@Data +@TableName("room_daily_task_claim_record") +public class RoomDailyTaskClaimRecord { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long userId; + + private Long taskId; + + private String taskCode; + + /** 领取的档位序号 */ + private Integer tierIndex; + + /** 奖励类型:1-金币 */ + private Integer rewardType; + + /** 奖励金币数 */ + private Integer rewardValue; + + private LocalDate cycleDate; + + /** 幂等key:userId:taskCode:cycleDate:tierIndex */ + private String bizNo; + + private LocalDateTime claimTime; + + private LocalDateTime createTime; +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskConfig.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskConfig.java new file mode 100644 index 00000000..bf97c969 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskConfig.java @@ -0,0 +1,44 @@ +package com.red.circle.other.infra.database.rds.entity.task; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 每日任务配置 + */ +@Data +@TableName("room_daily_task_config") +public class RoomDailyTaskConfig { + + @TableId(type = IdType.AUTO) + private Long id; + + /** 任务编码,唯一 */ + private String taskCode; + + /** 任务名称 */ + private String taskName; + + /** 任务分类:1-Personal 2-Room Owner */ + private Integer taskCategory; + + /** 任务类型:MIC_TIME/INVITE_USER/ONLINE_USER/SEND_GIFT/GAME_CONSUME等 */ + private String taskType; + + /** 任务图标 */ + private String iconUrl; + + /** 排序 */ + private Integer sortOrder; + + /** 状态:0-禁用 1-启用 */ + private Integer status; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskProgress.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskProgress.java new file mode 100644 index 00000000..753b98f4 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskProgress.java @@ -0,0 +1,45 @@ +package com.red.circle.other.infra.database.rds.entity.task; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 用户每日任务进度 + */ +@Data +@TableName("room_daily_task_progress") +public class RoomDailyTaskProgress { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long userId; + + private Long taskId; + + private String taskCode; + + /** 任务分类:1-Personal 2-Room Owner */ + private Integer taskCategory; + + /** 任务日期(每日重置key,Riyadh时区) */ + private LocalDate cycleDate; + + /** 当前进度值 */ + private Integer currentValue; + + /** 已完成的最高档位序号,0=未完成任何档位 */ + private Integer maxTierCompleted; + + /** 已领取的最高档位序号,0=未领取 */ + private Integer maxTierClaimed; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskTier.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskTier.java new file mode 100644 index 00000000..780c54d1 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/entity/task/RoomDailyTaskTier.java @@ -0,0 +1,42 @@ +package com.red.circle.other.infra.database.rds.entity.task; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 任务档位配置 + */ +@Data +@TableName("room_daily_task_tier") +public class RoomDailyTaskTier { + + @TableId(type = IdType.AUTO) + private Long id; + + /** 关联任务配置ID */ + private Long taskId; + + /** 任务编码(冗余) */ + private String taskCode; + + /** 档位序号:1/2/3/4 */ + private Integer tierIndex; + + /** 达到该档位的目标值 */ + private Integer targetValue; + + /** 目标单位:MINUTES/COUNT/GOLD */ + private String targetUnit; + + /** 奖励类型:1-金币 */ + private Integer rewardType; + + /** 奖励金币数 */ + private Integer rewardValue; + + private LocalDateTime createTime; +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/RoomDailyTaskDatabaseService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/RoomDailyTaskDatabaseService.java new file mode 100644 index 00000000..d06aa073 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/RoomDailyTaskDatabaseService.java @@ -0,0 +1,97 @@ +package com.red.circle.other.infra.database.rds.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.red.circle.other.infra.database.rds.dao.task.RoomDailyTaskClaimRecordDAO; +import com.red.circle.other.infra.database.rds.dao.task.RoomDailyTaskConfigDAO; +import com.red.circle.other.infra.database.rds.dao.task.RoomDailyTaskProgressDAO; +import com.red.circle.other.infra.database.rds.dao.task.RoomDailyTaskTierDAO; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskClaimRecord; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskConfig; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskProgress; +import com.red.circle.other.infra.database.rds.entity.task.RoomDailyTaskTier; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class RoomDailyTaskDatabaseService { + + private final RoomDailyTaskConfigDAO configDAO; + private final RoomDailyTaskTierDAO tierDAO; + private final RoomDailyTaskProgressDAO progressDAO; + private final RoomDailyTaskClaimRecordDAO claimRecordDAO; + + public List listEnabledConfigs() { + return configDAO.selectList( + new LambdaQueryWrapper() + .eq(RoomDailyTaskConfig::getStatus, 1) + .orderByAsc(RoomDailyTaskConfig::getSortOrder) + ); + } + + public List listTiersByTaskCodes(List taskCodes) { + return tierDAO.selectList( + new LambdaQueryWrapper() + .in(RoomDailyTaskTier::getTaskCode, taskCodes) + .orderByAsc(RoomDailyTaskTier::getTierIndex) + ); + } + + public List listProgressByUser(Long userId, LocalDate cycleDate) { + return progressDAO.selectList( + new LambdaQueryWrapper() + .eq(RoomDailyTaskProgress::getUserId, userId) + .eq(RoomDailyTaskProgress::getCycleDate, cycleDate) + ); + } + + public RoomDailyTaskProgress getProgress(Long userId, String taskCode, LocalDate cycleDate) { + return progressDAO.selectList( + new LambdaQueryWrapper() + .eq(RoomDailyTaskProgress::getUserId, userId) + .eq(RoomDailyTaskProgress::getTaskCode, taskCode) + .eq(RoomDailyTaskProgress::getCycleDate, cycleDate) + .last("limit 1") + ).stream().findFirst().orElse(null); + } + + public void saveOrUpdateProgress(RoomDailyTaskProgress progress) { + if (progress.getId() == null) { + progressDAO.insert(progress); + } else { + progressDAO.updateById(progress); + } + } + + public boolean existsClaimRecord(String bizNo) { + return claimRecordDAO.selectCount( + new LambdaQueryWrapper() + .eq(RoomDailyTaskClaimRecord::getBizNo, bizNo) + ) > 0; + } + + public void saveClaimRecord(RoomDailyTaskClaimRecord record) { + claimRecordDAO.insert(record); + } + + public RoomDailyTaskConfig getConfigByCode(String taskCode) { + return configDAO.selectList( + new LambdaQueryWrapper() + .eq(RoomDailyTaskConfig::getTaskCode, taskCode) + .eq(RoomDailyTaskConfig::getStatus, 1) + .last("limit 1") + ).stream().findFirst().orElse(null); + } + + public RoomDailyTaskTier getTier(String taskCode, Integer tierIndex) { + return tierDAO.selectList( + new LambdaQueryWrapper() + .eq(RoomDailyTaskTier::getTaskCode, taskCode) + .eq(RoomDailyTaskTier::getTierIndex, tierIndex) + .last("limit 1") + ).stream().findFirst().orElse(null); + } +}