Light Blue Pointer
본문 바로가기
Developing/개발일지

2024-01-17, Today I Learned

by Greedy 2024. 1. 17.

오늘 한 일

💡전체글 조회 페이지 생성

🚩문제 : 화면에 아무것도 출력되지 않는 문제 해결

🚩문제 : 그런데 이제 조회 버튼을 누르면 undefined로 뜨는 문제 해결

💡마감시간 스케쥴링 기능 구현

💡Post 삭제시 Menu도 함께 삭제하지 않고 Order로 옮겨줌

🚩문제 : tt1과 tt2 둘 다 postId가 null이 되어야 하는데 하나만 null이 되는 문제 해결

🚩문제 :  Host 의 Menu 는 글과 함께 사라져버리는 문제 해결

 

 

🚀Feature🚀

나가기 기능 수정

모집마감이 된 상태면 나갈 수 없게 변경함

CANNOT_EXIT_AFTER_CLOSED(HttpStatus.BAD_REQUEST.value(), "모집마감 후에 나가기를 할 수 없습니다."),
if(post.getPostStatus()!= PostStatusEnum.OPEN){
            throw new GlobalException(PostErrorCode.CANNOT_EXIT_AFTER_CLOSED);
        }

 

전체글 조회 페이지 생성

리턴값이 이것의 List로 된 게 돌아옴

public record BriefPostResponse(
    Long id,
    String author,
    String address,
    String store,
    Integer minPrice,
    Integer sumPrice,
    LocalDateTime deadline
) {

}
 <html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <meta
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"
      name="viewport">
  <title>글 전체페이지</title>
  <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
<div style="padding:10px;width:1000px; height:max-content">
  <div id="posts" style="width:1000px; height:min-content;"></div>
</div>
<script th:inline="javascript">

  $(document).ready(function () {
    getData();
  });

  function getData() {

    $.ajax({
      type: 'GET',
      url: `/api/v1/readonly/posts`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      success: function (response) {
        console.log('Success:', response);

        drawAllPosts(response.data);

      },
      error: function (error) {
        console.error('Error:', error);
      }
    });
  }

  function drawAllPosts(data) {
    data.forEach((post) =>
        $('#posts').append(
            `
              <div style="padding:10px;width:1000px; height:max-content; margin:auto">
                <div>작성자</div>
                <div>${post.author}</div>
                <div>가게</div>
                <div>${post.store}</div>
                <div>합계 금액</div>
                <div>${post.sumPrice}</div>
                <div>최소주문금액</div>
                <div>${post.minPrice}</div>
                <div>마감 기한</div>
                <div>${post.deadline}</div>
                <button postId = ${post.id}  class="btn btn-outline-secondary" onclick="sendData(${postId})" type="button">조회</button>
              </div>
            `
        )
    )
  }

  function sendData(postId) {

    $.ajax({
      type: 'POST',
      url: `/moayo/readpost/${postId}`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);
      },
      error: function (error,response) {
        alert(response.message);
        console.error('Error:', error);
      }
    });
  }

</script>

</body>
</html>
 

 

🚩문제 : 화면에 아무것도 출력되지 않는다

 

다른것들은 다 잘 나옴

 

💡해결시도중

브라우저 콘솔 확인해봄

Success: Objectdata: (2) [{…}, {…}]message: "모든 글 조회에 성공했습니다."status: 200[[Prototype]]: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()__proto__: (...)get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()
allposts:55 Uncaught ReferenceError: postId is not defined
    at allposts:55:100
    at Array.forEach (<anonymous>)
    at drawAllPosts (allposts:41:10)
    at Object.success (allposts:31:9)
    at c (jquery-3.6.4.min.js:2:28447)
    at Object.fireWith [as resolveWith] (jquery-3.6.4.min.js:2:29192)
    at l (jquery-3.6.4.min.js:2:80176)
    at XMLHttpRequest.<anonymous> (jquery-3.6.4.min.js:2:82630)

postId가 정의되지 않았다는게 무슨 뜻이지

<button postId = ${post.id}  class="btn btn-outline-secondary" onclick="sendData(${postId})" type="button">조회</button>

이게 안된거 같음!

 

<button data-postId = ${post.id}  class="btn btn-outline-secondary" onclick="sendData()" type="button">조회</button>
function sendData() {

    var postId=$(this).attr("data-postId");

    $.ajax({
      type: 'POST',
      url: `/moayo/readpost/${postId}`,

이렇게 바꿔봄

 

 

해결되었다!

 

🚩문제 : 그런데 이제 조회 버튼을 누르면 undefined로 뜸

당연함 POST가 아니라 GET을 해야함

$.ajax({
      type: 'POST',
      url: `/moayo/readpost/${postId}`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);
      },
      error: function (error,response) {
        alert(response.message);
        console.error('Error:', error);
      }
    });

$.ajax({
      type: 'GET',
      url: `/moayo/readpost/${postId}`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);
      },
      error: function (error,response) {
        alert(response.message);
        console.error('Error:', error);
      }
    });
  }

GET을 해도 undefined로 뜸

   GET <http://localhost:8080/moayo/readpost/undefined> 403 (Forbidden)

@GetMapping("/readpost/{postId}")
    public String readpostPage(@PathVariable(name = "postId") Long postId) {
        ModelAndView mav = new ModelAndView("postId");
        mav.addObject("postId", postId);
        return "domain/post/readpost";
    }

moayo 하위 path 자체를 필터에서 걸렀는데 무슨소리임

 

 

직접 들어가면 나오긴 함

생각해보니

ajax get은 이 페이지에다 정보를 가져오는거고 다른데로 넘어가는건 redirect등등을 써야할 거 같음!

$.ajax({
      type: 'GET',
      url: `/moayo/readpost/${postId}`,
      dataType: "json",
      contentType: 'application/json',
      data: {},
      success: function (response) {
        console.log('Success:', response);
        alert(response.message);
      },
      error: function (error,response) {
        alert(response.message);
        console.error('Error:', error);
      }
    });

function sendData() {

    var postId=$(this).attr("data-postId");
    const host = 'http://' + window.location.host;

    window.location.href = host + `/moayo/readpost/${postId}`;

  }

오 이제 버튼 누르면 넘어가지긴 하는데 인증이 안 됐다고 뜸

moayo걸렀는데??

 

그리고 주소가 잘못됨 애초에

<http://localhost:8080/moayo/readpost/undefined>

이렇게 출력되면 안 됨

postId가 안 들고와지나봄

<button id = "button" post-id = ${post.id}  class="btn btn-outline-secondary" type="button">조회</button>
$(function() {
    $("button").click(function(){
      var postId=$(this).attr("postId");
      const host = 'http://' + window.location.host;
      window.location.href = host + `/moayo/readpost/${postId}`;
    })
  });

이렇게 해봄

이제 버튼이 눌려도 함수 작동도 안 돼서 옛날 방식으로 롤백함

<button id = "button" post = ${post.id}  class="btn btn-outline-secondary" onclick="sendData(#post)" type="button">조회</button>
function sendData(postId) {

    //var postId=$(this).attr("post-id");
    const host = 'http://' + window.location.host;

    window.location.href = host + `/moayo/readpost/${postId}`;

  }

Uncaught SyntaxError: Private field '#post' must be declared in an enclosing class (at allposts:1:9)

이렇게는 안되나봄

post = ${post.id}

post = "${post.id}"

어제부터 계속 쌍따옴표 까먹는듯…

왠지 될 듯 하다

해봄

<http://localhost:8080/moayo/readpost/undefined>

여전히 undefined임

⛳해결 : onclick에서 값 대신 this로 버튼을 보내도록 수정함

<button id = "${post.id}" post = "${post.id}"  class="btn btn-outline-secondary" onclick="sendData(this)" type="button">조회</button>
function sendData(button) {

    var postId=$(button).attr("post");
    const host = 'http://' + window.location.host;

    window.location.href = host + `/moayo/readpost/${postId}`;

  }

잘 넘어간다!

조회 버튼 클릭하면 글이 잘 보여짐

 

마감시간 스케쥴링 기능 구현

https://spring.io/guides/gs/scheduling-tasks/

이거 읽어봄

build.gradle에 이거 추가함

testImplementation 'org.awaitility:awaitility:4.2.0'

예시 코드 살펴봄

package com.example.schedulingtasks;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

	private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

	@Scheduled(fixedRate = 5000)
	public void reportCurrentTime() {
		log.info("The time is now {}", dateFormat.format(new Date()));
	}
}

The Scheduled annotation defines when a particular method runs.

This example uses fixedRate, which specifies the interval between method invocations, measured from the start time of each invocation. There are other options, such as fixedDelay, which specifies the interval between invocations measured from the completion of the task. You can also use [@Scheduled(cron=". . .")](<https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html>) expressions for more sophisticated task scheduling.

Enable Scheduling

package com.example.schedulingtasks;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class SchedulingTasksApplication {

	public static void main(String[] args) {
		SpringApplication.run(SchedulingTasksApplication.class);
	}
}

@SpringBootApplication is a convenience annotation that adds all of the following:

  • @Configuration: Tags the class as a source of bean definitions for the application context.
  • @EnableAutoConfiguration: Tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. For example, if spring-webmvc is on the classpath, this annotation flags the application as a web application and activates key behaviors, such as setting up a DispatcherServlet.
  • @ComponentScan: Tells Spring to look for other components, configurations, and services in the com/example package, letting it find the controllers.
Build an executable JAR
You can run the application from the command line with Gradle or Maven. You can also build a single executable JAR file that contains all the necessary dependencies, classes, and resources and run that. Building an executable jar makes it easy to ship, version, and deploy the service as an application throughout the development lifecycle, across different environments, and so forth.

If you use Gradle, you can run the application by using ./gradlew bootRun. Alternatively, you can build the JAR file by using ./gradlew build and then run the JAR file, as follows:

java -jar build/libs/gs-scheduling-tasks-0.1.0.jar
If you use Maven, you can run the application by using ./mvnw spring-boot:run. Alternatively, you can build the JAR file with ./mvnw clean package and then run the JAR file, as follows:

java -jar target/gs-scheduling-tasks-0.1.0.jar
The steps described here create a runnable JAR. You can also build a classic WAR file.
Logging output is displayed, and you can see from the logs that it is on a background thread. You should see your scheduled task fire every five seconds. The following listing shows typical output:

...
2019-10-02 12:07:35.659  INFO 28617 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 12:07:35
2019-10-02 12:07:40.659  INFO 28617 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 12:07:40
2019-10-02 12:07:45.659  INFO 28617 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 12:07:45
2019-10-02 12:07:50.657  INFO 28617 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 12:07:50
...
/**
     * Compares this date-time to another date-time.
     * <p>
     * The comparison is primarily based on the date-time, from earliest to latest.
     * It is "consistent with equals", as defined by {@link Comparable}.
     * <p>
     * If all the date-times being compared are instances of {@code LocalDateTime},
     * then the comparison will be entirely based on the date-time.
     * If some dates being compared are in different chronologies, then the
     * chronology is also considered, see {@link ChronoLocalDateTime#compareTo}.
     *
     * @param other  the other date-time to compare to, not null
     * @return the comparator value, negative if less, positive if greater
     */
    @Override  // override for Javadoc and performance
    public int compareTo(ChronoLocalDateTime<?> other) {
        if (other instanceof LocalDateTime) {
            return compareTo0((LocalDateTime) other);
        }
        return ChronoLocalDateTime.super.compareTo(other);
    }

 

예시 코드를 보고 아래와 같이 해봄

@Scheduled(fixedRate = 5000)
    public void deletePastDeadlilne() {
        List<Post> posts = postRepository.findAll();
        List<Post> pastDeadline  = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for(Post post : posts){
            if(post.getDeadline().compareTo(now)<0){
                pastDeadline.add(post);
                userPostRepository.deleteAll(userPostRepository.findAllByPost(post));
            }
        }
        postRepository.deleteAll(pastDeadline);
    }

 

Post가 성공적으로 지워졌다

{
    "address":"주소주소",
    "store": "storestore",
    "minPrice": 20000,
    "deliveryCost":2000,
    "deadlineHours":0,
    "deadlineMins":2,
    "category":"KOREAN"

}

 

🤓테스트를 해봄🤓

deadlineMins 2인거 1인거 만들고 기다려봤다 

 

시간 지나니까 사라졌다

 

1,2,3분으로 만들어서 넣고 새로고침 계속해봤다

@Scheduled(fixedRate = 5000)
    public void scheduledDelete() {
        List<Post> posts = postRepository.findAll();
        List<Post> pastDeadline  = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for(Post post : posts){
            if(post.getDeadline().compareTo(now)<0){
                pastDeadline.add(post);
                userPostRepository.deleteAll(userPostRepository.findAllByPost(post));
            }
        }
        postRepository.deleteAll(pastDeadline);
    }

아 근데 모집마감이 안 되었고 데드라인 넘긴거만 지워야할듯?

방치된채로 하루 지난것도 걍 지우고!

 

그리고 1분에 한번정도만 실행하면 되지 않을까 싶다

public @interface Scheduled {

이 파일에 들어가서 fixedRate를 찾아봄

/**
	 * Execute the annotated method with a fixed period between invocations.
	 * <p>The time unit is milliseconds by default but can be overridden via
	 * {@link #timeUnit}.
	 * @return the period
	 */
	long fixedRate() default -1;

1분이millisecond로 뭐임

multiply the time value by 60000

1분 → 60000milliseconds

@Scheduled(fixedRate = 60000)//executed every 1 min
    public void scheduledDelete() {
        List<Post> posts = postRepository.findAll();
        List<Post> pastDeadline  = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        for(Post post : posts){
            //delete if the post hasn't been closed and past deadline
            if(post.getPostStatus()==PostStatusEnum.OPEN){
                if(post.getDeadline().compareTo(now)<0){
                    pastDeadline.add(post);
                    userPostRepository.deleteAll(userPostRepository.findAllByPost(post));
                }
            }else{//delete if the post has closed but one more day has passed
                if(post.getDeadline().plusDays(1).compareTo(now)<0){
                    pastDeadline.add(post);
                    userPostRepository.deleteAll(userPostRepository.findAllByPost(post));
                }
            }
        }
        postRepository.deleteAll(pastDeadline);
    }

완성본!

 

⛏️Fix

지금 상태로 테스트하니까 Order에 Menu가 안 옮겨지고 걍 다 삭제됨

Service

@Transactional
    @Override
    public void receiveOrder(PostIdRequest postIdReq, User user) {
        Post post = getPostById(postIdReq.postId());

        //get relations
        List<UserPost> userPosts = getUserPostsByPost(post);
        UserPost userpost = getUserPostByUserIfParticipant(user, userPosts);
        User host = getAuthor(userPosts);

        //make order for me to review
        Order order = makeOrder(post, host, user, UserPostRole.PARTICIPANT);
        orderRepository.save(order);
        //make order for host to review
        Order hostOrder = makeOrder(post, user, host, UserPostRole.HOST);
        orderRepository.save(hostOrder);

        //remove menus from the post
        List<Menu> menus = getUserMenus(user, post);
        menus.forEach(menu -> menuRepository.save(menu.receive(order)));

        if (userPosts.size() <= 2) {
            userPostRepository.deleteAll(userPosts);
            postRepository.delete(post);
            return;
        }
        userPostRepository.delete(userpost);

    }

Menu

public Menu receive(Order order){
        this.order = order;
        this.post.dismissMenu(this);
        this.post = null;
        return this;
    }

Post

@Transactional
    public void dismissMenu(Menu menu) {
        this.menus.remove(menu);
    }
//remove menus from the post
        List<Menu> menus = getUserMenus(user, post);
        menus.forEach(menu -> menuRepository.save(menu.receive(order)));
        postRepository.save(post);

메뉴 삭제한다음에 post도 다시 한번 save를 해봄

저렇게 바꿔도 여전히 post삭제할때 menu가 삭제가 됨

연관관계 해제 어떻게 하는거지..?

양쪽에 null을 넣고 save하는게 안 되나?

public Menu receive(Order order){
        this.order = order;
        //this.post.dismissMenu(this);
        this.post = null;
        return this;
    }

dismissMenu를 빼봄

@Transactional
    @Override
    public void receiveOrder(PostIdRequest postIdReq, User user) {
        Post post = getPostById(postIdReq.postId());

        //get relations
        List<UserPost> userPosts = getUserPostsByPost(post);
        UserPost userpost = getUserPostByUserIfParticipant(user, userPosts);
        User host = getAuthor(userPosts);

        //make order for me to review
        Order order = makeOrder(post, host, user, UserPostRole.PARTICIPANT);
        orderRepository.save(order);
        //make order for host to review
        Order hostOrder = makeOrder(post, user, host, UserPostRole.HOST);
        orderRepository.save(hostOrder);

        //remove menus from the post
        List<Menu> menus = getUserMenus(user, post);
        menus.forEach(menu -> menuRepository.save(menu.receive(order)));
        //postRepository.save(post);

        if (userPosts.size() <= 2) {
            userPostRepository.deleteAll(userPosts);
            postRepository.delete(post);
            return;
        }
        userPostRepository.delete(userpost);

    }

안되는듯하고 너무 졸림 ㅜㅜ

 

1차 시도

Menu의 receive메서드에다가

@Transactional 달아봄 ㅋㅋ 아무소용없을거같긴 한데

public Menu receive(Order order){
        this.order = order;
        this.post.dismissMenu(this);
        this.post = null;
        return this;
    }

아무소용 없었음 post와 함께 삭제됨

3. ON DELETE SET NULL

  • 부모 테이블의 값이 삭제되면 해당 PK를 참조하는 자식 테이블의 FK값들을 NULL값으로 설정해주는 옵션이다.
  • JPA로 설정할 순 없고, DB에서 직접 FK의 설정을 바꿔야 한다.

만약 성능이 고민된다면, 배치 update JPQL을 사용해서 한번에 해당 부모와 관련있는 모든 자식 엔티티의 부모 FK 값을 null로 변경하는 방법도 있다.

부모 엔티티 삭제 시, 자식 엔티티의 FK를 NULL으로 변경하는 방법

https://velog.io/@seulki412/CASCADE-ON-DELETE

https://wrkbr.tistory.com/691

4. FK에 NULL 값을 직접 넣어준다.

3번과 동일한 방법이지만, 직접 비즈니스 로직을 작성하는 방법이다.

오히려 명확한 방법이고 이슈 발생도 적을 것 같다.

Post에서 List<Menu> 를 끊어버림

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "tb_post")
public class Post {

//    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
//    private List<Menu> menus;

//    @Transactional
//    public void dismissMenu(Menu menu) {
//        this.menus.remove(menu);
//    }

}

Menu

@Transactional
    public Menu receive(Order order){
        this.order = order;
        //this.post.dismissMenu(this);
        this.post = null;
        return this;
    }

메뉴테이블에 두개 넣어봄

그리고 receive를 해보면

{
    "postId":"19"
}

java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (moayo.tb_menu, CONSTRAINT FK73ajeiqisy76wg0q7h8nwbcxx FOREIGN KEY (post_id) REFERENCES tb_post (id))

라는 에러가 뜨며 삭제되지 않는다.

 

Cascade 뺐으니 Menu 자동삭제는 안 되는데 연관관계 해제가 안 되는거 같다! 

 

대안 1. 그냥 메뉴 삭제하고 order만 달아서 다시 올리는 방법이 있긴 함

대안 2. orderId도 등록해주고 post는 received 1시간 후에 Cascade로 삭제해봄

→ 일단 대안 2로 해보겠음

@Override
    public void receiveOrder(PostIdRequest postIdReq, User user) {
        Post post = getPostById(postIdReq.postId());

        //get relations
        List<UserPost> userPosts = getUserPostsByPost(post);
        UserPost userpost = getUserPostByUserIfParticipant(user, userPosts);
        User host = getAuthor(userPosts);

        //make order for me to review
        Order order = makeOrder(post, host, user, UserPostRole.PARTICIPANT);
        orderRepository.save(order);
        //make order for host to review
        Order hostOrder = makeOrder(post, user, host, UserPostRole.HOST);
        orderRepository.save(hostOrder);

        //remove menus from the post
        List<Menu> menus = getUserMenus(user, post);
        menus.forEach(menu -> menuRepository.save(menu.receive(order)));

        if (userPosts.size() <= 2) {
            userPostRepository.deleteAll(userPosts);
            postRepository.delete(post);
            return;
        }
        userPostRepository.delete(userpost);

    }

postRepository.delete(post);

이부분 삭제해주고 post의 상태를 received로 변경함

 

아 근데 문제 찾은거같음

지금까지는 cascade로 아예 삭제되어서 몰랐는데 지금보니 orderId도 안 들어가있음

 

💡문제 발견 :  이 코드가 작동되지 않는다.

menus.forEach(menu -> menuRepository.save(menu.receive(order)));

이게 작동을 안 하는거 같았다

 

Post에 이거 만들어줌

public void allReceived(){
        this.postStatus = PostStatusEnum.RECEIVED;
    }

Menu

public Menu receive(Order order){
        this.order = order;
        this.post = null;
        return this;
    }

 

⛳ 해결 : forEach 대신 for문으로 함

//relate the order with the menus
        List<Menu> menus = getUserMenus(user, post);
        for(Menu menu : menus){
            menu = menu.receive(order);
        }
        menuRepository.saveAll(menus);

이렇게 한번 해봄

잘 되었다!

드디어 postId가 null로 변한것을 볼 수 있다(tt2)

 

🚩문제 : tt1과 tt2 둘 다 postId가 null이 되어야 하는데 하나만 null이 됨

당연히 이렇게 하면 host쪽은 저장이 안 됨

//make order for me to review
        Order order = makeOrder(post, host, user, UserPostRole.PARTICIPANT);
        orderRepository.save(order);
        //make order for host to review
        Order hostOrder = makeOrder(post, user, host, UserPostRole.HOST);
        orderRepository.save(hostOrder);

        //relate the order with the menus
        List<Menu> menus = getUserMenus(user, post);
        for(Menu menu : menus){
            menu = menu.receive(order);
        }
        menuRepository.saveAll(menus);

host는 자기 메뉴가 매번 보이는것도 이상하니까 그냥 맨 마지막에만 저장함

@Override
    public void receiveOrder(PostIdRequest postIdReq, User user) {
        Post post = getPostById(postIdReq.postId());

        //get relations
        List<UserPost> userPosts = getUserPostsByPost(post);
        UserPost userpost = getUserPostByUserIfParticipant(user, userPosts);
        User host = getAuthor(userPosts);

        //make order for me to review
        Order order = makeOrder(post, host, user, UserPostRole.PARTICIPANT);
        orderRepository.save(order);
        //make order for host to review
        Order hostOrder = makeOrder(post, user, host, UserPostRole.HOST);
        orderRepository.save(hostOrder);

        //relate the order with the menus
        List<Menu> menus = getUserMenus(user, post);
        for(Menu menu : menus){
            menu = menu.receive(order);
        }
        menuRepository.saveAll(menus);

        if (userPosts.size() <= 2) {
            post.allReceived();
            userPostRepository.deleteAll(userPosts);
            return;
        }
        userPostRepository.delete(userpost);
    }

리팩토링 진행

private Order makeOrder(Post post, User receiver, User user, UserPostRole role) {
        return Order.builder()
            .receiver(receiver)
            .user(user)
            .store(post.getStore())
            .senderRole(role)
            .build();
    }

이미 나름 리팩토링 한거였는데 save도 양쪽에서 다 쓰니까 그냥 메서드 안으로 넣음

private Order makeAndSaveOrder(Post post, User receiver, User user, UserPostRole role) {
        Order order = Order.builder()
            .receiver(receiver)
            .user(user)
            .store(post.getStore())
            .senderRole(role)
            .build();
        orderRepository.save(order);
        return order;
    }

메뉴 저장하는 코드 분리함

 

🚩문제 :  Host 의 Menu 는 글과 함께 사라져버림

 

order에는 둘다 잘 들어가 있다

 

💡문제 발견 : host를 보내줘야하는데 user를 보내줌

⛳ 해결 : host로 바꾸고 다시 한번 해봄

if (userPosts.size() <= 2) {
            post.allReceived();
            relateOrderWithMenus(user,post,hostOrder);-> 지금보니 이부분이 이상하다!!!
            userPostRepository.deleteAll(userPosts);
            postRepository.delete(post);
            return;
        }

 

잘 되었다

 

Menu 테이블

 

Order테이블

 

 

'Developing > 개발일지' 카테고리의 다른 글

2024-01-19,Today I Learned  (0) 2024.01.20
2024-01-18, Today I Learned  (0) 2024.01.18
2024-01-16, Today I Learned  (0) 2024.01.16
2024-01-15, Today I Learned  (0) 2024.01.15
2024-01-14, Today I Learned  (0) 2024.01.15