Skip to content
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package com.somemore.domains.recruitboard.controller;


import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;

import com.somemore.domains.recruitboard.dto.request.RecruitBoardCreateRequestDto;
import com.somemore.domains.recruitboard.dto.request.RecruitBoardLocationUpdateRequestDto;
import com.somemore.domains.recruitboard.dto.request.RecruitBoardStatusUpdateRequestDto;
import com.somemore.domains.recruitboard.dto.request.RecruitBoardUpdateRequestDto;
import com.somemore.domains.recruitboard.usecase.CreateRecruitBoardUseCase;
import com.somemore.domains.recruitboard.usecase.DeleteRecruitBoardUseCase;
import com.somemore.domains.recruitboard.usecase.UpdateRecruitBoardUseCase;
import com.somemore.global.auth.annotation.CurrentUser;
import com.somemore.global.auth.annotation.RoleId;
import com.somemore.global.common.response.ApiResponse;
import com.somemore.global.imageupload.dto.ImageUploadRequestDto;
import com.somemore.global.imageupload.usecase.ImageUploadUseCase;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
Expand All @@ -27,9 +23,7 @@
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Tag(name = "Recruit Board Command API", description = "봉사 활동 모집글 생성 수정 삭제 API")
@RequiredArgsConstructor
Expand All @@ -40,70 +34,65 @@ public class RecruitBoardCommandApiController {
private final CreateRecruitBoardUseCase createRecruitBoardUseCase;
private final UpdateRecruitBoardUseCase updateRecruitBoardUseCase;
private final DeleteRecruitBoardUseCase deleteRecruitBoardUseCase;
private final ImageUploadUseCase imageUploadUseCase;

@Secured("ROLE_CENTER")
@Operation(summary = "봉사 활동 모집글 등록", description = "봉사 활동 모집글을 등록합니다.")
@PostMapping(value = "/recruit-board", consumes = MULTIPART_FORM_DATA_VALUE)
@PostMapping(value = "/recruit-board")
public ApiResponse<Long> createRecruitBoard(
@CurrentUser UUID userId,
@Valid @RequestPart("data") RecruitBoardCreateRequestDto requestDto,
@RequestPart(value = "img_file", required = false) MultipartFile image
@RoleId UUID centerId,
@Valid @RequestBody RecruitBoardCreateRequestDto requestDto
) {
String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image));
return ApiResponse.ok(
201,
createRecruitBoardUseCase.createRecruitBoard(requestDto, userId, imgUrl),
createRecruitBoardUseCase.createRecruitBoard(requestDto, centerId),
"봉사 활동 모집글 등록 성공"
);
}

@Secured("ROLE_CENTER")
@Operation(summary = "봉사 활동 모집글 수정", description = "봉사 활동 모집글을 수정합니다.")
@PutMapping(value = "/recruit-board/{id}", consumes = MULTIPART_FORM_DATA_VALUE)
@PutMapping(value = "/recruit-board/{id}")
public ApiResponse<String> updateRecruitBoard(
@CurrentUser UUID userId,
@RoleId UUID centerId,
@PathVariable Long id,
@Valid @RequestPart("data") RecruitBoardUpdateRequestDto requestDto,
@RequestPart(value = "img_file", required = false) MultipartFile image
@Valid @RequestBody RecruitBoardUpdateRequestDto requestDto
) {
String imgUrl = imageUploadUseCase.uploadImage(new ImageUploadRequestDto(image));
updateRecruitBoardUseCase.updateRecruitBoard(requestDto, id, userId, imgUrl);
updateRecruitBoardUseCase.updateRecruitBoard(requestDto, id, centerId);
return ApiResponse.ok("봉사 활동 모집글 수정 성공");
}

@Secured("ROLE_CENTER")
@Operation(summary = "봉사 활동 모집글 위치 수정", description = "봉사 활동 모집글의 위치를 수정합니다.")
@PutMapping(value = "/recruit-board/{id}/location")
public ApiResponse<String> updateRecruitBoardLocation(
@CurrentUser UUID userId,
@RoleId UUID centerId,
@PathVariable Long id,
@Valid @RequestBody RecruitBoardLocationUpdateRequestDto requestDto
) {
updateRecruitBoardUseCase.updateRecruitBoardLocation(requestDto, id, userId);
updateRecruitBoardUseCase.updateRecruitBoardLocation(requestDto, id, centerId);
return ApiResponse.ok("봉사 활동 모집글 위치 수정 성공");
}

@Secured("ROLE_CENTER")
@Operation(summary = "봉사 활동 모집글 상태 수정", description = "봉사 활동 모집글의 상태를 수정합니다.")
@PatchMapping(value = "/recruit-board/{id}")
public ApiResponse<String> updateRecruitBoardStatus(
@CurrentUser UUID userId,
@RoleId UUID centerId,
@PathVariable Long id,
@RequestBody RecruitBoardStatusUpdateRequestDto requestDto
) {
updateRecruitBoardUseCase.updateRecruitBoardStatus(requestDto.status(), id, userId);
updateRecruitBoardUseCase.updateRecruitBoardStatus(requestDto.status(), id, centerId);
return ApiResponse.ok("봉사 활동 모집글 상태 수정 성공");
}

@Secured("ROLE_CENTER")
@Operation(summary = "봉사 활동 모집글 삭제", description = "봉사 활동 모집글을 삭제합니다.")
@DeleteMapping(value = "/recruit-board/{id}")
public ApiResponse<String> deleteRecruitBoard(
@CurrentUser UUID userId,
@RoleId UUID centerId,
@PathVariable Long id
) {
deleteRecruitBoardUseCase.deleteRecruitBoard(userId, id);
deleteRecruitBoardUseCase.deleteRecruitBoard(centerId, id);
return ApiResponse.ok("봉사 활동 모집글 삭제 성공");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,30 +50,25 @@ public class RecruitBoard extends BaseEntity {
@Column(name = "recruit_status", nullable = false, length = 20)
private RecruitStatus recruitStatus;

@Column(name = "img_url", nullable = false)
private String imgUrl;

@Builder
public RecruitBoard(UUID centerId, Long locationId, String title, String content,
RecruitmentInfo recruitmentInfo, RecruitStatus status, String imgUrl) {
RecruitmentInfo recruitmentInfo, RecruitStatus status) {
this.centerId = centerId;
this.locationId = locationId;
this.title = title;
this.content = content;
this.recruitmentInfo = recruitmentInfo;
this.recruitStatus = status;
this.imgUrl = imgUrl;
}

public boolean isWriter(UUID centerId) {
return this.centerId.equals(centerId);
}

public void updateWith(RecruitBoardUpdateRequestDto dto, String imgUrl) {
public void updateWith(RecruitBoardUpdateRequestDto dto) {
updateRecruitmentInfo(dto);
this.title = dto.title();
this.content = dto.content();
this.imgUrl = imgUrl;
}

public void updateWith(String region) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public record RecruitBoardCreateRequestDto(
LocationCreateRequestDto location
) {

public RecruitBoard toEntity(UUID centerId, Long locationId, String imgUrl) {
public RecruitBoard toEntity(UUID centerId, Long locationId) {
RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder()
.region(region)
.recruitmentCount(recruitmentCount)
Expand All @@ -68,7 +68,6 @@ public RecruitBoard toEntity(UUID centerId, Long locationId, String imgUrl) {
.locationId(locationId)
.title(title)
.content(content)
.imgUrl(imgUrl)
.recruitmentInfo(recruitmentInfo)
.status(RECRUITING)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ public record RecruitBoardDetailResponseDto(
Integer volunteerHours,
@Schema(description = "시간 인정 여부", example = "true")
Boolean admitted,
@Schema(description = "이미지 URL", example = "https://image.domain.com/links")
String imgUrl,
@Schema(description = "센터 간단 정보")
CenterSimpleInfoResponseDto center,
@Schema(description = "위치 정보 DTO")
Expand Down Expand Up @@ -76,7 +74,6 @@ public static RecruitBoardDetailResponseDto from(RecruitBoardDetail recruitBoard
.volunteerCategory(info.getVolunteerCategory())
.volunteerHours(info.getVolunteerHours())
.admitted(info.getAdmitted())
.imgUrl(board.getImgUrl())
.location(location)
.center(center)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ public record RecruitBoardResponseDto(
@Schema(description = "봉사 시간", example = "4")
Integer volunteerHours,
@Schema(description = "시간 인정 여부", example = "true")
Boolean admitted,
@Schema(description = "이미지 URL", example = "https://image.domain.com/links")
String imgUrl
Boolean admitted
) {

public static RecruitBoardResponseDto from(RecruitBoard board) {
Expand All @@ -68,7 +66,6 @@ public static RecruitBoardResponseDto from(RecruitBoard board) {
.volunteerCategory(info.getVolunteerCategory())
.volunteerHours(info.getVolunteerHours())
.admitted(info.getAdmitted())
.imgUrl(board.getImgUrl())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ public record RecruitBoardWithCenterResponseDto(
Integer volunteerHours,
@Schema(description = "시간 인정 여부", example = "true")
Boolean admitted,
@Schema(description = "이미지 URL", example = "https://image.domain.com/links")
String imgUrl,
@Schema(description = "센터 간단 정보")
CenterSimpleInfoResponseDto center
) {
Expand All @@ -71,7 +69,6 @@ public static RecruitBoardWithCenterResponseDto from(
.volunteerCategory(info.getVolunteerCategory())
.volunteerHours(info.getVolunteerHours())
.admitted(info.getAdmitted())
.imgUrl(board.getImgUrl())
.center(CenterSimpleInfoResponseDto.of(board.getCenterId(),
recruitBoardWithCenter.centerName()))
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ public record RecruitBoardWithLocationResponseDto(
Integer volunteerHours,
@Schema(description = "시간 인정 여부", example = "true")
Boolean admitted,
@Schema(description = "이미지 URL", example = "https://image.domain.com/links")
String imgUrl,
@Schema(description = "위치 정보 DTO")
LocationResponseDto location
) {
Expand All @@ -72,7 +70,6 @@ public static RecruitBoardWithLocationResponseDto from(
.volunteerCategory(info.getVolunteerCategory())
.volunteerHours(info.getVolunteerHours())
.admitted(info.getAdmitted())
.imgUrl(board.getImgUrl())
.location(
LocationResponseDto.of(recruitBoardWithLocation.address(),
recruitBoardWithLocation.latitude(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.somemore.domains.center.domain.QCenter;
import com.somemore.center.domain.QNEWCenter;
import com.somemore.domains.location.domain.QLocation;
import com.somemore.domains.location.utils.GeoUtils;
import com.somemore.domains.recruitboard.domain.QRecruitBoard;
Expand All @@ -22,6 +22,7 @@
import com.somemore.domains.recruitboard.repository.mapper.RecruitBoardDetail;
import com.somemore.domains.recruitboard.repository.mapper.RecruitBoardWithCenter;
import com.somemore.domains.recruitboard.repository.mapper.RecruitBoardWithLocation;
import com.somemore.user.domain.QUserCommonAttribute;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
Expand All @@ -44,7 +45,8 @@ public class RecruitBoardRepositoryImpl implements RecruitBoardRepository {

private static final QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard;
private static final QLocation location = QLocation.location;
private static final QCenter center = QCenter.center;
private static final QNEWCenter center = QNEWCenter.nEWCenter;
private static final QUserCommonAttribute userCommonAttribute = QUserCommonAttribute.userCommonAttribute;

@Override
public RecruitBoard save(RecruitBoard recruitBoard) {
Expand Down Expand Up @@ -79,8 +81,7 @@ public Optional<RecruitBoardWithLocation> findWithLocationById(Long id) {
RecruitBoardWithLocation result = queryFactory
.select(getRecruitBoardWithLocationConstructorExpression())
.from(recruitBoard)
.join(location)
.on(recruitBoard.locationId.eq(location.id))
.join(location).on(recruitBoard.locationId.eq(location.id))
.where(exp)
.fetchOne();

Expand All @@ -104,6 +105,7 @@ public Page<RecruitBoardWithCenter> findAllWithCenter(RecruitBoardSearchConditio
.from(recruitBoard)
.where(exp)
.join(center).on(recruitBoard.centerId.eq(center.id))
.join(userCommonAttribute).on(center.userId.eq(userCommonAttribute.userId))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(toOrderSpecifiers(pageable.getSort()))
Expand All @@ -113,7 +115,8 @@ public Page<RecruitBoardWithCenter> findAllWithCenter(RecruitBoardSearchConditio
.select(recruitBoard.count())
.from(recruitBoard)
.where(exp)
.join(center).on(recruitBoard.centerId.eq(center.id));
.join(center).on(recruitBoard.centerId.eq(center.id))
.join(userCommonAttribute).on(center.userId.eq(userCommonAttribute.userId));

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
}
Expand All @@ -133,6 +136,7 @@ public Page<RecruitBoardDetail> findAllNearby(RecruitBoardNearByCondition condit
.from(recruitBoard)
.join(location).on(recruitBoard.locationId.eq(location.id))
.join(center).on(recruitBoard.centerId.eq(center.id))
.join(userCommonAttribute).on(center.userId.eq(userCommonAttribute.userId))
.where(exp)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
Expand All @@ -144,6 +148,7 @@ public Page<RecruitBoardDetail> findAllNearby(RecruitBoardNearByCondition condit
.from(recruitBoard)
.join(location).on(recruitBoard.locationId.eq(location.id))
.join(center).on(recruitBoard.centerId.eq(center.id))
.join(userCommonAttribute).on(center.userId.eq(userCommonAttribute.userId))
.where(exp);

return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne);
Expand Down Expand Up @@ -223,7 +228,8 @@ public long updateStatusToClosedForDateRange(LocalDateTime startTime,
}

@Override
public long updateStatusToCompletedForDateRange(LocalDateTime startTime, LocalDateTime endTime) {
public long updateStatusToCompletedForDateRange(LocalDateTime startTime,
LocalDateTime endTime) {
return queryFactory.update(recruitBoard)
.set(recruitBoard.recruitStatus, COMPLETED)
.where(
Expand Down Expand Up @@ -415,7 +421,7 @@ private OrderSpecifier<?>[] toOrderSpecifiers(Sort sort) {

private static ConstructorExpression<RecruitBoardWithCenter> getRecruitBoardWithCenterConstructorExpression() {
return Projections.constructor(RecruitBoardWithCenter.class,
recruitBoard, center.name);
recruitBoard, userCommonAttribute.name);
}

private static ConstructorExpression<RecruitBoardWithLocation> getRecruitBoardWithLocationConstructorExpression() {
Expand All @@ -425,7 +431,8 @@ private static ConstructorExpression<RecruitBoardWithLocation> getRecruitBoardWi

private static ConstructorExpression<RecruitBoardDetail> getRecruitBoardDetailConstructorExpression() {
return Projections.constructor(RecruitBoardDetail.class,
recruitBoard, location.address, location.latitude, location.longitude, center.name);
recruitBoard, location.address, location.latitude, location.longitude,
userCommonAttribute.name);
}

// private List<RecruitBoardDocument> convertEntityToDocuments(List<RecruitBoard> recruitBoards) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ public class CreateRecruitBoardService implements CreateRecruitBoardUseCase {
private final ServerEventPublisher serverEventPublisher;

@Override
public Long createRecruitBoard(RecruitBoardCreateRequestDto dto, UUID centerId, String imgUrl) {
public Long createRecruitBoard(RecruitBoardCreateRequestDto dto, UUID centerId) {
recruitBoardValidator.validateRecruitBoardTime(dto.volunteerStartDateTime(), dto.volunteerEndDateTime());

Long locationId = createLocationUseCase.createLocation(dto.location());
RecruitBoard recruitBoard = dto.toEntity(centerId, locationId, imgUrl);
RecruitBoard recruitBoard = dto.toEntity(centerId, locationId);

recruitBoardRepository.save(recruitBoard);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.somemore.domains.recruitboard.service;

import com.somemore.domains.center.usecase.query.CenterQueryUseCase;
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_RECRUIT_BOARD;

import com.somemore.domains.recruitboard.domain.RecruitBoard;
import com.somemore.domains.recruitboard.dto.condition.RecruitBoardNearByCondition;
import com.somemore.domains.recruitboard.dto.condition.RecruitBoardSearchCondition;
Expand All @@ -14,23 +15,19 @@
import com.somemore.domains.recruitboard.repository.mapper.RecruitBoardWithLocation;
import com.somemore.domains.recruitboard.usecase.RecruitBoardQueryUseCase;
import com.somemore.global.exception.BadRequestException;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_RECRUIT_BOARD;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class RecruitBoardQueryService implements RecruitBoardQueryUseCase {

private final RecruitBoardRepository recruitBoardRepository;
private final CenterQueryUseCase centerQueryUseCase;

@Override
public RecruitBoard getById(Long id) {
Expand Down Expand Up @@ -70,9 +67,7 @@ public Page<RecruitBoardDetailResponseDto> getRecruitBoardsNearby(

@Override
public Page<RecruitBoardResponseDto> getRecruitBoardsByCenterId(UUID centerId,
RecruitBoardSearchCondition condition) {
centerQueryUseCase.validateCenterExists(centerId);

RecruitBoardSearchCondition condition) {
Page<RecruitBoard> boards = recruitBoardRepository.findAllByCenterId(centerId, condition);
return boards.map(RecruitBoardResponseDto::from);
}
Expand Down
Loading
Loading