Skip to content

Commit

Permalink
Merge pull request #95 from 1jeongg/feature/add-chat-wj
Browse files Browse the repository at this point in the history
채팅방 생성 API 수정 및 테스트 코드 추가
  • Loading branch information
chaee813 authored Oct 14, 2023
2 parents e3fea4b + 4580e4a commit 57c525d
Show file tree
Hide file tree
Showing 20 changed files with 737 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,55 @@
// 모든 에러의 메시지를 관리
@RequiredArgsConstructor
public enum BaseException {
// user 관련
USER_NOT_FOUND("서비스를 탈퇴했거나 가입하지 않은 유저의 요청입니다.", 404),
ACCESS_TOKEN_EXPIRED("access-token이 만료되었습니다. refresh-token 으로 다시 요청해주세요.", 403),
ALL_TOKEN_EXPIRED("모든 토큰이 만료되었습니다. 다시 로그인 해야합니다.", 401),
TOKEN_NOT_FOUND("토큰을 찾을 수 없습니다.", 404),
TOKEN_NOT_VALID("로그인 토큰이 유효하지 않습니다. 다시 로그인 해주세요", 403),
INVALID_TOKEN_ACCESS_DETECTED("올바르지 않은 접근입니다. 다시 로그인 해주세요.", 403),
TOKEN_REFRESH_FORBIDDEN("토큰을 갱신할 수 없습니다.", 403),
PLANNER_NOT_FOUND("서비스를 탈퇴하거나 가입하지 않은 플래너입니다", 404),
USER_EMAIL_EXIST("동일한 이메일이 존재합니다.", 400),
USER_EMAIL_NOT_FOUND("이메일을 찾을 수 없습니다 : ", 400),
USER_ROLE_WRONG("role은 플래너, 또는 예비 부부만 가능합니다.", 400),
USER_PASSWORD_WRONG("패스워드를 잘못 입력하셨습니다",400),
USER_PASSWORD_NOT_SAME("패스워드1과 패스워드2는 동일해야 합니다.: ", 400),
USER_ALREADY_PREMIUM("이미 프리미엄 회원입니다.", 400),
USER_TOKEN_WRONG("잘못된 토큰입니다", 401),
PAYMENT_WRONG_INFORMATION("잘못된 결제 정보입니다.", 404),
USER_UNEXPECTED_ERROR("[User] 예상치 못한 문제가 발생했습니다.", 500),

// token 관련
ACCESS_TOKEN_EXPIRED("access-token이 만료되었습니다. refresh-token 으로 다시 요청해주세요.", 403),
ALL_TOKEN_EXPIRED("모든 토큰이 만료되었습니다. 다시 로그인 해야합니다.", 401),
TOKEN_NOT_FOUND("토큰을 찾을 수 없습니다.", 404),
TOKEN_NOT_VALID("로그인 토큰이 유효하지 않습니다. 다시 로그인 해주세요", 403),
TOKEN_REFRESH_FORBIDDEN("토큰을 갱신할 수 없습니다.", 403),
INVALID_TOKEN_ACCESS_DETECTED("올바르지 않은 접근입니다. 다시 로그인 해주세요.", 403),

// 결제 관련
PAYMENT_WRONG_INFORMATION("잘못된 결제 정보입니다.", 404),

//포트폴리오 관련
PORTFOLIO_NOT_FOUND("해당하는 플래너의 포트폴리오가 삭제되었거나 존재하지 않습니다.", 404),
PORTFOLIO_ALREADY_EXIST("해당 플래너의 포트폴리오가 이미 존재합니다. 포트폴리오는 플래너당 하나만 생성할 수 있습니다.", 400),
PORTFOLIO_IMAGE_NOT_FOUND("포트폴리오 이미지를 불러올 수 없습니다.", 404),
PORTFOLIO_IMAGE_CREATE_ERROR("포트폴리오 이미지 생성 과정에서 오류가 발생했습니다.", 500),
PORTFOLIO_IMAGE_ENCODING_ERROR("이미지 인코딩 과정에서 오류가 발생했습니다.", 500),
PORTFOLIO_CREATE_DIRECTORY_ERROR("포트폴리오 폴더 생성 과정에서 오류가 발생했습니다.", 500),
PORTFOLIO_CLEAN_DIRECTORY_ERROR("포트폴리오 폴더를 비우는 과정에서 오류가 발생했습니다.", 500),
PERMISSION_DENIED_METHOD_ACCESS("사용할 수 없는 기능입니다.", 403),
DATABASE_ERROR("데이터베이스 에러입니다", 500),

// 견적서 관련
QUOTATIONS_NOT_ALL_CONFIRMED("확정되지 않은 견적서가 있습니다.",400),
NO_QUOTATION_TO_CONFIRM("확정할 견적서가 없습니다",400),
NOT_CONFIRMED_ALL_QUOTATIONS("견적서 전체 확정을 해야 합니다.", 400),
MATCHING_NOT_FOUND("매칭 내역을 찾을 수 없습니다.", 404),
QUOTATION_NOTHING_TO_CONFIRM("확정할 견적서가 없습니다",400),
QUOTATION_NOT_CONFIRMED_ALL("견적서 전체 확정을 해야 합니다.", 400),
QUOTATION_NOT_FOUND("해당 견적서를 찾을 수 없습니다.", 404),
QUOTATION_CHANGE_DENIED("견적서가 이미 확정되어 수정할 수 없습니다.", 403),
QUOTATION_ACCESS_DENIED("해당 매칭 내역에 접근할 수 없습니다.", 403),
QUOTATION_ALREADY_CONFIRMED("견적서가 확정된 상태입니다.", 403),
MATCHING_ALREADY_CONFIRMED("전체 확정되어 견적서를 추가할 수 없습니다.", 403);

// 매칭 관련
MATCHING_ALREADY_CONFIRMED("전체 확정되어 견적서를 추가할 수 없습니다.", 403),
MATCHING_NOT_FOUND("매칭 내역을 찾을 수 없습니다.", 404),
MATCHING_ALREADY_EXIST("이미 존재하는 매칭입니다.", 400),

// 공통
PERMISSION_DENIED_METHOD_ACCESS("사용할 수 없는 기능입니다.", 403),
DATABASE_ERROR("데이터베이스 에러입니다", 500),
;

@Getter
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
} catch (TokenExpiredException tee) {
log.error("access token 만료됨");
// access token 만 만료 시에는 403 에러 전달
throw new ForbiddenException(BaseException.ACCESS_TOKEN_EXPIRED.getMessage());
//throw new ForbiddenException(BaseException.ACCESS_TOKEN_EXPIRED.getMessage());
} catch (JWTDecodeException jde) {
log.error("잘못된 access token");
} catch (Exception e){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
filterResponseUtils.notFound(response, notFoundException);
}
catch (JWTCreationException | JWTVerificationException e) {
filterResponseUtils.unAuthorized(response, new UnauthorizedException(BaseException.USER_TOKEN_WRONG));
filterResponseUtils.unAuthorized(response, new UnauthorizedException(BaseException.TOKEN_NOT_FOUND));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.requestMatchers(
new AntPathRequestMatcher("/user/**"),
new AntPathRequestMatcher("/portfolios/**"),
new AntPathRequestMatcher("/myportfolio"),
new AntPathRequestMatcher("/chat/**"),
new AntPathRequestMatcher("/quotations/**"),
new AntPathRequestMatcher("/payments/**")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ public interface MatchJPARepository extends JpaRepository<Match, Long> {

@Query("select m from Match m where m.planner = :planner and m.confirmedAt != null order by m.confirmedAt desc limit 10")
List<Match> findLatestTenByPlanner(@Param("planner") Planner planner);

@Query("select m from Match m where m.planner = :planner and m.couple = :couple")
List<Match> findByCoupleAndPlanner(@Param("couple") Couple couple, @Param("planner") Planner plannerId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.kakao.sunsuwedding.match;

import com.kakao.sunsuwedding.user.couple.Couple;
import com.kakao.sunsuwedding.user.planner.Planner;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;

public class MatchResponse {

@Getter @Setter
public static class ChatByIdDTO {
Long chatId;

public ChatByIdDTO(Match match){
this.chatId = match.getId();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public class MatchRestController {
public ResponseEntity<?> addChat(
@AuthenticationPrincipal CustomUserDetails userDetails,
@Valid @RequestBody MatchRequest.AddMatchDTO request) {
matchService.addChat(userDetails.getInfo(), request);
return ResponseEntity.ok().body(ApiUtils.success(null));
MatchResponse.ChatByIdDTO response = matchService.addChat(userDetails.getInfo(), request);
return ResponseEntity.ok().body(ApiUtils.success(response));
}

// Match Delete : isActive 필드 false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void deleteChat(Pair<String, Long> info, Long matchId) {
List<Quotation> quotations = quotationJPARepository.findAllByMatch(match);
// 견적서 존재하는데 전체 확정이 되지 않은 경우, 채팅방 삭제 불가
if ((!quotations.isEmpty()) && (match.getStatus().equals(MatchStatus.UNCONFIRMED))) {
throw new BadRequestException(BaseException.NOT_CONFIRMED_ALL_QUOTATIONS);
throw new BadRequestException(BaseException.QUOTATION_NOT_CONFIRMED_ALL);
}
// 전체확정 됐거나, 견적서가 없는 경우 채팅방 삭제
matchJPARepository.delete(match);
Expand All @@ -77,7 +77,7 @@ public void deleteChat(Pair<String, Long> info, Long matchId) {
private Pair<Boolean, Long> isAllConfirmed(Match match) {
List<Quotation> quotations = quotationJPARepository.findAllByMatch(match);
if (quotations.isEmpty()) {
throw new BadRequestException(BaseException.NO_QUOTATION_TO_CONFIRM);
throw new BadRequestException(BaseException.QUOTATION_NOTHING_TO_CONFIRM);
}
else {
// 모든 견적서 확정 됐는지 여부 구하기
Expand All @@ -91,17 +91,27 @@ private Pair<Boolean, Long> isAllConfirmed(Match match) {
}
}

public void addChat(Pair<String, Long> user, MatchRequest.AddMatchDTO requestDTO) {
@Transactional
public MatchResponse.ChatByIdDTO addChat(Pair<String, Long> user, MatchRequest.AddMatchDTO requestDTO) {

Long coupleId = user.getSecond();
Long plannerId = requestDTO.getPlannerId();

Couple couple = coupleJPARepository.findById(coupleId).orElseThrow(
() -> new NotFoundException(BaseException.USER_NOT_FOUND.getMessage() + " couple")
);
Planner planner = plannerJPARepository.findById(plannerId).orElseThrow(
() -> new NotFoundException(BaseException.USER_NOT_FOUND.getMessage() + " planner")
() -> new NotFoundException(BaseException.PLANNER_NOT_FOUND.getMessage() + " planner")
);
matchJPARepository.save(requestDTO.toMatchEntity(couple, planner));
List<Match> matches = matchJPARepository.findByCoupleAndPlanner(couple, planner);

// 플래너, 유저 매칭은 최대 한 개까지만 생성 가능
if (!matches.isEmpty()){
throw new BadRequestException(BaseException.MATCHING_ALREADY_EXIST);
}
Match match = matchJPARepository.save(requestDTO.toMatchEntity(couple, planner));

return new MatchResponse.ChatByIdDTO(match);
}

private void permissionCheck(Pair<String, Long> info, Match match) {
Expand Down
16 changes: 12 additions & 4 deletions sunsu-wedding/src/main/resources/db/teardown.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
SET REFERENTIAL_INTEGRITY FALSE;
truncate table user_tb;
truncate table token_tb;
truncate table portfolio_tb;
truncate table imageitem_tb;
truncate table priceitem_tb;
Expand All @@ -8,7 +9,7 @@ truncate table quotation_tb;
SET REFERENTIAL_INTEGRITY TRUE;

-- planner 비밀번호 : planner1234!
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('2','[email protected]','{bcrypt}$2a$10$89SwVjyXVDhK3GFcN4c8Bu3kQlNiWqjaTvgiXaCi9D/1eWx2w7CBa','planner','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','NORMAL', 'true', 'planner');
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`, `order_id`, `payed_amount`) VALUES ('2','[email protected]','{bcrypt}$2a$10$89SwVjyXVDhK3GFcN4c8Bu3kQlNiWqjaTvgiXaCi9D/1eWx2w7CBa','planner','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','NORMAL', 'true', 'planner', 'orderId', '5000');
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('3','[email protected]','{bcrypt}$2a$10$89SwVjyXVDhK3GFcN4c8Bu3kQlNiWqjaTvgiXaCi9D/1eWx2w7CBa','planner2','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','PREMIUM', 'true', 'planner');
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('6','[email protected]','{bcrypt}$2a$10$89SwVjyXVDhK3GFcN4c8Bu3kQlNiWqjaTvgiXaCi9D/1eWx2w7CBa','planner5','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','PREMIUM', 'true', 'planner');
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('7','[email protected]','{bcrypt}$2a$10$89SwVjyXVDhK3GFcN4c8Bu3kQlNiWqjaTvgiXaCi9D/1eWx2w7CBa','planner6','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','PREMIUM', 'true', 'planner');
Expand All @@ -26,6 +27,11 @@ INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,
-- couple 비밀번호 : couple1234!
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('4','[email protected]','{bcrypt}$2a$10$bKgX34po45/xYw1Dd8C81OYW4dkkVQV5lHd7a.06m1gBX689XERA.','couple','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','NORMAL', 'true', 'couple');
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('5','[email protected]','{bcrypt}$2a$10$bKgX34po45/xYw1Dd8C81OYW4dkkVQV5lHd7a.06m1gBX689XERA.','couple2','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','PREMIUM', 'true', 'couple');
INSERT INTO user_tb (`id`,`email`,`password`,`username`,`created_at`,`payed_at`,`grade`, `is_active`, `dtype`) VALUES ('18','[email protected]','{bcrypt}$2a$10$bKgX34po45/xYw1Dd8C81OYW4dkkVQV5lHd7a.06m1gBX689XERA.','couple3','2023-09-16 01:06:55.00','2023-09-20 15:26:55.00','PREMIUM', 'true', 'couple');

-- token
--INSERT INTO token_tb (`id`,`user_id`,`access_token`,`refresh_token`) VALUES ('2', '3','accesToken1', 'refreshToken1');
--INSERT INTO token_tb (`id`,`user_id`,`access_token`,`refresh_token`) VALUES ('3', '4','accesToken2', 'refreshToken2');

INSERT INTO portfolio_tb (`id`, `planner_id`, `title`, `description`, `location`, `career`, `partner_company`, `total_price`, `contract_count`, `avg_price`, `min_price`, `max_price`, `created_at`) VALUES ('1', '2', 'test1', 'test1', '부산', 'none', 'none', '1000000', '10', '1000000', '1000000', '1000000', '2023-09-15 15:26:55.00');
INSERT INTO portfolio_tb (`id`, `planner_id`, `title`, `description`, `location`, `career`, `partner_company`, `total_price`, `contract_count`, `avg_price`, `min_price`, `max_price`, `created_at`) VALUES ('2', '3', 'test2', 'test2', '부산', 'none', 'none', '2000000', '20', '2000000', '2000000', '2000000', '2023-09-22 15:26:55.00');
Expand Down Expand Up @@ -61,14 +67,16 @@ INSERT INTO imageitem_tb (`id`, `portfolio_id`, `origin_file_name`, `file_path`,
INSERT INTO imageitem_tb (`id`, `portfolio_id`, `origin_file_name`, `file_path`, `file_size`, `thumbnail`) VALUES ('9', '2', '2-4.jpg', '/Users/seokjun/Downloads/images/', '522499', 'false');
INSERT INTO imageitem_tb (`id`, `portfolio_id`, `origin_file_name`, `file_path`, `file_size`, `thumbnail`) VALUES ('10', '2', '2-5.jpg', '/Users/seokjun/Downloads/images/', '522499', 'false');

INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('1', '2', '4', 'CONFIRMED', '1000000', '1000000', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
--INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('1', '2', '4', 'CONFIRMED', '1000000', '1000000', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('2', '2', '4', 'UNCONFIRMED', '1000000', '0', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('3', '2', '5', 'UNCONFIRMED', '1000000', '0', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('4', '2', '4', 'UNCONFIRMED', '1000000', '0', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('5', '3', '4', 'UNCONFIRMED', '1000000', '0', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO match_tb (`id`, `planner_id`, `couple_id`, `status`, `price`, `confirmed_price`, `confirmed_at`, `created_at`, `is_active`) VALUES ('6', '2', '4', 'CONFIRMED', '1000000', '1000000', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');


INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('1', '1', 'test', '1000000', 'abc', 'asdf', 'CONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('2', '1', 'test2', '1000000', 'abc2', 'asdf2', 'CONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('1', '6', 'test', '1000000', 'abc', 'asdf', 'CONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('2', '6', 'test2', '1000000', 'abc2', 'asdf2', 'CONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('3', '2', 'test', '1000000', 'abc', 'asdf', 'UNCONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('4', '2', 'test2', '1000000', 'abc2', 'asdf2', 'UNCONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
INSERT INTO quotation_tb (`id`, `match_id`, `title`, `price`, `company`, `description`, `status`, `modified_at`, `created_at`, `is_active`) VALUES ('5', '3', 'test2', '1000000', 'abc2', 'asdf2', 'UNCONFIRMED', '2023-10-08 08:30:12.00', '2023-10-08 08:30:12.00', 'true');
Expand Down
Loading

0 comments on commit 57c525d

Please sign in to comment.