diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index 1fc3af7c..ca67e812 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -54,6 +54,20 @@ jobs:
echo "${{ secrets.AWS_PROPERTIES }}" > ./application.yml
shell: bash
+<<<<<<< HEAD
+ # Google Translation key 설정
+ - name: Create Google Translation JSON file from secret
+ uses: jsdaniell/create-json@1.1.2
+ with:
+ name: "./back-end/src/main/resources/service-account-file.json"
+ json: ${{ secrets.GOOGLE_TRANSLATION_KEY }}
+
+ - name: Verify JSON file creation
+ run: cat ./back-end/src/main/resources/service-account-file.json
+
+
+=======
+>>>>>>> develop
# gradlew 파일 실행권한 설정
- name: Grant execute permission for gradlew
run: |
diff --git a/.idea/SKYTeam.iml b/.idea/SKYTeam.iml
new file mode 100644
index 00000000..d6ebd480
--- /dev/null
+++ b/.idea/SKYTeam.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/back-end/.gitignore b/back-end/.gitignore
index 0e09f120..ec34837b 100644
--- a/back-end/.gitignore
+++ b/back-end/.gitignore
@@ -38,4 +38,11 @@ out/
### *.yml / *.properties ###
*.yml
-application.properties
\ No newline at end of file
+<<<<<<< HEAD
+application.properties
+
+### google cloud translation api key ###
+service-account-file.json
+=======
+application.properties
+>>>>>>> develop
diff --git a/back-end/build.gradle b/back-end/build.gradle
index 8936c720..67bdd000 100644
--- a/back-end/build.gradle
+++ b/back-end/build.gradle
@@ -76,6 +76,16 @@ dependencies {
// WebSocket
implementation 'org.springframework.boot:spring-boot-starter-websocket'
+<<<<<<< HEAD
+
+ // ChatGpt
+ implementation 'com.squareup.okhttp3:okhttp:4.9.1'
+ implementation 'org.apache.commons:commons-io:1.3.2'
+
+ // Google Cloud Translation
+ implementation 'com.google.cloud:google-cloud-translate:2.6.0'
+=======
+>>>>>>> develop
}
tasks.named('test') {
diff --git a/back-end/lambda/EmbeddingCategory.py b/back-end/lambda/EmbeddingCategory.py
new file mode 100644
index 00000000..eeaf0116
--- /dev/null
+++ b/back-end/lambda/EmbeddingCategory.py
@@ -0,0 +1,70 @@
+import os
+import json
+import urllib3
+from openai import OpenAI
+from pymongo.mongo_client import MongoClient
+from pymongo.server_api import ServerApi
+
+mongo_uri = os.environ.get("MONGO_URI")
+
+def lambda_handler(event, context):
+ # Fetch user's profile data
+ request_event = json.loads(event["body"])
+ category_id = request_event["category_id"]
+ category = request_event["category"]
+ prompt = request_event["prompt"]
+
+ # Create a new client and connect to the server
+ client = MongoClient(mongo_uri, server_api=ServerApi('1'))
+
+ # Name of database
+ db = client.CategoryEmbedding
+
+ # Name of collection
+ collection = db.Embedding
+
+ embedding = getEmbedding(prompt)
+ document = {"category": category, "prompt": prompt, "embedding": embedding}
+
+ # Insert document
+ result = collection.update_one({"category_id": category_id}, {"$set": document}, upsert=True)
+
+ if result.acknowledged:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 200,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "Successfully added the category."
+ }
+ else:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 502,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "There was error during the insertion."
+ }
+
+
+def getEmbedding(document):
+ open_ai_url = os.environ.get("OPENAI_URI")
+ open_ai_key = os.environ.get("OPENAI_KEY")
+
+ header = {
+ 'Content-Type': 'application/json',
+ 'Authorization': f'Bearer {open_ai_key}'
+ }
+
+ body = json.dumps({
+ 'input': f'{document}',
+ 'model': "text-embedding-3-large",
+ 'format': "float"
+ })
+
+ http = urllib3.PoolManager()
+ response = http.request('POST', open_ai_url, body=body, headers=header)
+
+ data = json.loads(response.data)
+
+ return data['data'][0]['embedding']
\ No newline at end of file
diff --git a/back-end/lambda/EmbeddingMeeting.py b/back-end/lambda/EmbeddingMeeting.py
new file mode 100644
index 00000000..fbc5562a
--- /dev/null
+++ b/back-end/lambda/EmbeddingMeeting.py
@@ -0,0 +1,74 @@
+import os
+import json
+import urllib3
+from openai import OpenAI
+from pymongo.mongo_client import MongoClient
+from pymongo.server_api import ServerApi
+
+mongo_uri = os.environ.get("MONGO_URI")
+
+def lambda_handler(event, context):
+ # Fetch user's profile data
+ event_body = json.loads(event["body"])
+ moim_id = event_body['moimId']
+ moimname = event_body['moimTitle']
+ prompt = event_body['prompt']
+
+ # Create a new client and connect to the server
+ client = MongoClient(mongo_uri, server_api=ServerApi('1'))
+
+ # Name of database
+ db = client.MoimEmbedding
+
+ # Name of collection
+ collection = db.Embedding
+
+ embedding = getEmbedding(prompt)
+ document = {
+ "moim_id": moim_id,
+ "moim_title": moimname,
+ "prompt": prompt,
+ "embedding": embedding}
+
+ # Insert document
+ result = collection.update_one({"moim_id": moim_id}, {"$set": document}, upsert=True)
+
+ if result.acknowledged:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 200,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "Success"
+ }
+ else:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 400,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "Failed"
+ }
+
+
+def getEmbedding(document):
+ open_ai_url = os.environ.get("OPENAI_URI")
+ open_ai_key = os.environ.get("OPENAI_KEY")
+
+ header = {
+ 'Content-Type': 'application/json',
+ 'Authorization': f'Bearer {open_ai_key}'
+ }
+
+ body = json.dumps({
+ 'input': f'{document}',
+ 'model': "text-embedding-3-large",
+ 'format': "float"
+ })
+
+ http = urllib3.PoolManager()
+ response = http.request('POST', open_ai_url, body=body, headers=header)
+
+ data = json.loads(response.data)
+
+ return data['data'][0]['embedding']
\ No newline at end of file
diff --git a/back-end/lambda/EmbeddingSearchCategory.py b/back-end/lambda/EmbeddingSearchCategory.py
new file mode 100644
index 00000000..d36e9db5
--- /dev/null
+++ b/back-end/lambda/EmbeddingSearchCategory.py
@@ -0,0 +1,78 @@
+import os
+import json
+import urllib3
+from openai import OpenAI
+from pymongo.mongo_client import MongoClient
+from pymongo.server_api import ServerApi
+
+mongo_uri = os.environ.get("MONGO_URI")
+
+def lambda_handler(event, context):
+ # Fetch user's profile data
+ user_id = int(event['queryStringParameters']['userID'])
+
+ # Create a new client and connect to the server
+ client = MongoClient(mongo_uri, server_api=ServerApi('1'))
+
+ # Name of database
+ db = client.UserEmbedding
+
+ # Name of collection
+ collection = db.Embedding
+
+ query = { "user_id": user_id }
+ projection = { "embedding": 1 }
+
+ # Insert document
+ result = collection.find_one(query, projection)
+ if result == None:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 400,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "There's no such user in DB."
+ }
+
+ query_embedding = result['embedding']
+
+ pipeline = [
+ {
+ '$vectorSearch': {
+ 'index': 'CategoryVectorIndex',
+ 'path': 'embedding',
+ 'queryVector': query_embedding,
+ 'numCandidates': 100,
+ 'limit': 100
+ }
+ }, {
+ '$project': {
+ '_id': 0,
+ 'prompt': 0,
+ 'embedding': 0
+ }
+ }
+ ]
+
+ results = client['CategoryEmbedding']['Embedding'].aggregate(pipeline)
+
+ moim_list = []
+ for search_result in results:
+ moim_list.append(search_result['category_id'])
+
+ if (len(moim_list) > 0):
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 200,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "[" + ','.join(str(e) for e in moim_list) + "]"
+ }
+ else:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 502,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "Error occured during insertion."
+ }
diff --git a/back-end/lambda/EmbeddingSearchMeeting.py b/back-end/lambda/EmbeddingSearchMeeting.py
new file mode 100644
index 00000000..fe0b5c84
--- /dev/null
+++ b/back-end/lambda/EmbeddingSearchMeeting.py
@@ -0,0 +1,69 @@
+import os
+import json
+import urllib3
+from openai import OpenAI
+from pymongo.mongo_client import MongoClient
+from pymongo.server_api import ServerApi
+
+mongo_uri = os.environ.get("MONGO_URI")
+
+def lambda_handler(event, context):
+ # Fetch user's profile data
+ user_id = int(event['queryStringParameters']['userID'])
+
+ # Create a new client and connect to the server
+ client = MongoClient(mongo_uri, server_api=ServerApi('1'))
+
+ # Name of database
+ db = client.UserEmbedding
+
+ # Name of collection
+ collection = db.Embedding
+
+ query = { "user_id": user_id }
+ projection = { "embedding": 1 }
+
+ # Insert document
+ result = collection.find_one(query, projection)
+
+ query_embedding = result['embedding']
+
+ pipeline = [
+ {
+ '$vectorSearch': {
+ 'index': 'MoimVectorIndex',
+ 'path': 'embedding',
+ 'queryVector': query_embedding,
+ 'numCandidates': 100,
+ 'limit': 50
+ }
+ }, {
+ '$project': {
+ '_id': 0,
+ 'embedding': 0
+ }
+ }
+ ]
+
+ results = client['MoimEmbedding']['Embedding'].aggregate(pipeline)
+
+ moim_list = []
+ for search_result in results:
+ moim_list.append(search_result['moim_id'])
+
+ if (len(moim_list) > 0):
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 200,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "[" + ','.join(str(e) for e in moim_list) + "]"
+ }
+ else:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 400,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "Failed"
+ }
diff --git a/back-end/lambda/EmbeddingUser.py b/back-end/lambda/EmbeddingUser.py
new file mode 100644
index 00000000..7da4e262
--- /dev/null
+++ b/back-end/lambda/EmbeddingUser.py
@@ -0,0 +1,74 @@
+import os
+import json
+import urllib3
+from openai import OpenAI
+from pymongo.mongo_client import MongoClient
+from pymongo.server_api import ServerApi
+
+mongo_uri = os.environ.get("MONGO_URI")
+
+def lambda_handler(event, context):
+ # Fetch user's profile data
+ request_event = json.loads(event["body"])
+ user_id = int(request_event["userId"])
+ username = request_event["username"]
+ prompt = request_event["prompt"]
+
+ # Create a new client and connect to the server
+ client = MongoClient(mongo_uri, server_api=ServerApi('1'))
+
+ # Name of database
+ db = client.UserEmbedding
+
+ # Name of collection
+ collection = db.Embedding
+
+ embedding = getEmbedding(prompt)
+ document = {
+ "user_id": user_id,
+ "username": username,
+ "prompt": prompt,
+ "embedding": embedding}
+
+ # Insert document
+ result = collection.update_one({"user_id": user_id}, {"$set": document}, upsert = True)
+
+ if result.acknowledged:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 200,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "Success"
+ }
+ else:
+ return {
+ "isBase64Encoded": False,
+ "statusCode": 400,
+ "headers": {},
+ "multiValueHeaders": {},
+ "body": "FAILED"
+ }
+
+
+def getEmbedding(document):
+ open_ai_url = os.environ.get("OPENAI_URI")
+ open_ai_key = os.environ.get("OPENAI_KEY")
+
+ header = {
+ 'Content-Type': 'application/json',
+ 'Authorization': f'Bearer {open_ai_key}'
+ }
+
+ body = json.dumps({
+ 'input': f'{document}',
+ 'model': "text-embedding-3-large",
+ 'format': "float"
+ })
+
+ http = urllib3.PoolManager()
+ response = http.request('POST', open_ai_url, body=body, headers=header)
+
+ data = json.loads(response.data)
+
+ return data['data'][0]['embedding']
\ No newline at end of file
diff --git a/back-end/src/main/java/kr/co/ssalon/config/CorsMvcConfig.java b/back-end/src/main/java/kr/co/ssalon/config/CorsMvcConfig.java
index c72aa630..2549bdb5 100644
--- a/back-end/src/main/java/kr/co/ssalon/config/CorsMvcConfig.java
+++ b/back-end/src/main/java/kr/co/ssalon/config/CorsMvcConfig.java
@@ -10,6 +10,11 @@ public class CorsMvcConfig implements WebMvcConfigurer {
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.exposedHeaders("Set-Cookie")
+<<<<<<< HEAD
+ .allowedMethods("*")
+ .allowCredentials(true)
+=======
+>>>>>>> develop
.allowedOrigins("http://localhost:3000", "https://ssalon.co.kr");
}
}
diff --git a/back-end/src/main/java/kr/co/ssalon/config/CustomLocalDateTimeSerializer.java b/back-end/src/main/java/kr/co/ssalon/config/CustomLocalDateTimeSerializer.java
new file mode 100644
index 00000000..eeb7daa7
--- /dev/null
+++ b/back-end/src/main/java/kr/co/ssalon/config/CustomLocalDateTimeSerializer.java
@@ -0,0 +1,19 @@
+package kr.co.ssalon.config;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class CustomLocalDateTimeSerializer extends JsonSerializer {
+
+ private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS");
+
+ @Override
+ public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ gen.writeString(value.format(FORMATTER));
+ }
+}
\ No newline at end of file
diff --git a/back-end/src/main/java/kr/co/ssalon/config/GoogleCredentialsConfig.java b/back-end/src/main/java/kr/co/ssalon/config/GoogleCredentialsConfig.java
new file mode 100644
index 00000000..9a6bff6b
--- /dev/null
+++ b/back-end/src/main/java/kr/co/ssalon/config/GoogleCredentialsConfig.java
@@ -0,0 +1,28 @@
+package kr.co.ssalon.config;
+
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.cloud.translate.Translate;
+import com.google.cloud.translate.TranslateOptions;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+@Configuration
+public class GoogleCredentialsConfig {
+
+ @Value("${google.cloud.credentials.location}")
+ private Resource credentialsLocation;
+
+ @Bean
+ public Translate translate() throws IOException {
+ try (InputStream inputStream = credentialsLocation.getInputStream()) {
+ GoogleCredentials credentials = GoogleCredentials.fromStream(inputStream);
+ return TranslateOptions.newBuilder().setCredentials(credentials).build().getService();
+ }
+ }
+}
diff --git a/back-end/src/main/java/kr/co/ssalon/config/JacksonConfig.java b/back-end/src/main/java/kr/co/ssalon/config/JacksonConfig.java
new file mode 100644
index 00000000..35b34a07
--- /dev/null
+++ b/back-end/src/main/java/kr/co/ssalon/config/JacksonConfig.java
@@ -0,0 +1,27 @@
+package kr.co.ssalon.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.LocalDateTime;
+
+@Configuration
+public class JacksonConfig {
+
+ @Bean
+ public ObjectMapper objectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+ javaTimeModule.addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer());
+
+ mapper.registerModule(javaTimeModule);
+ mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+
+ return mapper;
+ }
+}
\ No newline at end of file
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/dto/MeetingDomainDTO.java b/back-end/src/main/java/kr/co/ssalon/domain/dto/MeetingDomainDTO.java
index e1c2faf0..6211ea9a 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/dto/MeetingDomainDTO.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/dto/MeetingDomainDTO.java
@@ -1,5 +1,12 @@
package kr.co.ssalon.domain.dto;
+<<<<<<< HEAD
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+=======
+>>>>>>> develop
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -20,10 +27,20 @@ public class MeetingDomainDTO {
private String description;
private String location;
private Integer capacity;
+<<<<<<< HEAD
+
+ @JsonSerialize(using = LocalDateTimeSerializer.class)
+ @JsonDeserialize(using = LocalDateTimeDeserializer.class)
+=======
+>>>>>>> develop
private LocalDateTime meetingDate;
private Integer payment;
private Boolean isSharable;
+<<<<<<< HEAD
+}
+=======
}
+>>>>>>> develop
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/dto/MemberDomainDTO.java b/back-end/src/main/java/kr/co/ssalon/domain/dto/MemberDomainDTO.java
index 50cc8721..eabb789b 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/dto/MemberDomainDTO.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/dto/MemberDomainDTO.java
@@ -16,6 +16,10 @@
@Builder
public class MemberDomainDTO {
+<<<<<<< HEAD
+ private Long id;
+=======
+>>>>>>> develop
private String email;
private String nickname;
private String profilePictureUrl;
@@ -28,6 +32,10 @@ public class MemberDomainDTO {
private MemberDates memberDates;
public MemberDomainDTO(Member member) {
+<<<<<<< HEAD
+ this.id = member.getId();
+=======
+>>>>>>> develop
this.email = member.getEmail();
this.nickname = member.getNickname();
this.profilePictureUrl = member.getProfilePictureUrl();
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/entity/AdvertisePayment.java b/back-end/src/main/java/kr/co/ssalon/domain/entity/AdvertisePayment.java
new file mode 100644
index 00000000..62be1bb5
--- /dev/null
+++ b/back-end/src/main/java/kr/co/ssalon/domain/entity/AdvertisePayment.java
@@ -0,0 +1,25 @@
+package kr.co.ssalon.domain.entity;
+
+import jakarta.persistence.DiscriminatorValue;
+import jakarta.persistence.Entity;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Getter
+@DiscriminatorValue("A")
+@NoArgsConstructor
+public class AdvertisePayment extends Payment{
+
+ public AdvertisePayment(Member member, Meeting meeting, Integer amount, String purpose, String tid) {
+ super(member, meeting, amount, purpose, tid);
+ }
+
+ public static Payment createAdvertisePayment(Member member, Meeting meeting, String purpose, Integer amount, String tid) {
+ AdvertisePayment advertisePayment = new AdvertisePayment(member, meeting, amount, purpose, tid);
+ advertisePayment.changeMemberByAdvertise(member);
+ advertisePayment.changeMeeting(meeting);
+ return advertisePayment;
+ }
+
+}
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/entity/Meeting.java b/back-end/src/main/java/kr/co/ssalon/domain/entity/Meeting.java
index 5c1c9ebd..4bb0c38c 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/entity/Meeting.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/entity/Meeting.java
@@ -37,10 +37,21 @@ public class Meeting {
@OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL, orphanRemoval = true)
private final List participants = new ArrayList<>();
+<<<<<<< HEAD
+ @OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL, orphanRemoval = true)
+ private final List meetingOuts = new ArrayList<>();
+
+=======
+>>>>>>> develop
@ElementCollection
@CollectionTable(name = "meeting_picture", joinColumns = @JoinColumn(name = "meeting_id"))
private final List meetingPictureUrls = new ArrayList<>();
+<<<<<<< HEAD
+ @OneToMany(mappedBy = "meeting", cascade = CascadeType.ALL, orphanRemoval = true)
+ private final List payments = new ArrayList<>();
+=======
+>>>>>>> develop
private String title;
private String description;
@@ -91,22 +102,38 @@ public void changeThumbnail(String thumbnail) {
this.thumbnail = thumbnail != null ? thumbnail : this.thumbnail;
}
+<<<<<<< HEAD
+ public void changePayment(Integer payment) {this.payment = payment != null ? payment : this.payment;}
+ public void changeIsSharable(Boolean isSharable) {this.isSharable = isSharable != null ? isSharable : this.isSharable;}
+=======
+
+>>>>>>> develop
public void addMeetingPictureUrls(List meetingPictureUrls) {
for (String meetingPictureUrl : meetingPictureUrls) {
getMeetingPictureUrls().add(meetingPictureUrl);
}
}
+<<<<<<< HEAD
+ public void updateMeeting(Category category, Integer payment, List meetingPictureUrls, String title, String description, String location, Integer capacity, LocalDateTime meetingDates, Boolean isSharable) {
+ changeCategory(category);
+ changePayment(payment);
+=======
public void updateMeeting(Category category, List meetingPictureUrls, String title, String description, String location, Integer capacity, LocalDateTime meetingDates) {
changeCategory(category);
+>>>>>>> develop
addMeetingPictureUrls(meetingPictureUrls);
changeTitle(title);
changeDescription(description);
changeLocation(location);
changeCapacity(capacity);
changeLocalDateTime(meetingDates);
+<<<<<<< HEAD
+ changeIsSharable(isSharable);
+=======
+>>>>>>> develop
}
// ***** 연관 메서드 *****
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/entity/Member.java b/back-end/src/main/java/kr/co/ssalon/domain/entity/Member.java
index 350e5139..01baf234 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/entity/Member.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/entity/Member.java
@@ -24,8 +24,17 @@ public class Member {
private final List joinedMeetings = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
+<<<<<<< HEAD
+ private final List meetingOuts = new ArrayList<>();
+
+ @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
+ private final List payments = new ArrayList<>();
+ @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true)
+ private final List advertisements = new ArrayList<>();
+=======
private final List payments = new ArrayList<>();
+>>>>>>> develop
private String username;
private String email;
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/entity/MemberMeeting.java b/back-end/src/main/java/kr/co/ssalon/domain/entity/MemberMeeting.java
index 14078ab3..e2ba3de5 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/entity/MemberMeeting.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/entity/MemberMeeting.java
@@ -37,7 +37,11 @@ public class MemberMeeting {
@JoinColumn(name = "qr_link_id")
private QrLink qrLink;
+<<<<<<< HEAD
+ @OneToMany(mappedBy = "memberMeeting", cascade = CascadeType.ALL)
+=======
@OneToMany(mappedBy = "memberMeeting")
+>>>>>>> develop
private final List messages = new ArrayList<>();
private boolean attendance;
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/entity/MoimPayment.java b/back-end/src/main/java/kr/co/ssalon/domain/entity/MoimPayment.java
new file mode 100644
index 00000000..ba3cd01e
--- /dev/null
+++ b/back-end/src/main/java/kr/co/ssalon/domain/entity/MoimPayment.java
@@ -0,0 +1,24 @@
+package kr.co.ssalon.domain.entity;
+
+
+import jakarta.persistence.DiscriminatorValue;
+import jakarta.persistence.Entity;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@Getter
+@DiscriminatorValue("M")
+@NoArgsConstructor
+public class MoimPayment extends Payment{
+
+ public MoimPayment(Member member, Meeting meeting, Integer amount, String purpose, String tid) {
+ super(member, meeting, amount, purpose, tid);
+ }
+ public static Payment createMoimPayment(Member member, Meeting meeting, String purpose, Integer amount, String tid) {
+ MoimPayment moimPayment = new MoimPayment(member, meeting, amount, purpose, tid);
+ moimPayment.changeMeeting(meeting);
+ moimPayment.changeMemberByMoim(member);
+ return moimPayment;
+ }
+}
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/entity/Payment.java b/back-end/src/main/java/kr/co/ssalon/domain/entity/Payment.java
index 4a68b644..3ddbf13c 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/entity/Payment.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/entity/Payment.java
@@ -5,11 +5,23 @@
import lombok.Builder;
import lombok.Getter;
+<<<<<<< HEAD
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+
+@Entity
+@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
+@DiscriminatorColumn
+@Getter
+@AllArgsConstructor
+public abstract class Payment {
+=======
@Entity
@Getter
@Builder
@AllArgsConstructor
public class Payment {
+>>>>>>> develop
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -21,12 +33,47 @@ public class Payment {
@JoinColumn(name = "member_id")
private Member member;
+<<<<<<< HEAD
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "meeting_id")
+=======
@OneToOne(fetch = FetchType.LAZY)
+>>>>>>> develop
private Meeting meeting;
private Integer amount;
private String purpose;
+<<<<<<< HEAD
+ private String tid;
+ @Column(insertable = false, updatable = false)
+ private String dtype;
+
+ public Payment(Member member, Meeting meeting, Integer amount, String purpose, String tid) {
+ this.member = member;
+ this.meeting = meeting;
+ this.amount = amount;
+ this.purpose = purpose;
+ this.tid = tid;
+ }
+
+ protected Payment() {
+ }
+
+ // ***** 연관 메서드 *****
+ public void changeMemberByMoim(Member member) {
+ this.member = member;
+ member.getPayments().add(this);
+ }
+
+ public void changeMemberByAdvertise(Member member) {
+ this.member = member;
+ member.getAdvertisements().add(this);
+ }
+
+ public void changeMeeting(Meeting meeting) {
+ this.meeting = meeting;
+=======
protected Payment() {}
@@ -42,5 +89,6 @@ public static Payment createPayment(Member member, Integer amount) {
payment.changeMember(member);
return payment;
+>>>>>>> develop
}
}
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepository.java b/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepository.java
index 08790207..83f25299 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepository.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepository.java
@@ -1,8 +1,16 @@
package kr.co.ssalon.domain.repository;
import kr.co.ssalon.domain.entity.Meeting;
+<<<<<<< HEAD
+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 org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+>>>>>>> develop
import org.springframework.stereotype.Repository;
import java.util.List;
@@ -12,4 +20,13 @@ public interface MeetingRepository extends JpaRepository, MeetingR
@Query("SELECT m FROM Meeting m WHERE m.isFinished = false")
List findAllUnfinishedMeetings();
+<<<<<<< HEAD
+
+
+ @Query("SELECT m FROM Meeting m WHERE m.title LIKE %:keyword% OR m.description LIKE %:keyword%")
+ Page searchByTitleOrDescription(@Param("keyword") String keyword, Pageable pageable);
+
+
+=======
+>>>>>>> develop
}
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepositoryCustomImpl.java b/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepositoryCustomImpl.java
index 56ed4349..fcbc2f37 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepositoryCustomImpl.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/repository/MeetingRepositoryCustomImpl.java
@@ -14,7 +14,10 @@
import kr.co.ssalon.domain.entity.Meeting;
import kr.co.ssalon.domain.entity.Member;
import kr.co.ssalon.domain.entity.MemberMeeting;
+<<<<<<< HEAD
+=======
import kr.co.ssalon.domain.entity.QMemberMeeting;
+>>>>>>> develop
import kr.co.ssalon.domain.service.MeetingService;
import kr.co.ssalon.web.dto.MeetingSearchCondition;
import org.springframework.beans.factory.annotation.Autowired;
@@ -23,7 +26,13 @@
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Component;
+<<<<<<< HEAD
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
+=======
+import java.util.List;
+>>>>>>> develop
import static com.querydsl.jpa.JPAExpressions.select;
import static kr.co.ssalon.domain.entity.QMeeting.meeting;
@@ -32,7 +41,10 @@
@Component
public class MeetingRepositoryCustomImpl implements MeetingRepositoryCustom {
+<<<<<<< HEAD
+=======
MeetingService meetingService;
+>>>>>>> develop
EntityManager em;
JPAQueryFactory query;
@@ -128,6 +140,17 @@ public List findMeetingsByCategoryId(Long categoryId) {
}
private Member findMemberByUsername(String username) {
+<<<<<<< HEAD
+ System.out.println("Finding member by username: " + username);
+ Member member = em.createQuery("SELECT m FROM Member m WHERE m.username = :username", Member.class)
+ .setParameter("username", username)
+ .getSingleResult();
+ System.out.println("Found member: " + member);
+ return member;
+ }
+
+
+=======
// Implement a method to find a Member entity by username
// Example:
return em.createQuery("SELECT m FROM Member m WHERE m.username = :username", Member.class)
@@ -135,4 +158,5 @@ private Member findMemberByUsername(String username) {
.getSingleResult();
}
+>>>>>>> develop
}
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/repository/PaymentRepository.java b/back-end/src/main/java/kr/co/ssalon/domain/repository/PaymentRepository.java
index 2a9592c4..2b183b14 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/repository/PaymentRepository.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/repository/PaymentRepository.java
@@ -1,7 +1,26 @@
package kr.co.ssalon.domain.repository;
+<<<<<<< HEAD
+import kr.co.ssalon.domain.entity.Meeting;
+import kr.co.ssalon.domain.entity.Member;
+import kr.co.ssalon.domain.entity.Payment;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface PaymentRepository extends JpaRepository {
+ Optional findPaymentByMemberAndMeeting(Member member, Meeting meeting);
+
+ List findAllByMeetingIdAndDtype(Long moimid, String dtype);
+
+ List findAllByMemberIdAndDtype(Long memberId, String dtype);
+ List findAllByDtype(String dtype);
+
+=======
import kr.co.ssalon.domain.entity.Payment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PaymentRepository extends JpaRepository {
+>>>>>>> develop
}
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/service/AwsLambdaService.java b/back-end/src/main/java/kr/co/ssalon/domain/service/AwsLambdaService.java
index 718695b7..9565f555 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/service/AwsLambdaService.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/service/AwsLambdaService.java
@@ -49,6 +49,11 @@ public void updateUserEmbedding(Long userID, String username, String prompt) {
jsonObject.addProperty("username", username);
jsonObject.addProperty("prompt", prompt);
+<<<<<<< HEAD
+ log.info("Sending request to update user embedding for userID: {}", userID);
+
+=======
+>>>>>>> develop
webClient.post()
.uri(uriBuilder -> uriBuilder
.path("/api/embedding/user")
@@ -57,6 +62,11 @@ public void updateUserEmbedding(Long userID, String username, String prompt) {
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(10))
+<<<<<<< HEAD
+ .doOnNext(response -> log.info("Response received: {}", response))
+ .doOnError(error -> log.error("Error occurred: ", error))
+=======
+>>>>>>> develop
.block();
log.warn("UserEmbedding query sent.");
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/service/AwsS3Service.java b/back-end/src/main/java/kr/co/ssalon/domain/service/AwsS3Service.java
index 19cdca4e..94f426e6 100644
--- a/back-end/src/main/java/kr/co/ssalon/domain/service/AwsS3Service.java
+++ b/back-end/src/main/java/kr/co/ssalon/domain/service/AwsS3Service.java
@@ -17,6 +17,10 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+<<<<<<< HEAD
+import java.util.UUID;
+=======
+>>>>>>> develop
@Slf4j
@RequiredArgsConstructor
@@ -109,6 +113,35 @@ public String uploadFileViaStream(Long moimId, String userEmail, String uploadFi
return "200 OK";
}
+<<<<<<< HEAD
+ public String uploadFileViaByteArray(Long moimId, byte[] byteArray) {
+ String keyName = "Images/" + moimId + "/" + UUID.randomUUID() + ".png";
+ try {
+ // Byte -> InputStream 변환
+ InputStream inputStream = new ByteArrayInputStream(byteArray);
+
+ // PutObjectRequest 설정
+ PutObjectRequest putObjectRequest = PutObjectRequest.builder()
+ .bucket(bucketStaticName)
+ .contentType("image/png")
+ .contentLength((long) byteArray.length)
+ .key(keyName)
+ .build();
+
+ // 업로드 실행
+ s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(inputStream, byteArray.length));
+ } catch (Exception e) {
+ // 임시 에러 로깅 처리
+ e.printStackTrace();
+ return "502 Bad Gateway";
+ }
+
+ String imageUrl = "https://" + bucketStaticName + ".s3.ap-northeast-2.amazonaws.com/" + keyName;
+ return imageUrl;
+ }
+
+=======
+>>>>>>> develop
public int uploadMultiFilesViaMultipart(List multipartFiles, Map imageKeyMap) {
int successfulUpload = 0;
diff --git a/back-end/src/main/java/kr/co/ssalon/domain/service/ChatGptService.java b/back-end/src/main/java/kr/co/ssalon/domain/service/ChatGptService.java
new file mode 100644
index 00000000..c34f0909
--- /dev/null
+++ b/back-end/src/main/java/kr/co/ssalon/domain/service/ChatGptService.java
@@ -0,0 +1,161 @@
+package kr.co.ssalon.domain.service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import kr.co.ssalon.web.dto.ImageGenerationDTO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.http.*;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class ChatGptService {
+
+ @Value("${openai.api.key}")
+ private String apiKey;
+
+ @Value("${karlo.api.key}")
+ private String karloApiKey;
+
+ private static final String OPENAI_API_URL = "https://api.openai.com/v1/images/generations";
+ private final ObjectMapper objectMapper;
+ private final TranslationService translationService;
+ private final AwsS3Service awsS3Service;
+ private static final OkHttpClient client = new OkHttpClient.Builder()
+ .connectTimeout(30, TimeUnit.SECONDS)
+ .writeTimeout(30, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .build();
+
+// public String generateAndResizeImage(Long moimId, ImageGenerationDTO imageGenerationDTO) throws IOException {
+// String prompt = imageGenerationDTO.getPrompt();
+// Boolean highQuality = imageGenerationDTO.getHighQuality();
+// Integer imageSize = highQuality ? 1024 : 512;
+//
+// String translatedText = translationService.translateText(prompt, "ko", "en");
+// log.info("translatedText = {}", translatedText);
+//
+// Map requestHashMap = new HashMap<>();
+// requestHashMap.put("prompt", translatedText);
+// requestHashMap.put("n", 1);
+// requestHashMap.put("size", String.format("%dx%d", imageSize, imageSize));
+// if (highQuality) {
+// requestHashMap.put("model", "dall-e-3");
+// requestHashMap.put("quality", "hd");
+// }
+//
+// String requestBodyJson = objectMapper.writeValueAsString(requestHashMap);
+//
+// RequestBody body = RequestBody.create(
+// requestBodyJson,
+// MediaType.get("application/json; charset=utf-8")
+// );
+//
+// Request request = new Request.Builder()
+// .url(OPENAI_API_URL)
+// .post(body)
+// .addHeader("Authorization", "Bearer " + apiKey)
+// .addHeader("Content-Type", "application/json")
+// .build();
+// Response response = client.newCall(request).execute();
+//
+// if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+//
+// String jsonData = response.body().string();
+// log.info("openai api response = {}", jsonData);
+// String imageUrl = extractImageUrlFromResponse(jsonData);
+//
+// byte[] imageBytes = downloadImage(imageUrl);
+//
+// return awsS3Service.uploadFileViaByteArray(moimId, imageBytes);
+// }
+
+ private String extractImageUrlFromResponse(String jsonData) throws IOException {
+ JsonNode rootNode = objectMapper.readTree(jsonData);
+ JsonNode dataNode = rootNode.path("data");
+ if (dataNode.isArray() && dataNode.size() > 0) {
+ JsonNode firstImageNode = dataNode.get(0);
+ JsonNode urlNode = firstImageNode.path("url");
+ if (urlNode.isTextual()) {
+ return urlNode.asText();
+ }
+ }
+ throw new IOException("Invalid JSON response or missing URL");
+ }
+
+ private byte[] downloadImage(String imageUrl) throws IOException {
+ OkHttpClient client = new OkHttpClient();
+ Request request = new Request.Builder().url(imageUrl).build();
+ Response response = client.newCall(request).execute();
+
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ return IOUtils.toByteArray(response.body().byteStream());
+ }
+
+ private byte[] resizeImage(byte[] originalImageBytes) throws IOException {
+ ByteArrayInputStream bais = new ByteArrayInputStream(originalImageBytes);
+ BufferedImage originalImage = ImageIO.read(bais);
+
+ BufferedImage resizedImage = new BufferedImage(350, 600, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = resizedImage.createGraphics();
+ g.drawImage(originalImage, 0, 0, 350, 600, null);
+ g.dispose();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ImageIO.write(resizedImage, "png", baos);
+ return baos.toByteArray();
+ }
+
+ public String generateByKarlo(Long moimId, ImageGenerationDTO imageGenerationDTO) throws IOException {
+ String prompt = imageGenerationDTO.getPrompt();
+ String translatedText = translationService.translateText(prompt, "ko", "en");
+ log.info("translatedText = {}", translatedText);
+
+ String url = "https://api.kakaobrain.com/v2/inference/karlo/t2i";
+ RestTemplate restTemplate = new RestTemplate();
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ headers.set("Authorization", "KakaoAK " + karloApiKey);
+
+ Map body = Map.of(
+ "version", "v2.1",
+ "prompt", translatedText,
+ "negative_prompt", "",
+ "height", 1024,
+ "width", 1024,
+ "image_quality", 100
+ );
+
+ HttpEntity