HouseholdMemberService.java
package com.hwhub.backend.application.service;
import com.hwhub.backend.application.service.notification.NotificationPublisher;
import com.hwhub.backend.domain.enums.ProgramType;
import com.hwhub.backend.domain.model.HouseholdMemberModel;
import com.hwhub.backend.domain.model.HouseholdModel;
import com.hwhub.backend.domain.repository.HouseholdMemberRepository;
import com.hwhub.backend.domain.repository.HouseholdRepository;
import com.hwhub.backend.domain.repository.HouseworkRepository;
import com.hwhub.backend.domain.repository.HouseworkTaskRepository;
import com.hwhub.backend.presentation.rest.common.ResourceNotFoundException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class HouseholdMemberService {
private final HouseholdMemberRepository memberRepository;
private final HouseholdRepository householdRepository;
private final HouseworkRepository houseworkRepository;
private final HouseworkTaskRepository houseworkTaskRepository;
private final HouseholdAuthorizationService authorizationService;
private final UserIconService iconService;
private final NotificationPublisher notificationPublisher;
/**
* 指定された世帯IDのメンバーを取得する。
*
* @param householdId 世帯ID
* @return 指定された世帯IDのメンバー
*/
public List<HouseholdMemberModel> getMembers(Long householdId) {
List<HouseholdMemberModel> list = memberRepository.findActiveByHouseholdId(householdId);
return list.stream()
.map(
e -> {
e.changeIconUrl(iconService.getIconUrl(e.getProfileImageKey()));
return e;
})
.toList();
}
/**
* ニックネームを更新する。
*
* @param householdId 世帯ID
* @param userId ユーザID
* @param nickname ニックネーム
*/
@Transactional
public void updateMyNickname(Long householdId, Long userId, String nickname) {
// 認可チェック
authorizationService.assertUserBelongsToHousehold(householdId, userId);
HouseholdMemberModel model = memberRepository.findById(householdId, userId);
if (model == null) {
throw new ResourceNotFoundException(
"HouseholdMember not found for householdId=" + householdId + ", userId=" + userId);
}
model.changeNickname(nickname);
memberRepository.update(model, userId, ProgramType.ONL_HLDMEM.getCode());
}
/**
* メンバーを追加する。
*
* @param householdId 世帯ID
* @param userId ユーザID
* @param displayName ユーザの表示名
* @param loginUserId ログインユーザのユーザID
*/
@Transactional
public void createMember(Long householdId, Long userId, String displayName, Long loginUserId) {
// 過去に離脱したメンバーの場合がありえる
HouseholdMemberModel model = memberRepository.findById(householdId, userId);
if (model == null) {
model = HouseholdMemberModel.create(householdId, userId, displayName);
memberRepository.insert(model, loginUserId, ProgramType.ONL_HLDMEM.getCode());
} else {
// 離脱からの復帰
model.rejoin();
memberRepository.update(model, loginUserId, ProgramType.ONL_HLDMEM.getCode());
}
}
/**
* 自身が指定された世帯から離脱する。
*
* @param householdId 世帯ID
* @param userId ユーザID
*/
@Transactional
public void deleteMyself(Long householdId, Long userId) {
// 認可チェック
authorizationService.assertUserBelongsToHousehold(householdId, userId);
HouseholdMemberModel model = memberRepository.findById(householdId, userId);
model.leave();
memberRepository.update(model, userId, ProgramType.ONL_HLDMEM.getCode());
// 世帯ID内の担当となっている家事、タスクから担当解除
clearAssignee(householdId, userId, userId, ProgramType.ONL_HLDMEM.getCode());
// 通知を送る
notificationPublisher.publishMemberRemoved(
householdId, userId, model.getDisplayName(), ProgramType.ONL_HLDMEM.getCode());
}
/**
* 指定されたユーザを世帯から離脱させる。
*
* @param householdId 世帯ID
* @param userId ユーザID
* @param loginUserId ログインユーザのユーザID
*/
@Transactional
public void deleteMember(Long householdId, Long userId, Long loginUserId) {
// 認可チェック
if (!authorizationService.canAccessHousehold(householdId, loginUserId)) {
throw new AccessDeniedException(
"User does not belong to household: userId="
+ loginUserId
+ ", householdId="
+ householdId);
}
// オーナーであるかチェック
HouseholdModel household = householdRepository.findById(householdId);
if (!household.isOwner(loginUserId)) {
throw new AccessDeniedException(
"User cannot delete members because they are not the household owner.: userId="
+ loginUserId
+ ", householdId="
+ householdId);
}
HouseholdMemberModel model = memberRepository.findById(householdId, userId);
model.leave();
memberRepository.update(model, loginUserId, ProgramType.ONL_HLDMEM.getCode());
// 世帯ID内の担当となっている家事、タスクから担当解除
clearAssignee(householdId, userId, loginUserId, ProgramType.ONL_HLDMEM.getCode());
// 通知を送る
notificationPublisher.publishRemoveMemberByOwner(
householdId, loginUserId, userId, ProgramType.ONL_HLDMEM.getCode());
}
/**
* 指定されたユーザが世帯内で担当する家事、タスクから担当を解除する。
*
* @param householdId 世帯ID
* @param userId 担当から解除するユーザのユーザID
* @param loginUserId ログインユーザのユーザID
* @param program 更新プログラム名
*/
private void clearAssignee(Long householdId, Long userId, Long loginUserId, String program) {
// 家事マスタからの担当解除
houseworkRepository.clearAssignee(householdId, userId, loginUserId, program);
// タスクからの担当解除
houseworkTaskRepository.clearAssignee(householdId, userId, loginUserId, program);
}
}