|
|
@@ -0,0 +1,233 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.etotem.cfc.dto.FamilyStatusDTO;
|
|
|
+import com.etotem.cfc.dto.InviteValidateDTO;
|
|
|
+import com.etotem.cfc.entity.Child;
|
|
|
+import com.etotem.cfc.entity.Family;
|
|
|
+import com.etotem.cfc.entity.FamilyInvitation;
|
|
|
+import com.etotem.cfc.entity.User;
|
|
|
+import com.etotem.cfc.mapper.ChildMapper;
|
|
|
+import com.etotem.cfc.mapper.FamilyInvitationMapper;
|
|
|
+import com.etotem.cfc.mapper.FamilyMapper;
|
|
|
+import com.etotem.cfc.mapper.UserMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class FamilyInvitationService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyInvitationMapper familyInvitationMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyMapper familyMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private UserMapper userMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ChildMapper childMapper;
|
|
|
+
|
|
|
+ public InviteValidateDTO validateInvitation(String token) {
|
|
|
+ FamilyInvitation invitation = familyInvitationMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyInvitation>()
|
|
|
+ .eq(FamilyInvitation::getToken, token)
|
|
|
+ .eq(FamilyInvitation::getStatus, "active")
|
|
|
+ .and(w -> w.isNull(FamilyInvitation::getExpiresAt)
|
|
|
+ .or().gt(FamilyInvitation::getExpiresAt, new Date()))
|
|
|
+ );
|
|
|
+ if (invitation == null) {
|
|
|
+ throw new RuntimeException("邀请链接无效或已过期");
|
|
|
+ }
|
|
|
+
|
|
|
+ Family family = familyMapper.selectById(invitation.getFamilyId());
|
|
|
+ if (family == null) {
|
|
|
+ throw new RuntimeException("家庭不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ User inviter = userMapper.selectById(invitation.getCreatedBy());
|
|
|
+ Long memberCount = userMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<User>()
|
|
|
+ .eq(User::getFamilyId, invitation.getFamilyId())
|
|
|
+ );
|
|
|
+
|
|
|
+ InviteValidateDTO dto = new InviteValidateDTO();
|
|
|
+ dto.setToken(token);
|
|
|
+ dto.setFamilyId(invitation.getFamilyId());
|
|
|
+ dto.setFamilyName(family.getName());
|
|
|
+ dto.setInviterName(inviter != null ? inviter.getNickname() : null);
|
|
|
+ dto.setMemberCount(memberCount.intValue());
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String generateInvitation(Long familyId, Long userId) {
|
|
|
+ Family family = familyMapper.selectById(familyId);
|
|
|
+ if (family == null) {
|
|
|
+ throw new RuntimeException("家庭不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ FamilyInvitation invitation = new FamilyInvitation();
|
|
|
+ invitation.setFamilyId(familyId);
|
|
|
+ invitation.setToken(UUID.randomUUID().toString().replace("-", ""));
|
|
|
+ invitation.setCreatedBy(userId);
|
|
|
+ invitation.setStatus("active");
|
|
|
+ invitation.setExpiresAt(new Date(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000L));
|
|
|
+ invitation.setCreatedAt(new Date());
|
|
|
+ invitation.setUpdatedAt(new Date());
|
|
|
+ familyInvitationMapper.insert(invitation);
|
|
|
+
|
|
|
+ return invitation.getToken();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String acceptInvitation(Long userId, String token, String familyRole, Boolean mergeFamily) {
|
|
|
+ FamilyInvitation invitation = familyInvitationMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyInvitation>()
|
|
|
+ .eq(FamilyInvitation::getToken, token)
|
|
|
+ .eq(FamilyInvitation::getStatus, "active")
|
|
|
+ .and(w -> w.isNull(FamilyInvitation::getExpiresAt)
|
|
|
+ .or().gt(FamilyInvitation::getExpiresAt, new Date()))
|
|
|
+ );
|
|
|
+ if (invitation == null) {
|
|
|
+ throw new RuntimeException("邀请链接无效或已过期");
|
|
|
+ }
|
|
|
+
|
|
|
+ User user = userMapper.selectById(userId);
|
|
|
+ if (user == null) {
|
|
|
+ throw new RuntimeException("用户不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ Family family = familyMapper.selectById(invitation.getFamilyId());
|
|
|
+ if (family == null) {
|
|
|
+ throw new RuntimeException("家庭不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (user.getFamilyId() != null) {
|
|
|
+ if (mergeFamily == null || !mergeFamily) {
|
|
|
+ throw new RuntimeException("您已加入其他家庭,如需加入请选择合并家庭");
|
|
|
+ }
|
|
|
+ mergeIntoFamily(userId, invitation.getFamilyId());
|
|
|
+ }
|
|
|
+
|
|
|
+ user.setFamilyId(invitation.getFamilyId());
|
|
|
+ if (familyRole != null) {
|
|
|
+ user.setFamilyRole(familyRole);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (family.getCreatorId() == null) {
|
|
|
+ family.setCreatorId(userId);
|
|
|
+ user.setIsFamilyAdmin(true);
|
|
|
+ familyMapper.updateById(family);
|
|
|
+ }
|
|
|
+
|
|
|
+ user.setUpdatedAt(new Date());
|
|
|
+ userMapper.updateById(user);
|
|
|
+
|
|
|
+ invitation.setStatus("used");
|
|
|
+ invitation.setUpdatedAt(new Date());
|
|
|
+ familyInvitationMapper.updateById(invitation);
|
|
|
+
|
|
|
+ return "加入家庭成功";
|
|
|
+ }
|
|
|
+
|
|
|
+ public void mergeIntoFamily(Long userId, Long targetFamilyId) {
|
|
|
+ User user = userMapper.selectById(userId);
|
|
|
+ if (user == null) {
|
|
|
+ throw new RuntimeException("用户不存在");
|
|
|
+ }
|
|
|
+ Long oldFamilyId = user.getFamilyId();
|
|
|
+ if (oldFamilyId == null) {
|
|
|
+ throw new RuntimeException("用户尚未加入任何家庭");
|
|
|
+ }
|
|
|
+
|
|
|
+ user.setFamilyId(targetFamilyId);
|
|
|
+ user.setUpdatedAt(new Date());
|
|
|
+ userMapper.updateById(user);
|
|
|
+
|
|
|
+ List<Child> children = childMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<Child>()
|
|
|
+ .eq(Child::getFamilyId, oldFamilyId)
|
|
|
+ );
|
|
|
+ for (Child child : children) {
|
|
|
+ child.setFamilyId(targetFamilyId);
|
|
|
+ child.setUpdatedAt(new Date());
|
|
|
+ childMapper.updateById(child);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!oldFamilyId.equals(targetFamilyId)) {
|
|
|
+ Long memberCount = userMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<User>()
|
|
|
+ .eq(User::getFamilyId, oldFamilyId)
|
|
|
+ );
|
|
|
+ if (memberCount == 0) {
|
|
|
+ familyMapper.deleteById(oldFamilyId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public FamilyStatusDTO checkUserFamilyStatus(Long userId) {
|
|
|
+ User user = userMapper.selectById(userId);
|
|
|
+ if (user == null) {
|
|
|
+ throw new RuntimeException("用户不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ FamilyStatusDTO dto = new FamilyStatusDTO();
|
|
|
+ if (user.getFamilyId() == null) {
|
|
|
+ dto.setInFamily(false);
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ Family family = familyMapper.selectById(user.getFamilyId());
|
|
|
+ if (family == null) {
|
|
|
+ dto.setInFamily(false);
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ Long memberCount = userMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<User>()
|
|
|
+ .eq(User::getFamilyId, user.getFamilyId())
|
|
|
+ );
|
|
|
+
|
|
|
+ dto.setInFamily(true);
|
|
|
+ dto.setFamilyId(family.getId());
|
|
|
+ dto.setFamilyName(family.getName());
|
|
|
+ dto.setIsAdmin(user.getIsFamilyAdmin() != null && user.getIsFamilyAdmin());
|
|
|
+ dto.setMemberCount(memberCount.intValue());
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void transferAdmin(Long familyId, Long currentUserId, Long newAdminId) {
|
|
|
+ Family family = familyMapper.selectById(familyId);
|
|
|
+ if (family == null) {
|
|
|
+ throw new RuntimeException("家庭不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (family.getCreatorId() == null || !family.getCreatorId().equals(currentUserId)) {
|
|
|
+ throw new RuntimeException("只有家庭创建者才能转让管理员权限");
|
|
|
+ }
|
|
|
+
|
|
|
+ User newAdmin = userMapper.selectById(newAdminId);
|
|
|
+ if (newAdmin == null || !familyId.equals(newAdmin.getFamilyId())) {
|
|
|
+ throw new RuntimeException("新管理员不是该家庭成员");
|
|
|
+ }
|
|
|
+
|
|
|
+ User currentUser = userMapper.selectById(currentUserId);
|
|
|
+ if (currentUser != null) {
|
|
|
+ currentUser.setIsFamilyAdmin(false);
|
|
|
+ currentUser.setUpdatedAt(new Date());
|
|
|
+ userMapper.updateById(currentUser);
|
|
|
+ }
|
|
|
+
|
|
|
+ family.setCreatorId(newAdminId);
|
|
|
+ family.setUpdatedAt(new Date());
|
|
|
+ familyMapper.updateById(family);
|
|
|
+
|
|
|
+ newAdmin.setIsFamilyAdmin(true);
|
|
|
+ newAdmin.setUpdatedAt(new Date());
|
|
|
+ userMapper.updateById(newAdmin);
|
|
|
+ }
|
|
|
+}
|