Skip to content

Commit

Permalink
주차장 즐겨찾기 (#38)
Browse files Browse the repository at this point in the history
* feat: 즐겨찾기 엔티티 생성

* feat: 컴파일 에러 수정

* feat: 즐겨찾기 Repository 구현

* feat: 즐겨찾기 dto 구현

* feat: 즐겨찾기 service 구현

* feat: 즐겨찾기 controller 구현

* feat: memberId, parkingId 값 객체 생성

* Create ci.yml

* fix: 없어진 괄호 수정

* fix: 테스트용 설정 파일 추가

* Update ci.yml

PR 코멘트는 pr일때만 보내도록 변경

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Update ci.yml

* Feat/#19 리뷰 관리 기능 구현 (#33)

* Refactor: DB <-> Application 간 데이터 변환하는 컨버터 위치 수정

* feat: 이미지 저장할 패키지 추가

* fix: 오류나는 패키지 구조 변경

* feat: 리뷰에서 선택할 수 있는 글 생성

* feat: 이미지 저장하는 기능 구현

* feat: 리뷰 작성하는 기능 구현

* feat: 리뷰 컨트롤러 작성(테스트용)

* test: mysql 도 돌릴 수 있도록 수정

* gitignroe 추가

* properties 추가

* test: 안쓰는 어노테이션 제거

* refactor: 이미지 제거

* refactor: 연관관계 ID 참조로 변경

* feat: 주차장 조회 기능 구현

* refactor: 패키지명 변경 common -> support

* refactor: 기본 생성자 접근자 변경

* refactor: Convert 어노테이션 필드에 붙이도록 변경

* refactor: createdAt 필드 변경

* ci test

* ci test2

* refactor: 이미지 관련 파일 삭제

* fix: conflict 해결

* feat: 즐겨찾기 엔티티 생성

* feat: 컴파일 에러 수정

* feat: 즐겨찾기 Repository 구현

* feat: 즐겨찾기 dto 구현

* feat: 즐겨찾기 service 구현

* feat: 즐겨찾기 controller 구현

* feat: memberId, parkingId 값 객체 생성

* feat: api 스펙 변경

* feat: association 적용

---------

Co-authored-by: LeeGeonHo <[email protected]>
  • Loading branch information
youngh0 and This2sho authored Mar 12, 2024
1 parent 41fe5c4 commit 1df91f3
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.example.parking.api.favorite;

import com.example.parking.application.favorite.FavoriteService;
import com.example.parking.application.favorite.dto.FavoriteCreateRequest;
import com.example.parking.application.favorite.dto.FavoriteDeleteRequest;
import com.example.parking.config.argumentresolver.MemberAuth;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
public class FavoriteController {

private final FavoriteService favoriteService;

@PostMapping("/favorites")
public ResponseEntity<Void> create(@RequestBody FavoriteCreateRequest favoriteCreateRequest,
@MemberAuth Long memberId) {
favoriteService.createFavorite(favoriteCreateRequest, memberId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

@DeleteMapping("/favorites")
public ResponseEntity<Void> delete(@RequestBody FavoriteDeleteRequest favoriteDeleteRequest,
@MemberAuth Long memberId) {
favoriteService.deleteFavorite(favoriteDeleteRequest, memberId);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.example.parking.application.favorite;

import com.example.parking.application.favorite.dto.FavoriteCreateRequest;
import com.example.parking.application.favorite.dto.FavoriteDeleteRequest;
import com.example.parking.domain.favorite.Favorite;
import com.example.parking.domain.favorite.FavoriteRepository;
import com.example.parking.support.Association;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@RequiredArgsConstructor
@Transactional
@Service
public class FavoriteService {

private final FavoriteRepository favoriteRepository;

public void createFavorite(FavoriteCreateRequest favoriteCreateRequest, Long memberId) {
Long parkingId = favoriteCreateRequest.getParkingId();

Favorite favorite = new Favorite(Association.from(memberId), Association.from(parkingId));
saveFavorite(favorite);
}

private void saveFavorite(Favorite favorite) {
try {
favoriteRepository.save(favorite);
} catch (DataIntegrityViolationException e) {
log.warn("memberId: {}, parkingId: {} request duplicate favorite create", favorite.getMemberId(),
favorite.getParkingId());
}
}

public void deleteFavorite(FavoriteDeleteRequest favoriteDeleteRequest, Long memberId) {
Long parkingId = favoriteDeleteRequest.getParkingId();

favoriteRepository.deleteByMemberIdAndParkingId(Association.from(memberId), Association.from(parkingId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.parking.application.favorite.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class FavoriteCreateRequest {

private Long parkingId;

public FavoriteCreateRequest(Long parkingId) {
this.parkingId = parkingId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.parking.application.favorite.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class FavoriteDeleteRequest {

private Long parkingId;

public FavoriteDeleteRequest(Long parkingId) {
this.parkingId = parkingId;
}
}
48 changes: 48 additions & 0 deletions src/main/java/com/example/parking/domain/favorite/Favorite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.example.parking.domain.favorite;

import com.example.parking.domain.AuditingEntity;
import com.example.parking.domain.member.Member;
import com.example.parking.domain.parking.Parking;
import com.example.parking.support.Association;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "favorite",
uniqueConstraints = {
@UniqueConstraint(
columnNames = {"memberId", "parkingId"}
)
}
)
@Entity
public class Favorite extends AuditingEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Embedded
@AttributeOverride(name = "id", column = @Column(name = "member_id"))
private Association<Member> memberId;

@Embedded
@AttributeOverride(name = "id", column = @Column(name = "parking_id"))
private Association<Parking> parkingId;

public Favorite(Association<Member> memberId, Association<Parking> parkingId) {
this.memberId = memberId;
this.parkingId = parkingId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.parking.domain.favorite;

import com.example.parking.domain.member.Member;
import com.example.parking.domain.parking.ParkingId;
import com.example.parking.support.Association;
import java.util.List;
import org.springframework.data.repository.Repository;

public interface FavoriteRepository extends Repository<Favorite, Long> {

Favorite save(Favorite favorite);

void deleteByMemberIdAndParkingId(Association<Member> memberId, Association<ParkingId> parkingId);

List<Favorite> findByMemberId(Association<Member> memberId);
}
10 changes: 3 additions & 7 deletions src/main/java/com/example/parking/domain/member/Member.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package com.example.parking.domain.member;

import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.util.Objects;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Objects;

@Getter
@Entity
//@SQLRestriction(value = "deleted = false")
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/example/parking/domain/member/MemberId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.parking.domain.member;

import jakarta.persistence.Embeddable;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Embeddable
@NoArgsConstructor
@Getter
public class MemberId {

private Long memberId;

public MemberId(Long memberId) {
this.memberId = memberId;
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/example/parking/domain/parking/ParkingId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.parking.domain.parking;

import jakarta.persistence.Embeddable;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Embeddable
@Getter
@NoArgsConstructor
public class ParkingId {

private Long parkingId;

public ParkingId(Long parkingId) {
this.parkingId = parkingId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.example.parking.domain.favorite;

import static org.assertj.core.api.Assertions.assertThat;

import com.example.parking.support.Association;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

@DataJpaTest
class FavoriteRepositoryTest {

@Autowired
private FavoriteRepository favoriteRepository;

@Test
void 멤버의_즐겨찾기_주차장을_삭제한다() {
Long memberId = 1L;
Long parkingId = 1L;
Favorite favorite = new Favorite(Association.from(memberId), Association.from(parkingId));
favoriteRepository.save(favorite);

favoriteRepository.deleteByMemberIdAndParkingId(Association.from(memberId), Association.from(parkingId));
assertThat(favoriteRepository.findByMemberId(Association.from(memberId))).isEmpty();
}

@Test
void 멤버의_즐겨찾기_주차장을_조회한다() {
// given
Long memberId = 1L;
Long memberId2 = 2L;

Long parkingId = 1L;
Long parkingId2 = 2L;
Long parkingId3 = 3L;
Long parkingId4 = 4L;

// when
favoriteRepository.save(new Favorite(Association.from(memberId), Association.from(parkingId)));
favoriteRepository.save(new Favorite(Association.from(memberId), Association.from(parkingId2)));
favoriteRepository.save(new Favorite(Association.from(memberId), Association.from(parkingId3)));

favoriteRepository.save(new Favorite(Association.from(memberId2), Association.from(parkingId3)));
favoriteRepository.save(new Favorite(Association.from(memberId2), Association.from(parkingId4)));

// then
assertThat(favoriteRepository.findByMemberId(Association.from(memberId))).hasSize(3);
}
}

0 comments on commit 1df91f3

Please sign in to comment.