Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/becooq81 step3 #8

Open
wants to merge 10 commits into
base: feature/becooq81_step2
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ public ResponseEntity<Void> createFriendship(@RequestBody @Valid FriendshipReque
@GetMapping("/my")
public ResponseEntity<List<FriendshipResponse>> findFriendshipsByMember(@RequestParam(defaultValue = "0") int page) {
String username = getLoginUsername();
List<FriendshipResponse> responses = friendshipService.findFriendshipsByMember(username, page)
List<FriendshipResponse> responses = friendshipService.getFriendshipsByMember(username, page)
.stream()
.map(FriendshipResponse::of)
.collect(Collectors.toList());

return ResponseEntity.ok(responses);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.gdscys.cokepoke.friendship.domain;

import com.gdscys.cokepoke.member.domain.Member;
import com.gdscys.cokepoke.poke.domain.Poke;
import lombok.Getter;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity(name = "Friendship")
@Getter
Expand All @@ -24,16 +27,24 @@ public class Friendship {
@Column(name = "is_accepted", columnDefinition = "boolean default false")
private boolean isAccepted;

@OneToMany(mappedBy = "friendship")
private List<Poke> pokes;

protected Friendship() {}

public Friendship(Member from, Member to) {
this.from = from;
this.to = to;
this.isAccepted = false;
this.pokes = new ArrayList<>();
}

public void accept() {
this.isAccepted = true;
}

public void addPoke(Poke poke) {
this.pokes.add(poke);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public class FriendshipService implements IFriendshipService {
@Override
@Transactional
public void createFriendship(String username, String recipientUsername) {
Member member = memberService.findMemberByUsername(username);
Member to = memberService.findMemberByUsername(recipientUsername);
Member member = memberService.getMemberByUsername(username);
Member to = memberService.getMemberByUsername(recipientUsername);
if (member.equals(to)) throw new IllegalArgumentException("You cannot be friends with yourself");
if (friendshipRepository.findByFromAndTo(member, to).isPresent()) {
throw new IllegalArgumentException("You already sent a friend request");
Expand All @@ -40,25 +40,33 @@ public void createFriendship(String username, String recipientUsername) {
}

@Override
public Friendship findFriendshipByMembers(String username, String username2) {
Member member = memberService.findMemberByUsername(username);
Member to = memberService.findMemberByUsername(username2);
public Friendship getFriendshipById(Long friendshipId) {
return friendshipRepository.findById(friendshipId)
.orElseThrow(() -> new NoSuchElementException("No friendship found with given id: "+ friendshipId));
}

@Override
public Friendship getFriendshipByMembers(String username, String username2) {
Member member = memberService.getMemberByUsername(username);
Member to = memberService.getMemberByUsername(username2);

Optional<Friendship> friendship = friendshipRepository.findByFromAndTo(member, to);
Optional<Friendship> friendship2 = friendshipRepository.findByFromAndTo(to, member);

if (friendship.isEmpty() && friendship2.isEmpty()) throw new NoSuchElementException("No friendship found between " + to.getUsername() + " and " + username2);
if (friendship.isEmpty() || friendship2.isEmpty()) throw new NoSuchElementException("No friendship found between " + to.getUsername() + " and " + username2);
else return friendship.orElseGet(friendship2::get);
}

@Override
public List<Friendship> findFriendshipsByMember(String username, int page) {
Member member = memberService.findMemberByUsername(username);
public List<Friendship> getFriendshipsByMember(String username, int page) {
Member member = memberService.getMemberByUsername(username);
PageRequest pageRequest = PageRequest.of(page, PAGE_SIZE);
return friendshipRepository.findAllByFrom(member, pageRequest)
List<Friendship> friendships = friendshipRepository.findAllByFrom(member, pageRequest)
.stream()
.filter(Friendship::isAccepted)
.collect(Collectors.toList());
if (friendships.isEmpty()) throw new IllegalArgumentException("No friendships found");
return friendships;
}

private void checkIfFriendshipExists(Friendship friendship) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
public interface IFriendshipService {

void createFriendship(String username, String recipientUsername);
Friendship getFriendshipById(Long friendshipId);

Friendship findFriendshipByMembers(String username, String username2);
Friendship getFriendshipByMembers(String username, String username2);

List<Friendship> findFriendshipsByMember(String username, int page);
List<Friendship> getFriendshipsByMember(String username, int page);
}
13 changes: 13 additions & 0 deletions src/main/java/com/gdscys/cokepoke/member/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.springframework.security.core.userdetails.UserDetails;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
Expand Down Expand Up @@ -53,6 +54,9 @@ public class Member implements UserDetails {
@UpdateTimestamp
private LocalDateTime updatedAt;

@Column(name = "timezone", nullable = false)
private ZoneId timezone;

@OneToOne(mappedBy = "member", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private RefreshToken refreshToken;

Expand All @@ -67,6 +71,15 @@ public Member(String email, String username, String passwordHash, Set<String> ro
this.username = username;
this.passwordHash = passwordHash;
this.roles = roles;
this.timezone = ZoneId.of("Asia/Seoul");
}

public Member(String email, String username, String passwordHash, Set<String> roles, ZoneId timezone) {
this.email = email;
this.username = username;
this.passwordHash = passwordHash;
this.roles = roles;
this.timezone = timezone;
}

public void addRequested(Friendship friendship) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public interface IMemberService {
Member saveMember(String email, String username, String password);
Member findMemberByUsername(String username);
Member getMemberByUsername(String username);
void updateMember(Member member, UpdateMemberRequest request);
void deleteMember(Member member);
List<Member> findAll(int page);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public Member saveMember(String email, String username, String password) {
}

@Override
public Member findMemberByUsername(String username) {
public Member getMemberByUsername(String username) {
return memberRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.gdscys.cokepoke.poke.controller;

import com.gdscys.cokepoke.poke.dto.PokeRequest;
import com.gdscys.cokepoke.poke.dto.PokeResponse;
import com.gdscys.cokepoke.poke.service.PokeService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

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

import static com.gdscys.cokepoke.auth.SecurityUtil.getLoginUsername;
import static java.util.Arrays.stream;

@Controller
@RequiredArgsConstructor
@RequestMapping("/poke")
public class PokeController {
private final PokeService pokeService;

@PostMapping("/")
public ResponseEntity<String> poke(@RequestBody @Valid PokeRequest request) {
String senderUsername = getLoginUsername();
pokeService.poke(senderUsername, request.getReceiverUsername());
return ResponseEntity.status(HttpStatus.CREATED).body("Poked " + request.getReceiverUsername());
}

@GetMapping("/{username}")
public ResponseEntity<List<PokeResponse>> getPokes(@PathVariable String username,
@RequestParam(defaultValue = "0") int page) {
String senderUsername = getLoginUsername();
List<PokeResponse> responses = pokeService.getPokesByUsernames(senderUsername, username, page)
.stream()
.map(PokeResponse::of)
.collect(Collectors.toList());
return ResponseEntity.ok(responses);
}

@GetMapping("/{username}/{pokeId}")
public ResponseEntity<PokeResponse> getPoke(@PathVariable String username, @PathVariable Long pokeId) {
String senderUsername = getLoginUsername();
PokeResponse response = PokeResponse.of(pokeService.getPokeById(pokeId));
return ResponseEntity.ok(response);
}
}
35 changes: 35 additions & 0 deletions src/main/java/com/gdscys/cokepoke/poke/domain/Poke.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.gdscys.cokepoke.poke.domain;


import com.gdscys.cokepoke.friendship.domain.Friendship;
import com.gdscys.cokepoke.member.domain.Member;
import lombok.Getter;
import org.hibernate.annotations.CreationTimestamp;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity(name = "Poke")
@Getter
@SequenceGenerator(name = "POKE_SEQ_GEN", sequenceName = "POKE_SEQ", allocationSize = 1)
public class Poke {

@Id @GeneratedValue(generator = "POKE_SEQ_GEN")
private Long id;

@CreationTimestamp
private LocalDateTime createdAt;

private String senderUsername;

@ManyToOne
@JoinColumn(name="friendship_id")
private Friendship friendship;

protected Poke() {}

public Poke(Friendship friendship) {
this.friendship = friendship;
}

}
15 changes: 15 additions & 0 deletions src/main/java/com/gdscys/cokepoke/poke/dto/PokeRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gdscys.cokepoke.poke.dto;

import lombok.Getter;

@Getter
public class PokeRequest {

private String receiverUsername;

protected PokeRequest() {}

public PokeRequest(String receiverUsername) {
this.receiverUsername = receiverUsername;
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/gdscys/cokepoke/poke/dto/PokeResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.gdscys.cokepoke.poke.dto;

import com.gdscys.cokepoke.poke.domain.Poke;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
public class PokeResponse {
private String senderUsername;
private LocalDateTime createdAt;

protected PokeResponse() {}

public static PokeResponse of (Poke poke) {
PokeResponse response = new PokeResponse();
response.senderUsername = poke.getSenderUsername();
response.createdAt = poke.getCreatedAt();
return response;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.gdscys.cokepoke.poke.repository;

import com.gdscys.cokepoke.friendship.domain.Friendship;
import com.gdscys.cokepoke.poke.domain.Poke;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface PokeRepository extends JpaRepository<Poke, Long> {
Page<Poke> findAllByFriendship(Friendship friendship, Pageable pageable);

}
12 changes: 12 additions & 0 deletions src/main/java/com/gdscys/cokepoke/poke/service/IPokeService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gdscys.cokepoke.poke.service;

import com.gdscys.cokepoke.poke.domain.Poke;

import java.util.List;

public interface IPokeService {
List<Poke> getPokesByUsernames(String senderUsername, String receiverName, int page);
Poke getPokeById(Long pokeId);
Poke poke(String senderUsername, String receiverUsername);

}
66 changes: 66 additions & 0 deletions src/main/java/com/gdscys/cokepoke/poke/service/PokeService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.gdscys.cokepoke.poke.service;

import com.gdscys.cokepoke.friendship.domain.Friendship;
import com.gdscys.cokepoke.friendship.service.FriendshipService;
import com.gdscys.cokepoke.member.domain.Member;
import com.gdscys.cokepoke.poke.domain.Poke;
import com.gdscys.cokepoke.poke.repository.PokeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class PokeService implements IPokeService {

private final PokeRepository pokeRepository;
private final FriendshipService friendshipService;

private final int PAGE_SIZE = 15;

@Override
public List<Poke> getPokesByUsernames(String senderUsername, String receiverUsername, int page) {
PageRequest pageRequest = PageRequest.of(page, PAGE_SIZE);
Friendship friendship = friendshipService.getFriendshipByMembers(senderUsername, receiverUsername);
Page<Poke> pokes = pokeRepository.findAllByFriendship(friendship, pageRequest);
if (pokes.isEmpty()) throw new IllegalArgumentException("No pokes found");
return pokes.stream().collect(Collectors.toList());
}

@Override
public Poke getPokeById(Long pokeId) {
return pokeRepository.findById(pokeId).orElseThrow(() -> new IllegalArgumentException("No poke found"));
}

@Override
public Poke poke(String senderUsername, String receiverUsername) {
Friendship friendship = friendshipService.getFriendshipByMembers(senderUsername, receiverUsername);
checkOncePerDay(friendship, senderUsername);
Poke poke = new Poke(friendship);
pokeRepository.save(poke);
friendship.addPoke(poke);
return poke;
}

private void checkOncePerDay(Friendship friendship, String username) {
Member member = friendship.getFrom().getUsername().equals(username) ? friendship.getFrom() : friendship.getTo();

LocalDateTime todayStart = LocalDateTime.now(member.getTimezone()).with(LocalTime.MIN);
LocalDateTime todayEnd = LocalDateTime.now(member.getTimezone()).with(LocalTime.MAX);

List<Poke> pokes = friendship.getPokes().stream()
.filter(poke -> poke.getCreatedAt().isAfter(todayStart)
&& poke.getCreatedAt().isBefore(todayEnd)
&& poke.getSenderUsername().equals(username))
.collect(Collectors.toList());

if (!pokes.isEmpty()) throw new IllegalArgumentException("You can only poke once per day");
}
}
Loading