Skip to content

Commit

Permalink
Merge pull request #10 from gutanbug/feat/trade
Browse files Browse the repository at this point in the history
feat: 단국거래 게시판 서비스 로직 추가 및 강제 회원가입 수정
  • Loading branch information
gutanbug authored Dec 18, 2023
2 parents 8fa0394 + e2d6a17 commit 8da876b
Show file tree
Hide file tree
Showing 11 changed files with 321 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import com.dku.council.domain.user.exception.AlreadyPhoneException;
import com.dku.council.domain.user.exception.AlreadyStudentIdException;
import com.dku.council.domain.user.exception.MajorNotFoundException;
import com.dku.council.domain.user.model.UserStatus;
import com.dku.council.domain.user.model.entity.Major;
import com.dku.council.domain.user.model.entity.User;
import com.dku.council.domain.user.repository.MajorRepository;
import com.dku.council.domain.user.repository.UserRepository;
import com.dku.council.global.auth.role.UserRole;
import com.dku.council.global.error.exception.UserNotFoundException;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -55,7 +57,9 @@ public void addUser(@RequestParam String studentId,
@RequestParam String nickname,
@RequestParam Long majorId,
@RequestParam Integer yearOfAdmission,
@RequestParam String phone) {
@RequestParam String phone,
@RequestParam String age,
@RequestParam String gender) {
if (userRepository.findByStudentId(studentId).isPresent()) {
throw new AlreadyStudentIdException();
}
Expand All @@ -78,10 +82,14 @@ public void addUser(@RequestParam String studentId,
.password(encryptedPassword)
.name(name)
.nickname(nickname)
.age(age)
.gender(gender)
.major(major)
.yearOfAdmission(yearOfAdmission)
.academicStatus("재학")
.phone(phone)
.status(UserStatus.ACTIVE)
.role(UserRole.USER)
.build();

userRepository.save(user);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.dku.council.domain.with_dankook.controller;

import com.dku.council.domain.post.model.dto.response.ResponsePage;
import com.dku.council.domain.with_dankook.model.dto.list.SummarizedTradeDto;
import com.dku.council.domain.with_dankook.model.dto.request.RequestCreateTradeDto;
import com.dku.council.domain.with_dankook.service.TradeService;
import com.dku.council.global.auth.jwt.AppAuthentication;
import com.dku.council.global.auth.role.UserAuth;
import com.dku.council.global.model.dto.ResponseIdDto;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

Expand All @@ -23,14 +25,42 @@ public class TradeController {

private final TradeService tradeService;

// /**
// * 단국 거래 게시글 작성
// */
// @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
// @UserAuth
// public ResponseIdDto create(AppAuthentication auth,
// @Valid @ModelAttribute RequestCreateTradeDto dto) {
// Long id = tradeService.create(auth.getUserId(), dto);
// return new ResponseIdDto(id);
// }
/**
* 단국 거래 게시글 목록 조회
*
* @param keyword 제목이나 내용에 포함된 검색어. 지정하지 않으면 모든 게시글 조회.
* @param bodySize 게시글 본문 길이. (글자 단위) 지정하지 않으면 50 글자.
* @param pageable 페이징 size, sort, page
* @return 페이징된 단국 거래 게시판 목록
*/
@GetMapping
public ResponsePage<SummarizedTradeDto> list(@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "50") int bodySize,
@ParameterObject Pageable pageable) {
Page<SummarizedTradeDto> list = tradeService.list(keyword, pageable, bodySize);
return new ResponsePage<>(list);
}

/**
* 단국 거래 게시글 등록
*/
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@UserAuth
public ResponseIdDto create(AppAuthentication auth,
@Valid @ModelAttribute RequestCreateTradeDto dto) {
Long id = tradeService.create(auth.getUserId(), dto);
return new ResponseIdDto(id);
}

/**
* 단국 거래 게시글 삭제
*
* @param auth 사용자 인증정보
* @param id 삭제할 게시글 id
*/
@DeleteMapping("/{id}")
@UserAuth
public void delete(AppAuthentication auth, @PathVariable Long id) {
tradeService.delete(id, auth.getUserId(), auth.isAdmin());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.dku.council.domain.with_dankook.model.dto;

import com.dku.council.domain.with_dankook.model.entity.TradeImage;
import com.dku.council.infra.nhn.s3.service.ObjectUploadContext;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.http.MediaType;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class TradeImageDto {

@Schema(description = "이미지 아이디", example = "1")
private final Long id;

@Schema(description = "이미지 url", example = "http://1.2.3.4/1ddee68d-6afb-48d0-9cb6-04a8d8fea4ae.png")
private final String url;

@Schema(description = "썸네일 이미지 url (없으면 기본 이미지)", example = "http://1.2.3.4/thumb-1ddee68d-6afb-48d0-9cb6-04a8d8fea4ae.png")
private final String thumbnailUrl;

@Schema(description = "원본이미지 파일 이름", example = "my_image.png")
private final String originalName;

@Schema(description = "이미지 파일 타입", example = "image/jpeg")
private final String mimeType;

public TradeImageDto(ObjectUploadContext context, TradeImage image) {
this.id = image.getId();
this.url = context.getImageUrl(image.getFileId());
this.thumbnailUrl = context.getThumbnailUrl(image.getThumbnailId());
this.originalName = image.getFileName();

String fileMimeType = image.getMimeType();
this.mimeType = Objects.requireNonNullElse(fileMimeType, MediaType.APPLICATION_OCTET_STREAM_VALUE);
}

public static List<TradeImageDto> listOf(ObjectUploadContext context, List<TradeImage> entities) {
List<TradeImage> result = new ArrayList<>();

for (TradeImage entity : entities) {
if (entity.getThumbnailId() != null) {
result.add(entity);
}
}
return result.stream()
.map(image -> new TradeImageDto(context, image))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.dku.council.domain.with_dankook.model.dto.list;

import com.dku.council.domain.with_dankook.model.dto.TradeImageDto;
import com.dku.council.domain.with_dankook.model.entity.type.Trade;
import com.dku.council.infra.nhn.s3.service.ObjectUploadContext;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

import java.util.List;

@Getter
public class SummarizedTradeDto extends SummarizedWithDankookDto{

@Schema(description = "제목", example = "게시글 제목")
private final String title;

@Schema(description = "가격", example = "10000")
private final int price;

@Schema(description = "내용", example = "게시글 본문")
private final String content;

@Schema(description = "거래 장소", example = "단국대학교 정문")
private final String tradePlace;

@Schema(description = "이미지 목록")
private final List<TradeImageDto> images;

public SummarizedTradeDto(SummarizedWithDankookDto dto, Trade trade, ObjectUploadContext context){
super(dto);
this.title = trade.getTitle();
this.price = trade.getPrice();
this.content = trade.getContent();
this.tradePlace = trade.getTradePlace();
this.images = TradeImageDto.listOf(context, trade.getImages());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.dku.council.domain.with_dankook.model.dto.list;

import com.dku.council.domain.with_dankook.model.entity.WithDankook;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
public class SummarizedWithDankookDto {

@Schema(description = "With-Dankook 게시글 아이디", example = "1")
private final Long id;

@Schema(description = "작성자", example = "익명")
private final String author;

@Schema(description = "생성 날짜")
private final LocalDateTime createdAt;

@Schema(description = "채팅 링크", example = "https://open.kakao.com/o/ghjgjgjg")
private final String chatLink;

public SummarizedWithDankookDto(int bodySize, WithDankook withDankook) {
this.id = withDankook.getId();
this.author = withDankook.getDisplayingUsername();
this.createdAt = withDankook.getCreatedAt();
this.chatLink = withDankook.getChatLink();
}

public SummarizedWithDankookDto(SummarizedWithDankookDto copy) {
this.id = copy.getId();
this.author = copy.getAuthor();
this.createdAt = copy.getCreatedAt();
this.chatLink = copy.getChatLink();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,17 @@ public class RequestCreateTradeDto extends RequestCreateWithDankookDto<Trade> {
@Schema(description = "이미지 파일 목록")
private final List<MultipartFile> images;

public RequestCreateTradeDto(@NotBlank String title, @NotBlank int price, @NotBlank String content, @NotBlank String tradePlace, List<MultipartFile> images) {
@NotBlank
@Schema(description = "오픈채팅방 링크", example = "https://open.kakao.com/o/abc123")
private final String chatLink;

public RequestCreateTradeDto(@NotBlank String title, @NotBlank int price, @NotBlank String content, @NotBlank String tradePlace, List<MultipartFile> images, @NotBlank String chatLink) {
this.title = title;
this.price = price;
this.content = content;
this.tradePlace = tradePlace;
this.images = Objects.requireNonNullElseGet(images, ArrayList::new);
this.chatLink = chatLink;
}

public Trade toEntity(User user) {
Expand All @@ -50,6 +55,7 @@ public Trade toEntity(User user) {
.content(content)
.tradePlace(tradePlace)
.user(user)
.chatLink(chatLink)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ protected WithDankook(User user, String chatLink) {
}

public abstract String getDisplayingUsername();

public void markAsDeleted(boolean byAdmin) {
this.withDankookStatus = byAdmin ? WithDankookStatus.DELETED_BY_ADMIN : WithDankookStatus.DELETED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
import com.dku.council.domain.with_dankook.model.entity.WithDankook;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface WithDankookRepository<T extends WithDankook> extends JpaRepository<WithDankook, Long>, JpaSpecificationExecutor<T> {
import java.util.Optional;

public interface WithDankookRepository<T extends WithDankook> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {

@Override
@Query("select w from WithDankook w " +
"join fetch w.masterUser u " +
"join fetch u.major " +
"where w.id=:id and w.withDankookStatus ='ACTIVE' ")
Optional<T> findById(@Param("id") Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.dku.council.domain.with_dankook.repository.spec;

import com.dku.council.domain.with_dankook.model.WithDankookStatus;
import com.dku.council.domain.with_dankook.model.entity.WithDankook;
import org.springframework.data.jpa.domain.Specification;

public class WithDankookSpec {

public static <T extends WithDankook> Specification<T> withActive() {
return (root, query, builder) ->
builder.equal(root.get("withDankookStatus"), WithDankookStatus.ACTIVE);
}

public static <T extends WithDankook> Specification<T> withTitleOrBody(String keyword) {
if (keyword == null || keyword.equals("null")) {
return Specification.where(null);
}

String pattern = "%" + keyword + "%";
return (root, query, builder) ->
builder.or(
builder.like(root.get("title"), pattern),
builder.like(root.get("content"), pattern)
);
}
}
Loading

0 comments on commit 8da876b

Please sign in to comment.