[Practice] 사용자 관련 API 만들기 (1)

2021. 4. 17. 15:37Spring/Practice

1. 문제

  • 관심사용자에 등록하는 API

 

 

 

2. 풀이

- schema.sql

DROP TABLE IF EXISTS USER;
DROP TABLE IF EXISTS NOTICE;

create table USER (
    ID          BIGINT auto_increment primary key,
    EMAIL       VARCHAR(255),
    NAME        VARCHAR(255),
    PASSWORD    VARCHAR(255),
    PHONE       VARCHAR(255),
    REG_DATE    TIMESTAMP,
    UPDATE_DATE TIMESTAMP,
    STATUS      INTEGER,
    LOCK_YN     BOOLEAN DEFAULT FALSE
);

create table NOTICE (
    ID          BIGINT auto_increment primary key,
    TITLE       VARCHAR(255),
    CONTENTS    VARCHAR(255),

    HITS        INTEGER,
    LIKES       INTEGER,

    REG_DATE    TIMESTAMP,
    UPDATE_DATE TIMESTAMP,
    DELETED     BOOLEAN DEFAULT FALSE,
    DELETED_DATE    TIMESTAMP,

    USER_ID     BIGINT,
    constraint FK_NOTICE_USER_ID foreign key(USER_ID) references USER(ID)
);

create table NOTICE_LIKE (
    ID          BIGINT auto_increment primary key,

    NOTICE_ID   BIGINT,
    constraint FK_NOTICE_LIKE_NOTICE_ID foreign key(NOTICE_ID) references NOTICE(ID),

    USER_ID     BIGINT,
    constraint FK_NOTICE_LIKE_USER_ID foreign key(USER_ID) references USER(ID)
);

create table USER_LOGIN_HISTORY (
    ID          BIGINT auto_increment primary key,
    USER_ID     BIGINT,
    EMAIL       VARCHAR(255),
    NAME        VARCHAR(255),
    LOGIN_DATE  TIMESTAMP,
    IP_ADDR     VARCHAR(255)
);

create table BOARD_TYPE (
    ID          BIGINT auto_increment primary key,
    BOARD_NAME  VARCHAR(255),
    REG_DATE    TIMESTAMP,
    UPDATE_DATE TIMESTAMP,
    USING_YN    BOOLEAN DEFAULT FALSE
);

-- auto-generated definition
create table BOARD
(
    ID            BIGINT auto_increment primary key,
    CONTENTS      VARCHAR(255),
    REG_DATE      TIMESTAMP,
    TITLE         VARCHAR(255),
    BOARD_TYPE_ID BIGINT,
    USER_ID       BIGINT,
    TOP_YN        BOOLEAN DEFAULT FALSE,
    PUBLISH_START_DATE    DATE,
    PUBLISH_END_DATE      DATE,

    constraint FK_BOARD_BOARD_TYPE_ID foreign key (BOARD_TYPE_ID) references BOARD_TYPE (ID),
    constraint FK_BOARD_USER_ID foreign key (USER_ID) references USER (ID)
);

-- auto-generated definition
create table BOARD_HITS
(
    ID       BIGINT auto_increment primary key,
    REG_DATE TIMESTAMP,
    BOARD_ID BIGINT,
    USER_ID  BIGINT,

    constraint FK_BOARD_HITS_BOARD_ID foreign key (BOARD_ID) references BOARD (ID),
    constraint FK_BOARD_HITS_USER_ID foreign key (USER_ID) references USER (ID)
);

create table BOARD_LIKE
(
    ID       BIGINT auto_increment primary key,
    REG_DATE TIMESTAMP,
    BOARD_ID BIGINT,
    USER_ID  BIGINT,

    constraint FK_BOARD_LIKE_BOARD_ID foreign key (BOARD_ID) references BOARD (ID),
    constraint FK_BOARD_LIKE_USER_ID foreign key (USER_ID) references USER (ID)
);

-- auto-generated definition
create table BOARD_BAD_REPORT
(
    ID             BIGINT auto_increment primary key,
    BOARD_CONTENTS VARCHAR(255),
    BOARD_ID       BIGINT,
    BOARD_REG_DATE TIMESTAMP,
    BOARD_TITLE    VARCHAR(255),
    BOARD_USER_ID  BIGINT,
    COMMENTS       VARCHAR(255),
    USER_EMAIL     VARCHAR(255),
    USER_ID        BIGINT,
    USER_NAME      VARCHAR(255)
);

-- auto-generated definition
create table BOARD_SCRAP
(
    ID             BIGINT auto_increment primary key,
    BOARD_CONTENTS VARCHAR(255),
    BOARD_ID       BIGINT,
    BOARD_REG_DATE TIMESTAMP,
    BOARD_TITLE    VARCHAR(255),
    BOARD_TYPE_ID  BIGINT,
    BOARD_USER_ID  BIGINT,
    REG_DATE       TIMESTAMP,
    USER_ID        BIGINT,
    constraint FK_BOARD_SCRAP_USER_ID foreign key (USER_ID) references USER (ID)
);

-- auto-generated definition
create table BOARD_BOOKMARK
(
    ID             BIGINT auto_increment primary key,
    BOARD_ID       BIGINT,
    BOARD_TITLE    VARCHAR(255),
    BOARD_TYPE_ID  BIGINT,
    BOARD_URL      VARCHAR(255),
    REG_DATE       TIMESTAMP,
    USER_ID        BIGINT,

    constraint FK_BOARD_BOOKMARK_USER_ID foreign key (USER_ID) references USER (ID)
);

create table USER_INTEREST (
    ID                  BIGINT auto_increment primary key,
    USER_ID             BIGINT,
    INTEREST_USER_ID    BIGINT,
    REG_DATE            TIMESTAMP,
    constraint FK_USER_INTEREST_USER_ID foreign key (USER_ID) references USER (ID),
    constraint FK_USER_INTEREST_INTEREST_USER_ID foreign key (INTEREST_USER_ID) references USER (ID)
);

- UserInterest.java

package com.example.jpa.sample.user.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

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

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
public class UserInterest {

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

    @ManyToOne
    @JoinColumn
    private User user;

    @ManyToOne
    @JoinColumn
    private User interestUser;

    @Column
    private LocalDateTime regDate;
}

- UserInterestRepository.java

package com.example.jpa.sample.user.repository;

import com.example.jpa.sample.user.entity.User;
import com.example.jpa.sample.user.entity.UserInterest;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserInterestRepository extends JpaRepository<UserInterest, Long> {
    
    long countByUserAndInterestUser(User user, User interestUser);
}

- UserService.java

package com.example.jpa.sample.user.service;

import com.example.jpa.sample.board.model.ServiceResult;
import com.example.jpa.sample.user.entity.User;
import com.example.jpa.sample.user.model.UserLogCount;
import com.example.jpa.sample.user.model.UserNoticeCount;
import com.example.jpa.sample.user.model.UserSummary;

import java.util.List;

public interface UserService {

    UserSummary getUserStatusCount();

    List<User> getTodayUsers();

    List<UserNoticeCount> getUserNoticeCount();

    List<UserLogCount> getUserLogCount();

    List<UserLogCount> getUserLikeBest();

    ServiceResult addInterestUser(Long id, String email);
}

- UserServiceImpl.java

package com.example.jpa.sample.user.service;

import com.example.jpa.sample.board.model.ServiceResult;
import com.example.jpa.sample.user.entity.User;
import com.example.jpa.sample.user.entity.UserInterest;
import com.example.jpa.sample.user.model.UserLogCount;
import com.example.jpa.sample.user.model.UserNoticeCount;
import com.example.jpa.sample.user.model.UserStatus;
import com.example.jpa.sample.user.model.UserSummary;
import com.example.jpa.sample.user.repository.UserCustomRepository;
import com.example.jpa.sample.user.repository.UserInterestRepository;
import com.example.jpa.sample.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@RequiredArgsConstructor
@Service
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final UserCustomRepository userCustomRepository;
    private final UserInterestRepository userInterestRepository;

    @Override
    public UserSummary getUserStatusCount() {

        Long stopUserCount = userRepository.countByStatus(UserStatus.Stop);
        Long usingUserCount = userRepository.countByStatus(UserStatus.Using);
        Long totalUserCount = userRepository.count();

        return UserSummary.builder()
                .stopUserCount(stopUserCount)
                .usingUserCount(usingUserCount)
                .totalUserCount(totalUserCount)
                .build();
    }

    @Override
    public List<User> getTodayUsers() {
        // 현재 시간을 기준
        LocalDateTime t = LocalDateTime.now();
        LocalDateTime startDate = LocalDateTime.of(t.getYear(), t.getMonth(), t.getDayOfMonth(), 0, 0);
        LocalDateTime endDate = startDate.plusDays(1);

        return userRepository.findToday(startDate, endDate);
    }

    @Override
    public List<UserNoticeCount> getUserNoticeCount() {
        return userCustomRepository.findUserNoticeCount();
    }

    @Override
    public List<UserLogCount> getUserLogCount() {
        return userCustomRepository.findUserLogCount();
    }

    @Override
    public List<UserLogCount> getUserLikeBest() {
        return userCustomRepository.findUserLikeBest();
    }

    @Override
    public ServiceResult addInterestUser(Long id, String email) {
        Optional<User> optionalUser = userRepository.findByEmail(email);
        if(!optionalUser.isPresent()) {
            return ServiceResult.fail("회원 정보가 존재하지 않습니다.");
        }
        User user = optionalUser.get();

        Optional<User> optionalUserInterest = userRepository.findById(id);
        if(!optionalUserInterest.isPresent()) {
            return ServiceResult.fail("관심사용자에 추가할 회원 정보가 존재하지 않습니다.");
        }
        User interestUser = optionalUserInterest.get();

        if(userInterestRepository.countByUserAndInterestUser(user, interestUser) > 0 ) {
            return ServiceResult.fail("이미 관심사용자 목록에 추가하였습니다.");
        }

        // 내가 나를 추가할 경우
        if(user.getId() == interestUser.getId()) {
            return ServiceResult.fail("자기 자신은 추가할 수 없습니다.");
        }

        userInterestRepository.save(UserInterest.builder()
                .user(user)
                .interestUser(interestUser)
                .regDate(LocalDateTime.now())
                .build());

        return ServiceResult.success();
    }
}

- ApiUserInterestController.java

package com.example.jpa.sample.user.controller;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.jpa.sample.board.model.ServiceResult;
import com.example.jpa.sample.common.model.ResponseResult;
import com.example.jpa.sample.user.service.UserService;
import com.example.jpa.sample.util.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
public class ApiUserInterestController {

    private final UserService userService;

    // 문제 1
    @PutMapping("/api/user/{id}/interest")
    public ResponseEntity<?> interestUser(@PathVariable Long id, @RequestHeader("X-ACCESS-TOKEN") String token) {
        String email = "";
        try {
            email = JwtUtils.getIssuer(token);
        } catch(JWTVerificationException e) {
            return ResponseResult.fail("토큰 정보가 정확하지 않습니다.");
        }

        ServiceResult result = userService.addInterestUser(id, email);
        return ResponseResult.result(result);
    }
}
728x90