34
Dockerfile
34
Dockerfile
@@ -1,34 +0,0 @@
|
||||
FROM adoptopenjdk/openjdk11:latest as BUILD_IMAGE
|
||||
|
||||
ENV WORK_DIR=/usr/app/
|
||||
|
||||
# app 작업 디렉토리 설정
|
||||
WORKDIR $WORK_DIR
|
||||
|
||||
# gradle 실행을 위한 필수 디렉토리 준비
|
||||
COPY gradlew $WORK_DIR
|
||||
COPY build.gradle $WORK_DIR
|
||||
COPY settings.gradle $WORK_DIR
|
||||
COPY gradle $WORK_DIR/gradle
|
||||
|
||||
RUN ./gradlew -x test build || return 0
|
||||
|
||||
COPY src src
|
||||
|
||||
# jar 파일 build
|
||||
RUN ./gradlew bootjar
|
||||
|
||||
FROM adoptopenjdk/openjdk11:latest
|
||||
|
||||
ENV WORK_DIR=/usr/app/
|
||||
|
||||
WORKDIR $WORK_DIR
|
||||
|
||||
COPY --from=BUILD_IMAGE $WORK_DIR/build/libs/*.jar app-server.jar
|
||||
|
||||
ENTRYPOINT ["java", \
|
||||
"-jar", \
|
||||
"-Dspring.profiles.active=${PROFILE_OPTION}", \
|
||||
"-Dspring.datasource.url=${SPRING_DATASOURCE_URL}", \
|
||||
"-Dredis.host=${REDIS_HOST}", \
|
||||
"app-server.jar"]
|
||||
@@ -1,4 +1,9 @@
|
||||
# 동네 카페 전용 사이렌 오더 서비스
|
||||
|
||||
- 스타벅스 사이렌 오더에 착안해 소규모 카페에도 적용해볼 수 있지 않을까해서 만든 프로젝트
|
||||
- 수많은 사용자들이 유입돼도 어떻게 하면 신뢰성있고 안정적인 서버를 구축할 수 있을지에 대한 고민
|
||||
개인 프로젝트
|
||||
|
||||
## Specification
|
||||
- java 17
|
||||
- kotlin 1.6.21
|
||||
- Spring Boot 2.7.0
|
||||
- MySQL
|
||||
|
||||
72
build.gradle
72
build.gradle
@@ -1,48 +1,74 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.5.4'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id 'java'
|
||||
buildscript {
|
||||
ext {
|
||||
springBootVersion = '2.7.0'
|
||||
dependencyManagementVersion = '1.0.11.RELEASE'
|
||||
kotlinVersion = '1.6.21'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
|
||||
classpath "io.spring.gradle:dependency-management-plugin:${dependencyManagementVersion}"
|
||||
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
|
||||
classpath "org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}"
|
||||
classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'kotlin-spring'
|
||||
apply plugin: "kotlin-jpa"
|
||||
apply plugin: "kotlin-noarg"
|
||||
apply plugin: "kotlin-allopen"
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
group = 'io.beaniejoy.dongecafe'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
sourceCompatibility = '11'
|
||||
|
||||
configurations {
|
||||
compileOnly {
|
||||
extendsFrom annotationProcessor
|
||||
}
|
||||
}
|
||||
sourceCompatibility = '17'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
allOpen {
|
||||
annotation("javax.persistence.Entity")
|
||||
annotation("javax.persistence.MappedSuperclass")
|
||||
annotation("javax.persistence.Embeddable")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
|
||||
implementation('io.github.microutils:kotlin-logging:2.1.21')
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
|
||||
// log4j2
|
||||
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-log4j2'
|
||||
// implementation 'org.springframework.boot:spring-boot-starter-log4j2'
|
||||
// testImplementation 'org.springframework.boot:spring-boot-starter-log4j2'
|
||||
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
|
||||
// MySQL
|
||||
runtimeOnly 'mysql:mysql-connector-java'
|
||||
runtimeOnly 'mysql:mysql-connector-java' // MySQL
|
||||
runtimeOnly 'com.h2database:h2' // H2
|
||||
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
configurations {
|
||||
all {
|
||||
// log4j2 적용을 위해 기존 spring boot에서 제공하는 logging exclude
|
||||
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
|
||||
}
|
||||
}
|
||||
//configurations {
|
||||
// all {
|
||||
// // log4j2 적용을 위해 기존 spring boot에서 제공하는 logging exclude
|
||||
// exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
|
||||
// }
|
||||
//}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
nginx:
|
||||
image: nginx
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./nginx/:/etc/nginx/conf.d/
|
||||
depends_on:
|
||||
- app-server-1
|
||||
- app-server-2
|
||||
app-server-1:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
env_file:
|
||||
- env/app.env
|
||||
depends_on:
|
||||
- db-mysql
|
||||
app-server-2:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
env_file:
|
||||
- env/app.env
|
||||
depends_on:
|
||||
- db-mysql
|
||||
migration:
|
||||
build:
|
||||
context: ./flyway
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
FLYWAY_EDITION: community
|
||||
volumes:
|
||||
- ${PWD}/flyway/db-migration:/flyway/sql
|
||||
- ${PWD}/flyway/conf:/flyway/conf
|
||||
depends_on:
|
||||
- db-mysql
|
||||
db-mysql:
|
||||
image: mysql:5.7
|
||||
ports:
|
||||
- "3306:3306"
|
||||
env_file:
|
||||
- env/mysql.env
|
||||
4
env/app.env
vendored
4
env/app.env
vendored
@@ -1,4 +0,0 @@
|
||||
PROFILE_OPTION=dev
|
||||
SPRING_DATASOURCE_URL=jdbc:mysql://db-mysql:3306/dongnecafe?autoreconnect=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
|
||||
SPRING_DATASOURCE_USERNAME=root
|
||||
SPRING_DATASOURCE_PASSWORD=dev
|
||||
2
env/mysql.env
vendored
2
env/mysql.env
vendored
@@ -1,2 +0,0 @@
|
||||
MYSQL_DATABASE=dongnecafe
|
||||
MYSQL_ROOT_PASSWORD=dev
|
||||
@@ -1,17 +0,0 @@
|
||||
FROM flyway/flyway:7-alpine
|
||||
|
||||
USER root
|
||||
|
||||
RUN apk add --no-cache openssl
|
||||
|
||||
# run flyway in order through dockerize utility.
|
||||
ENV DOCKERIZE_VERSION v0.6.1
|
||||
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
|
||||
&& tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
|
||||
&& rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz
|
||||
|
||||
COPY ./docker-entrypoint.sh docker-entrypoint.sh
|
||||
|
||||
RUN chmod +x docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["./docker-entrypoint.sh"]
|
||||
@@ -1,4 +0,0 @@
|
||||
flyway.url=jdbc:mysql://db-mysql:3306/dongnecafe?autoreconnect=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
|
||||
flyway.user=root
|
||||
flyway.password=dev
|
||||
flyway.driver=com.mysql.cj.jdbc.Driver
|
||||
@@ -1,4 +0,0 @@
|
||||
flyway.url=jdbc:mysql://db-mysql:3306/dongnecafe?autoreconnect=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
|
||||
flyway.user=root
|
||||
flyway.password=dev
|
||||
flyway.driver=com.mysql.cj.jdbc.Driver
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `cafe` (
|
||||
`cafe_id` binary(16) NOT NULL COMMENT '카페식별번호',
|
||||
`name` varchar(20) NOT NULL COMMENT '카페명',
|
||||
`address` varchar(100) NOT NULL COMMENT '카페 주소',
|
||||
`phone_number` varchar(11) NOT NULL COMMENT '카페 전화번호',
|
||||
`total_rate` float NOT NULL COMMENT '카페 종합 평가 점수',
|
||||
`description` varchar(255) COMMENT '카페 상세설명',
|
||||
`created_date` datetime NOT NULL COMMENT '카페 등록날짜',
|
||||
`updated_date` datetime COMMENT '카페 수정날짜',
|
||||
PRIMARY KEY (`cafe_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `cafe_menu` (
|
||||
`menu_id` binary(16) NOT NULL COMMENT '카페 메뉴 식별번호',
|
||||
`name` varchar(50) NOT NULL COMMENT '카페 메뉴명',
|
||||
`price` int NOT NULL COMMENT '메뉴 가격',
|
||||
`created_date` datetime NOT NULL COMMENT '메뉴 등록날짜',
|
||||
`updated_date` datetime COMMENT '메뉴 수정날짜',
|
||||
`cafe_id` binary(16) NOT NULL COMMENT '연관된 카페식별번호',
|
||||
PRIMARY KEY (`menu_id`),
|
||||
KEY `cafe_id` (`cafe_id`),
|
||||
FOREIGN KEY (`cafe_id`) REFERENCES `cafe` (`cafe_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,10 +0,0 @@
|
||||
CREATE TABLE `cafe_image` (
|
||||
`cafe_img_id` binary(16) NOT NULL COMMENT '카페 이미지 식별번호',
|
||||
`img_url` varchar(255) NOT NULL COMMENT '이미지 경로',
|
||||
`created_date` datetime NOT NULL COMMENT '이미지 등록날짜',
|
||||
`updated_date` datetime COMMENT '이미지 수정날짜',
|
||||
`cafe_id` binary(16) NOT NULL COMMENT '연관된 카페식별번호',
|
||||
PRIMARY KEY (`cafe_img_id`),
|
||||
KEY `cafe_id` (`cafe_id`),
|
||||
FOREIGN KEY (`cafe_id`) REFERENCES `cafe` (`cafe_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,10 +0,0 @@
|
||||
CREATE TABLE `menu_option`(
|
||||
`option_id` binary(16) NOT NULL COMMENT '옵션 식별번호',
|
||||
`title`varchar(50) NOT NULL COMMENT '메뉴 옵션 이름',
|
||||
`created_date` datetime NOT NULL COMMENT '옵션 등록날짜',
|
||||
`updated_date` datetime COMMENT '옵션 수정날짜',
|
||||
`menu_id` binary(16) NOT NULL COMMENT '연관된 카페 메뉴 식별번호',
|
||||
PRIMARY KEY (`option_id`),
|
||||
KEY `menu_id` (`menu_id`),
|
||||
FOREIGN KEY (`menu_id`) REFERENCES `cafe_menu` (`menu_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `option_detail` (
|
||||
`option_detail_id` bigint NOT NULL COMMENT '옵션 상세 번호',
|
||||
`name` varchar(50) NOT NULL COMMENT '옵션 상세명',
|
||||
`extra` int NOT NULL COMMENT '옵션 추가 요금',
|
||||
`created_date` datetime NOT NULL COMMENT '옵션 상세 등록날짜',
|
||||
`updated_date` datetime COMMENT '옵션 상세 수정날짜',
|
||||
`option_id` binary(16) NOT NULL COMMENT '연관된 옵션 식별번호',
|
||||
PRIMARY KEY (`option_detail_id`),
|
||||
KEY `option_id` (`option_id`),
|
||||
FOREIGN KEY (`option_id`) REFERENCES `menu_option` (`option_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `user` (
|
||||
`user_id` binary(16) NOT NULL COMMENT '사용자 식별번호',
|
||||
`email`varchar(50) NOT NULL COMMENT '사용자 이메일',
|
||||
`password` varchar(100) NOT NULL COMMENT '계정 비밀번호',
|
||||
`address` varchar(100) NOT NULL COMMENT '사용자 주소',
|
||||
`phone_number` varchar(11) NOT NULL COMMENT '사용자 전화번호',
|
||||
`role` varchar(20) NOT NULL COMMENT '사용자 권한',
|
||||
`created_date` datetime NOT NULL COMMENT '사용자 등록날짜',
|
||||
`updated_date` datetime COMMENT '사용자 수정날짜',
|
||||
PRIMARY KEY (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,15 +0,0 @@
|
||||
CREATE TABLE `review` (
|
||||
`review_id` binary(16) NOT NULL COMMENT '리뷰 식별번호',
|
||||
`content`varchar(255) NOT NULL COMMENT '리뷰 내용',
|
||||
`img_url` varchar(255) NOT NULL COMMENT '리뷰 첨부사진 주소',
|
||||
`rate` tinyint NOT NULL COMMENT '평가점수(0 ~ 5점)',
|
||||
`created_date` datetime NOT NULL COMMENT '리뷰 등록날짜',
|
||||
`updated_date` datetime COMMENT '리뷰 수정날짜',
|
||||
`user_id` binary(16) NOT NULL COMMENT '리뷰 작성한 사용자 식별번호',
|
||||
`cafe_id` binary(16) NOT NULL COMMENT '리뷰 대상 카페 식별번호',
|
||||
PRIMARY KEY (`review_id`),
|
||||
KEY `user_id` (`user_id`),
|
||||
FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`),
|
||||
KEY `cafe_id` (`cafe_id`),
|
||||
FOREIGN KEY (`cafe_id`) REFERENCES `cafe` (`cafe_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,13 +0,0 @@
|
||||
CREATE TABLE `cart` (
|
||||
`cart_id` binary(16) NOT NULL COMMENT '장바구니 식별번호',
|
||||
`cafe_name` varchar(20) NOT NULL COMMENT '장바구니에 담긴 카페 이름',
|
||||
`check_ordered` tinyint NOT NULL COMMENT '장바구니의 주문 여부',
|
||||
`total_price` int NOT NULL COMMENT '장바구니에 담긴 총 금액',
|
||||
`created_date` datetime NOT NULL COMMENT '장바구니 등록날짜',
|
||||
`updated_date` datetime COMMENT '장바구니 수정날짜',
|
||||
`cafe_id` binary(16) NOT NULL COMMENT '장바구니에 담긴 카페 식별번호',
|
||||
`user_id` binary(16) NOT NULL COMMENT '장바구니 주인 사용자 식별번호',
|
||||
PRIMARY KEY (`cart_id`),
|
||||
KEY `user_id` (`user_id`),
|
||||
FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,12 +0,0 @@
|
||||
CREATE TABLE `basket` (
|
||||
`basket_id` binary(16) NOT NULL COMMENT '장바구니 품목 식별번호',
|
||||
`menu_name` varchar(50) NOT NULL COMMENT '장바구니 품목 이름',
|
||||
`menu_count` int NOT NULL COMMENT '장바구니 품목 개수',
|
||||
`menu_price` int NOT NULL COMMENT '장바구니 품목 가격',
|
||||
`created_date` datetime NOT NULL COMMENT '장바구니 품목 등록날짜',
|
||||
`updated_date` datetime COMMENT '장바구니 품목 수정날짜',
|
||||
`cart_id` binary(16) NOT NULL COMMENT '해당 품목이 담긴 장바구니 식별번호',
|
||||
PRIMARY KEY (`basket_id`),
|
||||
KEY `cart_id` (`cart_id`),
|
||||
FOREIGN KEY (`cart_id`) REFERENCES `cart` (`cart_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,11 +0,0 @@
|
||||
CREATE TABLE `basket_option` (
|
||||
`basket_option_id` binary(16) NOT NULL COMMENT '품목 추가옵션 식별번호',
|
||||
`option_name`varchar(50) NOT NULL COMMENT '품목 추가옵션 내용',
|
||||
`option_extra` int NOT NULL COMMENT '품목 추가옵션 추가요금',
|
||||
`created_date` datetime NOT NULL COMMENT '품목 추가옵션 등록날짜',
|
||||
`updated_date` datetime COMMENT '품목 추가옵션 수정날짜',
|
||||
`basket_id` binary(16) NOT NULL COMMENT '추가옵션 대상 장바구니 품목 식별번호',
|
||||
PRIMARY KEY (`basket_option_id`),
|
||||
KEY `basket_id` (`basket_id`),
|
||||
FOREIGN KEY (`basket_id`) REFERENCES `basket` (`basket_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,14 +0,0 @@
|
||||
CREATE TABLE `menu_order` (
|
||||
`order_id` binary(16) NOT NULL COMMENT '주문 식별번호',
|
||||
`order_status` varchar(20) NOT NULL COMMENT '주문 상태',
|
||||
`request_message` varchar(255) NOT NULL COMMENT '주문 요청사항',
|
||||
`created_date` datetime NOT NULL COMMENT '주문 등록날짜',
|
||||
`updated_date` datetime COMMENT '주문 수정날짜',
|
||||
`cart_id` binary(16) NOT NULL COMMENT '주문된 카트 식별번호',
|
||||
`user_id` binary(16) NOT NULL COMMENT '주문한 사용자 식별번호',
|
||||
PRIMARY KEY (`order_id`),
|
||||
KEY `cart_id` (`cart_id`),
|
||||
FOREIGN KEY (`cart_id`) REFERENCES `cart` (`cart_id`),
|
||||
KEY `user_id` (`user_id`),
|
||||
FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -1,20 +0,0 @@
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), '비니카페', '서울시 동대문구 전농로', '01011112222', 3.98, '언제나 상쾌한 비니카페', now());
|
||||
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), '조이카페', '서울시 영등포구', '01033334444', 4.67, '언제나 상쾌한 조이카페', now());
|
||||
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), 'abc카페', '서울시 서대문구', '01025341432', 4.89, '언제나 상쾌한 abc카페', now());
|
||||
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), '동네주변카페', '서울시 송파구', '01022223333', 4.23, '언제나 상쾌한 동네주변카페', now());
|
||||
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), '방긋카페', '서울시 광진구', '01099998888', 4.35, '언제나 상쾌한 방긋카페', now());
|
||||
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), 'example cafe1', '서울시 종로구', '01077779999', 2.85, '언제나 상쾌한 example cafe1', now());
|
||||
|
||||
INSERT IGNORE INTO `cafe` (cafe_id, name, address, phone_number, total_rate, description, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), 'example cafe2', '서울시', '01044445555', 3.12, '언제나 상쾌한 example cafe2', now());
|
||||
@@ -1,26 +0,0 @@
|
||||
DROP PROCEDURE IF EXISTS insertCafeImages;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE insertCafeImages()
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 0;
|
||||
DECLARE j INT;
|
||||
DECLARE idx_img INT DEFAULT 1;
|
||||
DECLARE var_cafe_id binary(16);
|
||||
DECLARE count_cafe INT;
|
||||
SET count_cafe = (SELECT COUNT(*) FROM `cafe`);
|
||||
WHILE(i <= count_cafe) DO
|
||||
SET j = 1;
|
||||
SET var_cafe_id = (SELECT cafe_id FROM `cafe` LIMIT i, 1);
|
||||
WHILE(j <= 3) DO
|
||||
INSERT IGNORE INTO `cafe_image` (cafe_img_id, img_url, cafe_id, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), CONCAT('test_img_url_', idx_img), var_cafe_id, now());
|
||||
SET j = j + 1;
|
||||
SET idx_img = idx_img + 1;
|
||||
END WHILE;
|
||||
SET i = i + 1;
|
||||
END WHILE;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
CALL insertCafeImages();
|
||||
@@ -1,22 +0,0 @@
|
||||
DROP PROCEDURE IF EXISTS insertMenus;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE insertCafeMenus()
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 0;
|
||||
DECLARE j INT;
|
||||
DECLARE var_cafe_id binary(16);
|
||||
WHILE(i <= 4) DO
|
||||
SET j = 1;
|
||||
SET var_cafe_id = (SELECT cafe_id FROM `cafe` LIMIT i, 1);
|
||||
WHILE(j <= 10) DO
|
||||
INSERT IGNORE INTO `cafe_menu` (menu_id, name, price, cafe_id, created_date)
|
||||
VALUES (unhex(replace(uuid(), '-', '')), CONCAT('커피', j), FLOOR(RAND() * 10 + 1) * 1000, var_cafe_id, now());
|
||||
SET j = j + 1;
|
||||
END WHILE;
|
||||
SET i = i + 1;
|
||||
END WHILE;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
CALL insertCafeMenus();
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
echo "wait DB container up"
|
||||
dockerize -wait tcp://db-mysql:3306 -timeout 20s
|
||||
|
||||
# DB Migration
|
||||
echo "run database migration"
|
||||
flyway -configFiles=/flyway/conf/flyway_main.conf -locations=filesystem:/flyway/sql/main migrate
|
||||
|
||||
# Seed Migration
|
||||
echo "insert seed data"
|
||||
flyway -configFiles=/flyway/conf/flyway_seed.conf -locations=filesystem:/flyway/sql/seed migrate
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
upstream appserver {
|
||||
server app-server-1:8080;
|
||||
server app-server-2:8080;
|
||||
}
|
||||
server {
|
||||
listen 80;
|
||||
location / {
|
||||
proxy_pass http://appserver;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DongneCafeSirenOrderApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DongneCafeSirenOrderApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package io.beaniejoy.dongnecafe
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
|
||||
@SpringBootApplication
|
||||
class DongneCafeSirenOrderApplication
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<DongneCafeSirenOrderApplication>(*args)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.controller;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeInfoResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeSearchResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeUpdateRequestDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.service.CafeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/cafes")
|
||||
public class CafeController {
|
||||
|
||||
private final CafeService cafeService;
|
||||
|
||||
@GetMapping(value = "")
|
||||
public ResponseEntity<List<CafeSearchResponseDto>> searchCafeList(
|
||||
@PageableDefault(sort = "name", direction = Sort.Direction.ASC, size = 10) Pageable pageable) {
|
||||
List<CafeSearchResponseDto> cafeResponseList = cafeService.getCafeList(pageable);
|
||||
|
||||
return ResponseEntity.ok(cafeResponseList);
|
||||
}
|
||||
|
||||
@GetMapping("/{cafeId}")
|
||||
public ResponseEntity<CafeInfoResponseDto> getCafeDetailedInfo(@PathVariable("cafeId") UUID cafeId) {
|
||||
CafeInfoResponseDto cafeResponse = cafeService.getCafeInfoByCafeId(cafeId);
|
||||
|
||||
return ResponseEntity.ok(cafeResponse);
|
||||
}
|
||||
|
||||
@PutMapping("/{cafeId}")
|
||||
public ResponseEntity<String> updateCafeInfo(
|
||||
@PathVariable("cafeId") UUID cafeId,
|
||||
@RequestBody CafeUpdateRequestDto resource) {
|
||||
|
||||
cafeService.updateCafe(cafeId, resource);
|
||||
|
||||
return ResponseEntity.ok("Successfully Cafe[" + cafeId + "] Info Updated");
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.controller;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.CafeMenuDetailResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.service.CafeMenuService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class CafeMenuController {
|
||||
|
||||
private final CafeMenuService cafeMenuService;
|
||||
|
||||
@GetMapping("/cafes/{cafeId}/menus/{menuId}")
|
||||
public ResponseEntity<CafeMenuDetailResponseDto> getCafeMenuDetailedInfo(
|
||||
@PathVariable("cafeId") UUID cafeId,
|
||||
@PathVariable("menuId") UUID menuId
|
||||
) {
|
||||
|
||||
CafeMenuDetailResponseDto menuDetail = cafeMenuService.getCafeMenuInfoByCafeIdAndMenuId(menuId, cafeId);
|
||||
return ResponseEntity.ok(menuDetail);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.domain;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeInfoResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeSearchResponseDto;
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
public class Cafe extends BaseTimeEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Column(name = "cafe_id", columnDefinition = "BINARY(16)")
|
||||
private UUID cafeId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
private String phoneNumber;
|
||||
|
||||
private Double totalRate;
|
||||
|
||||
private String description;
|
||||
|
||||
@OneToMany(mappedBy = "cafe", fetch = FetchType.LAZY)
|
||||
private List<CafeMenu> cafeMenuList;
|
||||
|
||||
@OneToMany(mappedBy = "cafe", fetch = FetchType.LAZY)
|
||||
private List<CafeImage> cafeImageList;
|
||||
|
||||
public void updateInfo(String name, String address, String phoneNumber, String description) {
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.phoneNumber = phoneNumber;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public CafeSearchResponseDto toSearchResponseDto() {
|
||||
return CafeSearchResponseDto.builder()
|
||||
.cafeId(cafeId)
|
||||
.name(name)
|
||||
.address(address)
|
||||
.totalRate(totalRate)
|
||||
.imageList(cafeImageList
|
||||
.stream()
|
||||
.map(CafeImage::toResponseDto)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
|
||||
public CafeInfoResponseDto toInfoResponseDto() {
|
||||
return CafeInfoResponseDto.builder()
|
||||
.cafeId(cafeId)
|
||||
.name(name)
|
||||
.address(address)
|
||||
.phoneNumber(phoneNumber)
|
||||
.totalRate(totalRate)
|
||||
.description(description)
|
||||
.menuList(cafeMenuList
|
||||
.stream()
|
||||
.map(CafeMenu::toListResponseDto)
|
||||
.collect(Collectors.toList()))
|
||||
.imageList(cafeImageList
|
||||
.stream()
|
||||
.map(CafeImage::toResponseDto)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.domain;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeImageResponseDto;
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
public class CafeImage extends BaseTimeEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Column(name = "cafe_img_id", columnDefinition = "BINARY(16)")
|
||||
private UUID cafeImgId;
|
||||
|
||||
private String imgUrl;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cafe_id")
|
||||
private Cafe cafe;
|
||||
|
||||
public CafeImageResponseDto toResponseDto() {
|
||||
return CafeImageResponseDto.builder()
|
||||
.imgUrl(imgUrl)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.domain;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.CafeMenuDetailResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.CafeMenuListResponseDto;
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
public class CafeMenu extends BaseTimeEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Column(name = "menu_id", columnDefinition = "BINARY(16)")
|
||||
private UUID menuId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer price;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cafe_id")
|
||||
private Cafe cafe;
|
||||
|
||||
@OneToMany(mappedBy = "cafeMenu", fetch = FetchType.LAZY)
|
||||
private List<MenuOption> menuOptionList;
|
||||
|
||||
public CafeMenuListResponseDto toListResponseDto() {
|
||||
return CafeMenuListResponseDto.builder()
|
||||
.menuId(menuId)
|
||||
.name(name)
|
||||
.price(price)
|
||||
.build();
|
||||
}
|
||||
|
||||
public CafeMenuDetailResponseDto toDetailResponseDto() {
|
||||
return CafeMenuDetailResponseDto.builder()
|
||||
.name(name)
|
||||
.price(price)
|
||||
.optionList(menuOptionList
|
||||
.stream()
|
||||
.map(MenuOption::toResponseDto)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.domain;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.MenuOptionResponseDto;
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
public class MenuOption extends BaseTimeEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Column(name = "option_id", columnDefinition = "BINARY(16)")
|
||||
private UUID optionId;
|
||||
|
||||
private String title;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "menu_id")
|
||||
private CafeMenu cafeMenu;
|
||||
|
||||
@OneToMany(mappedBy = "menuOption", fetch = FetchType.EAGER)
|
||||
private List<OptionDetail> optionDetailList;
|
||||
|
||||
public MenuOptionResponseDto toResponseDto() {
|
||||
return MenuOptionResponseDto.builder()
|
||||
.optionId(optionId)
|
||||
.title(title)
|
||||
.optionDetailList(optionDetailList
|
||||
.stream()
|
||||
.map(OptionDetail::toResponseDto)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.domain;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.OptionDetailResponseDto;
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Entity
|
||||
public class OptionDetail extends BaseTimeEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long optionDetailId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer extra;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "option_id")
|
||||
private MenuOption menuOption;
|
||||
|
||||
public OptionDetailResponseDto toResponseDto() {
|
||||
return OptionDetailResponseDto.builder()
|
||||
.optionDetailId(optionDetailId)
|
||||
.name(name)
|
||||
.extra(extra)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.cafe;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CafeImageResponseDto {
|
||||
|
||||
private String imgUrl;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.cafe;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.CafeMenuListResponseDto;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CafeInfoResponseDto {
|
||||
private UUID cafeId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
private String phoneNumber;
|
||||
|
||||
private Double totalRate;
|
||||
|
||||
private String description;
|
||||
|
||||
private List<CafeMenuListResponseDto> menuList;
|
||||
|
||||
private List<CafeImageResponseDto> imageList;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.cafe;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CafeSearchResponseDto {
|
||||
|
||||
private UUID cafeId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
private Double totalRate;
|
||||
|
||||
private List<CafeImageResponseDto> imageList;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.cafe;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CafeUpdateRequestDto {
|
||||
|
||||
private String name;
|
||||
|
||||
private String address;
|
||||
|
||||
private String phoneNumber;
|
||||
|
||||
private String description;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.menu;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CafeMenuDetailResponseDto {
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer price;
|
||||
|
||||
private List<MenuOptionResponseDto> optionList;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.menu;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CafeMenuListResponseDto {
|
||||
|
||||
private UUID menuId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer price;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.menu;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MenuOptionResponseDto {
|
||||
|
||||
private UUID optionId;
|
||||
|
||||
private String title;
|
||||
|
||||
private List<OptionDetailResponseDto> optionDetailList;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.dto.menu;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OptionDetailResponseDto {
|
||||
|
||||
private Long optionDetailId;
|
||||
|
||||
private String name;
|
||||
|
||||
private Integer extra;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.error;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class CafeExceptionHandler {
|
||||
|
||||
@ExceptionHandler(CafeNotFoundException.class)
|
||||
public ResponseEntity<String> handleNotFound(CafeNotFoundException exception) {
|
||||
return ResponseEntity.badRequest().body(exception.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.error;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CafeMenuNotFoundException extends RuntimeException{
|
||||
public CafeMenuNotFoundException(UUID menuId, UUID cafeId) {
|
||||
super("Cafe[" + cafeId + "]의 Menu[" + menuId + "]는 존재하지 않는 메뉴입니다.");
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.error;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CafeNotFoundException extends RuntimeException {
|
||||
public CafeNotFoundException(UUID cafeId) {
|
||||
super("Cafe[" + cafeId + "] is not found");
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.repository;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.domain.CafeMenu;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface CafeMenuRepository extends JpaRepository<CafeMenu, UUID> {
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.repository;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.domain.Cafe;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface CafeRepository extends JpaRepository<Cafe, UUID> {
|
||||
|
||||
Page<Cafe> findAll(Pageable pageable);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.service;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.domain.CafeMenu;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.menu.CafeMenuDetailResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.error.CafeMenuNotFoundException;
|
||||
import io.beaniejoy.dongnecafe.cafe.repository.CafeMenuRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CafeMenuService {
|
||||
|
||||
private final CafeMenuRepository cafeMenuRepository;
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public CafeMenuDetailResponseDto getCafeMenuInfoByCafeIdAndMenuId(UUID menuId, UUID cafeId) {
|
||||
|
||||
CafeMenu cafeMenu = cafeMenuRepository.findById(menuId)
|
||||
.orElseThrow(() -> new CafeMenuNotFoundException(menuId, cafeId));
|
||||
|
||||
return cafeMenu.toDetailResponseDto();
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.cafe.service;
|
||||
|
||||
import io.beaniejoy.dongnecafe.cafe.domain.Cafe;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeInfoResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeSearchResponseDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.dto.cafe.CafeUpdateRequestDto;
|
||||
import io.beaniejoy.dongnecafe.cafe.error.CafeNotFoundException;
|
||||
import io.beaniejoy.dongnecafe.cafe.repository.CafeRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CafeService {
|
||||
|
||||
private final CafeRepository cafeRepository;
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<CafeSearchResponseDto> getCafeList(Pageable pageable) {
|
||||
|
||||
Page<Cafe> cafeListWithPagination = cafeRepository.findAll(pageable);
|
||||
|
||||
return cafeListWithPagination.stream()
|
||||
.map(Cafe::toSearchResponseDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public CafeInfoResponseDto getCafeInfoByCafeId(UUID cafeId) {
|
||||
Cafe cafe = cafeRepository.findById(cafeId)
|
||||
.orElseThrow(() -> new CafeNotFoundException(cafeId));
|
||||
|
||||
return cafe.toInfoResponseDto();
|
||||
}
|
||||
|
||||
public void updateCafe(UUID cafeId, CafeUpdateRequestDto resource) {
|
||||
Cafe cafe = cafeRepository.findById(cafeId)
|
||||
.orElseThrow(() -> new CafeNotFoundException(cafeId));
|
||||
|
||||
cafe.updateInfo(
|
||||
resource.getName(),
|
||||
resource.getAddress(),
|
||||
resource.getPhoneNumber(),
|
||||
resource.getDescription());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
@Configuration
|
||||
@EnableJpaAuditing
|
||||
public class AuditingConfig {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package io.beaniejoy.dongnecafe.common.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
|
||||
|
||||
@Configuration
|
||||
@EnableJpaAuditing
|
||||
class AuditingConfig
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.beaniejoy.dongnecafe.common.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import javax.persistence.EntityListeners;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public abstract class BaseTimeEntity {
|
||||
@CreatedDate
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@LastModifiedDate
|
||||
private LocalDateTime updatedDate;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.beaniejoy.dongnecafe.common.domain
|
||||
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.LastModifiedDate
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.EntityListeners
|
||||
import javax.persistence.MappedSuperclass
|
||||
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener::class)
|
||||
open class BaseTimeEntity(
|
||||
@CreatedDate
|
||||
val createdAt: LocalDateTime = LocalDateTime.now(),
|
||||
|
||||
@LastModifiedDate
|
||||
val updatedAt: LocalDateTime? = null
|
||||
)
|
||||
@@ -0,0 +1,46 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.controller
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeInfoResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeSearchResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeUpdateRequestDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.service.CafeService
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.domain.Sort
|
||||
import org.springframework.data.web.PageableDefault
|
||||
import org.springframework.web.bind.annotation.*
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/cafes")
|
||||
class CafeController(
|
||||
private val cafeService: CafeService
|
||||
) {
|
||||
@GetMapping
|
||||
fun searchCafeList(
|
||||
@PageableDefault(sort = ["name"], direction = Sort.Direction.ASC, size = 10) pageable: Pageable
|
||||
): Page<CafeSearchResponseDto> {
|
||||
return cafeService.getCafeList(pageable)
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
fun getCafeDetailedInfo(@PathVariable("id") id: Long): CafeInfoResponseDto {
|
||||
return cafeService.getCafeInfoByCafeId(id)
|
||||
}
|
||||
|
||||
// TODO spring boot validation 적용 필요
|
||||
@PutMapping("/{id}")
|
||||
fun updateCafeInfo(
|
||||
@PathVariable("id") id: Long,
|
||||
@RequestBody resource: CafeUpdateRequestDto
|
||||
): String {
|
||||
cafeService.updateCafe(
|
||||
id = id,
|
||||
name = resource.name!!,
|
||||
address = resource.address!!,
|
||||
phoneNumber = resource.phoneNumber!!,
|
||||
description = resource.description!!
|
||||
)
|
||||
|
||||
return "Successfully Cafe[$id] Info Updated"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.controller
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.menu.CafeMenuDetailResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.service.CafeMenuService
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
class CafeMenuController(
|
||||
private val cafeMenuService: CafeMenuService
|
||||
) {
|
||||
@GetMapping("/cafes/{cafeId}/menus/{menuId}")
|
||||
fun getCafeMenuDetailedInfo(
|
||||
@PathVariable("cafeId") cafeId: Long,
|
||||
@PathVariable("menuId") menuId: Long
|
||||
): CafeMenuDetailResponseDto {
|
||||
return cafeMenuService.getCafeMenuInfoByCafeIdAndMenuId(
|
||||
menuId = menuId,
|
||||
cafeId = cafeId
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.domain
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "cafe")
|
||||
class Cafe(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Long = 0L,
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
var name: String,
|
||||
|
||||
@Column(name = "address", nullable = false)
|
||||
var address: String,
|
||||
|
||||
@Column(name = "phone_number", nullable = false)
|
||||
var phoneNumber: String,
|
||||
|
||||
@Column(name = "total_rate", nullable = false)
|
||||
val totalRate: Double,
|
||||
|
||||
@Column(name = "description", nullable = false)
|
||||
var description: String,
|
||||
|
||||
@OneToMany(mappedBy = "cafe", fetch = FetchType.LAZY)
|
||||
val cafeMenuList: MutableList<CafeMenu>,
|
||||
|
||||
@OneToMany(mappedBy = "cafe", fetch = FetchType.LAZY)
|
||||
val cafeImageList: MutableList<CafeImage>
|
||||
) : BaseTimeEntity() {
|
||||
fun updateInfo(name: String, address: String, phoneNumber: String, description: String) {
|
||||
this.name = name
|
||||
this.address = address
|
||||
this.phoneNumber = phoneNumber
|
||||
this.description = description
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.domain
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "cafe_image")
|
||||
class CafeImage(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Long,
|
||||
|
||||
@Column(name = "img_url", nullable = false)
|
||||
val imgUrl: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cafe_id", nullable = false)
|
||||
val cafe: Cafe
|
||||
) : BaseTimeEntity()
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.domain
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import java.math.BigDecimal
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "cafe_menu")
|
||||
class CafeMenu(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Long = 0L,
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
val name: String,
|
||||
|
||||
@Column(name = "price", nullable = false)
|
||||
val price: BigDecimal = BigDecimal.ZERO,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "cafe_id", nullable = false)
|
||||
val cafe: Cafe,
|
||||
|
||||
@OneToMany(mappedBy = "cafeMenu", fetch = FetchType.LAZY)
|
||||
val menuOptionList: MutableList<MenuOption>
|
||||
) : BaseTimeEntity()
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.domain
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "menu_option")
|
||||
class MenuOption(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Long = 0L,
|
||||
|
||||
@Column(name = "title", nullable = false)
|
||||
val title: String,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "menu_id", nullable = false)
|
||||
val cafeMenu: CafeMenu,
|
||||
|
||||
@OneToMany(mappedBy = "menuOption", fetch = FetchType.EAGER)
|
||||
val optionDetailList: MutableList<OptionDetail>
|
||||
) : BaseTimeEntity()
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.domain
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import java.math.BigDecimal
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
@Table(name = "option_detail")
|
||||
class OptionDetail(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
val id: Long = 0L,
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
val name: String,
|
||||
|
||||
@Column(name = "extra", nullable = false)
|
||||
val extra: BigDecimal,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "option_id", nullable = false)
|
||||
val menuOption: MenuOption
|
||||
): BaseTimeEntity() {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.cafe
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.CafeImage
|
||||
|
||||
data class CafeImageResponseDto(
|
||||
val imgUrl: String? = null
|
||||
) {
|
||||
companion object {
|
||||
fun of(cafeImage: CafeImage): CafeImageResponseDto {
|
||||
return CafeImageResponseDto(cafeImage.imgUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.cafe
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.Cafe
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.menu.CafeMenuResponseDto
|
||||
|
||||
data class CafeInfoResponseDto(
|
||||
val id: Long? = null,
|
||||
val name: String? = null,
|
||||
val address: String? = null,
|
||||
val phoneNumber: String? = null,
|
||||
val totalRate: Double? = null,
|
||||
val description: String? = null,
|
||||
val menuList: List<CafeMenuResponseDto> = emptyList(),
|
||||
val imageList: List<CafeImageResponseDto> = emptyList()
|
||||
) {
|
||||
companion object {
|
||||
fun of(cafe: Cafe): CafeInfoResponseDto {
|
||||
return CafeInfoResponseDto(
|
||||
id = cafe.id,
|
||||
name = cafe.name,
|
||||
address = cafe.address,
|
||||
phoneNumber = cafe.phoneNumber,
|
||||
totalRate = cafe.totalRate,
|
||||
description = cafe.description,
|
||||
menuList = cafe.cafeMenuList.map { CafeMenuResponseDto.of(it) },
|
||||
imageList = cafe.cafeImageList.map { CafeImageResponseDto.of(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.cafe
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.Cafe
|
||||
|
||||
data class CafeSearchResponseDto(
|
||||
val id: Long = 0L,
|
||||
val name: String? = null,
|
||||
val address: String? = null,
|
||||
val totalRate: Double? = null,
|
||||
val imageList: List<CafeImageResponseDto> = emptyList()
|
||||
) {
|
||||
companion object {
|
||||
fun of(cafe: Cafe): CafeSearchResponseDto {
|
||||
return CafeSearchResponseDto(
|
||||
id = cafe.id,
|
||||
name = cafe.name,
|
||||
address = cafe.address,
|
||||
totalRate = cafe.totalRate,
|
||||
imageList = cafe.cafeImageList.map { CafeImageResponseDto.of(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.cafe
|
||||
|
||||
data class CafeUpdateRequestDto(
|
||||
val name: String? = null,
|
||||
val address: String? = null,
|
||||
val phoneNumber: String? = null,
|
||||
val description: String? = null
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.menu
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.CafeMenu
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class CafeMenuDetailResponseDto(
|
||||
val name: String? = null,
|
||||
val price: BigDecimal = BigDecimal.ZERO,
|
||||
val optionList: List<MenuOptionResponseDto> = emptyList()
|
||||
) {
|
||||
companion object {
|
||||
fun of(cafeMenu: CafeMenu): CafeMenuDetailResponseDto {
|
||||
return CafeMenuDetailResponseDto(
|
||||
name = cafeMenu.name,
|
||||
price = cafeMenu.price,
|
||||
optionList = cafeMenu.menuOptionList.map { MenuOptionResponseDto.of(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.menu
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.CafeMenu
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class CafeMenuResponseDto(
|
||||
val id: Long = 0L,
|
||||
val name: String? = null,
|
||||
val price: BigDecimal = BigDecimal.ZERO,
|
||||
) {
|
||||
companion object {
|
||||
fun of(cafeMenu: CafeMenu): CafeMenuResponseDto {
|
||||
return CafeMenuResponseDto(
|
||||
id = cafeMenu.id,
|
||||
name = cafeMenu.name,
|
||||
price = cafeMenu.price
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.menu
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.MenuOption
|
||||
|
||||
data class MenuOptionResponseDto(
|
||||
val id: Long = 0L,
|
||||
val title: String? = null,
|
||||
val optionDetailList: List<OptionDetailResponseDto> = emptyList()
|
||||
) {
|
||||
companion object {
|
||||
fun of(menuOption: MenuOption): MenuOptionResponseDto {
|
||||
return MenuOptionResponseDto(
|
||||
id = menuOption.id,
|
||||
title = menuOption.title,
|
||||
optionDetailList = menuOption.optionDetailList.map { OptionDetailResponseDto.of(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.dto.menu
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.OptionDetail
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class OptionDetailResponseDto(
|
||||
val id: Long = 0L,
|
||||
val name: String? = null,
|
||||
val extra: BigDecimal = BigDecimal.ZERO
|
||||
) {
|
||||
companion object {
|
||||
fun of(optionDetail: OptionDetail): OptionDetailResponseDto {
|
||||
return OptionDetailResponseDto(
|
||||
id = optionDetail.id,
|
||||
name = optionDetail.name,
|
||||
extra = optionDetail.extra
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.error
|
||||
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||
|
||||
@RestControllerAdvice
|
||||
class CafeExceptionHandler {
|
||||
@ExceptionHandler(CafeNotFoundException::class)
|
||||
fun handleNotFound(exception: CafeNotFoundException): ResponseEntity<String> {
|
||||
return ResponseEntity.badRequest().body(exception.message)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.error
|
||||
|
||||
class CafeMenuNotFoundException(menuId: Long, cafeId: Long) :
|
||||
RuntimeException("Cafe[${cafeId}]의 Menu[${menuId}]는 존재하지 않는 메뉴입니다.")
|
||||
@@ -0,0 +1,3 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.error
|
||||
|
||||
class CafeNotFoundException(cafeId: Long) : RuntimeException("Cafe[$cafeId] is not found")
|
||||
@@ -0,0 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.repository
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.CafeMenu
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface CafeMenuRepository : JpaRepository<CafeMenu, Long>
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.repository
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.domain.Cafe
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface CafeRepository : JpaRepository<Cafe, Long> {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.menu.CafeMenuDetailResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.error.CafeMenuNotFoundException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeMenuRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@Service
|
||||
class CafeMenuService(
|
||||
private val cafeMenuRepository: CafeMenuRepository
|
||||
) {
|
||||
@Transactional(readOnly = true)
|
||||
fun getCafeMenuInfoByCafeIdAndMenuId(menuId: Long, cafeId: Long): CafeMenuDetailResponseDto {
|
||||
val cafeMenu = cafeMenuRepository.findByIdOrNull(menuId)
|
||||
?: throw CafeMenuNotFoundException(menuId, cafeId)
|
||||
|
||||
return CafeMenuDetailResponseDto.of(cafeMenu)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeInfoResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeSearchResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.error.CafeNotFoundException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeRepository
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
class CafeService(
|
||||
private val cafeRepository: CafeRepository
|
||||
) {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getCafeList(pageable: Pageable): Page<CafeSearchResponseDto> {
|
||||
val cafeListWithPagination = cafeRepository.findAll(pageable)
|
||||
|
||||
return cafeListWithPagination.map { CafeSearchResponseDto.of(it) }
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getCafeInfoByCafeId(id: Long): CafeInfoResponseDto {
|
||||
val cafe = cafeRepository.findByIdOrNull(id)
|
||||
?: throw CafeNotFoundException(id)
|
||||
|
||||
return CafeInfoResponseDto.of(cafe)
|
||||
}
|
||||
|
||||
fun updateCafe(
|
||||
id: Long,
|
||||
name: String,
|
||||
address: String,
|
||||
phoneNumber: String,
|
||||
description: String,
|
||||
) {
|
||||
val cafe = cafeRepository.findByIdOrNull(id)
|
||||
?: throw CafeNotFoundException(id)
|
||||
|
||||
cafe.updateInfo(
|
||||
name = name,
|
||||
address = address,
|
||||
phoneNumber = phoneNumber,
|
||||
description = description
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:mem:testdb;MODE=MySQL
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
show-sql: true
|
||||
format_sql: true
|
||||
show-sql: true
|
||||
|
||||
Reference in New Issue
Block a user