diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1c38773..6573dd3 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -45,23 +45,18 @@ jobs: distribution: temurin java-version: 17 - # 3) GitHub Secret으로 application.yml 생성 - - name: Make application.yml from secret - shell: bash - run: | - mkdir -p ./src/main/resources - cat > ./src/main/resources/application.yml <<'EOF' - ${{ secrets.APPLICATION_YML }} - EOF - sed -i 's/\r$//' ./src/main/resources/application.yml + # 3) Gradle 캐시(빌드 속도 개선) + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 # 4) gradlew 실행 권한 - name: Grant execute permission for gradlew run: chmod +x ./gradlew - # 5) 빌드 + # 5) 빌드(테스트 포함) + # 테스트는 src/test/resources/application.yml(H2) 설정으로 자동 실행됨 - name: Build with Gradle - run: ./gradlew clean build + run: ./gradlew clean build --no-daemon # 6) 테스트 리포트 업로드 - name: Upload Test Reports diff --git "a/docs/Chapter4/\354\233\214\355\201\254\353\266\2014.png" "b/docs/Chapter4/\354\233\214\355\201\254\353\266\2014.png" new file mode 100644 index 0000000..8adbba7 Binary files /dev/null and "b/docs/Chapter4/\354\233\214\355\201\254\353\266\2014.png" differ diff --git "a/docs/Chapter4/\355\205\214\354\235\264\353\270\224 DDL" "b/docs/Chapter4/\355\205\214\354\235\264\353\270\224 DDL" new file mode 100644 index 0000000..2d6c0e5 --- /dev/null +++ "b/docs/Chapter4/\355\205\214\354\235\264\353\270\224 DDL" @@ -0,0 +1,244 @@ + +create table event_notice +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + content varchar(255) not null, + title varchar(150) not null +); + +create table food_category +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + category_name varchar(10) not null +); + +create table inquiry_notice +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + content varchar(255) not null, + title varchar(150) not null +); + +create table region +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + region_name varchar(50) not null +); + +create table restaurant +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + owner_number bigint null, + rating double not null, + restaurant_category varchar(50) not null, + restaurant_name varchar(50) not null, + region_id bigint null, + constraint FKa42f32i7rvo56cb6laomg565s + foreign key (region_id) references region (id) +); + +create table mission +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + deadline date not null, + mission_name varchar(50) not null, + mission_point int not null, + restaurant_id bigint null, + constraint FKgae6qenatvwyoxwh163hm1sp + foreign key (restaurant_id) references restaurant (id) +); + +create table review_notice +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + content varchar(255) not null, + title varchar(150) not null +); + +create table term +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + term_name enum ('AGE', 'LOCATION', 'MARKETING', 'PRIVACY', 'SERVICE') not null +); + +create table user +( + id bigint auto_increment + primary key, + address varchar(125) not null, + birth date not null, + gender enum ('FEMALE', 'MALE', 'NONE') not null, + is_active bit not null, + name varchar(10) not null, + phone_num varchar(15) not null, + phone_verification_status enum ('UNVERIFIED', 'VERIFIED') not null, + point int not null, + social_type enum ('APPLE', 'GOOGLE', 'KAKAO', 'NAVER') null +); + +create table inquiry +( + id bigint auto_increment + primary key, + inquiry_content varchar(255) not null, + inquiry_title varchar(150) not null, + inquiry_type enum ('ACCOUNT', 'EVENT', 'GENERAL', 'OTHER', 'REVIEW') not null, + user_id bigint not null, + constraint FKff1ylwlwujmed7diqs8ykf6pv + foreign key (user_id) references user (id) +); + +create table inquiry_photo +( + id bigint auto_increment + primary key, + inquiry_photo_url varchar(255) null, + inquiry_id bigint not null, + constraint FK9m88uysxflyu2jdoehj473bs + foreign key (inquiry_id) references inquiry (id) +); + +create table inquiry_reply +( + id bigint auto_increment + primary key, + inquiry_content varchar(255) not null, + inquiry_id bigint not null, + constraint FKlswrro8h5dy5y2ba8q9useih7 + foreign key (inquiry_id) references inquiry (id) +); + +create table notice +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + is_confirmed bit not null, + event_notice_id bigint not null, + inquiry_notice_id bigint not null, + review_notice_id bigint not null, + user_id bigint not null, + constraint UK4k97mbcsgk6w6dh6xjuma9n29 + unique (event_notice_id), + constraint UK76earbdvxb80rb530qcq2cpbx + unique (inquiry_notice_id), + constraint UKg0b3vrsrje34nvekb1l3cbc7o + unique (review_notice_id), + constraint FK6vmstvjnqtftlrk5yobu8xk4j + foreign key (review_notice_id) references review_notice (id), + constraint FKbhhoinw4ffgwdn2pps37nmqqs + foreign key (event_notice_id) references event_notice (id), + constraint FKcvf4mh5se36inrxn7xlh2brfv + foreign key (user_id) references user (id), + constraint FKns7lmqww3hp3tf5xd03o6ev1 + foreign key (inquiry_notice_id) references inquiry_notice (id) +); + +create table review +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + rating double not null, + review_content varchar(255) not null, + restaurant_id bigint not null, + user_id bigint not null, + constraint FK70ry7cuti298yxet366rynxch + foreign key (restaurant_id) references restaurant (id), + constraint FKiyf57dy48lyiftdrf7y87rnxi + foreign key (user_id) references user (id) +); + +create table reply +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + reply_content varchar(255) null, + review_id bigint not null, + constraint UK4uh4vegunuxj6p9ilmeyy6gm2 + unique (review_id), + constraint FKd5ckwt38d4ibe84wlfc3o8jw8 + foreign key (review_id) references review (id) +); + +create table review_photo +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + photo_url varchar(255) null, + review_id bigint not null, + constraint FK80ti8nek4uv8vn4vjhpre6mwg + foreign key (review_id) references review (id) +); + +create table user_mission +( + id bigint auto_increment + primary key, + is_completed bit not null, + mission_id bigint not null, + user_id bigint not null, + constraint FKdlc6c9h0rifeykrviy3fgmygv + foreign key (mission_id) references mission (id), + constraint FKfsmo8ipks83kcuqtky39hxyvc + foreign key (user_id) references user (id) +); + +create table user_preferrence_food +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + food_id bigint not null, + user_id bigint not null, + constraint FK9oxejgu6kw58dbywwjiee06w4 + foreign key (user_id) references user (id), + constraint FKld36amxnmtmkupbhf7kcaeaec + foreign key (food_id) references food_category (id) +); + +create table user_term +( + id bigint auto_increment + primary key, + created_at datetime(6) not null, + updated_at datetime(6) not null, + term_id bigint not null, + user_id bigint not null, + constraint FK1q9gmsebfsty95vmb262jers + foreign key (term_id) references term (id), + constraint FK3wbl3i7dlc7ctj7ris8vtbhd1 + foreign key (user_id) references user (id) +); + diff --git a/src/main/java/com/example/umc9th/domain/inquiry/entity/Inquiry.java b/src/main/java/com/example/umc9th/domain/inquiry/entity/Inquiry.java new file mode 100644 index 0000000..d7e1778 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/inquiry/entity/Inquiry.java @@ -0,0 +1,42 @@ +package com.example.umc9th.domain.inquiry.entity; + +import com.example.umc9th.domain.inquiry.enums.InquiryType; +import com.example.umc9th.domain.member.entity.Member; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "inquiry") +public class Inquiry { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "inquiry_title", length = 150, nullable = false) + private String inquiryTitle; + + @Column(name = "inquiry_content", nullable = false) + private String inquiryContent; + + @Column(name = "inquiry_type", length = 20, nullable = false) + @Enumerated(EnumType.STRING) + private InquiryType inquiryType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @OneToMany(mappedBy = "inquiry", cascade = CascadeType.REMOVE) + private List photos = new ArrayList<>(); + + @OneToMany(mappedBy = "inquiry", cascade = CascadeType.REMOVE) + private List replies = new ArrayList<>(); + +} diff --git a/src/main/java/com/example/umc9th/domain/inquiry/entity/InquiryPhoto.java b/src/main/java/com/example/umc9th/domain/inquiry/entity/InquiryPhoto.java new file mode 100644 index 0000000..0b1151c --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/inquiry/entity/InquiryPhoto.java @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.inquiry.entity; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "inquiry_photo") +public class InquiryPhoto { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "inquiry_photo_url") + private String inquiryPhotoUrl; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "inquiry_id", nullable = false) + private Inquiry inquiry; +} diff --git a/src/main/java/com/example/umc9th/domain/inquiry/entity/InquiryReply.java b/src/main/java/com/example/umc9th/domain/inquiry/entity/InquiryReply.java new file mode 100644 index 0000000..df83e91 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/inquiry/entity/InquiryReply.java @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.inquiry.entity; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "inquiry_reply") +public class InquiryReply { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "inquiry_content", nullable = false) + private String inquiryContent; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "inquiry_id", nullable = false) + private Inquiry inquiry; +} diff --git a/src/main/java/com/example/umc9th/domain/inquiry/enums/InquiryType.java b/src/main/java/com/example/umc9th/domain/inquiry/enums/InquiryType.java new file mode 100644 index 0000000..9cbf11b --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/inquiry/enums/InquiryType.java @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.inquiry.enums; + +public enum InquiryType { + GENERAL, ACCOUNT, REVIEW, EVENT, OTHER +} diff --git a/src/main/java/com/example/umc9th/domain/member/entity/Food.java b/src/main/java/com/example/umc9th/domain/member/entity/Food.java new file mode 100644 index 0000000..8307a32 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/entity/Food.java @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.member.entity; + +import com.example.umc9th.domain.member.entity.mapping.MemberFood; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "food_category") +public class Food extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "category_name", length = 10, nullable = false) + private String categoryName; // 음식 카테고리 + + @OneToMany(mappedBy = "food", cascade = CascadeType.REMOVE) + private List memberFoodList = new ArrayList<>(); +} diff --git a/src/main/java/com/example/umc9th/domain/member/entity/Member.java b/src/main/java/com/example/umc9th/domain/member/entity/Member.java new file mode 100644 index 0000000..f0c5404 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/entity/Member.java @@ -0,0 +1,73 @@ +package com.example.umc9th.domain.member.entity; + +import com.example.umc9th.domain.mission.entity.mapping.MemberMission; +import com.example.umc9th.domain.member.entity.mapping.MemberFood; +import com.example.umc9th.domain.member.entity.mapping.MemberTerm; +import com.example.umc9th.domain.member.enums.Gender; +import com.example.umc9th.domain.member.enums.PhoneVerificationStatus; +import com.example.umc9th.domain.member.enums.SocialType; +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "member") +public class Member { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name", length = 10, nullable = false) + private String name; + + @Column(name = "gender", nullable = false) + @Enumerated(EnumType.STRING) + @Builder.Default + private Gender gender = Gender.NONE; + + @Column(name = "phone_num", length = 15, nullable = false) + private String phoneNum; + + @Column(name = "birth", nullable = false) + private LocalDate birth; + + @Column(name = "address", length = 125, nullable = false) + private String address; + + + @Column(name = "point", nullable = false) + @Builder.Default + private Integer point = 0; + + @Column(name = "social_type") + @Enumerated(EnumType.STRING) + private SocialType socialType; + + @Column(name = "email", length = 50) + private String email; + + @Column(name = "phone_verification_status", nullable = false) + @Enumerated(EnumType.STRING) + @Builder.Default + private PhoneVerificationStatus phoneVerificationStatus = PhoneVerificationStatus.UNVERIFIED; + + @Column(name = "is_active", nullable = false) + @Builder.Default + private Boolean isActive = true; + + @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE) + private List memberFoodList = new ArrayList<>(); + + @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE) + private List memberTermList = new ArrayList<>(); + + @OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE) + private List memberMissionList = new ArrayList<>(); +} diff --git a/src/main/java/com/example/umc9th/domain/member/entity/Term.java b/src/main/java/com/example/umc9th/domain/member/entity/Term.java new file mode 100644 index 0000000..0c646e9 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/entity/Term.java @@ -0,0 +1,29 @@ +package com.example.umc9th.domain.member.entity; + +import com.example.umc9th.domain.member.entity.mapping.MemberTerm; +import com.example.umc9th.domain.member.enums.TermName; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "term") +public class Term extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "term_name", nullable = false) + @Enumerated(EnumType.STRING) + private TermName name; + + @OneToMany(mappedBy = "term", cascade = CascadeType.REMOVE) + private List memberTermList = new ArrayList<>(); +} diff --git a/src/main/java/com/example/umc9th/domain/member/entity/mapping/MemberFood.java b/src/main/java/com/example/umc9th/domain/member/entity/mapping/MemberFood.java new file mode 100644 index 0000000..699193d --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/entity/mapping/MemberFood.java @@ -0,0 +1,29 @@ +package com.example.umc9th.domain.member.entity.mapping; + + +import com.example.umc9th.domain.member.entity.Food; +import com.example.umc9th.domain.member.entity.Member; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "member_preferrence_food") +public class MemberFood extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "food_id", nullable = false) + private Food food; + +} diff --git a/src/main/java/com/example/umc9th/domain/member/entity/mapping/MemberTerm.java b/src/main/java/com/example/umc9th/domain/member/entity/mapping/MemberTerm.java new file mode 100644 index 0000000..b85fd86 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/entity/mapping/MemberTerm.java @@ -0,0 +1,28 @@ +package com.example.umc9th.domain.member.entity.mapping; + +import com.example.umc9th.domain.member.entity.Term; +import com.example.umc9th.domain.member.entity.Member; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "member_term") +public class MemberTerm extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "term_id", nullable = false) + private Term term; + +} diff --git a/src/main/java/com/example/umc9th/domain/member/enums/Gender.java b/src/main/java/com/example/umc9th/domain/member/enums/Gender.java new file mode 100644 index 0000000..400401b --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/enums/Gender.java @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.member.enums; + +public enum Gender { + MALE, FEMALE, NONE +} diff --git a/src/main/java/com/example/umc9th/domain/member/enums/PhoneVerificationStatus.java b/src/main/java/com/example/umc9th/domain/member/enums/PhoneVerificationStatus.java new file mode 100644 index 0000000..d4acc3b --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/enums/PhoneVerificationStatus.java @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.member.enums; + +public enum PhoneVerificationStatus { + UNVERIFIED, VERIFIED +} diff --git a/src/main/java/com/example/umc9th/domain/member/enums/SocialType.java b/src/main/java/com/example/umc9th/domain/member/enums/SocialType.java new file mode 100644 index 0000000..068cf10 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/enums/SocialType.java @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.member.enums; + +public enum SocialType { + KAKAO, NAVER, APPLE, GOOGLE +} diff --git a/src/main/java/com/example/umc9th/domain/member/enums/TermName.java b/src/main/java/com/example/umc9th/domain/member/enums/TermName.java new file mode 100644 index 0000000..db0e6a8 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/enums/TermName.java @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.member.enums; + +public enum TermName { + AGE, SERVICE, PRIVACY, LOCATION, MARKETING +} diff --git a/src/main/java/com/example/umc9th/domain/member/repository/MemberRepository.java b/src/main/java/com/example/umc9th/domain/member/repository/MemberRepository.java new file mode 100644 index 0000000..f9b12fa --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/member/repository/MemberRepository.java @@ -0,0 +1,11 @@ +package com.example.umc9th.domain.member.repository; + +import com.example.umc9th.domain.member.entity.Member; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface MemberRepository extends JpaRepository { + // 활성 상태인 회원 단건 조회 + Optional findByIdAndIsActiveTrue(Long id); +} diff --git a/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java b/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java new file mode 100644 index 0000000..f769910 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java @@ -0,0 +1,39 @@ +package com.example.umc9th.domain.mission.entity; + +import com.example.umc9th.domain.mission.entity.mapping.MemberMission; +import com.example.umc9th.domain.restaurant.entity.Restaurant; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "mission") +public class Mission extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "mission_name", length = 50, nullable = false) + private String missionName; + + @Column(name = "deadline", nullable = false) + private LocalDate deadline; + + @Column(name = "mission_point", nullable = false) + private Integer missionPoint; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "restaurant_id") + private Restaurant restaurant; + + @OneToMany(mappedBy = "mission") + private List memberMissionList = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/com/example/umc9th/domain/mission/entity/mapping/MemberMission.java b/src/main/java/com/example/umc9th/domain/mission/entity/mapping/MemberMission.java new file mode 100644 index 0000000..94c8ec1 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/mission/entity/mapping/MemberMission.java @@ -0,0 +1,29 @@ +package com.example.umc9th.domain.mission.entity.mapping; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.member.entity.Member; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "member_mission") +public class MemberMission { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "is_completed", nullable = false) + private boolean isCompleted; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id", nullable = false) + private Mission mission; +} diff --git a/src/main/java/com/example/umc9th/domain/mission/repository/MemberMissionRepository.java b/src/main/java/com/example/umc9th/domain/mission/repository/MemberMissionRepository.java new file mode 100644 index 0000000..951f301 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/mission/repository/MemberMissionRepository.java @@ -0,0 +1,16 @@ +package com.example.umc9th.domain.mission.repository; + +import com.example.umc9th.domain.mission.entity.mapping.MemberMission; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface MemberMissionRepository extends JpaRepository { + // 내가 진행 중인 미션 조회 + Page findAllByMember_IdAndIsCompletedFalse(Long memberId, Pageable pageable); + + // 내가 진행 완료한 미션 조회 + Page findAllByMember_IdAndIsCompletedTrue(Long memberId, Pageable pageable); +} diff --git a/src/main/java/com/example/umc9th/domain/mission/repository/MissionRepository.java b/src/main/java/com/example/umc9th/domain/mission/repository/MissionRepository.java new file mode 100644 index 0000000..952d9f4 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/mission/repository/MissionRepository.java @@ -0,0 +1,31 @@ +package com.example.umc9th.domain.mission.repository; + +import com.example.umc9th.domain.mission.entity.Mission; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.time.LocalDate; + +public interface MissionRepository extends JpaRepository { + + // 지역ID + 오늘 이후 마감 + 해당 회원이 '완료'한 미션 제외 + @Query(""" + select m + from Mission m + join m.restaurant r + left join m.memberMissionList mm + with mm.member.id = :memberId + where r.region.id = :regionId + and m.deadline >= :today + and (mm is null or mm.isCompleted = false) + """) + Page findAvailableMissionsByRegionId( + @Param("memberId") Long memberId, + @Param("regionId") Long regionId, + @Param("today") LocalDate today, + Pageable pageable + ); +} diff --git a/src/main/java/com/example/umc9th/domain/notification/entity/EventNotice.java b/src/main/java/com/example/umc9th/domain/notification/entity/EventNotice.java new file mode 100644 index 0000000..ed17111 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/notification/entity/EventNotice.java @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.notification.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "event_notice") +public class EventNotice extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "title", length = 150, nullable = false) + private String title; + + @Column(name = "content", nullable = false) + private String content; +} diff --git a/src/main/java/com/example/umc9th/domain/notification/entity/InquiryNotice.java b/src/main/java/com/example/umc9th/domain/notification/entity/InquiryNotice.java new file mode 100644 index 0000000..82fb6f3 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/notification/entity/InquiryNotice.java @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.notification.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "inquiry_notice") +public class InquiryNotice extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "title", length = 150, nullable = false) + private String title; + + @Column(name = "content", nullable = false) + private String content; +} diff --git a/src/main/java/com/example/umc9th/domain/notification/entity/Notice.java b/src/main/java/com/example/umc9th/domain/notification/entity/Notice.java new file mode 100644 index 0000000..d047a5e --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/notification/entity/Notice.java @@ -0,0 +1,37 @@ +package com.example.umc9th.domain.notification.entity; + +import com.example.umc9th.domain.member.entity.Member; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "notice") +public class Notice extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "is_confirmed", nullable = false) + private boolean isConfirmed; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "event_notice_id", nullable = false) + private EventNotice eventNotice; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_notice_id", nullable = false) + private ReviewNotice reviewNotice; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "Inquiry_notice_id", nullable = false) + private InquiryNotice inquiryNotice; +} diff --git a/src/main/java/com/example/umc9th/domain/notification/entity/ReviewNotice.java b/src/main/java/com/example/umc9th/domain/notification/entity/ReviewNotice.java new file mode 100644 index 0000000..76cad93 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/notification/entity/ReviewNotice.java @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.notification.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_notice") +public class ReviewNotice extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "title", length = 150, nullable = false) + private String title; + + @Column(name = "content", nullable = false) + private String content; +} diff --git a/src/main/java/com/example/umc9th/domain/restaurant/entity/Region.java b/src/main/java/com/example/umc9th/domain/restaurant/entity/Region.java new file mode 100644 index 0000000..12b74e5 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/restaurant/entity/Region.java @@ -0,0 +1,26 @@ +package com.example.umc9th.domain.restaurant.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "region") +public class Region extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "region_name", length = 50, nullable = false) + private String regionName; + + @OneToMany(mappedBy="region") + private List restaurants = new ArrayList<>(); +} diff --git a/src/main/java/com/example/umc9th/domain/restaurant/entity/Restaurant.java b/src/main/java/com/example/umc9th/domain/restaurant/entity/Restaurant.java new file mode 100644 index 0000000..96e3abb --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/restaurant/entity/Restaurant.java @@ -0,0 +1,43 @@ +package com.example.umc9th.domain.restaurant.entity; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "restaurant") +public class Restaurant extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "restaurant_name", length = 50, nullable = false) + private String restaurantName; + + @Column(name = "restaurant_category", length = 50, nullable = false) + private String restaurantCategory; + + @Column(name = "rating", nullable = false) + @Builder.Default + private Double rating = 0.0; + + @Column(name = "owner_number") + private Long ownerNumber; // Integer가 나을까?? + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "region_id") + private Region region; + + @OneToMany(mappedBy="restaurant", cascade = CascadeType.REMOVE) + private List missions = new ArrayList<>(); + +} + diff --git a/src/main/java/com/example/umc9th/domain/review/entity/Reply.java b/src/main/java/com/example/umc9th/domain/review/entity/Reply.java new file mode 100644 index 0000000..b541a12 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/review/entity/Reply.java @@ -0,0 +1,26 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Table(name = "reply") +public class Reply extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "reply_content") + private String replyContent; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id", nullable = false) + private Review review; +} diff --git a/src/main/java/com/example/umc9th/domain/review/entity/Review.java b/src/main/java/com/example/umc9th/domain/review/entity/Review.java new file mode 100644 index 0000000..15b5f08 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/review/entity/Review.java @@ -0,0 +1,43 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.domain.restaurant.entity.Restaurant; +import com.example.umc9th.domain.member.entity.Member; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review") +public class Review extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "review_content", nullable = false) + private String reviewContent; + + @Column(name = "rating", nullable = false) + @Builder.Default + private Double rating = 0.0; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "restaurant_id", nullable = false) + private Restaurant restaurant; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + private Member member; + + @OneToOne(mappedBy = "review", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private Reply reply; + + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL) + private List reviewPhotos = new ArrayList<>(); +} diff --git a/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java b/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java new file mode 100644 index 0000000..c88df27 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java @@ -0,0 +1,24 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_photo") +public class ReviewPhoto extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "photo_url") + private String photoUrl; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id", nullable = false) + private Review review; +} diff --git a/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java b/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java new file mode 100644 index 0000000..37161b0 --- /dev/null +++ b/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java @@ -0,0 +1,17 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.member.entity.Member; +import com.example.umc9th.domain.restaurant.entity.Restaurant; +import com.example.umc9th.domain.review.entity.Review; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ReviewRepository extends JpaRepository { + // 특정 식당의 리뷰 조회 + List findByRestaurant(Restaurant restaurant); + + // 특정 회원이 작성한 리뷰 조회 + List findByMember(Member member, Pageable pageable); +} diff --git a/src/main/java/com/example/umc9th/global/entity/BaseEntity.java b/src/main/java/com/example/umc9th/global/entity/BaseEntity.java new file mode 100644 index 0000000..963b7cf --- /dev/null +++ b/src/main/java/com/example/umc9th/global/entity/BaseEntity.java @@ -0,0 +1,25 @@ +package com.example.umc9th.global.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public class BaseEntity { + @CreatedDate + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index a0d89d4..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=umc9th diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..7a9401f --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,19 @@ +spring: + application: + name: "umc9th" # "umc9th" + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver # MySQL JDBC ???? ??? ?? + url: ${DB_URL} # jdbc:mysql://localhost:3306/{???????} + username: ${DB_USER} # MySQL ?? ?? + password: ${DB_PW} # MySQL ???? + + jpa: + database: mysql # ??? ?????? ?? ?? (MySQL) + database-platform: org.hibernate.dialect.MySQLDialect # Hibernate?? ??? MySQL ??(dialect) ?? + show-sql: true # ??? SQL ??? ??? ???? ?? ?? + hibernate: + ddl-auto: update # ?????? ?? ? ?????? ???? ??? ?? + properties: + hibernate: + format_sql: true # ???? SQL ??? ?? ?? ??? \ No newline at end of file diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..b356347 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: sa + password: + jpa: + database-platform: org.hibernate.dialect.H2Dialect + hibernate: + ddl-auto: create-drop