diff --git a/sql/setup-dev.sql b/sql/setup-dev.sql index 80254d14..fadb1995 100644 --- a/sql/setup-dev.sql +++ b/sql/setup-dev.sql @@ -2,40 +2,25 @@ use genti; set @adminId := 1; set @userId := 2; -set @emptyUserId := 3; -set @creatorUserId := 4; -set @emptyCreatorId := 5; -set @oauthFirstJoinUserId := 6; -set @deactivatedUserId := 7; -set @deactivatedCreatorId := 8; - -set @creatorId := 1; - -insert ignore into user (id, created_at, modified_at, deleted_at, email, email_verified, introduction, - last_login_social_platform, login_id, nickname, password, roles, user_status, - username, profile_picture_id) - -VALUES (1, localtime, localtime, null, 'admin@gmail.com', true, null, 'GOOGLE', null, '어드민테스트1_닉네임', null, - 'ROLE_ADMIN,ROLE_MANAGER,ROLE_CREATOR,ROLE_USER', - 'ACTIVATED', '어드민이름', null), - (2, localtime, localtime, null, 'user@gmail.com', true, '유저_소개1', 'GOOGLE', null, '유저테스트1_닉네임', null, - 'ROLE_USER', - 'ACTIVATED', '유저이름1', null), - (3, localtime, localtime, null, 'emptyUser@gmail.com', true, '유저_소개2', 'GOOGLE', null, '유저테스트1_닉네임', - null, - 'ROLE_USER', 'ACTIVATED', '유저이름2', null), - (4, localtime, localtime, null, 'creator@gmail.com', true, '공급자_소개', 'GOOGLE', null, '유저테스트2_닉네임', - null, - 'ROLE_CREATOR', 'ACTIVATED', '공급자이름1', null), - (5, localtime, localtime, null, 'emptyCreator@gmail.com', true, '공급자_소개2', 'GOOGLE', null, - '공급자테스트2_닉네임', null, 'ROLE_CREATOR', 'ACTIVATED', '공급자이름2', null), - (6, localtime, localtime, null, 'oauthFirstJoin@gmail.com', true, '최초가입자_소개', 'GOOGLE', null, - '최초가입자_닉네임', null, 'ROLE_OAUTH_FIRST_JOIN,ROLE_USER', 'ACTIVATED', '최초가입자이름', null), - (7, localtime, localtime, null, 'deactivatedUser@gmail.com', true, '최초가입자_소개', 'GOOGLE', null, - '비활성화된유저_닉네임', null, 'ROLE_USER', 'DEACTIVATED', '비활성화된유저이름', null), - (8, localtime, localtime, null, 'deactivatedCreator@gmail.com', true, '최초가입자_소개', 'GOOGLE', - null, - '비활성화된공급자_닉네임', null, 'ROLE_CREATOR', 'DEACTIVATED', '비활성화된공급자이름', null); +set @emptyUserId := 3; # 아무 사진 생성 요청하지 않은 유저의 UserId +set @creatorUserId := 4; # 공급자 UserId +set @emptyCreatorId := 5; # 사진 생성 요청 매칭되지 않은 공급자의 UserId +set @oauthFirstJoinUserId := 6; # 첫 회원가입 유저 - FE에서는 크게 신경쓸 일 없을 것 같긴 합니다. +set @deactivatedUserId := 7; # 비활성화된 유저의 UserId +set @deactivatedCreatorId := 8; # 비활성화된 공급자의 CreatorId + +set @creatorId := 1; # 공급자의 CreatorId + +insert ignore into user (id, created_at, modified_at, deleted_at, email, email_verified, introduction, last_login_social_platform, login_id, nickname, password, roles, user_status, username, profile_picture_id) + +VALUES (1, localtime, localtime, null, 'admin@gmail.com', true, null, 'GOOGLE', null, '어드민테스트1_닉네임', null, 'ROLE_ADMIN,ROLE_MANAGER,ROLE_CREATOR,ROLE_USER','ACTIVATED', '어드민이름', null), + (2, localtime, localtime, null, 'user@gmail.com', true, '유저_소개1', 'GOOGLE', null, '유저테스트1_닉네임', null, 'ROLE_USER', 'ACTIVATED', '유저이름1', null), + (3, localtime, localtime, null, 'emptyUser@gmail.com', true, '유저_소개2', 'GOOGLE', null, '유저테스트1_닉네임', null, 'ROLE_USER', 'ACTIVATED', '유저이름2', null), + (4, localtime, localtime, null, 'creator@gmail.com', true, '공급자_소개', 'GOOGLE', null, '유저테스트2_닉네임', null, 'ROLE_CREATOR', 'ACTIVATED', '공급자이름1', null), + (5, localtime, localtime, null, 'emptyCreator@gmail.com', true, '공급자_소개2', 'GOOGLE', null, '공급자테스트2_닉네임', null, 'ROLE_CREATOR', 'ACTIVATED', '공급자이름2', null), + (6, localtime, localtime, null, 'oauthFirstJoin@gmail.com', true, '최초가입자_소개', 'GOOGLE', null, '최초가입자_닉네임', null, 'ROLE_OAUTH_FIRST_JOIN,ROLE_USER', 'ACTIVATED', '최초가입자이름', null), + (7, localtime, localtime, null, 'deactivatedUser@gmail.com', true, '최초가입자_소개', 'GOOGLE', null, '비활성화된유저_닉네임', null, 'ROLE_USER', 'DEACTIVATED', '비활성화된유저이름', null), + (8, localtime, localtime, null, 'deactivatedCreator@gmail.com', true, '최초가입자_소개', 'GOOGLE', null, '비활성화된공급자_닉네임', null, 'ROLE_CREATOR', 'DEACTIVATED', '비활성화된공급자이름', null); insert ignore into creator (id, user_id, workable, created_at, modified_at) values (1, 4, true, localtime, localtime), @@ -60,19 +45,13 @@ values (1, LOCALTIME, LOCALTIME, 'user_face_picture_url1', 2), -insert ignore into picture_generate_request (id, creator_id, picture_pose_id, requester_id, prompt, camera_angle, - request_status, shot_coverage, created_at, modified_at) -VALUES (1, null, 4, 2, 'prompt_test_1', '위에서 촬영', 'BEFORE_WORK', '얼굴만 클로즈업', '2000-01-01 07:00:00', localtime), - (2, null, 3, 2, 'prompt_test_2', '같은 높이에서 촬영', 'CANCELED', '허리 위로 촬영', '2020-01-01 07:00:00', - localtime), - (3, 1, 2, 2, 'prompt_test_3', '아래에서 촬영', 'IN_PROGRESS', '무릎 위로 촬영', '2000-01-01 07:00:00', - localtime), - (4, 1, 2, 2, 'prompt_test_4', '아래에서 촬영', 'IN_PROGRESS', '무릎 위로 촬영', '2000-01-01 07:00:00', - localtime), - (5, 1, 2, 2, 'prompt_test_5', '아래에서 촬영', 'IN_PROGRESS', '무릎 위로 촬영', '2000-01-01 07:00:00', - localtime), - (6, 1, 2, 2, 'prompt_test_6', '아래에서 촬영', 'REPORTED', '무릎 위로 촬영', '2000-01-01 07:00:00', - localtime), +insert ignore into picture_generate_request (id, creator_id, picture_pose_id, requester_id, prompt, camera_angle, request_status, shot_coverage, created_at, modified_at) +VALUES (1, null, 4, 2, 'prompt_test_1', '위에서 촬영', 'CREATED', '얼굴만 클로즈업', '2000-01-01 07:00:00', localtime), + (2, null, 3, 2, 'prompt_test_2', '같은 높이에서 촬영', 'CANCELED', '허리 위로 촬영', '2020-01-01 07:00:00', localtime), + (3, 1, 2, 2, 'prompt_test_3', '아래에서 촬영', 'ASSIGNING', '무릎 위로 촬영', '2000-01-01 07:00:00', localtime), + (4, 1, 2, 2, 'prompt_test_4', '아래에서 촬영', 'IN_PROGRESS', '무릎 위로 촬영', '2000-01-01 07:00:00', localtime), + (5, 1, 2, 2, 'prompt_test_5', '아래에서 촬영', 'IN_PROGRESS', '무릎 위로 촬영', '2000-01-01 07:00:00', localtime), + (6, 1, 2, 2, 'prompt_test_6', '아래에서 촬영', 'REPORTED', '무릎 위로 촬영', '2000-01-01 07:00:00', localtime), (7, 1, 1, 2, 'prompt_test_7', '위에서 촬영', 'COMPLETED', '전신 촬영', '2020-01-01 07:00:00', localtime), (8, 1, 1, 2, 'prompt_test_7', '위에서 촬영', 'REPORTED', '전신 촬영', '2020-01-01 07:00:00', localtime); @@ -103,8 +82,6 @@ values (1, 1), (8, 8), (8, 9); - - insert ignore into picture_generate_response (id, created_at, modified_at, status, creator_id, request_id) values (1, localtime, localtime, 'BEFORE_WORK', 1, 3), (2, localtime, localtime, 'SUBMITTED_FIRST', 1, 4), @@ -117,21 +94,18 @@ insert ignore into report (id, created_at, modified_at, content, report_status, values (1, localtime, localtime, '변태자식이 본인 발가락 사진을 보낸 것 같습니다.', 'NOT_RESOLVED', 4), (2, localtime, localtime, '모르는 사람 얼굴이에요', 'RESOLVED', 6); -insert ignore into picture_created_by_creator (id, created_at, modified_at, url, picture_generate_response_id, - uploaded_by) +insert ignore into picture_created_by_creator (id, created_at, modified_at, url, picture_generate_response_id, uploaded_by) values (1, localtime, localtime, '얼굴 완성 전 url 1', 2, 4), (2, localtime, localtime, '얼굴 완성 전 url 2', 3, 4), (3, localtime, localtime, '얼굴 완성 전 url 3', 4, 4); -insert ignore into picture_completed (id, created_at, modified_at, url, picture_generate_response_id, user_id, - uploaded_by) +insert ignore into picture_completed (id, created_at, modified_at, url, picture_generate_response_id, user_id, uploaded_by) values (1, localtime, localtime, '얼굴 완성 사진 url 1', 3, 2, 1), (2, localtime, localtime, '얼굴 완성 사진 url 2', 4, 2, 1), (3, localtime, localtime, '얼굴 완성 사진 url 3', 5, 2, 1), (4, localtime, localtime, '얼굴 완성 사진 url 4', 6, 2, 1); -insert ignore into response_example (id, created_at, modified_at, example_picture_url, example_prompt, prompt_only, - uploaded_by) +insert ignore into response_example (id, created_at, modified_at, example_picture_url, example_prompt, prompt_only, uploaded_by) values (1, localtime, localtime, '/EXAMPLE/벚꽃벤치여자.png', '벚꽃 벤치 여자', false, 1), (2, localtime, localtime, '/EXAMPLE/한강잠수부.png', '한강잠수부', false, 1), (3, localtime, localtime, null, '프롬프트만있음 사진은 없고', true, 1); diff --git a/src/main/java/com/gt/genti/adapter/in/web/AdminPictureController.java b/src/main/java/com/gt/genti/adapter/in/web/AdminPictureController.java deleted file mode 100644 index fd31eb04..00000000 --- a/src/main/java/com/gt/genti/adapter/in/web/AdminPictureController.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gt.genti.adapter.in.web; - -import static com.gt.genti.other.util.ApiUtils.*; - -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.gt.genti.command.CreatePictureCompletedCommand; -import com.gt.genti.domain.PictureGenerateResponse; -import com.gt.genti.dto.UpdatePictureUrlRequestDto; -import com.gt.genti.error.ErrorCode; -import com.gt.genti.error.ExpectedException; -import com.gt.genti.other.auth.UserDetailsImpl; -import com.gt.genti.repository.PictureGenerateResponseRepository; -import com.gt.genti.service.PictureService; - -import lombok.RequiredArgsConstructor; - -@RestController -@RequestMapping("/api/admin/picture-generate-responses") -@RequiredArgsConstructor -public class AdminPictureController { - private final PictureService pictureService; - private final PictureGenerateResponseRepository pictureGenerateResponseRepository; - - @PostMapping("/{responseId}") - public ResponseEntity> updatePicture( - @AuthenticationPrincipal UserDetailsImpl userDetails, - UpdatePictureUrlRequestDto requestDto, - @PathVariable Long responseId) { - PictureGenerateResponse foundPictureGenerateResponse = pictureGenerateResponseRepository.findById(responseId) - .orElseThrow(() -> new ExpectedException( - ErrorCode.PictureGenerateResponseNotFound)); - - CreatePictureCompletedCommand command = CreatePictureCompletedCommand.builder() - .pictureGenerateResponse(foundPictureGenerateResponse) - .url(requestDto.getUrl()) - .userId(userDetails.getId()).build(); - pictureService.updatePicture(command); - return success(true); - } -} diff --git a/src/main/java/com/gt/genti/adapter/in/web/AdminPictureGenerateController.java b/src/main/java/com/gt/genti/adapter/in/web/AdminPictureGenerateController.java new file mode 100644 index 00000000..2a9f970c --- /dev/null +++ b/src/main/java/com/gt/genti/adapter/in/web/AdminPictureGenerateController.java @@ -0,0 +1,42 @@ +package com.gt.genti.adapter.in.web; + +import static com.gt.genti.other.util.ApiUtils.*; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.gt.genti.application.service.PictureGenerateWorkService; +import com.gt.genti.dto.PictureGenerateResponseAdminSubmitDto; +import com.gt.genti.dto.UpdatePictureUrlRequestDto; +import com.gt.genti.other.auth.UserDetailsImpl; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/api/admin/picture-generate-responses") +@RequiredArgsConstructor +public class AdminPictureGenerateController { + private final PictureGenerateWorkService pictureGenerateWorkService; + + @PostMapping("/{pictureGenerateResponseId}/submit") + public ResponseEntity> submit( + @PathVariable Long pictureGenerateResponseId) { + return success(pictureGenerateWorkService.submitFinal(pictureGenerateResponseId)); + } + + @PostMapping("/{pictureGenerateResponseId}/pictures") + public ResponseEntity> updatePictureList( + @AuthenticationPrincipal UserDetailsImpl userDetails, + @RequestBody List reuqestDtoList, + @PathVariable Long pictureGenerateResponseId) { + return success(pictureGenerateWorkService.updatePictureListCreatedByAdmin(userDetails.getId(), reuqestDtoList, + pictureGenerateResponseId)); + } +} diff --git a/src/main/java/com/gt/genti/adapter/in/web/PictureGenerateWorkController.java b/src/main/java/com/gt/genti/adapter/in/web/CreatorPictureGenerateController.java similarity index 96% rename from src/main/java/com/gt/genti/adapter/in/web/PictureGenerateWorkController.java rename to src/main/java/com/gt/genti/adapter/in/web/CreatorPictureGenerateController.java index 7be5659c..87ef102e 100644 --- a/src/main/java/com/gt/genti/adapter/in/web/PictureGenerateWorkController.java +++ b/src/main/java/com/gt/genti/adapter/in/web/CreatorPictureGenerateController.java @@ -27,7 +27,7 @@ @RestController @RequestMapping("/api/creators") @RequiredArgsConstructor -public class PictureGenerateWorkController { +public class CreatorPictureGenerateController { private final PictureGenerateWorkService pictureGenerateWorkService; @GetMapping("/picture-generate-requests/assigned") @@ -83,7 +83,7 @@ public ResponseEntity> updatePictureUrl( public ResponseEntity> submitPictureGenerateResponse( @AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long pictureGenerateResponseId) { - return success(pictureGenerateWorkService.submit(userDetails.getId(), pictureGenerateResponseId)); + return success(pictureGenerateWorkService.submitToAdmin(userDetails.getId(), pictureGenerateResponseId)); } @PostMapping("/picture-generate-responses/{pictureGenerateResponseId}/memo") diff --git a/src/main/java/com/gt/genti/adapter/in/web/UserController.java b/src/main/java/com/gt/genti/adapter/in/web/UserController.java index e18f4fb7..4a4e3bc9 100644 --- a/src/main/java/com/gt/genti/adapter/in/web/UserController.java +++ b/src/main/java/com/gt/genti/adapter/in/web/UserController.java @@ -2,6 +2,8 @@ import static com.gt.genti.other.util.ApiUtils.*; +import java.util.List; + import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.DeleteMapping; @@ -11,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.gt.genti.dto.CommonPictureResponseDto; import com.gt.genti.other.annotation.ToBeUpdated; import com.gt.genti.other.aop.annotation.CheckUserIsQuit; import com.gt.genti.other.auth.UserDetailsImpl; @@ -18,6 +21,7 @@ import com.gt.genti.dto.UserInfoUpdateRequestDto; import com.gt.genti.application.service.UserService; +import lombok.Getter; import lombok.RequiredArgsConstructor; @RestController @@ -56,4 +60,11 @@ public ResponseEntity> restoreSoftDeletedUser( @AuthenticationPrincipal UserDetailsImpl userDetails) { return success(userService.restoreSoftDeletedUser(userDetails.getId())); } + + @GetMapping("/pictures/my") + public ResponseEntity>> getAllMyGeneratedPicture( + @AuthenticationPrincipal UserDetailsImpl userDetails + ){ + return success(userService.getAllMyGeneratedPicture(userDetails.getId())); + } } diff --git a/src/main/java/com/gt/genti/adapter/in/web/PictureGenerateRequestController.java b/src/main/java/com/gt/genti/adapter/in/web/UserPictureGenerateRequestController.java similarity index 98% rename from src/main/java/com/gt/genti/adapter/in/web/PictureGenerateRequestController.java rename to src/main/java/com/gt/genti/adapter/in/web/UserPictureGenerateRequestController.java index b120d974..e7113b93 100644 --- a/src/main/java/com/gt/genti/adapter/in/web/PictureGenerateRequestController.java +++ b/src/main/java/com/gt/genti/adapter/in/web/UserPictureGenerateRequestController.java @@ -29,7 +29,7 @@ @RestController @RequestMapping("/api/users/picture-generate-requests") @RequiredArgsConstructor -public class PictureGenerateRequestController { +public class UserPictureGenerateRequestController { private final PictureGenerateRequestUseCase pictureGenerateRequestUseCase; @CheckUserIsQuit diff --git a/src/main/java/com/gt/genti/application/service/PictureGenerateWorkService.java b/src/main/java/com/gt/genti/application/service/PictureGenerateWorkService.java index 851d905a..5ef34744 100644 --- a/src/main/java/com/gt/genti/application/service/PictureGenerateWorkService.java +++ b/src/main/java/com/gt/genti/application/service/PictureGenerateWorkService.java @@ -3,7 +3,6 @@ import static com.gt.genti.other.util.TimeUtils.*; import java.time.Duration; -import java.time.LocalDateTime; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -11,6 +10,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.gt.genti.command.CreatePictureCompletedCommand; import com.gt.genti.command.CreatePictureCreatedByCreatorCommand; import com.gt.genti.domain.Creator; import com.gt.genti.domain.Deposit; @@ -18,9 +18,9 @@ import com.gt.genti.domain.PictureGenerateResponse; import com.gt.genti.domain.Settlement; import com.gt.genti.domain.enums.PictureGenerateRequestStatus; -import com.gt.genti.domain.enums.PictureGenerateResponseStatus; import com.gt.genti.dto.PictureGenerateRequestBriefResponseDto; import com.gt.genti.dto.PictureGenerateRequestDetailResponseDto; +import com.gt.genti.dto.PictureGenerateResponseAdminSubmitDto; import com.gt.genti.dto.PictureGenerateResponseSubmitDto; import com.gt.genti.dto.UpdateMemoRequestDto; import com.gt.genti.dto.UpdatePictureUrlRequestDto; @@ -90,47 +90,10 @@ public List getPictureGenerateRequestDe } - @Transactional - public PictureGenerateResponseSubmitDto submit(Long userId, Long pictureGenerateResponseId) { - PictureGenerateResponse foundPGRES = pictureGenerateResponseRepository.findById( - pictureGenerateResponseId) - .orElseThrow(() -> new ExpectedException(ErrorCode.PictureGenerateResponseNotFound)); - Creator foundCreator = creatorRepository.findByUserId(userId) - .orElseThrow(() -> new ExpectedException(ErrorCode.CreatorNotFound)); - - if (!Objects.equals(foundPGRES.getCreator().getId(), foundCreator.getId())) { - throw new ExpectedException(ErrorCode.NotAssignedToMe); - } - - foundPGRES.updateStatus(PictureGenerateResponseStatus.SUBMITTED_FINAL); - - LocalDateTime createdAt = foundPGRES.getCreatedAt(); - Duration elapsedDuration = Duration.between(createdAt, LocalDateTime.now()); - - if (elapsedDuration.compareTo(Duration.ofHours(TimeUtils.PGRES_LIMIT_HOUR)) > 0) { - throw new ExpectedException(ErrorCode.ExpiredPictureGenerateRequest); - } - Long reword = calculateReward(elapsedDuration.toMinutes()); - Settlement settlement = Settlement.builder() - .pictureGenerateResponse(foundPGRES) - .elapsed(elapsedDuration) - .reward(reword).build(); - - settlementRepository.save(settlement); - Deposit foundDeposit = depositRepository.findByUserId(userId) - .orElseThrow(() -> new ExpectedException(ErrorCode.DepositNotFound)); - foundDeposit.add(reword); - return PictureGenerateResponseSubmitDto.builder() - .elapsedTime(getTimeString(elapsedDuration)) - .build(); - } - @Transactional public Boolean updatePictureCreatedByCreatorList(Long pictureGenerateResponseId, List updatePictureUrlRequestDtoList, Long uploaderId) { - PictureGenerateResponse foundPictureGenerateResponse = pictureGenerateResponseRepository.findById( - pictureGenerateResponseId) - .orElseThrow(() -> new ExpectedException(ErrorCode.PictureGenerateResponseNotFound)); + PictureGenerateResponse foundPictureGenerateResponse = findPGRES(pictureGenerateResponseId); List newUploadPictures = updatePictureUrlRequestDtoList.stream() .map(command -> CreatePictureCreatedByCreatorCommand.builder() @@ -146,9 +109,7 @@ public Boolean updatePictureCreatedByCreatorList(Long pictureGenerateResponseId, @Transactional public Boolean updateMemo(Long pictureGenerateResponseId, UpdateMemoRequestDto updateMemoRequestDto) { - PictureGenerateResponse foundPictureGenerateResponse = pictureGenerateResponseRepository.findById( - pictureGenerateResponseId) - .orElseThrow(() -> new ExpectedException(ErrorCode.PictureGenerateResponseNotFound)); + PictureGenerateResponse foundPictureGenerateResponse = findPGRES(pictureGenerateResponseId); foundPictureGenerateResponse.updateMemo(updateMemoRequestDto.getMemo()); return true; } @@ -184,5 +145,88 @@ public Boolean rejectPictureGenerateRequest(Long userId, Long pictureGenerateReq requestMatchService.matchPictureGenerateRequest(foundPictureGenerateRequest); return true; } + + @Transactional + public PictureGenerateResponseSubmitDto submitToAdmin(Long userId, Long pictureGenerateResponseId) { + PictureGenerateResponse foundPGRES = findPGRES(pictureGenerateResponseId); + Creator foundCreator = findCreatorByUserId(userId); + + if (!Objects.equals(foundPGRES.getCreator().getId(), foundCreator.getId())) { + throw new ExpectedException(ErrorCode.NotAssignedToMe); + } + + pictureService.findPictureCreatedByCreatorByPictureGenerateResponse(foundPGRES) + .orElseThrow(() -> new ExpectedException(ErrorCode.CreatorsPictureNotUploadedYet)); + + foundPGRES.creatorSubmit(); + + Duration elapsedDuration = foundPGRES.getElapsedTime(); + + if (elapsedDuration.compareTo(Duration.ofHours(TimeUtils.PGRES_LIMIT_HOUR)) > 0) { + throw new ExpectedException(ErrorCode.ExpiredPictureGenerateRequest); + } + + Long reword = calculateReward(elapsedDuration.toMinutes()); + + Settlement settlement = Settlement.builder() + .pictureGenerateResponse(foundPGRES) + .elapsed(elapsedDuration) + .reward(reword).build(); + + settlementRepository.save(settlement); + Deposit foundDeposit = depositRepository.findByUserId(userId) + .orElseThrow(() -> new ExpectedException(ErrorCode.DepositNotFound)); + + foundDeposit.add(reword); + + return PictureGenerateResponseSubmitDto.builder() + .elapsedTime(getTimeString(elapsedDuration)) + .build(); + } + + @Transactional + public PictureGenerateResponseAdminSubmitDto submitFinal(Long pictureGenerateResponseId) { + PictureGenerateResponse foundPGRES = findPGRES(pictureGenerateResponseId); + pictureService.findPictureCompletedByPictureGenerateResponse( + foundPGRES).orElseThrow(() -> new ExpectedException(ErrorCode.FinalPictureNotUploadedYet)); + + foundPGRES.adminSubmit(); + Duration elapsedDuration = foundPGRES.getElapsedTime(); + + //TODO 어드민은 시간 체크 할 필요 없겠지? + // edited at 2024-05-20 + // author 서병렬 + + //TODO 요청자에게 앱 푸시알림 + // edited at 2024-05-21 + // author 서병렬 + + return PictureGenerateResponseAdminSubmitDto.builder() + .elapsedTime(getTimeString(elapsedDuration)) + .build(); + } + + private PictureGenerateResponse findPGRES(Long pictureGenerateResponseId) { + return pictureGenerateResponseRepository.findById( + pictureGenerateResponseId) + .orElseThrow(() -> new ExpectedException(ErrorCode.PictureGenerateResponseNotFound)); + } + + public Boolean updatePictureListCreatedByAdmin(Long userId, List requestDtoList, + Long pictureGenerateResponseId) { + PictureGenerateResponse foundPictureGenerateResponse = pictureGenerateResponseRepository.findById( + pictureGenerateResponseId) + .orElseThrow(() -> new ExpectedException( + ErrorCode.PictureGenerateResponseNotFound)); + + List commandList = requestDtoList.stream().map( + dto -> CreatePictureCompletedCommand.builder() + .pictureGenerateResponse(foundPictureGenerateResponse) + .url(dto.getUrl()) + .userId(userId).build() + ).toList(); + pictureService.updatePictures(commandList); + return true; + } } diff --git a/src/main/java/com/gt/genti/application/service/UserService.java b/src/main/java/com/gt/genti/application/service/UserService.java index 23898a5b..6bd5bd50 100644 --- a/src/main/java/com/gt/genti/application/service/UserService.java +++ b/src/main/java/com/gt/genti/application/service/UserService.java @@ -1,19 +1,23 @@ package com.gt.genti.application.service; +import java.util.List; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.gt.genti.domain.Creator; +import com.gt.genti.domain.PictureCompleted; import com.gt.genti.domain.PictureProfile; import com.gt.genti.domain.User; import com.gt.genti.dto.ChangeUserRoleDto; import com.gt.genti.dto.ChangeUserStatusDto; +import com.gt.genti.dto.CommonPictureResponseDto; import com.gt.genti.dto.UserInfoResponseDto; import com.gt.genti.dto.UserInfoUpdateRequestDto; import com.gt.genti.error.ErrorCode; import com.gt.genti.error.ExpectedException; import com.gt.genti.repository.CreatorRepository; -import com.gt.genti.repository.DepositRepository; +import com.gt.genti.repository.PictureCompletedRepository; import com.gt.genti.repository.UserRepository; import lombok.RequiredArgsConstructor; @@ -24,26 +28,22 @@ public class UserService { private final UserRepository userRepository; private final DepositService depositService; private final CreatorRepository creatorRepository; + private final PictureCompletedRepository pictureCompletedRepository; @Transactional - public UserInfoResponseDto getUserInfo(Long id) { - User findUser = userRepository.findById(id).orElseThrow(); - if (!findUser.isActivate()) { - throw new RuntimeException("탈퇴"); - } - PictureProfile pictureProfile = findUser.getPictureProfile(); + public UserInfoResponseDto getUserInfo(Long userId) { + User foundUser = findActivateUserByUserId(userId); + PictureProfile pictureProfile = foundUser.getPictureProfile(); return UserInfoResponseDto.builder() - .user(findUser) + .user(foundUser) .pictureProfile(pictureProfile) .build(); } @Transactional - public UserInfoResponseDto updateUserInfo(Long id, UserInfoUpdateRequestDto userInfoUpdateRequestDto) { - User findUser = userRepository.findById(id).orElseThrow(); - if (!findUser.isActivate()) { - throw new RuntimeException("탈퇴"); - } + public UserInfoResponseDto updateUserInfo(Long userId, UserInfoUpdateRequestDto userInfoUpdateRequestDto) { + User findUser = findActivateUserByUserId(userId); + findUser.update(userInfoUpdateRequestDto); return UserInfoResponseDto.builder() .user(findUser) @@ -52,37 +52,29 @@ public UserInfoResponseDto updateUserInfo(Long id, UserInfoUpdateRequestDto user } @Transactional - public Boolean deleteUserInfoSoft(Long id) { - User findUser = userRepository.findById(id).orElseThrow(); - if (!findUser.isActivate()) { - throw new RuntimeException("이미 탈퇴"); - } + public Boolean deleteUserInfoSoft(Long userId) { + User findUser = findActivateUserByUserId(userId); findUser.softDelete(); return true; } @Transactional - public Boolean restoreSoftDeletedUser(Long id) { - User findUser = userRepository.findById(id).orElseThrow(); - if (findUser.isActivate()) { - throw new RuntimeException("삭제되지 않은 사용자에 대한 잘못된 요청"); - } + public Boolean restoreSoftDeletedUser(Long userId) { + User findUser = findDeactivatedUserByUserId(userId); findUser.restore(); return true; } @Transactional public Boolean updateUserStatus(Long userId, ChangeUserStatusDto changeUserStatusDto) { - User foundUser = findUserById(userId); + User foundUser = findActivateUserByUserId(userId); foundUser.updateStatus(changeUserStatusDto.getUserStatus()); return true; } - - @Transactional public Boolean updateUserRole(Long userId, ChangeUserRoleDto changeUserRoleDto) { - User foundUser = findUserById(userId); + User foundUser = findActivateUserByUserId(userId); foundUser.updateUserRole(changeUserRoleDto.getUserRole()); Creator newCreator = new Creator(foundUser); creatorRepository.save(newCreator); @@ -90,7 +82,31 @@ public Boolean updateUserRole(Long userId, ChangeUserRoleDto changeUserRoleDto) return true; } - private User findUserById(Long userId) { - return userRepository.findById(userId).orElseThrow(() -> new ExpectedException(ErrorCode.UserNotFound)); + public List getAllMyGeneratedPicture(Long userId) { + User foundUser = findActivateUserByUserId(userId); + List pictureCompletedList = pictureCompletedRepository.findAllByUser(foundUser); + return pictureCompletedList.stream() + .map(entity -> new CommonPictureResponseDto(entity.getId(), entity.getUrl())) + .toList(); + } + + private User findActivateUserByUserId(Long userId) { + User foundUser = userRepository.findById(userId) + .orElseThrow(() -> new ExpectedException(ErrorCode.UserNotFound)); + + if (!foundUser.isActivate()) { + throw new ExpectedException(ErrorCode.UserDeactivated); + } + return foundUser; + } + + private User findDeactivatedUserByUserId(Long userId) { + User foundUser = userRepository.findById(userId) + .orElseThrow(() -> new ExpectedException(ErrorCode.UserNotFound)); + + if (foundUser.isActivate()) { + throw new ExpectedException(ErrorCode.AlreadyActivatedUser); + } + return foundUser; } } diff --git a/src/main/java/com/gt/genti/domain/PictureGenerateResponse.java b/src/main/java/com/gt/genti/domain/PictureGenerateResponse.java index 86bfc8a5..ec189b5f 100644 --- a/src/main/java/com/gt/genti/domain/PictureGenerateResponse.java +++ b/src/main/java/com/gt/genti/domain/PictureGenerateResponse.java @@ -1,10 +1,14 @@ package com.gt.genti.domain; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.List; import com.gt.genti.domain.common.BaseTimeEntity; import com.gt.genti.domain.enums.PictureGenerateResponseStatus; import com.gt.genti.domain.enums.converter.PictureGenerateResponseStatusConverter; +import com.gt.genti.error.ErrorCode; +import com.gt.genti.error.ExpectedException; import jakarta.persistence.Column; import jakarta.persistence.Convert; @@ -49,11 +53,22 @@ public class PictureGenerateResponse extends BaseTimeEntity { @Convert(converter = PictureGenerateResponseStatusConverter.class) PictureGenerateResponseStatus status; - public void updateStatus(PictureGenerateResponseStatus status) { - this.status = status; + public void creatorSubmit() { + //TODO 공급자가 제출시 불가한 상태가 있는지 생각해볼것 + // edited at 2024-05-20 + // author 서병렬 + this.status = PictureGenerateResponseStatus.SUBMITTED_FIRST; } public void updateMemo(String memo) { this.memo = memo; } + + public Duration getElapsedTime() { + return Duration.between(this.getCreatedAt(), LocalDateTime.now()); + } + + public void adminSubmit() { + this.status = PictureGenerateResponseStatus.SUBMITTED_FINAL; + } } diff --git a/src/main/java/com/gt/genti/domain/User.java b/src/main/java/com/gt/genti/domain/User.java index d9d6e26b..da292ea6 100644 --- a/src/main/java/com/gt/genti/domain/User.java +++ b/src/main/java/com/gt/genti/domain/User.java @@ -12,6 +12,8 @@ import com.gt.genti.domain.enums.converter.OauthTypeConverterIgnoreCase; import com.gt.genti.domain.enums.converter.UserStatusConverter; import com.gt.genti.dto.UserInfoUpdateRequestDto; +import com.gt.genti.error.ErrorCode; +import com.gt.genti.error.ExpectedException; import com.gt.genti.other.auth.OAuthAttributes; import jakarta.persistence.CascadeType; @@ -46,10 +48,6 @@ public class User extends BaseTimeEntity { @JoinColumn(name = "user_id") List pictureUserFaceList; - @OneToMany - @JoinColumn(name = "user_id") - List createdPictureList; - @Column(name = "email") String email; @@ -136,7 +134,7 @@ public void softDelete() { public void restore() { if (Period.between(this.deletedAt.toLocalDate(), LocalDate.now()).getMonths() >= 1) { - throw new RuntimeException("탈퇴한 지 한달이 지난 경우 재가입해야합니다."); + throw new ExpectedException(ErrorCode.CannotRestoreUser); } this.userStatus = UserStatus.ACTIVATED; diff --git a/src/main/java/com/gt/genti/dto/PictureGenerateResponseAdminSubmitDto.java b/src/main/java/com/gt/genti/dto/PictureGenerateResponseAdminSubmitDto.java new file mode 100644 index 00000000..8680a41d --- /dev/null +++ b/src/main/java/com/gt/genti/dto/PictureGenerateResponseAdminSubmitDto.java @@ -0,0 +1,16 @@ +package com.gt.genti.dto; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class PictureGenerateResponseAdminSubmitDto { + String elapsedTime; + + @Builder + public PictureGenerateResponseAdminSubmitDto(String elapsedTime) { + this.elapsedTime = elapsedTime; + } +} diff --git a/src/main/java/com/gt/genti/error/ErrorCode.java b/src/main/java/com/gt/genti/error/ErrorCode.java index c27af19f..23e608e3 100644 --- a/src/main/java/com/gt/genti/error/ErrorCode.java +++ b/src/main/java/com/gt/genti/error/ErrorCode.java @@ -40,8 +40,15 @@ public enum ErrorCode { ExpiredMatching(HttpStatus.BAD_REQUEST, ErrorUtils.ExpiredMatching, "수락 마감 시간을 초과하였습니다."), DepositNotFound(HttpStatus.NOT_FOUND, ErrorUtils.DepositNotFound, "사용자의 포인트 정보를 불러올 수 없습니다."), AddPointAmountCannotBeMinus(HttpStatus.BAD_REQUEST, ErrorUtils.AddPointAmountCannotBeMinus, "적립될 포인트는 음수일 수 없습니다."), + FinalPictureNotUploadedYet(HttpStatus.BAD_REQUEST, ErrorUtils.FinalPictureNotUploadedYet, "최종 작업 사진이 제출되지 않았습니다."), + CreatorsPictureNotUploadedYet(HttpStatus.BAD_REQUEST, ErrorUtils.CreatorsPictureNotUploadedYet, "작업 사진이 제출되지 않았습니다."), + UserDeactivated(HttpStatus.BAD_REQUEST, ErrorUtils.UserDeactivated, "비활성화된 계정입니다."), + AlreadyActivatedUser(HttpStatus.BAD_REQUEST, ErrorUtils.AlreadyActivatedUser, "비활성화 되지 않은 상태의 유저입니다."), + CannotRestoreUser(HttpStatus.BAD_REQUEST, ErrorUtils.CannotRestoreUser, "탈퇴 후 한달이 지난 경우 재가입해야합니다."), + Undefined(HttpStatus.INTERNAL_SERVER_ERROR, "UNDEFINED", "FOR FE 원래 비즈니스 로직 상 발생하면 안되는 오류입니다. 문의 부탁드립니다."); + private final HttpStatusCode status; private final String code; private final String message; diff --git a/src/main/java/com/gt/genti/other/util/ErrorUtils.java b/src/main/java/com/gt/genti/other/util/ErrorUtils.java index cb613752..aa159b97 100644 --- a/src/main/java/com/gt/genti/other/util/ErrorUtils.java +++ b/src/main/java/com/gt/genti/other/util/ErrorUtils.java @@ -48,5 +48,10 @@ private static String CODE(String type, int seq) { public static final String DepositNotFound = CODE(DEPOSIT, 1); public static final String AddPointAmountCannotBeMinus = CODE(DEPOSIT, 2); + public static final String FinalPictureNotUploadedYet = CODE(ADMIN, 1); + public static final String CreatorsPictureNotUploadedYet = CODE(RESPONSE, 3); + public static final String UserDeactivated = CODE(USER, 2); + public static String AlreadyActivatedUser = CODE(USER, 3); + public static String CannotRestoreUser = CODE(USER, 4); } diff --git a/src/main/java/com/gt/genti/repository/PictureCompletedRepository.java b/src/main/java/com/gt/genti/repository/PictureCompletedRepository.java index 26d1e15c..cb0809f9 100644 --- a/src/main/java/com/gt/genti/repository/PictureCompletedRepository.java +++ b/src/main/java/com/gt/genti/repository/PictureCompletedRepository.java @@ -1,13 +1,28 @@ package com.gt.genti.repository; +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import com.gt.genti.domain.PictureCompleted; import com.gt.genti.domain.PictureCreatedByCreator; +import com.gt.genti.domain.PictureGenerateResponse; +import com.gt.genti.domain.User; public interface PictureCompletedRepository extends JpaRepository { Optional findByUrl(String url); + // @Query("select pc from PictureCompleted pc " + // + "where pc.pictureGenerateResponse = :pictureGenerateResponse ") + Optional findByPictureGenerateResponse(PictureGenerateResponse pictureGenerateResponse); + + @Query("select p " + + "from PictureCompleted p " + + ", PictureGenerateResponse pgres " + + "where pgres.request.requester = :user " + + "and p.pictureGenerateResponse = pgres " + + "order by p.createdAt desc ") + List findAllByUser(User user); } diff --git a/src/main/java/com/gt/genti/repository/PictureCreatedByCreatorRepository.java b/src/main/java/com/gt/genti/repository/PictureCreatedByCreatorRepository.java index 44c98fa5..f145e421 100644 --- a/src/main/java/com/gt/genti/repository/PictureCreatedByCreatorRepository.java +++ b/src/main/java/com/gt/genti/repository/PictureCreatedByCreatorRepository.java @@ -5,7 +5,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import com.gt.genti.domain.PictureCreatedByCreator; +import com.gt.genti.domain.PictureGenerateResponse; public interface PictureCreatedByCreatorRepository extends JpaRepository { Optional findByUrl(String url); + + Optional findByPictureGenerateResponse(PictureGenerateResponse pictureGenerateResponse); } diff --git a/src/main/java/com/gt/genti/service/PictureService.java b/src/main/java/com/gt/genti/service/PictureService.java index ef0d5136..b5e83feb 100644 --- a/src/main/java/com/gt/genti/service/PictureService.java +++ b/src/main/java/com/gt/genti/service/PictureService.java @@ -16,6 +16,7 @@ import com.gt.genti.domain.Picture; import com.gt.genti.domain.PictureCompleted; import com.gt.genti.domain.PictureCreatedByCreator; +import com.gt.genti.domain.PictureGenerateResponse; import com.gt.genti.domain.PicturePose; import com.gt.genti.domain.PicturePost; import com.gt.genti.domain.PictureProfile; @@ -45,6 +46,10 @@ public class PictureService { private final PictureCompletedRepository pictureCompletedRepository; private final PicturePoseRepository picturePoseRepository; + public Optional findPictureCompletedByPictureGenerateResponse(PictureGenerateResponse pgres) { + return pictureCompletedRepository.findByPictureGenerateResponse(pgres); + } + public Optional findByUrlPictureUserFace(String url) { return pictureUserFaceRepository.findByUrl(url); } @@ -82,6 +87,18 @@ public Picture updatePicture(CreatePictureCompletedCommand command) { return pictureCompletedRepository.save(pictureCompleted); } + public List updatePictures(List commandList) { + User foundUser = findUser(commandList.get(0).getUserId()); + + List pictureCompletedList = commandList.stream().map( + command -> PictureEntityUtils.makePictureCompleted( + command.getUrl(), + command.getPictureGenerateResponse(), foundUser) + ).toList(); + + return pictureCompletedRepository.saveAll(pictureCompletedList); + } + public Picture updatePicture(CreatePictureUserFaceCommand createPictureUserFaceCommand) { PictureUserFace pictureUserFace = PictureEntityUtils.makePictureUserFace( createPictureUserFaceCommand.getUrl(), @@ -168,4 +185,9 @@ private User findUser(Long userId) { return userRepository.findById(userId) .orElseThrow(() -> new ExpectedException(ErrorCode.UserNotFound)); } + + public Optional findPictureCreatedByCreatorByPictureGenerateResponse( + PictureGenerateResponse pictureGenerateResponse) { + return pictureCreatedByCreatorRepository.findByPictureGenerateResponse(pictureGenerateResponse); + } }