package com.zxyj.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.zxyj.dto.CreateRewardDTO; import com.zxyj.dto.RewardDTO; import com.zxyj.entity.Child; import com.zxyj.entity.PointsLog; import com.zxyj.entity.Reward; import com.zxyj.entity.User; import com.zxyj.mapper.ChildMapper; import com.zxyj.mapper.PointsLogMapper; import com.zxyj.mapper.RewardMapper; import com.zxyj.mapper.UserMapper; import com.zxyj.service.api.RewardServiceInterface; import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Slf4j @Service public class RewardService implements RewardServiceInterface { @Resource private RewardMapper rewardMapper; @Resource private ChildMapper childMapper; @Resource private PointsLogMapper pointsLogMapper; @Resource private UserService userService; @Resource private UserMapper userMapper; /** * REWARD-001A: 孩子创建心愿单 * 孩子添加想要的奖励到心愿单,状态为 pending_approval(待家长填写积分) */ @Transactional public Long createWishlist(Long childId, CreateRewardDTO dto) { Child child = childMapper.selectById(childId); if (child == null) { throw new IllegalArgumentException("孩子不存在"); } Reward reward = new Reward(); reward.setFamilyId(child.getFamilyId()); reward.setChildId(childId); reward.setTitle(dto.getTitle()); reward.setCategory(dto.getCategory()); // 孩子创建心愿时积分为0,等待家长填写 reward.setPointsRequired(0); reward.setStatus("pending_approval"); // 待家长审批填写积分 reward.setIsTemplate(0); reward.setCreatedAt(new Date()); reward.setUpdatedAt(new Date()); rewardMapper.insert(reward); log.info("孩子{}创建心愿: {}", childId, dto.getTitle()); return reward.getId(); } /** * REWARD-001A: 家长填写积分,心愿进入奖励库 * 家长审批并填写所需积分后,心愿转为可兑换状态 */ @Transactional public boolean approveWishlist(Long rewardId, Long parentId, Integer pointsRequired) { Reward reward = rewardMapper.selectById(rewardId); if (reward == null) { return false; } // 验证家长权限:必须是同一家庭的家长 User parent = userMapper.selectById(parentId); if (parent == null || !parent.getFamilyId().equals(reward.getFamilyId())) { log.warn("家长{}无权操作奖励{}", parentId, rewardId); return false; } // 验证状态:只有待审批的心愿可以填写积分 if (!"pending_approval".equals(reward.getStatus())) { log.warn("奖励{}状态不是待审批: {}", rewardId, reward.getStatus()); return false; } // 更新积分和状态 reward.setPointsRequired(pointsRequired); reward.setStatus("available"); // 进入奖励库,可兑换 reward.setUpdatedAt(new Date()); rewardMapper.updateById(reward); log.info("家长{}审批心愿{},设置积分: {}", parentId, rewardId, pointsRequired); return true; } /** * 创建奖励(原有功能:家长直接创建奖励) */ @Transactional public Long createReward(Long userId, CreateRewardDTO dto) { // 参数校验 if (dto.getTitle() == null || dto.getTitle().trim().isEmpty()) { throw new IllegalArgumentException("请填写心愿名称"); } if (dto.getPointsRequired() == null || dto.getPointsRequired() < 1) { throw new IllegalArgumentException("请填写有效的积分值"); } // 获取用户信息并验证家庭归属 User user = userService.getUserInfo(userId); if (user == null || user.getFamilyId() == null) { throw new IllegalArgumentException("用户必须属于某个家庭"); } Reward reward = new Reward(); reward.setFamilyId(user.getFamilyId()); // 强制关联家庭 reward.setChildId(dto.getChildId()); reward.setTitle(dto.getTitle().trim()); reward.setPointsRequired(dto.getPointsRequired()); reward.setCategory(dto.getCategory()); reward.setStatus("available"); reward.setIsTemplate(0); reward.setCreatedAt(new Date()); reward.setUpdatedAt(new Date()); rewardMapper.insert(reward); return reward.getId(); } public List getWishlist(Long childId) { // 获取孩子信息以验证家庭归属 Child child = childMapper.selectById(childId); if (child == null) { return null; } // 按家庭ID和孩子ID筛选奖励,确保奖励必须关联家庭 List rewards = rewardMapper.selectList(new LambdaQueryWrapper() .eq(Reward::getFamilyId, child.getFamilyId()) .eq(Reward::getChildId, childId) .eq(Reward::getStatus, "available") .orderByAsc(Reward::getPointsRequired)); final int currentPoints = child != null ? child.getTotalPoints() : 0; return rewards.stream().map(r -> { RewardDTO dto = new RewardDTO(); dto.setId(r.getId()); dto.setTitle(r.getTitle()); dto.setPointsRequired(r.getPointsRequired()); dto.setCategory(r.getCategory()); dto.setStatus(r.getStatus()); dto.setExchangeApproved(r.getExchangeApproved()); dto.setProgress(currentPoints); return dto; }).collect(Collectors.toList()); } @Transactional public Map exchangeReward(Long rewardId, Long childId) { Reward reward = rewardMapper.selectById(rewardId); if (reward == null || !reward.getChildId().equals(childId)) { return null; } if (!"available".equals(reward.getStatus())) { return null; } Child child = childMapper.selectById(childId); if (child.getTotalPoints() < reward.getPointsRequired()) { return null; // 积分不足 } // 扣除积分 child.setTotalPoints(child.getTotalPoints() - reward.getPointsRequired()); child.setUpdatedAt(new Date()); childMapper.updateById(child); // 记录积分消耗 PointsLog log = new PointsLog(); log.setChildId(childId); log.setAmount(-reward.getPointsRequired()); log.setType("spend"); log.setDescription("兑换奖励: " + reward.getTitle()); log.setCreatedAt(new Date()); pointsLogMapper.insert(log); // 更新奖励状态 reward.setStatus("pending"); // 待审批 reward.setUpdatedAt(new Date()); rewardMapper.updateById(reward); Map result = new java.util.HashMap<>(); result.put("success", true); result.put("newBalance", child.getTotalPoints()); return result; } @Transactional public boolean approveReward(Long rewardId, boolean approved) { Reward reward = rewardMapper.selectById(rewardId); if (reward == null) { return false; } if (approved) { reward.setStatus("exchanged"); reward.setExchangeApproved(1); reward.setExchangedAt(new Date()); } else { // 拒绝,返还积分 Child child = childMapper.selectById(reward.getChildId()); child.setTotalPoints(child.getTotalPoints() + reward.getPointsRequired()); child.setUpdatedAt(new Date()); childMapper.updateById(child); // 记录积分退还 PointsLog log = new PointsLog(); log.setChildId(reward.getChildId()); log.setAmount(reward.getPointsRequired()); log.setType("refund"); log.setDescription("奖励兑换被拒绝,积分退还"); log.setCreatedAt(new Date()); pointsLogMapper.insert(log); reward.setStatus("rejected"); reward.setExchangeApproved(0); } reward.setUpdatedAt(new Date()); rewardMapper.updateById(reward); return true; } public List getTemplates() { // 模板也必须关联家庭,这里返回所有家庭的模板(family_id > 0) return rewardMapper.selectList(new LambdaQueryWrapper() .eq(Reward::getIsTemplate, 1) .gt(Reward::getFamilyId, 0)); // 确保模板关联到具体家庭 } public Page getExchangeHistory(Long childId, Integer page, Integer size) { Page pageParam = new Page<>(page, size); return rewardMapper.selectPage(pageParam, new LambdaQueryWrapper() .eq(Reward::getChildId, childId) .in(Reward::getStatus, Arrays.asList("exchanged", "rejected")) .orderByDesc(Reward::getExchangedAt)); } /** * REWARD-002A: 获取家庭奖励库 * 返回家庭所有可用的奖励(不含模板),多家长可查看 */ public List getFamilyRewardLibrary(Long familyId) { List rewards = rewardMapper.selectList(new LambdaQueryWrapper() .eq(Reward::getFamilyId, familyId) .eq(Reward::getIsTemplate, 0) .in(Reward::getStatus, Arrays.asList("available", "pending_approval")) .orderByAsc(Reward::getPointsRequired)); return rewards.stream().map(r -> { RewardDTO dto = new RewardDTO(); dto.setId(r.getId()); dto.setTitle(r.getTitle()); dto.setPointsRequired(r.getPointsRequired()); dto.setCategory(r.getCategory()); dto.setStatus(r.getStatus()); dto.setChildId(r.getChildId()); dto.setExchangeApproved(r.getExchangeApproved()); return dto; }).collect(Collectors.toList()); } /** * REWARD-002A: 家长修改奖励积分(多家长可调整) * 只有同一家庭的家长可以修改 */ @Transactional public boolean updateRewardPoints(Long rewardId, Long parentId, Integer newPoints) { Reward reward = rewardMapper.selectById(rewardId); if (reward == null) { return false; } // 验证家长权限 User parent = userMapper.selectById(parentId); if (parent == null || !parent.getFamilyId().equals(reward.getFamilyId())) { log.warn("家长{}无权修改奖励{}", parentId, rewardId); return false; } // 只有可用状态或待审批状态可以修改 if (!"available".equals(reward.getStatus()) && !"pending_approval".equals(reward.getStatus())) { log.warn("奖励{}状态不可修改: {}", rewardId, reward.getStatus()); return false; } reward.setPointsRequired(newPoints); reward.setUpdatedAt(new Date()); rewardMapper.updateById(reward); log.info("家长{}修改奖励{}积分为: {}", parentId, rewardId, newPoints); return true; } /** * REWARD-002B: 获取孩子的待审批心愿单(按孩子隔离) * 只返回指定孩子的心愿,不包含其他孩子 */ public List getChildPendingWishlists(Long childId) { Child child = childMapper.selectById(childId); if (child == null) { return null; } List rewards = rewardMapper.selectList(new LambdaQueryWrapper() .eq(Reward::getFamilyId, child.getFamilyId()) .eq(Reward::getChildId, childId) .eq(Reward::getStatus, "pending_approval") .orderByDesc(Reward::getCreatedAt)); return rewards.stream().map(r -> { RewardDTO dto = new RewardDTO(); dto.setId(r.getId()); dto.setTitle(r.getTitle()); dto.setPointsRequired(r.getPointsRequired()); dto.setCategory(r.getCategory()); dto.setStatus(r.getStatus()); dto.setChildId(r.getChildId()); return dto; }).collect(Collectors.toList()); } /** * REWARD-002B: 获取家长待处理的心愿审批列表(所有孩子) * 家长可以看到所有孩子的待审批心愿 */ public List getPendingApprovalList(Long familyId) { List rewards = rewardMapper.selectList(new LambdaQueryWrapper() .eq(Reward::getFamilyId, familyId) .eq(Reward::getStatus, "pending_approval") .eq(Reward::getIsTemplate, 0) .orderByDesc(Reward::getCreatedAt)); return rewards.stream().map(r -> { RewardDTO dto = new RewardDTO(); dto.setId(r.getId()); dto.setTitle(r.getTitle()); dto.setPointsRequired(r.getPointsRequired()); dto.setCategory(r.getCategory()); dto.setStatus(r.getStatus()); dto.setChildId(r.getChildId()); // 获取孩子昵称 Child child = childMapper.selectById(r.getChildId()); if (child != null) { dto.setChildName(child.getNickname()); } return dto; }).collect(Collectors.toList()); } }