Skip to content

Commit 563f15a

Browse files
authored
Merge pull request #53 from sumte-app/develop
[CICD] 25.08.11 develop 브랜치 배포
2 parents df8e76d + 9c83f56 commit 563f15a

File tree

69 files changed

+1861
-321
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1861
-321
lines changed

.github/workflows/main_cd_workflow.yml

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ jobs:
110110
# .env 파일 생성
111111
cat <<EOF > /home/ubuntu/.env
112112
SPRING_PROFILES_ACTIVE=prod
113+
EC2_HOST=${{ secrets.EC2_HOST }}
113114
DOCKER_HUB_USERNAME=${{ secrets.DOCKER_USERNAME }}
114115
DOCKER_HUB_REPOSITORY=${{ secrets.DOCKER_HUB_REPOSITORY }}
115116
RDS_HOST=${{ secrets.RDS_HOST }}
@@ -120,6 +121,7 @@ jobs:
120121
JWT_SECRET=${{ secrets.JWT_SECRET }}
121122
S3_ACCESS_KEY=${{ secrets.S3_ACCESS_KEY }}
122123
S3_SECRET_KEY=${{ secrets.S3_SECRET_KEY }}
124+
KAKAOPAY_SECRET_KEY=${{ secrets.KAKAOPAY_SECRET_KEY }}
123125
EOF
124126
125127
# .env 파일 권한 설정
@@ -132,29 +134,31 @@ jobs:
132134
docker compose -f /home/ubuntu/docker-compose.yml pull
133135
docker compose -f /home/ubuntu/docker-compose.yml up -d --force-recreate --remove-orphans
134136
135-
# - name: Send Discord Notification
136-
# if: always()
137-
# run: |
138-
# STATUS="${{ job.status }}"
139-
# if [ "$STATUS" == "success" ]; then
140-
# EMOJI="✅"
141-
# else
142-
# EMOJI="❌"
143-
# fi
144-
#
145-
# # 반복 폴링 헬스체크
146-
# HEALTH_STATUS="❌ 서버 비정상 작동"
147-
# for i in {1..30}; do
148-
# if curl -sSf https://sumteapi.duckdns.org/actuator/health >/dev/null; then
149-
# HEALTH_STATUS="✅ 서버 정상 작동"
150-
# break
151-
# fi
152-
# sleep 5
153-
# done
154-
#
155-
# MESSAGE="$EMOJI **sumte 배포 결과**\\n상태: $STATUS\\n$HEALTH_STATUS\\n🔗 프로젝트: ${{ github.repository }}\\n👤 커밋: ${{ github.actor }}"
156-
#
157-
# curl -H "Content-Type: application/json" \
158-
# -X POST \
159-
# -d "{\"content\": \"$MESSAGE\"}" \
160-
# ${{ secrets.DISCORD_WEBHOOK_URL }} || true
137+
- name: Send Discord Notification
138+
if: always()
139+
run: |
140+
STATUS="${{ job.status }}"
141+
if [ "$STATUS" == "success" ]; then
142+
EMOJI="✅"
143+
else
144+
EMOJI="❌"
145+
fi
146+
147+
# 반복 폴링 헬스체크
148+
HEALTH_STATUS="❌ 서버 비정상 작동"
149+
for i in {1..30}; do
150+
if curl -sSf https://sumteapi.duckdns.org/actuator/health >/dev/null; then
151+
HEALTH_STATUS="✅ 서버 정상 작동"
152+
break
153+
fi
154+
sleep 5
155+
done
156+
157+
MESSAGE="$EMOJI **sumte 배포 결과**\\n상태: $STATUS\\n$HEALTH_STATUS\\n🔗 프로젝트: ${{ github.repository }}\\n👤 커밋: ${{ github.actor }}"
158+
159+
curl -H "Content-Type: application/json" \
160+
-X POST \
161+
-d "{\"content\": \"$MESSAGE\"}" \
162+
${{ secrets.DISCORD_WEBHOOK_URL }} || true
163+
164+

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ dependencies {
2727
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
2828
implementation 'org.springframework.boot:spring-boot-starter-security'
2929
implementation 'org.springframework.boot:spring-boot-starter-web'
30+
implementation 'org.springframework.boot:spring-boot-starter-webflux'
3031
implementation 'org.springframework.boot:spring-boot-starter-validation' // 에러 핸들러 만들 때 씀
3132

3233
testImplementation 'org.springframework.boot:spring-boot-starter-test'

src/main/java/com/sumte/SumteApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import org.springframework.boot.SpringApplication;
44
import org.springframework.boot.autoconfigure.SpringBootApplication;
55
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
6+
import org.springframework.scheduling.annotation.EnableScheduling;
67

78
@SpringBootApplication
89
@EnableJpaAuditing
10+
@EnableScheduling
911
public class SumteApplication {
1012

1113
public static void main(String[] args) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.sumte.apiPayload.code.error;
2+
3+
import org.springframework.http.HttpStatus;
4+
5+
import lombok.Getter;
6+
import lombok.RequiredArgsConstructor;
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum ImageErrorCode implements ErrorCode {
11+
IMAGE_ALREADY_EXISTS(HttpStatus.BAD_REQUEST, "IMAGE400", "해당 이미지가 이미 등록되어 있습니다."),
12+
13+
GUESTHOUSE_NOT_FOUND(HttpStatus.NOT_FOUND, "IMAGE404", "해당 게스트하우스를 찾을 수 없습니다."),
14+
15+
ROOM_NOT_FOUND(HttpStatus.NOT_FOUND, "IMAGE404", "해당 룸을 찾을 수 없습니다."),
16+
17+
REVIEW_NOT_FOUND(HttpStatus.NOT_FOUND, "IMAGE404", "해당 리뷰를 찾을 수 없습니다."),
18+
19+
INVALID_OWNER_TYPE(HttpStatus.BAD_REQUEST, "IMAGE400", "지원하지 않는 이미지 소유자 타입입니다.");
20+
21+
private final HttpStatus httpStatus;
22+
private final String code;
23+
private final String message;
24+
}

src/main/java/com/sumte/guesthouse/controller/GuesthouseController.java

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package com.sumte.guesthouse.controller;
22

3+
import org.springdoc.core.annotations.ParameterObject;
34
import org.springframework.data.domain.Page;
45
import org.springframework.data.domain.PageRequest;
56
import org.springframework.data.domain.Pageable;
7+
import org.springframework.data.domain.Slice;
8+
import org.springframework.data.web.PageableDefault;
69
import org.springframework.http.ResponseEntity;
710
import org.springframework.web.bind.annotation.DeleteMapping;
11+
import org.springframework.web.bind.annotation.GetMapping;
812
import org.springframework.web.bind.annotation.PatchMapping;
913
import org.springframework.web.bind.annotation.PathVariable;
1014
import org.springframework.web.bind.annotation.PostMapping;
@@ -16,8 +20,10 @@
1620
import com.sumte.apiPayload.ApiResponse;
1721
import com.sumte.apiPayload.exception.annotation.CheckPage;
1822
import com.sumte.apiPayload.exception.annotation.CheckPageSize;
23+
import com.sumte.guesthouse.dto.GuesthouseDetailDTO;
1924
import com.sumte.guesthouse.dto.GuesthousePreviewDTO;
2025
import com.sumte.guesthouse.dto.GuesthouseRequestDTO;
26+
import com.sumte.guesthouse.dto.GuesthouseResponseDTO;
2127
import com.sumte.guesthouse.dto.GuesthouseSearchRequestDTO;
2228
import com.sumte.guesthouse.service.GuesthouseCommandService;
2329
import com.sumte.guesthouse.service.GuesthouseQueryService;
@@ -30,7 +36,7 @@
3036
import lombok.RequiredArgsConstructor;
3137

3238
@RestController
33-
@Tag(name = "게스트 하우스 관련 api", description = "게스트하우스 생성/수정/조회/삭제 api 입니다.")
39+
@Tag(name = "게스트 하우스 api", description = "게스트하우스 생성/수정/조회/삭제 api 입니다.")
3440
@RequiredArgsConstructor
3541
@RequestMapping("/guesthouse")
3642
public class GuesthouseController {
@@ -39,11 +45,11 @@ public class GuesthouseController {
3945

4046
@Operation(summary = "게스트하우스 등록", description = "게스트하우스를 등록합니다.")
4147
@PostMapping
42-
public ApiResponse<Void> registerGuesthouse(
48+
public ResponseEntity<ApiResponse<GuesthouseResponseDTO.Register>> registerGuesthouse(
4349
@RequestBody @Valid GuesthouseRequestDTO.Register dto) {
44-
guesthouseCommandService.registerGuesthouse(dto);
50+
GuesthouseResponseDTO.Register result = guesthouseCommandService.registerGuesthouse(dto);
4551

46-
return ApiResponse.successWithNoData();
52+
return ResponseEntity.ok(ApiResponse.success(result));
4753
}
4854

4955
@DeleteMapping("/{guesthouseId}")
@@ -64,12 +70,56 @@ public ApiResponse<Void> deleteGuesthouse(
6470
@Parameters({
6571
@Parameter(name = "guesthouseId", description = "게스트하우스 아이디를 넘겨주세요")
6672
})
67-
public ApiResponse<Void> updateGuesthouse(
73+
public ResponseEntity<Long> updateGuesthouse(
6874
@PathVariable(name = "guesthouseId") Long guesthouseId,
6975
@RequestBody @Valid GuesthouseRequestDTO.Update dto) {
7076
guesthouseCommandService.updateGuesthouse(guesthouseId, dto);
77+
78+
return ResponseEntity.ok(guesthouseId);
79+
}
80+
81+
// @Operation(summary = "홈 화면 게스트하우스 목록 조회 (광고 우선)", description = "게스트하우스 목록을 보여줍니다")
82+
// @GetMapping("/home")
83+
// public ApiResponse<Slice<GuesthouseResponseDTO.HomeSummary>> getGuesthousesForHome(
84+
// @ParameterObject
85+
// @PageableDefault(size = 10) Pageable pageable) {
86+
// return ApiResponse.success(guesthouseQueryService.getGuesthousesForHome(pageable));
87+
// }
88+
89+
@GetMapping("/home")
90+
@Operation(summary = "홈 화면 조회", description = "홈 화면에 출력할 홈 화면 전용 게스트하우스 조회 API입니다.")
91+
public ResponseEntity<ApiResponse<Slice<GuesthouseResponseDTO.HomeSummary>>> getGuesthousesForHome(
92+
@ParameterObject
93+
@PageableDefault(size = 10) Pageable pageable) {
94+
Slice<GuesthouseResponseDTO.HomeSummary> data = guesthouseQueryService.getGuesthousesForHome(pageable);
95+
ApiResponse<Slice<GuesthouseResponseDTO.HomeSummary>> response = ApiResponse.success(data);
96+
return ResponseEntity.ok(response);
97+
}
98+
99+
@PatchMapping("/{guesthouseId}/advertisement/on")
100+
@Operation(summary = "게스트하우스 광고 설정", description = "해당 게스트하우스를 광고 상태로 설정합니다.")
101+
public ApiResponse<Void> activateAdvertisement(@PathVariable Long guesthouseId) {
102+
guesthouseCommandService.activateAdvertisement(guesthouseId);
71103
return ApiResponse.successWithNoData();
104+
}
105+
106+
@PatchMapping("/{guesthouseId}/advertisement/off")
107+
@Operation(summary = "게스트하우스 광고 해제", description = "해당 게스트하우스를 광고 상태에서 해제합니다.")
108+
public ApiResponse<Void> deactivateAdvertisement(@PathVariable Long guesthouseId) {
109+
guesthouseCommandService.deactivateAdvertisement(guesthouseId);
110+
return ApiResponse.successWithNoData();
111+
}
72112

113+
@GetMapping("/{guesthouseId}")
114+
@Operation(summary = "게스트하우스 조회", description = "id기반으로 게스트하우스를 조회하는 api입니다")
115+
@Parameters({
116+
@Parameter(name = "guesthouseId", description = "게스트하우스 아이디를 넘겨주세요.")
117+
})
118+
public ResponseEntity<ApiResponse<GuesthouseDetailDTO>> getRoom(
119+
@PathVariable Long guesthouseId
120+
) {
121+
GuesthouseDetailDTO result = guesthouseQueryService.getHouseById(guesthouseId);
122+
return ResponseEntity.ok(ApiResponse.success(result));
73123
}
74124

75125
@PostMapping("/search")
@@ -88,4 +138,4 @@ public ResponseEntity<ApiResponse<Page<GuesthousePreviewDTO>>> searchGuesthouse(
88138

89139
}
90140

91-
}
141+
}

src/main/java/com/sumte/guesthouse/controller/OptionServiceController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import lombok.RequiredArgsConstructor;
1414

1515
@RestController
16-
@Tag(name = "부가서비스 조회 api", description = "부가서비스 리스트를 조회하는 api 입니다.")
16+
@Tag(name = "게스트 하우스 api", description = "게스트하우스 생성/수정/조회/삭제 api 입니다.")
1717
@RequiredArgsConstructor
1818
@RequestMapping("/option")
1919
public class OptionServiceController {

src/main/java/com/sumte/guesthouse/controller/TargetAudienceController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import lombok.RequiredArgsConstructor;
1414

1515
@RestController
16-
@Tag(name = "이용대상 조회 api", description = "게스트하우스의 이용대상을 조회하는 api 입니다.")
16+
@Tag(name = "게스트 하우스 api", description = "게스트하우스 생성/수정/조회/삭제 api 입니다.")
1717
@RequiredArgsConstructor
1818
@RequestMapping("/target")
1919
public class TargetAudienceController {

src/main/java/com/sumte/guesthouse/converter/GuesthouseConverter.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import com.sumte.guesthouse.dto.GuesthouseRequestDTO;
88
import com.sumte.guesthouse.dto.GuesthouseResponseDTO;
9+
import com.sumte.guesthouse.entity.AdType;
910
import com.sumte.guesthouse.entity.Guesthouse;
1011

1112
import lombok.RequiredArgsConstructor;
@@ -19,20 +20,40 @@ public Guesthouse toRegisterEntity(GuesthouseRequestDTO.Register dto) {
1920

2021
public GuesthouseResponseDTO.Register toRegisterResponseDTO(Guesthouse guesthouse) {
2122
return GuesthouseResponseDTO.Register.builder()
23+
.id(guesthouse.getId())
2224
.name(guesthouse.getName())
23-
.addressRegion(guesthouse.getAddressRegion())
2425
.build();
2526

2627
}
2728

2829
public GuesthouseResponseDTO.Update toUpdateResponseDTO(Guesthouse guesthouse, List<String> optionServices,
2930
List<String> targetAudience) {
3031
return GuesthouseResponseDTO.Update.builder()
32+
.id(guesthouse.getId())
3133
.name(guesthouse.getName())
3234
.addressRegion(guesthouse.getAddressRegion())
3335
.addressDetail(guesthouse.getAddressDetail())
3436
.targetAudience(targetAudience)
3537
.optionServices(optionServices)
3638
.build();
3739
}
40+
41+
public GuesthouseResponseDTO.HomeSummary toHomeSummary(
42+
Guesthouse guesthouse,
43+
Double avgScore,
44+
int reviewCount,
45+
String checkInTime,
46+
Long minPrice
47+
) {
48+
return GuesthouseResponseDTO.HomeSummary.builder()
49+
.guestHouseId(guesthouse.getId())
50+
.name(guesthouse.getName())
51+
.addressRegion(guesthouse.getAddressRegion())
52+
.averageScore(avgScore)
53+
.reviewCount(reviewCount)
54+
.checkInTime(checkInTime)
55+
.minPrice(minPrice)
56+
.isAd(guesthouse.getAdvertisement() == AdType.AD)
57+
.build();
58+
}
3859
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.sumte.guesthouse.dto;
2+
3+
import java.util.List;
4+
5+
import com.sumte.guesthouse.entity.AdType;
6+
import com.sumte.room.dto.RoomResponseDTO;
7+
8+
import lombok.AllArgsConstructor;
9+
import lombok.Builder;
10+
import lombok.Getter;
11+
import lombok.NoArgsConstructor;
12+
13+
@Getter
14+
@Builder
15+
@NoArgsConstructor
16+
@AllArgsConstructor
17+
public class GuesthouseDetailDTO {
18+
private Long id;
19+
private String name;
20+
private String addressRegion;
21+
private String addressDetail;
22+
private String information;
23+
private AdType advertisement;
24+
private List<String> optionServices;
25+
private List<String> targetAudience;
26+
private List<RoomResponseDTO.GetPreviewRoomByGuesthouseResponse> rooms;
27+
private List<String> imageUrls; // 모든 이미지 URL 리스트
28+
}

src/main/java/com/sumte/guesthouse/dto/GuesthousePreviewDTO.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,9 @@ public class GuesthousePreviewDTO {
1515
private Long id;
1616
private String name;
1717
private Double averageScore;
18-
private Long reviewCount;
18+
private Integer reviewCount;
1919
private Long lowerPrice;
2020
private String addressRegion;
2121
private LocalTime checkinTime;
22-
23-
public void setAverageScore(Double averageScore) {
24-
this.averageScore = averageScore;
25-
}
26-
27-
public void setReviewCount(Long reviewCount) {
28-
this.reviewCount = reviewCount;
29-
}
22+
private String imageUrl;
3023
}

0 commit comments

Comments
 (0)