using AutoMapper; using GroupService.Domain.IReposities; using GroupService.Domain.ValueObjects; using GroupService.WebApi.Application.Dtos; using GroupService.WebApi.Application.IntegrationServices; using IM.Commons; namespace GroupService.WebApi.Application.GroupInvitation { public class GroupInvitationService { private readonly IGroupInvitationReposity reposity; private readonly IGroupMemberReposity memberReposity; private readonly IIdentityIntegrationService idService; private readonly IGroupReposity groupReposity; private readonly IMapper mapper; public GroupInvitationService(IGroupInvitationReposity reposity, IGroupMemberReposity memberReposity, IIdentityIntegrationService idService, IGroupReposity groupReposity, IMapper mapper) { this.reposity = reposity; this.memberReposity = memberReposity; this.idService = idService; this.groupReposity = groupReposity; this.mapper = mapper; } public async Task> CreateAsync(Guid operatorId, Guid userId, Guid groupId) { var userRes = await idService.FindUserByIdAsync(userId); if (!userRes.Succeeded) { return Result.Fail(userRes); } var operatorInfo = await idService.FindUserByIdAsync(operatorId); var member = await memberReposity.FindOneByGroupIdAndUserIdAsync(groupId, operatorId); if (member == null) { return Result.Fail(ResultCode.PERMISSION_DENIED); } // 检查是否已存在对该用户的未处理邀请,避免 Duplicate entry 报错 var existing = await reposity.FindByGroupIdAndUserIdAsync(groupId, userId); if (existing != null) { return Result.Success(mapper.Map(existing)); } var group = await groupReposity.FindByIdAsync(groupId); var userProfile = new UserProfile() { Avatar = userRes.Data.Avatar, NickName = userRes.Data.NickName }; var operatorProfile = new UserProfile() { Avatar = operatorInfo.Data.Avatar, NickName = operatorInfo.Data.NickName }; var groupProfile = new GroupProfile() { Avatar = group.Avatar, GroupName = group.Name }; var invitation = new Domain.Entities.GroupInvitation(groupId, groupProfile, userId, userProfile , operatorId, operatorProfile); reposity.Create(invitation); return Result.Success(mapper.Map(invitation)); } public async Task> CreateBatchAsync(Guid operatorId, List userIds, Guid groupId) { var group = await groupReposity.FindByIdAsync(groupId); if (group is null) return Result.Fail(ResultCode.GROUP_NOT_FOUND); // 校验操作者是否有权限(群成员/管理员/群主) var operatorMember = await memberReposity.FindOneByGroupIdAndUserIdAsync(groupId, operatorId); if (operatorMember == null) return Result.Fail(ResultCode.PERMISSION_DENIED); var operatorInfo = await idService.FindUserByIdAsync(operatorId); var operatorProfile = new UserProfile() { Avatar = operatorInfo.Data?.Avatar, NickName = operatorInfo.Data?.NickName ?? string.Empty }; var groupProfile = new GroupProfile() { Avatar = group.Avatar, GroupName = group.Name }; // 批量创建邀请,跳过已存在未处理邀请的用户 foreach (var userId in userIds) { var existing = await reposity.FindByGroupIdAndUserIdAsync(groupId, userId); if (existing != null) continue; var userRes = await idService.FindUserByIdAsync(userId); if (!userRes.Succeeded) continue; var userProfile = new UserProfile() { Avatar = userRes.Data?.Avatar, NickName = userRes.Data?.NickName ?? string.Empty }; var invitation = new Domain.Entities.GroupInvitation( groupId, groupProfile, userId, userProfile, operatorId, operatorProfile); reposity.Create(invitation); } return Result.Success(); } public async Task> HandleAsync(GroupInvitationHandleCommand command) { var invitation = await reposity.FindByIdAsync(command.InvitationId); if (invitation is null || invitation.UserId != command.UserId) { return Result.Fail(ResultCode.GROUP_INVITE_EXPIRED); } if (command.Action == GroupInvitationAction.Accept) { invitation.Accept(); } else if (command.Action == GroupInvitationAction.Reject) { invitation.Reject(); } return Result.Success(); } public async Task> GetByIdAsync(Guid id, Guid userId) { var invitation = await reposity.FindByIdAsync(id); if (invitation is null || (invitation.UserId != userId && invitation.OperatorId != userId)) { return Result.Fail(ResultCode.GROUP_INVITE_EXPIRED); } return Result.Success(mapper.Map(invitation)); } } }