Skip to content

Commit

Permalink
Merge pull request #272 from TEAM-MODDY/develop
Browse files Browse the repository at this point in the history
1.2.0
  • Loading branch information
hellozo0 authored Mar 7, 2024
2 parents ad54370 + ce32eae commit 924e5c0
Show file tree
Hide file tree
Showing 18 changed files with 145 additions and 28 deletions.
4 changes: 0 additions & 4 deletions src/main/java/com/moddy/server/common/dto/TokenPair.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package com.moddy.server.common.dto;


import lombok.Getter;
import lombok.ToString;

public record TokenPair(
String accessToken, String refreshToken
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public enum ErrorCode {
NOT_FOUND_RESOURCE_EXCEPTION(HttpStatus.NOT_FOUND, "해당 자원을 찾을 수 없습니다."),
NOT_FOUND_REGION_EXCEPTION(HttpStatus.NOT_FOUND, "해당 지역을 찾을 수 없습니다."),
NOT_FOUND_VERIFICATION_CODE_EXCEPTION(HttpStatus.NOT_FOUND, "인증 코드가 존재하지 않습니다."),
NOT_FOUND_VALID_APPLICATION_EXCEPTION(HttpStatus.NOT_FOUND, "만료된 지원서입니다."),

// 405 METHOD_NOT_ALLOWED
METHOD_NOT_ALLOWED_EXCEPTION(HttpStatus.METHOD_NOT_ALLOWED, "지원하지 않는 메소드 입니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ public enum SuccessCode {
CREATE_MODEL_APPLICATION_SUCCESS(HttpStatus.OK, "모델 지원서 생성 성공입니다."),
USER_WITHDRAW_SUCCESS(HttpStatus.OK, "회원 탈퇴 성공입니다."),
GET_PRE_SIGNED_URL_SUCCESS(HttpStatus.OK, "제안서 다운로드 url 생성 성공"),
GET_APPLICATION_IMG_URL_SUCCESS(HttpStatus.OK, "지원서 이미지 url 가져오기 성공");
GET_APPLICATION_IMG_URL_SUCCESS(HttpStatus.OK, "지원서 이미지 url 가져오기 성공"),
CHECK_VALID_APPLICATION_SUCCESS(HttpStatus.OK, "유효한 지원서 입니다."),
APPLICATION_DELETE_SUCCESS(HttpStatus.OK, "지원서 삭제하기 성공");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import com.moddy.server.common.dto.ErrorResponse;
import com.moddy.server.common.dto.SuccessNonDataResponse;
import com.moddy.server.common.dto.SuccessResponse;
import com.moddy.server.common.exception.enums.SuccessCode;
import com.moddy.server.config.resolver.user.UserId;
import com.moddy.server.controller.application.dto.response.ApplicationExpireDateResponse;
import com.moddy.server.controller.model.dto.request.ModelApplicationRequest;
import com.moddy.server.service.application.HairModelApplicationRegisterService;
import com.moddy.server.service.offer.HairServiceOfferRegisterService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -17,6 +20,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
Expand All @@ -30,21 +34,36 @@
public class ApplicationRegisterController {

private final HairModelApplicationRegisterService hairModelApplicationRegisterService;
private final HairServiceOfferRegisterService hairServiceOfferRegisterService;

@Operation(summary = "[JWT] 모델 지원서 작성", description = "모델 지원서 작성 API입니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "모델 지원서 작성 성공"),
@ApiResponse(responseCode = "200", description = "모델 지원서 작성 성공", content = @Content(schema = @Schema(implementation = ApplicationExpireDateResponse.class))),
@ApiResponse(responseCode = "400", description = "인증 오류 입니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류 입니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
})
@SecurityRequirement(name = "JWT Auth")
@PostMapping(consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
public SuccessNonDataResponse submitModelApplication(
public SuccessResponse<ApplicationExpireDateResponse> submitModelApplication(
@Parameter(hidden = true) @UserId Long modelId,
@RequestPart(value = "modelImgUrl", required = false) MultipartFile modelImgUrl,
@RequestPart(value = "applicationCaptureImgUrl", required = false) MultipartFile applicationCaptureImgUrl,
@RequestPart(value = "applicationInfo") @Valid ModelApplicationRequest applicationInfo) {
hairModelApplicationRegisterService.postApplication(modelId, modelImgUrl, applicationCaptureImgUrl, applicationInfo);
return SuccessNonDataResponse.success(SuccessCode.CREATE_MODEL_APPLICATION_SUCCESS);
return SuccessResponse.success(SuccessCode.CREATE_MODEL_APPLICATION_SUCCESS, hairModelApplicationRegisterService.postApplication(modelId, modelImgUrl, applicationCaptureImgUrl, applicationInfo));
}

@DeleteMapping
@Operation(summary = "[JWT] 지원서 삭제하기 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "지원서 삭제하기 성공입니다."),
@ApiResponse(responseCode = "401", description = "토큰이 만료되었습니다. 다시 로그인 해주세요.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "404", description = "해당 유저는 존재하지 않습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류입니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
@SecurityRequirement(name = "JWT Auth")
public SuccessNonDataResponse deleteApplication(@Parameter(hidden = true) @UserId final Long modelId) {
hairServiceOfferRegisterService.deleteModelHairServiceOfferInfos(modelId);
hairModelApplicationRegisterService.deleteModelApplications(modelId);
return SuccessNonDataResponse.success(SuccessCode.APPLICATION_DELETE_SUCCESS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.moddy.server.common.dto.SuccessResponse;
import com.moddy.server.common.exception.enums.SuccessCode;
import com.moddy.server.config.resolver.user.UserId;
import com.moddy.server.controller.application.dto.response.ApplicationIdResponse;
import com.moddy.server.controller.designer.dto.response.ApplicationDetailInfoResponse;
import com.moddy.server.controller.designer.dto.response.ApplicationInfoResponse;
import com.moddy.server.controller.designer.dto.response.DesignerMainResponse;
Expand Down Expand Up @@ -94,7 +95,9 @@ public SuccessResponse<ApplicationDetailInfoResponse> getApplicationDetailInfo(
applicationDto.recordResponseList(),
applicationDto.hairDetail(),
hairServiceOfferRetrieveService.getIsSendStatus(applicationId, designerId),
applicationDto.instgramId()
applicationDto.instgramId(),
applicationDto.createdDate(),
applicationDto.expiredDate()
);

ModelInfoResponse modelInfoResponse = new ModelInfoResponse(
Expand Down Expand Up @@ -124,4 +127,19 @@ public SuccessResponse<ApplicationImgUrlResponse> getApplicationImgUrlOpenChat(
@PathVariable(value = "applicationId") Long applicationId) {
return SuccessResponse.success(SuccessCode.GET_APPLICATION_IMG_URL_SUCCESS, hairModelApplicationRetrieveService.getApplicationImgUrl(applicationId));
}

@Operation(summary = "[JWT] 나의 지원서 유무 확인하기", description = "마이페이지에서 유효한 지원서 유무를 확인하는 API입니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "유효한 지원서 존재여부 조회 성공", content = @Content(schema = @Schema(implementation = ApplicationIdResponse.class))),
@ApiResponse(responseCode = "401", description = "인증 오류 입니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "404", description = "해당 지원서를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류 입니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
})
@GetMapping("/check")
@SecurityRequirement(name = "JWT Auth")
public SuccessResponse<ApplicationIdResponse> getValidApplicationStatus(
@Parameter(hidden = true) @UserId Long modelId) {
return SuccessResponse.success(SuccessCode.CHECK_VALID_APPLICATION_SUCCESS, hairModelApplicationRetrieveService.checkValidApplicationStatus(modelId));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.moddy.server.controller.application.dto.response;

public record ApplicationExpireDateResponse(
String expirationDate
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.moddy.server.controller.application.dto.response;

public record ApplicationIdResponse(
Long applicationId
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public record ApplicationInfoResponse(
List<HairRecordResponse> hairServiceRecords,
String hairDetail,
boolean isSend,
String instagramId
String instagramId,
String createdDate,
String expiredDate
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public record ApplicationDto(
List<String> preferHairStyleList,
List<HairRecordResponse> recordResponseList,
String hairDetail,
String instgramId
String instgramId,
String createdDate,
String expiredDate
) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.moddy.server.controller.model.dto.response;

import com.moddy.server.domain.prefer_offer_condition.OfferCondition;
import com.moddy.server.domain.hair_service_offer.OfferStatus;

import java.util.List;

public record OfferResponse(
Expand All @@ -9,6 +10,6 @@ public record OfferResponse(
String name,
String shopName,
List<String> conditions,
boolean isClicked
OfferStatus status
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import com.moddy.server.domain.BaseTimeEntity;
import com.moddy.server.domain.model.Model;
import com.moddy.server.domain.user.User;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.time.LocalDate;

@Entity
@Getter
Expand Down Expand Up @@ -48,4 +48,20 @@ public HairModelApplication(Model model, HairLength hairLength, String hairDetai
this.instagramId = instagramId;
this.applicationCaptureUrl = applicationCaptureUrl;
}

public LocalDate getCreatedDate(){
LocalDate createdDate = getCreatedAt().toLocalDate();
return createdDate;
}
public LocalDate getExpiredDate(){
LocalDate expiredDate = getCreatedAt().plusDays(7).toLocalDate();
return expiredDate;
}

public boolean isExpired() {
LocalDate expiredDate = getCreatedAt().plusDays(7).toLocalDate();
LocalDate currentDate = LocalDate.now();

return currentDate.isAfter(expiredDate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
public interface HairModelApplicationJpaRepository extends JpaRepository<HairModelApplication, Long> {
Boolean existsByModelId(Long modelId);

Optional<HairModelApplication> findByModelId(Long modelId);
Optional<HairModelApplication> findFirstByModelIdOrderByCreatedAtDesc(Long modelId);

Page<HairModelApplication> findAll(Pageable pageable);

List<HairModelApplication> findAllByModelId(Long modelId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import jakarta.validation.constraints.NotNull;
import lombok.*;

import java.time.LocalDateTime;

@Entity
@Getter
@Builder
Expand Down Expand Up @@ -50,11 +48,8 @@ public HairServiceOffer(HairModelApplication hairModelApplication, Model model,
this.isClicked = isClicked;
}

public void agreeOfferToModel(){
this.isModelAgree = true;
}
public void agreeOfferToModel() { this.isModelAgree = true; }

public void updateClickStatus() { this.isClicked = true; }


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.moddy.server.domain.hair_service_offer;

import lombok.Getter;

@Getter
public enum OfferStatus {
EXPIRED, UNCLICKED, CLICKED
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.moddy.server.common.exception.enums.ErrorCode;
import com.moddy.server.common.exception.model.NotFoundException;
import com.moddy.server.controller.application.dto.response.ApplicationExpireDateResponse;
import com.moddy.server.controller.model.dto.request.ModelApplicationRequest;
import com.moddy.server.domain.hair_model_application.HairModelApplication;
import com.moddy.server.domain.hair_model_application.repository.HairModelApplicationJpaRepository;
Expand All @@ -17,6 +18,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
Expand All @@ -27,9 +29,10 @@ public class HairModelApplicationRegisterService {
private final PreferHairStyleJpaRepository preferHairStyleJpaRepository;
private final HairServiceRecordJpaRepository hairServiceRecordJpaRepository;
private final ModelJpaRepository modelJpaRepository;
private static final String DATE_FORMAT = "yyyy. MM. dd";

@Transactional
public void postApplication(final Long modelId, final MultipartFile modelImgUrl, final MultipartFile applicationCaptureImgUrl, final ModelApplicationRequest applicationInfo) {
public ApplicationExpireDateResponse postApplication(final Long modelId, final MultipartFile modelImgUrl, final MultipartFile applicationCaptureImgUrl, final ModelApplicationRequest applicationInfo) {
Model model = modelJpaRepository.findById(modelId).orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_MODEL_INFO));
String s3ModelImgUrl = s3Service.uploadProfileImage(modelImgUrl, model.getRole());
String s3applicationCaptureImgUrl = s3Service.uploadApplicationImage(applicationCaptureImgUrl);
Expand All @@ -39,8 +42,11 @@ public void postApplication(final Long modelId, final MultipartFile modelImgUrl,

savePreferHairStyles(applicationInfo, hairModelApplication);
saveHairServiceRecords(applicationInfo, hairModelApplication);

return new ApplicationExpireDateResponse(hairModelApplication.getCreatedDate().format(DateTimeFormatter.ofPattern(DATE_FORMAT)) + " - " + hairModelApplication.getExpiredDate().format(DateTimeFormatter.ofPattern(DATE_FORMAT)));
}

@Transactional
public void deleteModelApplications(final Long modelId) {
List<HairModelApplication> hairModelApplications = hairModelApplicationJpaRepository.findAllByModelId(modelId);
hairModelApplications.forEach(hairModelApplication -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.moddy.server.common.exception.enums.ErrorCode;
import com.moddy.server.common.exception.model.NotFoundException;
import com.moddy.server.controller.application.dto.response.ApplicationIdResponse;
import com.moddy.server.controller.application.dto.response.ApplicationInfoDetailResponse;
import com.moddy.server.controller.designer.dto.response.DesignerMainResponse;
import com.moddy.server.controller.designer.dto.response.DownloadUrlResponseDto;
Expand All @@ -16,12 +17,12 @@
import com.moddy.server.domain.hair_service_record.repository.HairServiceRecordJpaRepository;
import com.moddy.server.domain.prefer_hair_style.PreferHairStyle;
import com.moddy.server.domain.prefer_hair_style.repository.PreferHairStyleJpaRepository;
import com.moddy.server.domain.prefer_region.repository.PreferRegionJpaRepository;
import com.moddy.server.external.s3.S3Service;
import com.moddy.server.service.designer.DesignerRetrieveService;
import com.moddy.server.service.model.ModelRetrieveService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
Expand All @@ -30,6 +31,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.time.format.DateTimeFormatter;

@Service
@RequiredArgsConstructor
Expand All @@ -42,6 +44,7 @@ public class HairModelApplicationRetrieveService {
private final S3Service s3Service;
private final PreferHairStyleJpaRepository preferHairStyleJpaRepository;
private final HairServiceRecordJpaRepository hairServiceRecordJpaRepository;
private static final String DATE_FORMAT = "yyyy. MM. dd.";

public DesignerMainResponse getDesignerMainInfo(final Long designerId, final int page, final int size) {

Expand Down Expand Up @@ -96,7 +99,17 @@ public ApplicationDto getApplicationDetailInfo(final Long applicationId) {
preferhairStyleList,
recordResponseList,
hairModelApplication.getHairDetail(),
hairModelApplication.getInstagramId());
hairModelApplication.getInstagramId(),
hairModelApplication.getCreatedDate().format(DateTimeFormatter.ofPattern(DATE_FORMAT)),
hairModelApplication.getExpiredDate().format(DateTimeFormatter.ofPattern(DATE_FORMAT)));
}

public ApplicationIdResponse checkValidApplicationStatus(final Long modelId){
HairModelApplication hairModelApplication = hairModelApplicationJpaRepository.findFirstByModelIdOrderByCreatedAtDesc(modelId).orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_APPLICATION_EXCEPTION));

if(hairModelApplication.isExpired()) throw new NotFoundException(ErrorCode.NOT_FOUND_VALID_APPLICATION_EXCEPTION);

return new ApplicationIdResponse(hairModelApplication.getId());
}

public boolean fetchModelApplyStatus(final Long modelId) {
Expand All @@ -115,11 +128,25 @@ public DownloadUrlResponseDto getApplicationCaptureDownloadUrl(final Long applic
return new DownloadUrlResponseDto(applicationDownloadUrl);
}

public boolean getApplicationExpiredStatus(final Long applicationId){
final HairModelApplication hairModelApplication = hairModelApplicationJpaRepository.findById(applicationId)
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_APPLICATION_EXCEPTION));
return hairModelApplication.isExpired();
}

private Page<HairModelApplication> findApplicationsByPaging(final int page, final int size) {
PageRequest pageRequest = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "id"));
Page<HairModelApplication> applicationPage = hairModelApplicationJpaRepository.findAll(pageRequest);

return applicationPage;
Page<HairModelApplication> nonExpiredApplications = applicationPage
.stream()
.filter(application -> !application.isExpired())
.collect(Collectors.collectingAndThen(
Collectors.toList(),
list -> new PageImpl<>(list, pageRequest, list.size())
));

return nonExpiredApplications;
}

private String getApplicationHairDetail(final Long applicationId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class HairServiceOfferRegisterService {
private final HairModelApplicationJpaRepository hairModelApplicationJpaRepository;
private final SmsUtil smsUtil;

@Transactional
public void deleteModelHairServiceOfferInfos(final Long modelId) {
final List<HairServiceOffer> hairServiceOffers = hairServiceOfferJpaRepository.findAllByModelId(modelId);
hairServiceOffers.forEach(hairServiceOffer -> {
Expand Down
Loading

0 comments on commit 924e5c0

Please sign in to comment.