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

feat: 공모 상세 조회 기능 구현 #18

Merged
merged 11 commits into from
Jul 22, 2024
5 changes: 5 additions & 0 deletions backend/http/http-client.env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"local": {
"base-url": "localhost:8080"
}
}
2 changes: 2 additions & 0 deletions backend/http/offering.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### 공동구매 상세 조회 API
GET {{base-url}}/offerings/1
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.zzang.chongdae.comment.repository;
package com.zzang.chongdae.comment.repository.entity;

import com.zzang.chongdae.common.repository.BaseTimeEntity;
import com.zzang.chongdae.member.repository.Member;
import com.zzang.chongdae.offering.repository.Offering;
import com.zzang.chongdae.common.repository.entity.BaseTimeEntity;
import com.zzang.chongdae.member.repository.entity.MemberEntity;
import com.zzang.chongdae.offering.repository.entity.OfferingEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
Expand All @@ -19,18 +20,19 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@EqualsAndHashCode(of = "id", callSuper = false)
@Table(name = "comment")
@Entity
public class Comment extends BaseTimeEntity {
public class CommentEntity extends BaseTimeEntity {

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

@ManyToOne
private Member member;
private MemberEntity member;

@ManyToOne
private Offering offering;
private OfferingEntity offering;

@Column(length = 80)
private String content;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.zzang.chongdae.common.repository;
package com.zzang.chongdae.common.repository.entity;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
Expand All @@ -24,4 +24,4 @@ public abstract class BaseTimeEntity {
@NotNull
@Column
private LocalDateTime updatedAt;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.zzang.chongdae.member.repository;
package com.zzang.chongdae.member.repository.entity;

import com.zzang.chongdae.common.repository.BaseTimeEntity;
import com.zzang.chongdae.common.repository.entity.BaseTimeEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
Expand All @@ -17,8 +18,9 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@EqualsAndHashCode(of = "id", callSuper = false)
@Table(name = "member")
@Entity
public class Member extends BaseTimeEntity {
public class MemberEntity extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -27,4 +29,4 @@ public class Member extends BaseTimeEntity {
@NotNull
@Column(unique = true)
private String nickname;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.zzang.chongdae.offering.controller;

import com.zzang.chongdae.offering.service.OfferingService;
import com.zzang.chongdae.offering.service.dto.OfferingDetailResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@RequiredArgsConstructor
@Controller
public class OfferingController {

private final OfferingService offeringService;

@GetMapping("/offerings/{offering-id}")
public ResponseEntity<OfferingDetailResponse> getOfferingDetail(@PathVariable(value = "offering-id") Long id) {
OfferingDetailResponse response = offeringService.getOfferingDetail(id);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.zzang.chongdae.offering.domain;

public enum OfferingCondition {

FULL,
TIME_OUT,
CONFIRMED,
AVAILABLE;

public static OfferingCondition decideBy(OfferingStatus offeringStatus) {
if (offeringStatus.isCountFull()) {
return OfferingCondition.FULL;
}
if (offeringStatus.isDeadlineOver()) {
return OfferingCondition.TIME_OUT;
}
if (offeringStatus.isManualConfirmed() || offeringStatus.isAutoConfirmed()) {
return OfferingCondition.CONFIRMED;
}
return OfferingCondition.AVAILABLE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.zzang.chongdae.offering.domain;

import java.math.BigDecimal;
import java.math.RoundingMode;
import lombok.AllArgsConstructor;

@AllArgsConstructor
public class OfferingPrice {

private final Integer totalCount;
private final BigDecimal totalPrice;

public BigDecimal calculateDividedPrice() {
return totalPrice.divide(BigDecimal.valueOf(totalCount), RoundingMode.HALF_UP);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.zzang.chongdae.offering.domain;

import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class OfferingStatus {

private final LocalDateTime deadline;
private final int totalCount;
private final boolean isManualConfirmed;
private final int currentCount;

public OfferingCondition decideOfferingCondition() {
return OfferingCondition.decideBy(this);
}

public boolean isCountFull() {
return this.totalCount == this.currentCount;
}

public boolean isDeadlineOver() {
return LocalDateTime.now().isAfter(this.deadline);
}

public boolean isAutoConfirmed() {
return isCountFull() && isDeadlineOver();
}

public boolean isManualConfirmed() {
return isManualConfirmed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.zzang.chongdae.offering.repository;

import com.zzang.chongdae.offering.repository.entity.OfferingEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OfferingRepository extends JpaRepository<OfferingEntity, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.zzang.chongdae.offering.repository;
package com.zzang.chongdae.offering.repository.entity;

import com.zzang.chongdae.common.repository.BaseTimeEntity;
import com.zzang.chongdae.member.repository.Member;
import com.zzang.chongdae.common.repository.entity.BaseTimeEntity;
import com.zzang.chongdae.member.repository.entity.MemberEntity;
import com.zzang.chongdae.offering.domain.OfferingPrice;
import com.zzang.chongdae.offering.domain.OfferingStatus;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
Expand All @@ -21,15 +24,16 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@EqualsAndHashCode(of = "id", callSuper = false)
@Table(name = "offering")
@Entity
public class Offering extends BaseTimeEntity {
public class OfferingEntity extends BaseTimeEntity {

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

@ManyToOne
private Member member;
private MemberEntity member;

@NotNull
private String title;
Expand Down Expand Up @@ -60,4 +64,12 @@ public class Offering extends BaseTimeEntity {

@NotNull
private BigDecimal totalPrice;

public OfferingPrice toOfferingPrice() {
return new OfferingPrice(totalCount, totalPrice);
}

public OfferingStatus toOfferingStatus(int currentCount) {
return new OfferingStatus(deadline, totalCount, isManualConfirmed, currentCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.zzang.chongdae.offering.service;

import com.zzang.chongdae.offering.domain.OfferingPrice;
import com.zzang.chongdae.offering.domain.OfferingStatus;
import com.zzang.chongdae.offering.repository.OfferingRepository;
import com.zzang.chongdae.offering.repository.entity.OfferingEntity;
import com.zzang.chongdae.offering.service.dto.OfferingDetailResponse;
import com.zzang.chongdae.offeringmember.repository.OfferingMemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class OfferingService {

private final OfferingRepository offeringRepository;
private final OfferingMemberRepository offeringMemberRepository;

public OfferingDetailResponse getOfferingDetail(Long id) {
OfferingEntity offering = offeringRepository.findById(id)
.orElseThrow(); // TODO: 예외 처리하기

OfferingPrice offeringPrice = offering.toOfferingPrice();
int currentCount = offeringMemberRepository.countByOffering(offering);
OfferingStatus offeringStatus = offering.toOfferingStatus(currentCount);

return new OfferingDetailResponse(offering, offeringPrice, offeringStatus);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.zzang.chongdae.offering.service.dto;

import com.zzang.chongdae.offering.domain.OfferingCondition;
import com.zzang.chongdae.offering.domain.OfferingPrice;
import com.zzang.chongdae.offering.domain.OfferingStatus;
import com.zzang.chongdae.offering.repository.entity.OfferingEntity;
import java.math.BigDecimal;
import java.time.LocalDateTime;

public record OfferingDetailResponse(Long id,
String title,
String nickname,
String productUrl,
String meetingAddress,
String meetingAddressDetail,
String description,
LocalDateTime deadline,
Integer currentCount,
Integer totalCount,
String thumbnailUrl,
BigDecimal dividedPrice,
BigDecimal totalPrice,
OfferingCondition status) {

public OfferingDetailResponse(OfferingEntity offering, OfferingPrice offeringPrice, OfferingStatus offeringStatus) {
this(offering.getId(),
offering.getTitle(),
offering.getMember().getNickname(),
offering.getProductUrl(),
offering.getMeetingAddress(),
offering.getMeetingAddressDetail(),
offering.getDescription(),
offering.getDeadline(),
offeringStatus.getCurrentCount(),
offering.getTotalCount(),
offering.getThumbnailUrl(),
offeringPrice.calculateDividedPrice(),
offering.getTotalPrice(),
offeringStatus.decideOfferingCondition()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.zzang.chongdae.offeringmember.domain;

public enum OfferingMemberRole {

PROPOSER,
PARTICIPANT; // TODO: entity 패키지와 domain 패키지 중 위치 고민하기 (feat. vo)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.zzang.chongdae.offeringmember.repository;

import com.zzang.chongdae.offering.repository.entity.OfferingEntity;
import com.zzang.chongdae.offeringmember.repository.entity.OfferingMemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface OfferingMemberRepository extends JpaRepository<OfferingMemberEntity, Long> {

int countByOffering(OfferingEntity offering);
}

This file was deleted.

Loading