diff --git a/.github/workflows/release_cd_workflow.yml b/.github/workflows/release_cd_workflow.yml index 4d6d2e9..47a55a6 100644 --- a/.github/workflows/release_cd_workflow.yml +++ b/.github/workflows/release_cd_workflow.yml @@ -9,18 +9,18 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 # 저장소 코드를 가져옴 + - uses: actions/checkout@v4 - - name: Set up JDK 17 # 자바 설치 + - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'adopt' - name: Grant execute permission for gradlew - run: chmod +x gradlew # gradlew 실행 권한 부여 + run: chmod +x gradlew - - name: Gradle Caching # Gradle 빌드 캐싱을 통해 속도 향상 + - name: Gradle Caching uses: actions/cache@v3 with: path: | @@ -31,26 +31,24 @@ jobs: ${{ runner.os }}-gradle- - name: Build jar - run: ./gradlew --info clean bootJar -x test # 테스트는 생략하고 bootJar로 .jar 파일 생성 + run: ./gradlew --info clean bootJar -x test - - name: docker login # Docker Hub 로그인 + - name: docker login uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: docker build and push #Docker 이미지 빌드 & 푸시 + - name: docker build and push uses: docker/build-push-action@v5.1.0 with: context: . push: true tags: ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest -# cache-from: type=registry,ref=${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest -# cache-to: type=inline # 빌드 시 캐시 활용이 필요하면 추가(깃허브 액션) - deploy: # SSH 접속 방식 (Self-hosted Runner 방식X) # 배포 자동화 + deploy: runs-on: ubuntu-latest - needs: build-and-push-image # build가 끝난 후 실행됨 + needs: build-and-push-image steps: - name: SSH into EC2 and deploy @@ -60,32 +58,85 @@ jobs: username: ${{ secrets.EC2_USER }} key: ${{ secrets.EC2_SSH_KEY }} script: | + # docker-compose 설치 여부 확인 + if ! command -v docker-compose &> /dev/null + then + sudo apt-get update + sudo apt-get install -y docker-compose-plugin + fi + + # Docker 이미지 정리 + docker system prune -af || true + + # 최신 이미지 pull docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest - docker stop app || true - docker rm app || true - - docker run -d \ - --name app \ - --restart unless-stopped \ - -p 8080:8080 \ - --env SPRING_PROFILES_ACTIVE=prod \ - --env RDS_HOST=${{ secrets.RDS_HOST }} \ - --env RDS_PORT=${{ secrets.RDS_PORT }} \ - --env RDS_DB=${{ secrets.RDS_DB }} \ - --env RDS_USERNAME=${{ secrets.RDS_USERNAME }} \ - --env RDS_PASSWORD=${{ secrets.RDS_PASSWORD }} \ - --env OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} \ - --env JWT_SECRET=${{ secrets.JWT_SECRET }} \ - ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest - - # 디스코드 배포 알림 + # docker-compose.yml 생성 + cat < /home/ubuntu/docker-compose.yml +version: '3' +services: + app: + image: ${{ secrets.DOCKER_HUB_USERNAME }}/${{ secrets.DOCKER_HUB_REPOSITORY }}:latest + container_name: app + restart: always + ports: + - '8080:8080' + env_file: + - .env + read_only: true + tmpfs: + - /tmp + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] + interval: 30s + timeout: 5s + retries: 3 +EOF + + # .env 파일 생성 + cat < /home/ubuntu/.env +SPRING_PROFILES_ACTIVE=prod +RDS_HOST=${{ secrets.RDS_HOST }} +RDS_PORT=${{ secrets.RDS_PORT }} +RDS_DB=${{ secrets.RDS_DB }} +RDS_USERNAME=${{ secrets.RDS_USERNAME }} +RDS_PASSWORD=${{ secrets.RDS_PASSWORD }} +JWT_SECRET=${{ secrets.JWT_SECRET }} +OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} +EOF + + # .env 파일 권한 설정 + chmod 600 /home/ubuntu/.env + + # docker-compose pull + docker compose -f /home/ubuntu/docker-compose.yml pull + + # docker-compose 재배포 + docker compose -f /home/ubuntu/docker-compose.yml down || true + docker compose -f /home/ubuntu/docker-compose.yml up -d + - name: Send Discord Notification + if: always() run: | STATUS="${{ job.status }}" - MESSAGE="🚀 **Ouch 배포 완료**\n배포 상태: $STATUS\n🔗 프로젝트: ${{ github.repository }}\n👤 커밋: ${{ github.actor }}" + if [ "$STATUS" == "success" ]; then + EMOJI="✅" + else + EMOJI="❌" + fi + + # 서버 Healthcheck + sleep 5 + HEALTH=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/actuator/health || true) + if [ "$HEALTH" == "200" ]; then + HEALTH_STATUS="✅ 서버 정상 작동" + else + HEALTH_STATUS="❌ 서버 비정상 작동" + fi + + MESSAGE="$EMOJI **Ouch 배포 결과**\\n상태: $STATUS\\n$HEALTH_STATUS\\n🔗 프로젝트: ${{ github.repository }}\\n👤 커밋: ${{ github.actor }}" curl -H "Content-Type: application/json" \ -X POST \ -d "{\"content\": \"$MESSAGE\"}" \ - ${{ secrets.DISCORD_WEBHOOK_URL }} \ No newline at end of file + ${{ secrets.DISCORD_WEBHOOK_URL }} || true diff --git a/build.gradle b/build.gradle index 02bd293..f7826c4 100644 --- a/build.gradle +++ b/build.gradle @@ -49,6 +49,9 @@ dependencies { // 스프링 시큐리티 implementation "org.springframework.boot:spring-boot-starter-security" + // 도커 헬스체크용 + implementation 'org.springframework.boot:spring-boot-starter-actuator' + //jwt 토큰 implementation 'io.jsonwebtoken:jjwt-api:0.12.6' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6' diff --git a/src/main/java/com/onebridge/ouch/apiPayload/code/error/DiagnosisErrorCode.java b/src/main/java/com/onebridge/ouch/apiPayload/code/error/DiagnosisErrorCode.java new file mode 100644 index 0000000..11f2960 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/apiPayload/code/error/DiagnosisErrorCode.java @@ -0,0 +1,20 @@ +package com.onebridge.ouch.apiPayload.code.error; + +import org.springframework.http.HttpStatus; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum DiagnosisErrorCode implements ErrorCode { + + SYMPTOM_NOT_FOUND(HttpStatus.NOT_FOUND, "DIAGNOSIS401", "입력한 증상이 존재하지 않습니다."), + DIAGNOSIS_NOT_FOUND(HttpStatus.NOT_FOUND, "DIAGNOSIS402", "자가진단표가 존재하지 않습니다."), + SYMPTOM_ALREADY_ADDED(HttpStatus.BAD_REQUEST, "DIAGNOSIS403", "해당 증상이 이미 존재합니다."), + ; + + private final HttpStatus httpStatus; + private final String code; + private final String message; +} diff --git a/src/main/java/com/onebridge/ouch/apiPayload/code/error/HealthStatusErrorCode.java b/src/main/java/com/onebridge/ouch/apiPayload/code/error/HealthStatusErrorCode.java new file mode 100644 index 0000000..be3ac28 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/apiPayload/code/error/HealthStatusErrorCode.java @@ -0,0 +1,17 @@ +package com.onebridge.ouch.apiPayload.code.error; + +import org.springframework.http.HttpStatus; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum HealthStatusErrorCode implements ErrorCode { + + HEALTH_STATUS_NOT_FOUND(HttpStatus.NOT_FOUND, "HEALTH-STATUS401", "건강상태가 존재하지 않습니다."); + + private final HttpStatus httpStatus; + private final String code; + private final String message; +} diff --git a/src/main/java/com/onebridge/ouch/apiPayload/code/error/MedicalRecordErrorCode.java b/src/main/java/com/onebridge/ouch/apiPayload/code/error/MedicalRecordErrorCode.java new file mode 100644 index 0000000..cbb7c86 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/apiPayload/code/error/MedicalRecordErrorCode.java @@ -0,0 +1,21 @@ +package com.onebridge.ouch.apiPayload.code.error; + +import org.springframework.http.HttpStatus; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum MedicalRecordErrorCode implements ErrorCode { + + MEDICAL_RECORD_NOT_FOUND(HttpStatus.NOT_FOUND, "MEDICAL-RECORD401", "의료기록이 존재하지 않습니다."), + HOSPITAL_NOT_FOUND(HttpStatus.NOT_FOUND, "MEDICAL-RECORD402", "입력한 병원이 존재하지 않습니다."), + DEPARTMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "MEDICAL-RECORD403", "입력한 진료 과가 존재하지 않습니다."), + MEDICAL_RECORD_USER_NOT_MATCH(HttpStatus.FORBIDDEN, "MEDICAL-RECORD404", "해당 사용자의 의료기록이 아닙니다."), + ; + + private final HttpStatus httpStatus; + private final String code; + private final String message; +} diff --git a/src/main/java/com/onebridge/ouch/controller/healthStatus/HealthStatusController.java b/src/main/java/com/onebridge/ouch/controller/healthStatus/HealthStatusController.java new file mode 100644 index 0000000..0f37813 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/controller/healthStatus/HealthStatusController.java @@ -0,0 +1,90 @@ +package com.onebridge.ouch.controller.healthStatus; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.onebridge.ouch.apiPayload.ApiResponse; +import com.onebridge.ouch.dto.healthStatus.request.HealthStatusCreateRequest; +import com.onebridge.ouch.dto.healthStatus.request.HealthStatusUpdateRequest; +import com.onebridge.ouch.dto.healthStatus.response.DateAndDisease; +import com.onebridge.ouch.dto.healthStatus.response.GetHealthStatusResponse; +import com.onebridge.ouch.security.authorization.UserId; +import com.onebridge.ouch.service.healthStatus.HealthStatusService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@Tag(name = "건강 상태 API", description = "건강 상태 API") +@RestController +@RequestMapping("/health-status") +@RequiredArgsConstructor +public class HealthStatusController { + + private final HealthStatusService healthStatusService; + + //건강상태 생성 + @Operation(summary = "건강상태 생성 API", description = "건강상태 생성 API 입니다.") + @PostMapping + public ResponseEntity> createHealthStatus( + @RequestBody @Valid HealthStatusCreateRequest request, + @UserId Long userId + ) { + healthStatusService.createHealthStatus(request, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + //특정 건강상태 조회 + @Operation(summary = "건강상태 조회 API", description = "건강상태 조회 API 입니다.") + @GetMapping("/{healthStatusId}") + public ResponseEntity> getHealthStatus(@PathVariable Long healthStatusId, + @UserId Long userId + ) { + GetHealthStatusResponse response = healthStatusService.getHealthStatus(healthStatusId, userId); + return ResponseEntity.ok(ApiResponse.success(response)); + } + + /* + //특정 사용자의 모든 건강상태 조회 + @Operation(summary = "특정 사용자의 모든 건강상태 조회 API", description = "특정 사용자의 모든 건강상태 조회 API 입니다.") + @GetMapping + public ResponseEntity>> getUsersAllHealthStatus( + @UserId Long userId + ) { + List list = healthStatusService.getUsersAllHealthStatus(userId); + return ResponseEntity.ok(ApiResponse.success(list)); + } + */ // 건강 상태 한 개만 보유 + + //특정 건강상태 수정 + @Operation(summary = "건강상태 수정 API", description = "건강상태 수정 API 입니다.") + @PutMapping("/{healthStatusId}") + public ResponseEntity> updateHealthStatus( + @RequestBody @Valid HealthStatusUpdateRequest request, + @PathVariable Long healthStatusId, + @UserId Long userId + ) { + healthStatusService.updateHealthStatus(request, healthStatusId, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + //특정 건강상태 삭제 + @Operation(summary = "건강상태 삭제 API", description = "건강상태 삭제 API 입니다.") + @DeleteMapping("/{healthStatusId}") + public ResponseEntity> deleteHealthStatus(@PathVariable Long healthStatusId, + @UserId Long userId + ) { + healthStatusService.deleteHealthStatus(healthStatusId, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } +} diff --git a/src/main/java/com/onebridge/ouch/controller/medicalRecord/MedicalRecordController.java b/src/main/java/com/onebridge/ouch/controller/medicalRecord/MedicalRecordController.java new file mode 100644 index 0000000..776aeee --- /dev/null +++ b/src/main/java/com/onebridge/ouch/controller/medicalRecord/MedicalRecordController.java @@ -0,0 +1,88 @@ +package com.onebridge.ouch.controller.medicalRecord; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.onebridge.ouch.apiPayload.ApiResponse; +import com.onebridge.ouch.dto.medicalRecord.request.MedicalRecordCreateRequest; +import com.onebridge.ouch.dto.medicalRecord.request.MedicalRecordUpdateRequest; +import com.onebridge.ouch.dto.medicalRecord.response.DateAndHospital; +import com.onebridge.ouch.dto.medicalRecord.response.GetMedicalRecordResponse; +import com.onebridge.ouch.security.authorization.UserId; +import com.onebridge.ouch.service.medicalRecord.MedicalRecordService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@Tag(name = "의료기록 API", description = "의료기록 API 입니다.") +@RestController +@RequestMapping("/medical-record") +@RequiredArgsConstructor +public class MedicalRecordController { + + private final MedicalRecordService medicalRecordService; + + // 의료기록 생성 + @Operation(summary = "의료기록 생성 API", description = "의료기록을 생성 API 입니다.") + @PostMapping + public ResponseEntity> createMedicalRecord( + @RequestBody @Valid MedicalRecordCreateRequest request, + @UserId Long userId + ) { + medicalRecordService.createMedicalRecord(request, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + // 특정 의료기록 조회 + @Operation(summary = "의료기록 조회 API", description = "의료기록을 조회 API 입니다.") + @GetMapping("/{medicalRecordId}") + public ResponseEntity> getMedicalRecord(@PathVariable Long medicalRecordId, + @UserId Long userId + ) { + GetMedicalRecordResponse response = medicalRecordService.getMedicalRecord(medicalRecordId, userId); + return ResponseEntity.ok(ApiResponse.success(response)); + } + + // 특정 사용자의 모든 의료기록 조회 (의료기록 메인 페이지용) + @Operation(summary = "특정 사용자의 모든 의료기록 조회 API", description = "특정 사용자의 모든 의료기록 조회 API 입니다.") + @GetMapping + public ResponseEntity>> getUsersAllMedicalRecord( + @UserId Long userId + ) { + List list = medicalRecordService.getUsersAllMedicalRecord(userId); + return ResponseEntity.ok(ApiResponse.success(list)); + } + + //특정 의료기록 삭제 + @Operation(summary = "의료기록 삭제 API", description = "의료기록을 삭제 API 입니다.") + @DeleteMapping("/{medicalRecordId}") + public ResponseEntity> deleteMedicalRecord(@PathVariable Long medicalRecordId, + @UserId Long userId + ) { + medicalRecordService.deleteMedicalRecord(medicalRecordId, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + //특정 의료기록 수정 + @Operation(summary = "의료기록 수정 API", description = "의료기록을 수정 API 입니다.") + @PutMapping("/{medicalRecordId}") + public ResponseEntity> updateMedicalRecord( + @RequestBody @Valid MedicalRecordUpdateRequest request, + @PathVariable Long medicalRecordId, + @UserId Long userId + ) { + medicalRecordService.updateMedicalRecord(request, medicalRecordId, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } +} diff --git a/src/main/java/com/onebridge/ouch/controller/selfDiagnosis/SelfDiagnosisController.java b/src/main/java/com/onebridge/ouch/controller/selfDiagnosis/SelfDiagnosisController.java new file mode 100644 index 0000000..115f44b --- /dev/null +++ b/src/main/java/com/onebridge/ouch/controller/selfDiagnosis/SelfDiagnosisController.java @@ -0,0 +1,112 @@ +package com.onebridge.ouch.controller.selfDiagnosis; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.onebridge.ouch.apiPayload.ApiResponse; +import com.onebridge.ouch.dto.selfDiagnosis.request.AddSymptomsToDiagnosisRequest; +import com.onebridge.ouch.dto.selfDiagnosis.request.DiagnosisCreateRequest; +import com.onebridge.ouch.dto.selfDiagnosis.request.DiagnosisUpdateRequest; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetDiagnosisByUserIdResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetDiagnosisResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetSymptomsOfDiagnosisResponse; +import com.onebridge.ouch.security.authorization.UserId; +import com.onebridge.ouch.service.selfDiagnosis.SelfDiagnosisService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@Tag(name = "자가진단표 API", description = "자가진단표 API 입니다.") +@RestController +@RequestMapping("/self-diagnosis") +@RequiredArgsConstructor +public class SelfDiagnosisController { + + private final SelfDiagnosisService selfDiagnosisService; + + //자가진단표 생성 + @Operation(summary = "자가진단표 생성 API", description = "자가진단표 생성 API 입니다.") + @PostMapping + public ResponseEntity> createDiagnosis( //request dto 에 userid 지우기 + @RequestBody @Valid DiagnosisCreateRequest request, + @UserId Long userId + ) { + selfDiagnosisService.createDiagnosis(request, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + //(자가진단표)id로 자가진단표 조회 + @Operation(summary = "자가진단표 조회 API", description = "자가진단표 조회 API 입니다.") + @GetMapping("/{diagnosisId}") + public ResponseEntity> getDiagnosisById( + @PathVariable Long diagnosisId, + @UserId Long userId + ) { + GetDiagnosisResponse response = selfDiagnosisService.getDiagnosis(diagnosisId, userId); + return ResponseEntity.ok(ApiResponse.success(response)); + } + + //사용자 모든 자가진단표 조회 + @Operation(summary = "특정 사용자의 모든 자가진단표 조회 API", description = "특정 사용자의 모든 자가진단표 조회 API 입니다.") + @GetMapping + public ResponseEntity>> getAllDiagnosisByUserId( + @UserId Long userId + ) { + List list = selfDiagnosisService.getAllDiagnosisByUserId(userId); + return ResponseEntity.ok(ApiResponse.success(list)); + } + + //자가진단표 삭제 + @Operation(summary = "자가진단표 삭제 API", description = "자가진단표 삭제 API 입니다.") + @DeleteMapping("/{diagnosisId}") + public ResponseEntity> deleteDiagnosis(@PathVariable Long diagnosisId, + @UserId Long userId + ) { + selfDiagnosisService.deleteDiagnosis(diagnosisId, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + //특정 자가진단표의 증상 목록 조회 + @Operation(summary = "특정 자가진단표의 증상 목록 조회 API", description = "특정 자가진단표의 증상 목록 조회 API 입니다.") + @GetMapping("/{diagnosisId}/symptoms") + public ResponseEntity> getSymptomsOfDiagnosis( + @PathVariable Long diagnosisId, + @UserId Long userId + ) { + GetSymptomsOfDiagnosisResponse response = selfDiagnosisService.getSymptomsOfDiagnosis(diagnosisId, userId); + return ResponseEntity.ok(ApiResponse.success(response)); + } + + //자가진단표 수정 + @Operation(summary = "자가진단표 수정 API", description = "자가진단표 수정 API 입니다.") + @PutMapping("/{diagnosisId}") + public ResponseEntity> updateDiagnosis(@PathVariable Long diagnosisId, + @RequestBody @Valid DiagnosisUpdateRequest request, + @UserId Long userId + ) { + selfDiagnosisService.updateDiagnosis(diagnosisId, userId, request); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } + + //자가진단표에 증상 추가 + @Operation(summary = "특정 자가진단표에 증상 추가 API", description = "특정 자가진단표에 증상 추가 API 입니다.") + @PostMapping("/{diagnosisId}/symptoms") + public ResponseEntity> addSymptomsToSelfDiagnosis(@PathVariable Long diagnosisId, + @RequestBody @Valid AddSymptomsToDiagnosisRequest request, + @UserId Long userId + ) { + selfDiagnosisService.addSymptomsToSelfDiagnosis(diagnosisId, request, userId); + return ResponseEntity.ok(ApiResponse.successWithNoData()); + } +} diff --git a/src/main/java/com/onebridge/ouch/controller/symptom/SymptomController.java b/src/main/java/com/onebridge/ouch/controller/symptom/SymptomController.java new file mode 100644 index 0000000..ce40010 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/controller/symptom/SymptomController.java @@ -0,0 +1,33 @@ +package com.onebridge.ouch.controller.symptom; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.onebridge.ouch.apiPayload.ApiResponse; +import com.onebridge.ouch.dto.symptom.response.GetSymptomResponse; +import com.onebridge.ouch.service.symptom.SymptomService; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; + +@Tag(name = "증상 API", description = "증상 API 입니다.") +@RestController +@RequestMapping("/symptoms") +@RequiredArgsConstructor +public class SymptomController { + + private final SymptomService symptomService; + + //증상 목록 조회 + @Operation(summary = "증상 목록 조회 API", description = "증상 목록 조회 API 입니다.") + @GetMapping + public ResponseEntity>> getSymptomsList() { + List list = symptomService.getSymptomsList(); + return ResponseEntity.ok(ApiResponse.success(list)); + } +} diff --git a/src/main/java/com/onebridge/ouch/controller/user/UserController.java b/src/main/java/com/onebridge/ouch/controller/user/UserController.java index 4415df9..52f89e7 100644 --- a/src/main/java/com/onebridge/ouch/controller/user/UserController.java +++ b/src/main/java/com/onebridge/ouch/controller/user/UserController.java @@ -1,83 +1,39 @@ package com.onebridge.ouch.controller.user; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.onebridge.ouch.dto.MessageResponse; -import com.onebridge.ouch.dto.MessageResponseDetailed; -import com.onebridge.ouch.dto.user.request.MypageUserInfoUpdateRequest; -import com.onebridge.ouch.dto.user.response.MypageUserInfoResponse; +import com.onebridge.ouch.apiPayload.ApiResponse; import com.onebridge.ouch.dto.user.response.UserInfoResponse; +import com.onebridge.ouch.security.authorization.UserId; import com.onebridge.ouch.service.user.UserService; -import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; @RestController -@RequestMapping("/api") +@RequestMapping("/users") +@RequiredArgsConstructor public class UserController { private final UserService userService; - public UserController(UserService userService) { - this.userService = userService; - } - - //유저 조회(테스트용) - @GetMapping("/users/{userId}") - public UserInfoResponse getUserInfo(@PathVariable Long userId) { - return userService.getUserInfo(userId); + //유저 조회 + @GetMapping + public ResponseEntity> getUserInfo( + @UserId Long userId) { + UserInfoResponse response = userService.getUserInfo(userId); + return ResponseEntity.ok(ApiResponse.success(response)); } //유저 탈퇴(비활성화) - @PatchMapping("/users/{userId}") - public ResponseEntity deactivateUser(@PathVariable Long userId) { + @DeleteMapping + public ResponseEntity> deactivateUser( + @UserId Long userId) { userService.deactivateUser(userId); - MessageResponse body = new MessageResponse("Your account has been deactivated."); - HttpHeaders header = new HttpHeaders(); - header.add(HttpHeaders.CONTENT_TYPE, "application/json"); - - return new ResponseEntity<>(body, header, HttpStatus.OK); - } - - //유저 삭제(테스트용) - @DeleteMapping("/users/{userId}") - public ResponseEntity deleteUser(@PathVariable Long userId) { - userService.deleteUser(userId); - MessageResponse body = new MessageResponse("Your account has been deleted."); - HttpHeaders header = new HttpHeaders(); - header.add(HttpHeaders.CONTENT_TYPE, "application/json"); - - return new ResponseEntity<>(body, header, HttpStatus.OK); - } - - //마이페이지(내 정보) 조회 - @GetMapping("/mypage/users/{userId}") - public MypageUserInfoResponse myPageGetUserInfo(@PathVariable Long userId) { - return userService.myPageGetUserInfo(userId); - } - - //내 정보 수정 (사용자로부터 모든 필드의 값을 받아 put 요청 처리) - @PutMapping("/mypage/users/{userId}") - public ResponseEntity> myPageUpdateUserInfo(@PathVariable Long userId, - @RequestBody @Valid MypageUserInfoUpdateRequest request) { - // System.out.println("userId = " + userId); - userService.myPageUpdateUserInfo(userId, request); - MessageResponseDetailed body = new MessageResponseDetailed<>( - true, - "COMMON200", - "요청이 성공적으로 처리되었습니다.", - "유저 정보가 성공적으로 수정되었습니다." - ); - return ResponseEntity.ok(body); + return ResponseEntity.ok(ApiResponse.successWithNoData()); } } diff --git a/src/main/java/com/onebridge/ouch/converter/HealthStatusConverter.java b/src/main/java/com/onebridge/ouch/converter/HealthStatusConverter.java new file mode 100644 index 0000000..2fb64a9 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/converter/HealthStatusConverter.java @@ -0,0 +1,59 @@ +package com.onebridge.ouch.converter; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.onebridge.ouch.domain.HealthStatus; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.dto.healthStatus.request.HealthStatusCreateRequest; +import com.onebridge.ouch.dto.healthStatus.request.HealthStatusUpdateRequest; +import com.onebridge.ouch.dto.healthStatus.response.DateAndDisease; +import com.onebridge.ouch.dto.healthStatus.response.GetHealthStatusResponse; + +@Component +public class HealthStatusConverter { + + /* + public List healthStatusToGetUsersAllHealthStatusResponse( + List healthStatus) { + + List list = new ArrayList<>(); + + for (HealthStatus history : healthStatus) { + list.add(new DateAndDisease(history.getId(), history.getUpdatedAt().toString(), history.getDisease())); + } + + return list; + } + */ // 유저 한 명당 건강상태기록 한 개만 보유 + + public GetHealthStatusResponse healthStatusToGetHealthStatusResponse(HealthStatus healthStatus) { + return new GetHealthStatusResponse(healthStatus.getId(), healthStatus.getDisease(), + healthStatus.getAllergy(), healthStatus.getBloodPressure(), healthStatus.getBloodSugar(), + healthStatus.getMedicineHistory()); + } + + public HealthStatus healthStatusCreateRequestToHealthStatus(HealthStatusCreateRequest request, User user) { + return HealthStatus.builder() + .user(user) + .disease(request.getDisease()) + .allergy(request.getAllergy()) + .bloodPressure(request.getBloodPressure()) + .bloodSugar(request.getBloodSugar()) + .medicineHistory(request.getMedicineHistory()) + .build(); + } + + public HealthStatus healthStatusUpdateRequestToHealthStatus(HealthStatus healthStatus, + HealthStatusUpdateRequest request) { + return healthStatus.toBuilder() + .disease(request.getDisease()) + .allergy(request.getAllergy()) + .bloodPressure(request.getBloodPressure()) + .bloodSugar(request.getBloodSugar()) + .medicineHistory(request.getMedicineHistory()) + .build(); + } +} diff --git a/src/main/java/com/onebridge/ouch/converter/MedicalRecordConverter.java b/src/main/java/com/onebridge/ouch/converter/MedicalRecordConverter.java new file mode 100644 index 0000000..f87b571 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/converter/MedicalRecordConverter.java @@ -0,0 +1,60 @@ +package com.onebridge.ouch.converter; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.onebridge.ouch.domain.Summary; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.domain.mapping.MedicalRecord; +import com.onebridge.ouch.dto.medicalRecord.request.MedicalRecordCreateRequest; +import com.onebridge.ouch.dto.medicalRecord.request.MedicalRecordUpdateRequest; +import com.onebridge.ouch.dto.medicalRecord.response.DateAndHospital; +import com.onebridge.ouch.dto.medicalRecord.response.GetMedicalRecordResponse; + +import lombok.AllArgsConstructor; + +@Component +@AllArgsConstructor +public class MedicalRecordConverter { + + public GetMedicalRecordResponse medicalRecordToGetMedicalRecordResponse(MedicalRecord medicalRecord) { + return new GetMedicalRecordResponse(medicalRecord.getId(), medicalRecord.getVisitDate().toString(), + medicalRecord.getHospital(), + medicalRecord.getDepartment(), medicalRecord.getSymptoms(), + medicalRecord.getSummary().getContents_summary()); + } + + public List medicalRecordToGetUsersAllMedicalRecordResponse(List medicalRecords) { + List list = new ArrayList<>(); + for (MedicalRecord record : medicalRecords) { + list.add(new DateAndHospital(record.getId(), record.getUpdatedAt().toString(), + record.getHospital())); + } + return list; + } + + public MedicalRecord medicalRecordCreateRequestToMedicalRecord(MedicalRecordCreateRequest request, User user, + Summary summary) { + return MedicalRecord.builder() + .user(user) + .visitDate(request.getVisitDate()) + .hospital(request.getVisitingHospital()) + .department(request.getMedicalSubject()) + .symptoms(request.getSymptoms()) + .summary(summary) + .build(); + } + + public MedicalRecord medicalRecordUpdateRequestToMedicalRecord(MedicalRecord medicalRecord, + MedicalRecordUpdateRequest request, Summary summary) { + return medicalRecord.toBuilder() + .visitDate(request.getVisitDate()) + .hospital(request.getVisitingHospital()) + .department(request.getMedicalSubject()) + .symptoms(request.getSymptoms()) + .summary(summary) + .build(); + } +} diff --git a/src/main/java/com/onebridge/ouch/converter/SelfDiagnosisConverter.java b/src/main/java/com/onebridge/ouch/converter/SelfDiagnosisConverter.java new file mode 100644 index 0000000..a866d9d --- /dev/null +++ b/src/main/java/com/onebridge/ouch/converter/SelfDiagnosisConverter.java @@ -0,0 +1,84 @@ +package com.onebridge.ouch.converter; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.onebridge.ouch.domain.SelfDiagnosis; +import com.onebridge.ouch.domain.Symptom; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.domain.mapping.DiagnosisSymptom; +import com.onebridge.ouch.dto.selfDiagnosis.request.DiagnosisCreateRequest; +import com.onebridge.ouch.dto.selfDiagnosis.request.DiagnosisUpdateRequest; +import com.onebridge.ouch.dto.selfDiagnosis.response.DiagnosisUpdateResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetDiagnosisByUserIdResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetDiagnosisResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetSymptomsOfDiagnosisResponse; + +@Component +public class SelfDiagnosisConverter { + + public DiagnosisUpdateResponse diagnosisToDiagnosisUpdateResponse(SelfDiagnosis updatedDiagnosis) { + List symptoms = symptomListForResponseDto(updatedDiagnosis); + return new DiagnosisUpdateResponse(updatedDiagnosis.getId(), updatedDiagnosis.getVisitType(), symptoms, + updatedDiagnosis.getDuration(), updatedDiagnosis.getPainSeverity(), updatedDiagnosis.getAdditionalNote(), + updatedDiagnosis.getCreatedAt().toString()); + } + + public GetDiagnosisResponse diagnosisToGetDiagnosisResponse(SelfDiagnosis diagnosis) { + List symptoms = symptomListForResponseDto(diagnosis); + return new GetDiagnosisResponse(diagnosis.getUser().getId(), diagnosis.getVisitType(), symptoms, + diagnosis.getDuration(), + diagnosis.getPainSeverity(), diagnosis.getAdditionalNote(), diagnosis.getCreatedAt().toString()); + } + + public GetDiagnosisByUserIdResponse diagnosisToGetDiagnosisByUserIdResponse(SelfDiagnosis diagnosis) { + List symptoms = symptomListForResponseDto(diagnosis); + return new GetDiagnosisByUserIdResponse(diagnosis.getId(), diagnosis.getVisitType(), symptoms, + diagnosis.getDuration(), diagnosis.getPainSeverity(), diagnosis.getAdditionalNote(), + diagnosis.getCreatedAt().toString()); + } + + public GetSymptomsOfDiagnosisResponse diagnosisToGetSymptomsOfDiagnosisResponse(SelfDiagnosis diagnosis) { + List symptoms = symptomListForResponseDto(diagnosis); + return new GetSymptomsOfDiagnosisResponse(symptoms); + } + + public SelfDiagnosis diagnosisCreateRequestToSelfDiagnosis(DiagnosisCreateRequest request, User user) { + return SelfDiagnosis.builder() + .user(user) + .visitType(request.getVisitType()) + .diagnosisSymptomList(new ArrayList<>()) + .duration(request.getDuration()) + .painSeverity(request.getPainSeverity()) + .additionalNote(request.getAdditionalNote()) + .build(); + } + + public DiagnosisSymptom buildDiagnosisSymptom(SelfDiagnosis selfDiagnosis, Symptom foundSymptom) { + return DiagnosisSymptom.builder() + .selfDiagnosis(selfDiagnosis) + .symptom(foundSymptom) + .build(); + } + + public SelfDiagnosis diagnosisUpdateRequestToSelfDiagnosis(SelfDiagnosis diagnosis, User user, + DiagnosisUpdateRequest request) { + return diagnosis.toBuilder() + .visitType(request.getVisitType()) + .diagnosisSymptomList(new ArrayList<>()) + .duration(request.getDuration()) + .painSeverity(request.getPainSeverity()) + .additionalNote(request.getAdditionalNote()) + .build(); + } + + public List symptomListForResponseDto(SelfDiagnosis selfDiagnosis) { + List symptoms = new ArrayList<>(); + for (DiagnosisSymptom symptom : selfDiagnosis.getDiagnosisSymptomList()) { + symptoms.add(symptom.getSymptom().getName()); + } + return symptoms; + } +} diff --git a/src/main/java/com/onebridge/ouch/converter/SymptomConverter.java b/src/main/java/com/onebridge/ouch/converter/SymptomConverter.java new file mode 100644 index 0000000..3727f55 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/converter/SymptomConverter.java @@ -0,0 +1,20 @@ +package com.onebridge.ouch.converter; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.onebridge.ouch.domain.Symptom; +import com.onebridge.ouch.dto.symptom.response.GetSymptomResponse; + +@Component +public class SymptomConverter { + + public GetSymptomResponse symptomToGetSymptomsResponse(Symptom symptom) { + return new GetSymptomResponse(symptom.getId(), symptom.getName()); + } + + public List symptomsToGetSymptomsResponse(List symptoms) { + return symptoms.stream().map(this::symptomToGetSymptomsResponse).toList(); + } +} diff --git a/src/main/java/com/onebridge/ouch/converter/UserConverter.java b/src/main/java/com/onebridge/ouch/converter/UserConverter.java index 1235fdb..8a316db 100644 --- a/src/main/java/com/onebridge/ouch/converter/UserConverter.java +++ b/src/main/java/com/onebridge/ouch/converter/UserConverter.java @@ -3,7 +3,6 @@ import org.springframework.stereotype.Component; import com.onebridge.ouch.domain.User; -import com.onebridge.ouch.dto.user.response.MypageUserInfoResponse; import com.onebridge.ouch.dto.user.response.UserInfoResponse; @Component @@ -14,8 +13,4 @@ public UserInfoResponse convertToUserInfoResponse(User user) { user.getPhoneNumber(), user.getGender(), user.getBirthday(), user.getEmail(), user.getLanguage().getId(), user.getNation().getId()); } - - public MypageUserInfoResponse convertToMypageUserInfoResponse(User user) { - return new MypageUserInfoResponse(user.getNickname(), user.getEmail(), user.getLanguage().getId()); - } } diff --git a/src/main/java/com/onebridge/ouch/domain/HealthStatus.java b/src/main/java/com/onebridge/ouch/domain/HealthStatus.java new file mode 100644 index 0000000..83d8dea --- /dev/null +++ b/src/main/java/com/onebridge/ouch/domain/HealthStatus.java @@ -0,0 +1,48 @@ +package com.onebridge.ouch.domain; + +import com.onebridge.ouch.domain.common.BaseEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Builder(toBuilder = true) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class HealthStatus extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(nullable = true, columnDefinition = "TEXT") + private String disease; + + @Column(nullable = true, columnDefinition = "TEXT") + private String allergy; + + @Column(nullable = true, columnDefinition = "TEXT") + private Long bloodPressure; + + @Column(nullable = true, columnDefinition = "TEXT") + private Long bloodSugar; + + @Column(nullable = true, columnDefinition = "TEXT") + private String medicineHistory; +} diff --git a/src/main/java/com/onebridge/ouch/domain/Hospital.java b/src/main/java/com/onebridge/ouch/domain/Hospital.java index 7926dce..2a5e79d 100644 --- a/src/main/java/com/onebridge/ouch/domain/Hospital.java +++ b/src/main/java/com/onebridge/ouch/domain/Hospital.java @@ -26,6 +26,6 @@ public class Hospital extends BaseEntity { @Column(nullable = false, length = 100) private String address; - @OneToMany(mappedBy = "hospital", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "hospital", cascade = CascadeType.ALL, orphanRemoval = true) private List hospitalDepartmentList = new ArrayList<>(); } diff --git a/src/main/java/com/onebridge/ouch/domain/Language.java b/src/main/java/com/onebridge/ouch/domain/Language.java index 4a98dfb..f7e8960 100644 --- a/src/main/java/com/onebridge/ouch/domain/Language.java +++ b/src/main/java/com/onebridge/ouch/domain/Language.java @@ -15,14 +15,12 @@ public class Language extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - //언어 이름 - ex) 한국어, 영어 - @Column(nullable = false, length = 30) - private String name; + //국제 언어 코드 + @Column(nullable = false, length = 4) private String code; - public void updateLanguageFields(String name, String code) { - this.name = name; - this.code = code; - } + //언어 이름 - ex) 한국어, 영어 + @Column(nullable = false, length = 30) + private String name; } diff --git a/src/main/java/com/onebridge/ouch/domain/MedicalHistory.java b/src/main/java/com/onebridge/ouch/domain/MedicalHistory.java deleted file mode 100644 index 5fdf0d7..0000000 --- a/src/main/java/com/onebridge/ouch/domain/MedicalHistory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.onebridge.ouch.domain; - -import com.onebridge.ouch.domain.common.BaseEntity; - -import jakarta.persistence.*; -import lombok.*; - -@Entity -@Getter -@Builder -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -public class MedicalHistory extends BaseEntity { - - @Id - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - @MapsId // User의 id를 MedicalHistory의 기본 키로 매핑 - @JoinColumn(name = "user_id") //외래 키 이름을 user_id로 설정 - private User user; - - @Column(nullable = true, columnDefinition = "TEXT") - private String contents; -} diff --git a/src/main/java/com/onebridge/ouch/domain/Nation.java b/src/main/java/com/onebridge/ouch/domain/Nation.java index 6fe0d5a..a353900 100644 --- a/src/main/java/com/onebridge/ouch/domain/Nation.java +++ b/src/main/java/com/onebridge/ouch/domain/Nation.java @@ -2,6 +2,7 @@ import com.onebridge.ouch.domain.common.BaseEntity; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -23,6 +24,10 @@ public class Nation extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String name; + // 국가 코드 + @Column(nullable = false, length = 4) + private String code; + @Column(nullable = false, length = 30) + private String name; } diff --git a/src/main/java/com/onebridge/ouch/domain/SelfDiagnosis.java b/src/main/java/com/onebridge/ouch/domain/SelfDiagnosis.java index e6392f9..927183b 100644 --- a/src/main/java/com/onebridge/ouch/domain/SelfDiagnosis.java +++ b/src/main/java/com/onebridge/ouch/domain/SelfDiagnosis.java @@ -4,14 +4,17 @@ import java.util.List; import com.onebridge.ouch.domain.common.BaseEntity; -import com.onebridge.ouch.domain.mapping.SelfSymptom; +import com.onebridge.ouch.domain.enums.SymptomDuration; +import com.onebridge.ouch.domain.enums.VisitType; +import com.onebridge.ouch.domain.mapping.DiagnosisSymptom; import jakarta.persistence.*; import lombok.*; +import lombok.experimental.SuperBuilder; @Entity @Getter -@Builder +@Builder(toBuilder = true) @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class SelfDiagnosis extends BaseEntity { @@ -27,7 +30,16 @@ public class SelfDiagnosis extends BaseEntity { @Column(columnDefinition = "TEXT") private String contents; - @OneToMany(mappedBy = "selfDiagnosis", cascade = CascadeType.ALL) - private List selfSymptomList = new ArrayList<>(); + @OneToMany(mappedBy = "selfDiagnosis", cascade = CascadeType.ALL, orphanRemoval = true) + private List diagnosisSymptomList = new ArrayList<>(); + + private VisitType visitType; + + private SymptomDuration duration; + + private Integer painSeverity; + + @Column(columnDefinition = "TEXT") + private String additionalNote; } diff --git a/src/main/java/com/onebridge/ouch/domain/Summary.java b/src/main/java/com/onebridge/ouch/domain/Summary.java index 8124ca6..710d32b 100644 --- a/src/main/java/com/onebridge/ouch/domain/Summary.java +++ b/src/main/java/com/onebridge/ouch/domain/Summary.java @@ -1,25 +1,33 @@ package com.onebridge.ouch.domain; import com.onebridge.ouch.domain.common.BaseEntity; -import com.onebridge.ouch.domain.mapping.VisitHistory; -import jakarta.persistence.*; -import lombok.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; @Entity @Getter -@Builder +@Builder(toBuilder = true) @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class Summary extends BaseEntity { @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(fetch = FetchType.LAZY) - @MapsId - @JoinColumn(name = "visit_history_id") - private VisitHistory visitHistory; + //MedicalRecord → Summary 단방향으로 바꾸기로 했습니다. + // @OneToOne(fetch = FetchType.LAZY) + // @JoinColumn(name = "medical_record_id") + // private MedicalRecord medicalRecord; @Column(columnDefinition = "TEXT") private String contents; diff --git a/src/main/java/com/onebridge/ouch/domain/Translation.java b/src/main/java/com/onebridge/ouch/domain/Translation.java index 57cbf46..272e603 100644 --- a/src/main/java/com/onebridge/ouch/domain/Translation.java +++ b/src/main/java/com/onebridge/ouch/domain/Translation.java @@ -37,5 +37,7 @@ public class Translation { private Long entityId; + private String fieldName; + private String value; } diff --git a/src/main/java/com/onebridge/ouch/domain/User.java b/src/main/java/com/onebridge/ouch/domain/User.java index 2f7b352..9412ab9 100644 --- a/src/main/java/com/onebridge/ouch/domain/User.java +++ b/src/main/java/com/onebridge/ouch/domain/User.java @@ -7,7 +7,7 @@ import com.onebridge.ouch.domain.common.BaseEntity; import com.onebridge.ouch.domain.enums.Gender; import com.onebridge.ouch.domain.enums.UserStatus; -import com.onebridge.ouch.domain.mapping.VisitHistory; +import com.onebridge.ouch.domain.mapping.MedicalRecord; import com.onebridge.ouch.security.authority.OuchAuthority; import jakarta.persistence.CascadeType; @@ -22,6 +22,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -79,6 +80,11 @@ public class User extends BaseEntity { @JoinColumn(name = "nation_id", referencedColumnName = "id") // language_id를 외래 키로 설정 private Nation nation; + /* + @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private HealthStatus healthStatus; + */ // 단방향 설계로 수정 + // @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) // private List termsList = new ArrayList<>(); @@ -92,7 +98,7 @@ public class User extends BaseEntity { private List selfDiagnosisList = new ArrayList<>(); @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) - private List visitHistoryList = new ArrayList<>(); + private List medicalRecordList = new ArrayList<>(); public OuchAuthority getAuthority() { return OuchAuthority.INDIVIDUAL; diff --git a/src/main/java/com/onebridge/ouch/domain/common/BaseEntity.java b/src/main/java/com/onebridge/ouch/domain/common/BaseEntity.java index 1d4870d..a4906a9 100644 --- a/src/main/java/com/onebridge/ouch/domain/common/BaseEntity.java +++ b/src/main/java/com/onebridge/ouch/domain/common/BaseEntity.java @@ -7,12 +7,17 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import jakarta.persistence.*; -import lombok.*; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) public abstract class BaseEntity { @CreatedDate diff --git a/src/main/java/com/onebridge/ouch/domain/enums/SymptomDuration.java b/src/main/java/com/onebridge/ouch/domain/enums/SymptomDuration.java new file mode 100644 index 0000000..f77a93d --- /dev/null +++ b/src/main/java/com/onebridge/ouch/domain/enums/SymptomDuration.java @@ -0,0 +1,5 @@ +package com.onebridge.ouch.domain.enums; + +public enum SymptomDuration { + LESS_THAN_1_DAY, ONE_TO_3_DAYS, MORE_THAN_3_DAYS, MORE_THAN_1_WEEK, MORE_THAN_1_MONTH +} diff --git a/src/main/java/com/onebridge/ouch/domain/enums/VisitType.java b/src/main/java/com/onebridge/ouch/domain/enums/VisitType.java new file mode 100644 index 0000000..c418a48 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/domain/enums/VisitType.java @@ -0,0 +1,5 @@ +package com.onebridge.ouch.domain.enums; + +public enum VisitType { + HOSPITAL, PHARMACY +} diff --git a/src/main/java/com/onebridge/ouch/domain/mapping/SelfSymptom.java b/src/main/java/com/onebridge/ouch/domain/mapping/DiagnosisSymptom.java similarity index 54% rename from src/main/java/com/onebridge/ouch/domain/mapping/SelfSymptom.java rename to src/main/java/com/onebridge/ouch/domain/mapping/DiagnosisSymptom.java index 115d536..3729cb9 100644 --- a/src/main/java/com/onebridge/ouch/domain/mapping/SelfSymptom.java +++ b/src/main/java/com/onebridge/ouch/domain/mapping/DiagnosisSymptom.java @@ -3,7 +3,6 @@ import com.onebridge.ouch.domain.SelfDiagnosis; import com.onebridge.ouch.domain.Symptom; import com.onebridge.ouch.domain.common.BaseEntity; -import com.onebridge.ouch.domain.mapping.compositeKey.DiagnosisSymptomPK; import jakarta.persistence.*; import lombok.*; @@ -13,18 +12,17 @@ @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor -public class SelfSymptom extends BaseEntity { +public class DiagnosisSymptom extends BaseEntity { - @EmbeddedId - private DiagnosisSymptomPK diagnosisSymptomPk; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; @ManyToOne(fetch = FetchType.LAZY) - @MapsId("selfDiagnosisId") - //@JoinColumn(name = "selfDiagnosis_id", nullable = false) + @JoinColumn(name = "selfDiagnosis_id", nullable = false) private SelfDiagnosis selfDiagnosis; @ManyToOne(fetch = FetchType.LAZY) - @MapsId("symptomCategoryId") - //@JoinColumn(name = "symptomCategory_id", nullable = false) + @JoinColumn(name = "symptomCategory_id", nullable = false) private Symptom symptom; } diff --git a/src/main/java/com/onebridge/ouch/domain/mapping/HospitalDepartment.java b/src/main/java/com/onebridge/ouch/domain/mapping/HospitalDepartment.java index a3f87cc..a86eb63 100644 --- a/src/main/java/com/onebridge/ouch/domain/mapping/HospitalDepartment.java +++ b/src/main/java/com/onebridge/ouch/domain/mapping/HospitalDepartment.java @@ -3,7 +3,6 @@ import com.onebridge.ouch.domain.Hospital; import com.onebridge.ouch.domain.Department; import com.onebridge.ouch.domain.common.BaseEntity; -import com.onebridge.ouch.domain.mapping.compositeKey.HospitalCategoryPk; import jakarta.persistence.*; import lombok.*; @@ -15,16 +14,15 @@ @AllArgsConstructor public class HospitalDepartment extends BaseEntity { - @EmbeddedId - private HospitalCategoryPk hospitalCategoryPk; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; @ManyToOne(fetch = FetchType.LAZY) - @MapsId("medicalCategoryId") // HospitalCategoryId의 categoryId와 매핑 - //@JoinColumn(name = "medicalCategory_id", nullable = false) + @JoinColumn(name = "department_id") private Department department; @ManyToOne(fetch = FetchType.LAZY) - @MapsId("hospitalId") // HospitalCategoryId의 hospitalId와 매핑 - //@JoinColumn(name = "hospital_id", nullable = false) + @JoinColumn(name = "hospital_id") private Hospital hospital; } diff --git a/src/main/java/com/onebridge/ouch/domain/mapping/MedicalRecord.java b/src/main/java/com/onebridge/ouch/domain/mapping/MedicalRecord.java new file mode 100644 index 0000000..3a71328 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/domain/mapping/MedicalRecord.java @@ -0,0 +1,50 @@ +package com.onebridge.ouch.domain.mapping; + +import java.time.LocalDate; + +import com.onebridge.ouch.domain.Summary; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.domain.common.BaseEntity; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@Builder(toBuilder = true) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class MedicalRecord extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + private LocalDate visitDate; + + private String hospital; + + private String department; + + private String symptoms; + + @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @JoinColumn(name = "summary_id") + private Summary summary; +} diff --git a/src/main/java/com/onebridge/ouch/domain/mapping/VisitHistory.java b/src/main/java/com/onebridge/ouch/domain/mapping/VisitHistory.java deleted file mode 100644 index f80658c..0000000 --- a/src/main/java/com/onebridge/ouch/domain/mapping/VisitHistory.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.onebridge.ouch.domain.mapping; - -import com.onebridge.ouch.domain.Hospital; -import com.onebridge.ouch.domain.Summary; -import com.onebridge.ouch.domain.User; -import com.onebridge.ouch.domain.common.BaseEntity; - -import jakarta.persistence.*; -import lombok.*; - -@Entity -@Getter -@Builder -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -public class VisitHistory extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "hospital_id") - private Hospital hospital; - - @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) - @JoinColumn(name = "summary_id") - private Summary summary; -} diff --git a/src/main/java/com/onebridge/ouch/domain/mapping/compositeKey/DiagnosisSymptomPK.java b/src/main/java/com/onebridge/ouch/domain/mapping/compositeKey/DiagnosisSymptomPK.java deleted file mode 100644 index a609ab4..0000000 --- a/src/main/java/com/onebridge/ouch/domain/mapping/compositeKey/DiagnosisSymptomPK.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.onebridge.ouch.domain.mapping.compositeKey; - -import java.io.Serializable; -import java.util.Objects; - -import jakarta.persistence.Embeddable; - -@Embeddable -public class DiagnosisSymptomPK implements Serializable { - - private Long selfDiagnosisId; - private Long symptomCategoryId; - - public DiagnosisSymptomPK() { - } - - public DiagnosisSymptomPK(Long selfDiagnosisId, Long symptomCategoryId) { - this.selfDiagnosisId = selfDiagnosisId; - this.symptomCategoryId = symptomCategoryId; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof DiagnosisSymptomPK)) - return false; - DiagnosisSymptomPK that = (DiagnosisSymptomPK)o; - return Objects.equals(selfDiagnosisId, that.selfDiagnosisId) && - Objects.equals(symptomCategoryId, that.symptomCategoryId); - } - - @Override - public int hashCode() { - return Objects.hash(selfDiagnosisId, symptomCategoryId); - } -} diff --git a/src/main/java/com/onebridge/ouch/domain/mapping/compositeKey/HospitalCategoryPk.java b/src/main/java/com/onebridge/ouch/domain/mapping/compositeKey/HospitalCategoryPk.java deleted file mode 100644 index 7f23d82..0000000 --- a/src/main/java/com/onebridge/ouch/domain/mapping/compositeKey/HospitalCategoryPk.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.onebridge.ouch.domain.mapping.compositeKey; - -import java.io.Serializable; -import java.util.Objects; - -import jakarta.persistence.Embeddable; - -@Embeddable -public class HospitalCategoryPk implements Serializable { - - private Long medicalCategoryId; - private Long hospitalId; - - public HospitalCategoryPk() { - } - - public HospitalCategoryPk(Long medicalCategoryId, Long hospitalId) { - this.medicalCategoryId = medicalCategoryId; - this.hospitalId = hospitalId; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof HospitalCategoryPk)) - return false; - HospitalCategoryPk that = (HospitalCategoryPk)o; - return Objects.equals(medicalCategoryId, that.medicalCategoryId) && - Objects.equals(hospitalId, that.hospitalId); - } - - @Override - public int hashCode() { - return Objects.hash(medicalCategoryId, hospitalId); - } -} diff --git a/src/main/java/com/onebridge/ouch/domain/PrivateInformation.java b/src/main/java/com/onebridge/ouch/domain/tempDomain/PrivateInformation.txt similarity index 100% rename from src/main/java/com/onebridge/ouch/domain/PrivateInformation.java rename to src/main/java/com/onebridge/ouch/domain/tempDomain/PrivateInformation.txt diff --git a/src/main/java/com/onebridge/ouch/dto/healthStatus/request/HealthStatusCreateRequest.java b/src/main/java/com/onebridge/ouch/dto/healthStatus/request/HealthStatusCreateRequest.java new file mode 100644 index 0000000..98f8f2f --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/healthStatus/request/HealthStatusCreateRequest.java @@ -0,0 +1,24 @@ +package com.onebridge.ouch.dto.healthStatus.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class HealthStatusCreateRequest { + + @NotBlank(message = "Disease is required.") + private String disease; + + @NotBlank(message = "Allergy is required.") + private String allergy; + + @NotNull(message = "Blood pressure is required.") + private Long bloodPressure; + + @NotNull(message = "Blood sugar level is required.") + private Long bloodSugar; + + @NotBlank(message = "Medical History is required.") + private String medicineHistory; +} diff --git a/src/main/java/com/onebridge/ouch/dto/healthStatus/request/HealthStatusUpdateRequest.java b/src/main/java/com/onebridge/ouch/dto/healthStatus/request/HealthStatusUpdateRequest.java new file mode 100644 index 0000000..30a3a37 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/healthStatus/request/HealthStatusUpdateRequest.java @@ -0,0 +1,24 @@ +package com.onebridge.ouch.dto.healthStatus.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class HealthStatusUpdateRequest { + + @NotBlank(message = "Disease is required.") + private String disease; + + @NotBlank(message = "Allergy is required.") + private String allergy; + + @NotNull(message = "Blood pressure is required.") + private Long bloodPressure; + + @NotNull(message = "Blood sugar level is required.") + private Long bloodSugar; + + @NotBlank(message = "Medical History is required.") + private String medicineHistory; +} diff --git a/src/main/java/com/onebridge/ouch/dto/healthStatus/response/DateAndDisease.java b/src/main/java/com/onebridge/ouch/dto/healthStatus/response/DateAndDisease.java new file mode 100644 index 0000000..a066a1f --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/healthStatus/response/DateAndDisease.java @@ -0,0 +1,13 @@ +package com.onebridge.ouch.dto.healthStatus.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DateAndDisease { + + private Long id; + private String date; + private String disease; +} diff --git a/src/main/java/com/onebridge/ouch/dto/healthStatus/response/GetHealthStatusResponse.java b/src/main/java/com/onebridge/ouch/dto/healthStatus/response/GetHealthStatusResponse.java new file mode 100644 index 0000000..ae341e1 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/healthStatus/response/GetHealthStatusResponse.java @@ -0,0 +1,16 @@ +package com.onebridge.ouch.dto.healthStatus.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class GetHealthStatusResponse { + + private Long id; + private String disease; + private String allergy; + private Long bloodPressure; + private Long bloodSugar; + private String medicineHistory; +} diff --git a/src/main/java/com/onebridge/ouch/dto/medicalRecord/request/MedicalRecordCreateRequest.java b/src/main/java/com/onebridge/ouch/dto/medicalRecord/request/MedicalRecordCreateRequest.java new file mode 100644 index 0000000..b9a0d47 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/medicalRecord/request/MedicalRecordCreateRequest.java @@ -0,0 +1,26 @@ +package com.onebridge.ouch.dto.medicalRecord.request; + +import java.time.LocalDate; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class MedicalRecordCreateRequest { + + @NotNull(message = "Visit date is required.") + private LocalDate visitDate; + + @NotBlank(message = "Visiting hospital is required.") + private String visitingHospital; + + @NotBlank(message = "Medical subject is required.") + private String medicalSubject; + + @NotBlank(message = "Symptoms are required.") + private String symptoms; + + @NotBlank(message = "Treatment summary is required.") + private String treatmentSummary; +} diff --git a/src/main/java/com/onebridge/ouch/dto/medicalRecord/request/MedicalRecordUpdateRequest.java b/src/main/java/com/onebridge/ouch/dto/medicalRecord/request/MedicalRecordUpdateRequest.java new file mode 100644 index 0000000..07cce18 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/medicalRecord/request/MedicalRecordUpdateRequest.java @@ -0,0 +1,26 @@ +package com.onebridge.ouch.dto.medicalRecord.request; + +import java.time.LocalDate; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class MedicalRecordUpdateRequest { + + @NotNull(message = "Visit date is required.") + private LocalDate visitDate; + + @NotBlank(message = "Visiting hospital is required.") + private String visitingHospital; + + @NotBlank(message = "Medical subject is required.") + private String medicalSubject; + + @NotBlank(message = "Symptoms are required.") + private String symptoms; + + @NotBlank(message = "Treatment summary is required.") + private String treatmentSummary; +} diff --git a/src/main/java/com/onebridge/ouch/dto/medicalRecord/response/DateAndHospital.java b/src/main/java/com/onebridge/ouch/dto/medicalRecord/response/DateAndHospital.java new file mode 100644 index 0000000..db8afc4 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/medicalRecord/response/DateAndHospital.java @@ -0,0 +1,13 @@ +package com.onebridge.ouch.dto.medicalRecord.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DateAndHospital { + + private Long id; + private String date; + private String hospital; +} diff --git a/src/main/java/com/onebridge/ouch/dto/medicalRecord/response/GetMedicalRecordResponse.java b/src/main/java/com/onebridge/ouch/dto/medicalRecord/response/GetMedicalRecordResponse.java new file mode 100644 index 0000000..75e78e7 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/medicalRecord/response/GetMedicalRecordResponse.java @@ -0,0 +1,16 @@ +package com.onebridge.ouch.dto.medicalRecord.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GetMedicalRecordResponse { + + private Long id; + private String visitDate; + private String visitingHospital; + private String medicalSubject; + private String symptoms; + private String treatmentSummary; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/AddSymptomsToDiagnosisRequest.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/AddSymptomsToDiagnosisRequest.java new file mode 100644 index 0000000..71d1658 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/AddSymptomsToDiagnosisRequest.java @@ -0,0 +1,13 @@ +package com.onebridge.ouch.dto.selfDiagnosis.request; + +import java.util.List; + +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class AddSymptomsToDiagnosisRequest { + + @NotNull(message = "Please enter symptoms to add.") + private List symptoms; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/DiagnosisCreateRequest.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/DiagnosisCreateRequest.java new file mode 100644 index 0000000..72ab9cd --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/DiagnosisCreateRequest.java @@ -0,0 +1,35 @@ +package com.onebridge.ouch.dto.selfDiagnosis.request; + +import java.util.List; + +import com.onebridge.ouch.domain.enums.SymptomDuration; +import com.onebridge.ouch.domain.enums.VisitType; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class DiagnosisCreateRequest { + + // @NotNull(message = "User Id is required.") + // private Long userId; + + @NotNull(message = "Visit type is required.") + private VisitType visitType; + + @NotEmpty(message = "At least one symptom is required.") + private List symptoms; + + @NotNull(message = "Symptom duration is required.") + private SymptomDuration duration; + + @NotNull(message = "Pain severity is required.") + @Min(value = 0, message = "통증 정도는 최소 0 이상이어야 합니다.") + @Max(value = 10, message = "통증 정도는 최대 10 이하여야 합니다.") + private Integer painSeverity; + + private String additionalNote; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/DiagnosisUpdateRequest.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/DiagnosisUpdateRequest.java new file mode 100644 index 0000000..22680b7 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/request/DiagnosisUpdateRequest.java @@ -0,0 +1,32 @@ +package com.onebridge.ouch.dto.selfDiagnosis.request; + +import java.util.List; + +import com.onebridge.ouch.domain.enums.SymptomDuration; +import com.onebridge.ouch.domain.enums.VisitType; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; + +@Getter +public class DiagnosisUpdateRequest { + + @NotNull(message = "Visit type is required.") + private VisitType visitType; + + @NotEmpty(message = "At least one symptom is required.") + private List symptoms; + + @NotNull(message = "Symptom duration is required.") + private SymptomDuration duration; + + @NotNull(message = "Pain severity is required.") + @Min(value = 0, message = "통증 정도는 최소 0 이상이어야 합니다.") + @Max(value = 10, message = "통증 정도는 최대 10 이하여야 합니다.") + private Integer painSeverity; + + private String additionalNote; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/DiagnosisUpdateResponse.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/DiagnosisUpdateResponse.java new file mode 100644 index 0000000..d599a4b --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/DiagnosisUpdateResponse.java @@ -0,0 +1,22 @@ +package com.onebridge.ouch.dto.selfDiagnosis.response; + +import java.util.List; + +import com.onebridge.ouch.domain.enums.SymptomDuration; +import com.onebridge.ouch.domain.enums.VisitType; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DiagnosisUpdateResponse { + + private Long id; + private VisitType visitType; + private List symptoms; + private SymptomDuration duration; + private Integer painSeverity; + private String additionalNote; + private String createdAt; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetDiagnosisByUserIdResponse.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetDiagnosisByUserIdResponse.java new file mode 100644 index 0000000..33aceeb --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetDiagnosisByUserIdResponse.java @@ -0,0 +1,22 @@ +package com.onebridge.ouch.dto.selfDiagnosis.response; + +import java.util.List; + +import com.onebridge.ouch.domain.enums.SymptomDuration; +import com.onebridge.ouch.domain.enums.VisitType; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GetDiagnosisByUserIdResponse { + + private Long diagnosisId; + private VisitType visitType; + private List symptoms; + private SymptomDuration duration; + private Integer painSeverity; + private String additionalNote; + private String createdAt; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetDiagnosisResponse.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetDiagnosisResponse.java new file mode 100644 index 0000000..6efdeb1 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetDiagnosisResponse.java @@ -0,0 +1,22 @@ +package com.onebridge.ouch.dto.selfDiagnosis.response; + +import java.util.List; + +import com.onebridge.ouch.domain.enums.SymptomDuration; +import com.onebridge.ouch.domain.enums.VisitType; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GetDiagnosisResponse { + + private Long userId; + private VisitType visitType; + private List symptoms; + private SymptomDuration duration; + private Integer painSeverity; + private String additionalNote; + private String createdAt; +} diff --git a/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetSymptomsOfDiagnosisResponse.java b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetSymptomsOfDiagnosisResponse.java new file mode 100644 index 0000000..3d84f94 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/selfDiagnosis/response/GetSymptomsOfDiagnosisResponse.java @@ -0,0 +1,13 @@ +package com.onebridge.ouch.dto.selfDiagnosis.response; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GetSymptomsOfDiagnosisResponse { + + private List symptoms; +} diff --git a/src/main/java/com/onebridge/ouch/dto/symptom/response/GetSymptomResponse.java b/src/main/java/com/onebridge/ouch/dto/symptom/response/GetSymptomResponse.java new file mode 100644 index 0000000..71a80ec --- /dev/null +++ b/src/main/java/com/onebridge/ouch/dto/symptom/response/GetSymptomResponse.java @@ -0,0 +1,13 @@ +package com.onebridge.ouch.dto.symptom.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class GetSymptomResponse { + + private long id; + + private String name; +} diff --git a/src/main/java/com/onebridge/ouch/dto/user/request/UserUpdateRequest.java b/src/main/java/com/onebridge/ouch/dto/user/request/UserUpdateRequest.java deleted file mode 100644 index c38b99a..0000000 --- a/src/main/java/com/onebridge/ouch/dto/user/request/UserUpdateRequest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.onebridge.ouch.dto.user.request; - -import java.time.LocalDate; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class UserUpdateRequest { - - private String loginId; - - private String password; - - private String name; - - private String nickname; - - private String phoneNumber; - - private LocalDate birthday; - - private String email; - - private String address; -} diff --git a/src/main/java/com/onebridge/ouch/dto/user/response/AllUsersResponse.java b/src/main/java/com/onebridge/ouch/dto/user/response/AllUsersResponse.java deleted file mode 100644 index e4f3360..0000000 --- a/src/main/java/com/onebridge/ouch/dto/user/response/AllUsersResponse.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.onebridge.ouch.dto.user.response; - -import java.time.LocalDate; - -import com.onebridge.ouch.domain.enums.UserStatus; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@AllArgsConstructor -@NoArgsConstructor -public class AllUsersResponse { - - private Long id; - - private String loginId; - - private String password; - - private String name; - - private String nickname; - - private String phoneNumber; - - private LocalDate birthday; - - private String email; - - private String address; - - private UserStatus status; -} diff --git a/src/main/java/com/onebridge/ouch/dto/user/response/MypageUserInfoResponse.java b/src/main/java/com/onebridge/ouch/dto/user/response/MypageUserInfoResponse.java deleted file mode 100644 index 16729be..0000000 --- a/src/main/java/com/onebridge/ouch/dto/user/response/MypageUserInfoResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.onebridge.ouch.dto.user.response; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public class MypageUserInfoResponse { - - private String nickname; - - private String email; - - private Long languageId; -} diff --git a/src/main/java/com/onebridge/ouch/dto/user/response/UserSignupResponse.java b/src/main/java/com/onebridge/ouch/dto/user/response/UserSignupResponse.java deleted file mode 100644 index a927f55..0000000 --- a/src/main/java/com/onebridge/ouch/dto/user/response/UserSignupResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.onebridge.ouch.dto.user.response; - -import java.time.LocalDate; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -@Getter -public class UserSignupResponse { - - private Long id; - - private LocalDate createdAt; -} diff --git a/src/main/java/com/onebridge/ouch/repository/Symptom/SymptomRepository.java b/src/main/java/com/onebridge/ouch/repository/Symptom/SymptomRepository.java new file mode 100644 index 0000000..15be2fd --- /dev/null +++ b/src/main/java/com/onebridge/ouch/repository/Symptom/SymptomRepository.java @@ -0,0 +1,19 @@ +package com.onebridge.ouch.repository.Symptom; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.onebridge.ouch.domain.Symptom; + +@Repository +public interface SymptomRepository extends JpaRepository { + + boolean existsByName(String name); + + Optional findByName(String name); + + List findByNameIn(List names); +} diff --git a/src/main/java/com/onebridge/ouch/repository/healthStatus/HealthStatusRepository.java b/src/main/java/com/onebridge/ouch/repository/healthStatus/HealthStatusRepository.java new file mode 100644 index 0000000..a345892 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/repository/healthStatus/HealthStatusRepository.java @@ -0,0 +1,16 @@ +package com.onebridge.ouch.repository.healthStatus; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.onebridge.ouch.domain.HealthStatus; + +@Repository +public interface HealthStatusRepository extends JpaRepository { + List findAllByUserId(Long userId); + + Optional findByIdAndUserId(Long medicalHistoryId, Long userId); +} diff --git a/src/main/java/com/onebridge/ouch/repository/medicalRecord/MedicalRecordRepository.java b/src/main/java/com/onebridge/ouch/repository/medicalRecord/MedicalRecordRepository.java new file mode 100644 index 0000000..88e49b8 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/repository/medicalRecord/MedicalRecordRepository.java @@ -0,0 +1,16 @@ +package com.onebridge.ouch.repository.medicalRecord; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.onebridge.ouch.domain.mapping.MedicalRecord; + +@Repository +public interface MedicalRecordRepository extends JpaRepository { + List findAllByUserId(Long userId); + + Optional findByIdAndUserId(Long visitHistoryId, Long userId); +} diff --git a/src/main/java/com/onebridge/ouch/repository/selfDiagnosis/SelfDiagnosisRepository.java b/src/main/java/com/onebridge/ouch/repository/selfDiagnosis/SelfDiagnosisRepository.java new file mode 100644 index 0000000..14d56ed --- /dev/null +++ b/src/main/java/com/onebridge/ouch/repository/selfDiagnosis/SelfDiagnosisRepository.java @@ -0,0 +1,17 @@ +package com.onebridge.ouch.repository.selfDiagnosis; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.onebridge.ouch.domain.SelfDiagnosis; + +@Repository +public interface SelfDiagnosisRepository extends JpaRepository { + + List findAllByUserId(Long userId); + + Optional findByIdAndUserId(Long id, Long userId); +} diff --git a/src/main/java/com/onebridge/ouch/repository/summary/SummaryRepository.java b/src/main/java/com/onebridge/ouch/repository/summary/SummaryRepository.java new file mode 100644 index 0000000..ca55cba --- /dev/null +++ b/src/main/java/com/onebridge/ouch/repository/summary/SummaryRepository.java @@ -0,0 +1,10 @@ +package com.onebridge.ouch.repository.summary; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.onebridge.ouch.domain.Summary; + +@Repository +public interface SummaryRepository extends JpaRepository { +} diff --git a/src/main/java/com/onebridge/ouch/security/SecurityConfig.java b/src/main/java/com/onebridge/ouch/security/SecurityConfig.java index 7b4defa..1e69bfb 100644 --- a/src/main/java/com/onebridge/ouch/security/SecurityConfig.java +++ b/src/main/java/com/onebridge/ouch/security/SecurityConfig.java @@ -38,26 +38,20 @@ public SecurityFilterChain publicResourceConfig(HttpSecurity http) throws Except http.addFilterAt(new JwtAuthenticationFilter(tokenManager), BasicAuthenticationFilter.class); http.authorizeHttpRequests( (authorizeRequests) - -> authorizeRequests.anyRequest().permitAll() // 모든 사용자 접근 가능 + -> authorizeRequests.requestMatchers("/users/login", "/users/signup/**").permitAll() // 로그인, 회원가입 페이지는 모두 허용 + .anyRequest().authenticated() // 그 외의 요청은 인증 필요 + // -> authorizeRequests.anyRequest().permitAll() // 모든 사용자 접근 가능 // -> authorizeRequests.anyRequest().authenticated() // 로그인한 사용자만 접근 가능 ); return http.build(); - - /* - http.authorizeHttpRequests(authorizeRequests -> - authorizeRequests - .antMatchers("/login", "/signup").permitAll() // 로그인, 회원가입 페이지는 모두 허용 - .anyRequest().authenticated() // 그 외의 요청은 인증 필요 - ); - */ } public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - //configuration.addAllowedOriginPattern("*"); - configuration.addAllowedOrigin("http://localhost:5173"); - configuration.addAllowedOrigin("https://ouchs.netlify.app"); + configuration.addAllowedOriginPattern("*"); + // configuration.addAllowedOrigin("http://localhost:5173"); + // configuration.addAllowedOrigin("https://ouchs.netlify.app"); configuration.addAllowedHeader("*"); configuration.addAllowedMethod("*"); @@ -73,6 +67,7 @@ public CorsConfigurationSource corsConfigurationSource() { // http.cors() 설정은 Spring Security가 인식할 수 있도록 등록하는 용도 // 그런데 Spring Security의 인증 필터가 우선 적용돼서 OPTIONS 요청이 필터에서 차단되는 경우가 있음 // 그래서 별도로 FilterRegistrationBean를 추가하면 이 필터가 모든 요청에서 가장 우선 실행되어서 확실히 적용됨 + /* @Bean public FilterRegistrationBean corsFilter() { CorsConfiguration config = new CorsConfiguration(); @@ -91,4 +86,5 @@ public FilterRegistrationBean corsFilter() { bean.setOrder(0); // 필터 최우선 순위 설정 return bean; } + */ } diff --git a/src/main/java/com/onebridge/ouch/security/provider/OuchUserAuthenticationProvider.java b/src/main/java/com/onebridge/ouch/security/provider/OuchUserAuthenticationProvider.java index fcf9645..ecbfe54 100644 --- a/src/main/java/com/onebridge/ouch/security/provider/OuchUserAuthenticationProvider.java +++ b/src/main/java/com/onebridge/ouch/security/provider/OuchUserAuthenticationProvider.java @@ -31,10 +31,10 @@ public Authentication authenticate(Authentication authentication) throws Authent if (passwordEncoder.matches(password, userDetails.getPassword())) { return new OuchAuthenticationToken( - userDetails.getUsername(), - userDetails.getPassword(), + userDetails, // principal은 UserDetails 객체, 기존에는 userDetails.getUsername()로 string으로 받음 + null, // 인증 후 credentials는 null, 기존에는 userDetails.getPassword()로 비밀번호 유지 인증 후 credentials는 null userDetails.getAuthorities(), - ((OuchUserDetails)userDetails).getDatabaseId()); + ((OuchUserDetails)userDetails).getDatabaseId()); // PK를 getDetails()로 받기 위해 따로 만든 메소드이므로 다운캐스팅 } else { throw new OuchException(AuthorityErrorCode.PASSWORD_NOT_MATCH); } diff --git a/src/main/java/com/onebridge/ouch/security/tokenManger/JwtTokenManager.java b/src/main/java/com/onebridge/ouch/security/tokenManger/JwtTokenManager.java index 770682c..01815d9 100644 --- a/src/main/java/com/onebridge/ouch/security/tokenManger/JwtTokenManager.java +++ b/src/main/java/com/onebridge/ouch/security/tokenManger/JwtTokenManager.java @@ -75,8 +75,10 @@ public String writeToken(Authentication authentication) { "type", "accessToken" )) .setClaims(Map.of( - "loginId", authentication.getPrincipal(), - "authorities", authentication.getAuthorities(), + "loginId", authentication.getName(), // 기존 .getPrincipal()로 UserDetails 전체가 직렬화됨(다만 principle을 userDetails.getUsername() 넣었어서 string으로 문제가 없었음 -> username(String)만 + "authorities", authentication.getAuthorities().stream() // GrantedAuthority 객체 리스트 직렬화 문제 -> List + .map(GrantedAuthority::getAuthority) + .toList(), "id", authentication.getDetails() )) .setIssuedAt(new Date()) diff --git a/src/main/java/com/onebridge/ouch/service/LanguageService.java b/src/main/java/com/onebridge/ouch/service/LanguageService.java index 6a77637..8ddd9d5 100644 --- a/src/main/java/com/onebridge/ouch/service/LanguageService.java +++ b/src/main/java/com/onebridge/ouch/service/LanguageService.java @@ -19,6 +19,7 @@ public class LanguageService { private final LanguageRepository languageRepository; + /* public Long addLanguage(LanguageDto languageDto) { Language language = Language.builder() .name(languageDto.getName()) @@ -45,6 +46,7 @@ public void deleteLanguage(Long id) { } languageRepository.deleteById(id); } + */ public List getAllLanguages() { List languages = languageRepository.findAll(); @@ -52,5 +54,4 @@ public List getAllLanguages() { .map(language -> new LanguageDto(language.getName(), language.getCode())) .collect(Collectors.toList()); } - } diff --git a/src/main/java/com/onebridge/ouch/service/healthStatus/HealthStatusService.java b/src/main/java/com/onebridge/ouch/service/healthStatus/HealthStatusService.java new file mode 100644 index 0000000..0326704 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/service/healthStatus/HealthStatusService.java @@ -0,0 +1,81 @@ +package com.onebridge.ouch.service.healthStatus; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.onebridge.ouch.apiPayload.code.error.CommonErrorCode; +import com.onebridge.ouch.apiPayload.code.error.HealthStatusErrorCode; +import com.onebridge.ouch.apiPayload.exception.OuchException; +import com.onebridge.ouch.converter.HealthStatusConverter; +import com.onebridge.ouch.domain.HealthStatus; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.dto.healthStatus.request.HealthStatusCreateRequest; +import com.onebridge.ouch.dto.healthStatus.request.HealthStatusUpdateRequest; +import com.onebridge.ouch.dto.healthStatus.response.DateAndDisease; +import com.onebridge.ouch.dto.healthStatus.response.GetHealthStatusResponse; +import com.onebridge.ouch.repository.healthStatus.HealthStatusRepository; +import com.onebridge.ouch.repository.user.UserRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class HealthStatusService { + + private final UserRepository userRepository; + private final HealthStatusConverter healthStatusConverter; + private final HealthStatusRepository healthStatusRepository; + + //건강상태 생성 + @Transactional + public void createHealthStatus(HealthStatusCreateRequest request, Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new OuchException(CommonErrorCode.MEMBER_NOT_FOUND)); + + HealthStatus healthStatus = healthStatusConverter.healthStatusCreateRequestToHealthStatus(request, + user); + + healthStatusRepository.save(healthStatus); + } + + //특정 건강상태 조회 + @Transactional + public GetHealthStatusResponse getHealthStatus(Long healthStatusId, Long userId) { + HealthStatus healthStatus = healthStatusRepository.findByIdAndUserId(healthStatusId, userId) + .orElseThrow(() -> new OuchException(HealthStatusErrorCode.HEALTH_STATUS_NOT_FOUND)); + return healthStatusConverter.healthStatusToGetHealthStatusResponse(healthStatus); + } + + /* + //특정 사용자의 모든 건강상태 조회 + @Transactional + public List getUsersAllHealthStatus(Long userId) { + List healthStatus = healthStatusRepository.findAllByUserId(userId); + return healthStatusConverter.healthStatusToGetUsersAllHealthStatusResponse(healthStatus); + } + */ // 유저 한 명당 하나의 건강상태만 보유 + + //특정 건강상태 수정 + @Transactional + public void updateHealthStatus(HealthStatusUpdateRequest request, + Long healthStatusId, Long userId) { + HealthStatus healthStatus = healthStatusRepository.findByIdAndUserId(healthStatusId, userId) + .orElseThrow(() -> new OuchException(HealthStatusErrorCode.HEALTH_STATUS_NOT_FOUND)); + + HealthStatus updatedHealthStatus = healthStatusConverter + .healthStatusUpdateRequestToHealthStatus(healthStatus, request); + + healthStatusRepository.save(updatedHealthStatus); + } + + //특정 건강상태 삭제 + @Transactional + public void deleteHealthStatus(Long healthStatusId, Long userId) { + HealthStatus healthStatus = healthStatusRepository.findByIdAndUserId(healthStatusId, userId) + .orElseThrow(() -> new OuchException(HealthStatusErrorCode.HEALTH_STATUS_NOT_FOUND)); + + healthStatusRepository.delete(healthStatus); + } +} diff --git a/src/main/java/com/onebridge/ouch/service/medicalRecord/MedicalRecordService.java b/src/main/java/com/onebridge/ouch/service/medicalRecord/MedicalRecordService.java new file mode 100644 index 0000000..56bac37 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/service/medicalRecord/MedicalRecordService.java @@ -0,0 +1,97 @@ +package com.onebridge.ouch.service.medicalRecord; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.onebridge.ouch.apiPayload.code.error.CommonErrorCode; +import com.onebridge.ouch.apiPayload.code.error.MedicalRecordErrorCode; +import com.onebridge.ouch.apiPayload.exception.OuchException; +import com.onebridge.ouch.converter.MedicalRecordConverter; +import com.onebridge.ouch.domain.Summary; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.domain.mapping.MedicalRecord; +import com.onebridge.ouch.dto.medicalRecord.request.MedicalRecordCreateRequest; +import com.onebridge.ouch.dto.medicalRecord.request.MedicalRecordUpdateRequest; +import com.onebridge.ouch.dto.medicalRecord.response.DateAndHospital; +import com.onebridge.ouch.dto.medicalRecord.response.GetMedicalRecordResponse; +import com.onebridge.ouch.repository.medicalRecord.MedicalRecordRepository; +import com.onebridge.ouch.repository.summary.SummaryRepository; +import com.onebridge.ouch.repository.user.UserRepository; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class MedicalRecordService { + + private final UserRepository userRepository; + private final MedicalRecordRepository medicalRecordRepository; + private final MedicalRecordConverter medicalRecordConverter; + private final SummaryRepository summaryRepository; + + //의료 기록 생성 + @Transactional + public void createMedicalRecord(MedicalRecordCreateRequest request, Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new OuchException(CommonErrorCode.MEMBER_NOT_FOUND)); + + // Summary 생성 + Summary summary = Summary.builder() + .contents_summary(request.getTreatmentSummary()) + .build(); + + MedicalRecord medicalRecord = medicalRecordConverter.medicalRecordCreateRequestToMedicalRecord(request, user, + summary); + + medicalRecordRepository.save(medicalRecord); + } + + //특정 의료기록 조회 + @Transactional + public GetMedicalRecordResponse getMedicalRecord(Long medicalRecordId, Long userId) { + MedicalRecord medicalRecord = medicalRecordRepository.findByIdAndUserId(medicalRecordId, userId) + .orElseThrow(() -> new OuchException(MedicalRecordErrorCode.MEDICAL_RECORD_NOT_FOUND)); + + return medicalRecordConverter.medicalRecordToGetMedicalRecordResponse(medicalRecord); + } + + //특정 사용자의 모든 의료기록 조회 + @Transactional + public List getUsersAllMedicalRecord(Long userId) { + List medicalRecords = medicalRecordRepository.findAllByUserId(userId); + return medicalRecordConverter.medicalRecordToGetUsersAllMedicalRecordResponse(medicalRecords); + } + + //특정 의료기록 삭제 + @Transactional + public void deleteMedicalRecord(Long medicalRecordId, Long userId) { + MedicalRecord medicalRecord = medicalRecordRepository.findByIdAndUserId(medicalRecordId, userId) + .orElseThrow( + () -> new OuchException(MedicalRecordErrorCode.MEDICAL_RECORD_NOT_FOUND)); + + medicalRecordRepository.delete(medicalRecord); + } + + //특정 의료기록 수정 + @Transactional + public void updateMedicalRecord(@Valid MedicalRecordUpdateRequest request, + Long medicalRecordId, Long userId) { + MedicalRecord medicalRecord = medicalRecordRepository.findByIdAndUserId(medicalRecordId, userId) + .orElseThrow(() -> new OuchException(MedicalRecordErrorCode.MEDICAL_RECORD_NOT_FOUND)); + + Summary summary = medicalRecord.getSummary().toBuilder() + .contents_summary(request.getTreatmentSummary()) + .build(); + + MedicalRecord updatedMedicalRecord = medicalRecordConverter.medicalRecordUpdateRequestToMedicalRecord( + medicalRecord, + request, + summary); + + medicalRecordRepository.save(updatedMedicalRecord); + } + +} diff --git a/src/main/java/com/onebridge/ouch/service/selfDiagnosis/SelfDiagnosisService.java b/src/main/java/com/onebridge/ouch/service/selfDiagnosis/SelfDiagnosisService.java new file mode 100644 index 0000000..b4b3903 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/service/selfDiagnosis/SelfDiagnosisService.java @@ -0,0 +1,172 @@ +package com.onebridge.ouch.service.selfDiagnosis; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.onebridge.ouch.apiPayload.code.error.CommonErrorCode; +import com.onebridge.ouch.apiPayload.code.error.DiagnosisErrorCode; +import com.onebridge.ouch.apiPayload.exception.OuchException; +import com.onebridge.ouch.converter.SelfDiagnosisConverter; +import com.onebridge.ouch.domain.SelfDiagnosis; +import com.onebridge.ouch.domain.Symptom; +import com.onebridge.ouch.domain.User; +import com.onebridge.ouch.domain.mapping.DiagnosisSymptom; +import com.onebridge.ouch.dto.selfDiagnosis.request.AddSymptomsToDiagnosisRequest; +import com.onebridge.ouch.dto.selfDiagnosis.request.DiagnosisCreateRequest; +import com.onebridge.ouch.dto.selfDiagnosis.request.DiagnosisUpdateRequest; +import com.onebridge.ouch.dto.selfDiagnosis.response.DiagnosisUpdateResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetDiagnosisByUserIdResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetDiagnosisResponse; +import com.onebridge.ouch.dto.selfDiagnosis.response.GetSymptomsOfDiagnosisResponse; +import com.onebridge.ouch.repository.Symptom.SymptomRepository; +import com.onebridge.ouch.repository.selfDiagnosis.SelfDiagnosisRepository; +import com.onebridge.ouch.repository.user.UserRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class SelfDiagnosisService { + + private final SelfDiagnosisRepository selfDiagnosisRepository; + private final SymptomRepository symptomRepository; + private final UserRepository userRepository; + private final SelfDiagnosisConverter selfDiagnosisConverter; + + //자가진단표 생성 + @Transactional + public void createDiagnosis(DiagnosisCreateRequest request, Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new OuchException(CommonErrorCode.MEMBER_NOT_FOUND)); + + //일단 증상 리스트는 비워둔 채로 SelfDiagnosis 객체 생성 + SelfDiagnosis selfDiagnosis = selfDiagnosisConverter.diagnosisCreateRequestToSelfDiagnosis(request, user); + + List symptomNames = request.getSymptoms(); + List foundSymptoms = symptomRepository.findByNameIn(symptomNames); + + // 이름으로 빠르게 찾기 위해 Map 으로 변환 + Map symptomMap = foundSymptoms.stream() + .collect(Collectors.toMap(Symptom::getName, s -> s)); + + for (String symptomName : symptomNames) { + Symptom foundSymptom = symptomMap.get(symptomName); + if (foundSymptom == null) { + throw new OuchException(DiagnosisErrorCode.SYMPTOM_NOT_FOUND); + } + + DiagnosisSymptom diagnosisSymptom = selfDiagnosisConverter.buildDiagnosisSymptom(selfDiagnosis, + foundSymptom); + selfDiagnosis.getDiagnosisSymptomList().add(diagnosisSymptom); + } + + selfDiagnosisRepository.save(selfDiagnosis); + } + + //특정 자가진단표 조회 + @Transactional(readOnly = true) + public GetDiagnosisResponse getDiagnosis(Long diagnosisId, Long userId) { + SelfDiagnosis diagnosis = selfDiagnosisRepository.findByIdAndUserId(diagnosisId, userId) + .orElseThrow(() -> new OuchException(DiagnosisErrorCode.DIAGNOSIS_NOT_FOUND)); + + return selfDiagnosisConverter.diagnosisToGetDiagnosisResponse(diagnosis); + } + + //특정 사용자의 모든 자가진단표 조회 + @Transactional(readOnly = true) + public List getAllDiagnosisByUserId(Long userId) { + List diagnosisList = selfDiagnosisRepository.findAllByUserId(userId); + + List responseList = new ArrayList<>(); + for (SelfDiagnosis diagnosis : diagnosisList) { + responseList.add(selfDiagnosisConverter.diagnosisToGetDiagnosisByUserIdResponse(diagnosis)); + } + + return responseList; + } + + //특정 자가진단표 삭제 + @Transactional + public void deleteDiagnosis(Long diagnosisId, Long userId) { + SelfDiagnosis diagnosis = selfDiagnosisRepository.findByIdAndUserId(diagnosisId, userId) + .orElseThrow(() -> new OuchException(DiagnosisErrorCode.DIAGNOSIS_NOT_FOUND)); + + selfDiagnosisRepository.delete(diagnosis); + } + + //특정 자가진단표의 증상 목록 조회 + @Transactional(readOnly = true) + public GetSymptomsOfDiagnosisResponse getSymptomsOfDiagnosis(Long diagnosisId, Long userId) { + SelfDiagnosis diagnosis = selfDiagnosisRepository.findByIdAndUserId(diagnosisId, userId) + .orElseThrow(() -> new OuchException(DiagnosisErrorCode.DIAGNOSIS_NOT_FOUND)); + + return selfDiagnosisConverter.diagnosisToGetSymptomsOfDiagnosisResponse(diagnosis); + } + + //자가진단표 수정 + @Transactional + public DiagnosisUpdateResponse updateDiagnosis(Long diagnosisId, Long userId, DiagnosisUpdateRequest request) { + SelfDiagnosis diagnosis = selfDiagnosisRepository.findByIdAndUserId(diagnosisId, userId) + .orElseThrow(() -> new OuchException(DiagnosisErrorCode.DIAGNOSIS_NOT_FOUND)); + + User user = userRepository.findById(userId) + .orElseThrow(() -> new OuchException(CommonErrorCode.MEMBER_NOT_FOUND)); + + SelfDiagnosis updatedDiagnosis = selfDiagnosisConverter.diagnosisUpdateRequestToSelfDiagnosis(diagnosis, user, + request); + + List symptomNames = request.getSymptoms(); + List foundSymptoms = symptomRepository.findByNameIn(symptomNames); + + // 이름으로 빠르게 찾기 위해 Map 으로 변환 + Map symptomMap = foundSymptoms.stream() + .collect(Collectors.toMap(Symptom::getName, s -> s)); + + for (String symptomName : symptomNames) { + Symptom foundSymptom = symptomMap.get(symptomName); + if (foundSymptom == null) { + throw new OuchException(DiagnosisErrorCode.SYMPTOM_NOT_FOUND); + } + + DiagnosisSymptom diagnosisSymptom = selfDiagnosisConverter.buildDiagnosisSymptom(updatedDiagnosis, + foundSymptom); + updatedDiagnosis.getDiagnosisSymptomList().add(diagnosisSymptom); + } + + selfDiagnosisRepository.save(updatedDiagnosis); + + return selfDiagnosisConverter.diagnosisToDiagnosisUpdateResponse(updatedDiagnosis); + } + + //특정 자가진단표에 증상 추가 + @Transactional + public void addSymptomsToSelfDiagnosis(Long diagnosisId, AddSymptomsToDiagnosisRequest request, Long userId) { + + SelfDiagnosis diagnosis = selfDiagnosisRepository.findByIdAndUserId(diagnosisId, userId) + .orElseThrow(() -> new OuchException(DiagnosisErrorCode.DIAGNOSIS_NOT_FOUND)); + + for (String symptom : request.getSymptoms()) { + + if (diagnosis.getDiagnosisSymptomList() + .stream() + .anyMatch(diagnosisSymptom -> diagnosisSymptom.getSymptom().getName().equals(symptom))) { + throw new OuchException(DiagnosisErrorCode.SYMPTOM_ALREADY_ADDED); + } + + Symptom foundSymptom = symptomRepository.findByName(symptom) + .orElseThrow(() -> new OuchException(DiagnosisErrorCode.SYMPTOM_NOT_FOUND)); + + DiagnosisSymptom diagnosisSymptom = selfDiagnosisConverter.buildDiagnosisSymptom(diagnosis, foundSymptom); + + diagnosis.getDiagnosisSymptomList().add(diagnosisSymptom); + + } + } +} + + diff --git a/src/main/java/com/onebridge/ouch/service/symptom/SymptomService.java b/src/main/java/com/onebridge/ouch/service/symptom/SymptomService.java new file mode 100644 index 0000000..f6c1945 --- /dev/null +++ b/src/main/java/com/onebridge/ouch/service/symptom/SymptomService.java @@ -0,0 +1,27 @@ +package com.onebridge.ouch.service.symptom; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.onebridge.ouch.converter.SymptomConverter; +import com.onebridge.ouch.domain.Symptom; +import com.onebridge.ouch.dto.symptom.response.GetSymptomResponse; +import com.onebridge.ouch.repository.Symptom.SymptomRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class SymptomService { + + private final SymptomRepository symptomRepository; + private final SymptomConverter symptomConverter; + + @Transactional + public List getSymptomsList() { + List symptoms = symptomRepository.findAll(); + return symptomConverter.symptomsToGetSymptomsResponse(symptoms); + } +} diff --git a/src/main/java/com/onebridge/ouch/service/user/UserService.java b/src/main/java/com/onebridge/ouch/service/user/UserService.java index cf0b474..fa7ad70 100644 --- a/src/main/java/com/onebridge/ouch/service/user/UserService.java +++ b/src/main/java/com/onebridge/ouch/service/user/UserService.java @@ -3,40 +3,38 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import com.onebridge.ouch.apiPayload.code.error.CommonErrorCode; +import com.onebridge.ouch.apiPayload.exception.OuchException; import com.onebridge.ouch.converter.UserConverter; -import com.onebridge.ouch.domain.Nation; import com.onebridge.ouch.domain.User; import com.onebridge.ouch.domain.enums.UserStatus; -import com.onebridge.ouch.dto.user.request.MypageUserInfoUpdateRequest; -import com.onebridge.ouch.dto.user.response.MypageUserInfoResponse; import com.onebridge.ouch.dto.user.response.UserInfoResponse; import com.onebridge.ouch.repository.nation.NationRepository; import com.onebridge.ouch.repository.user.UserRepository; +import lombok.AllArgsConstructor; + @Service +@AllArgsConstructor public class UserService { private final UserRepository userRepository; private final NationRepository nationRepository; private final UserConverter userConverter; - public UserService(UserRepository userRepository, NationRepository nationRepository, UserConverter userConverter) { - this.userRepository = userRepository; - this.nationRepository = nationRepository; - this.userConverter = userConverter; - } - + //유저 조회(테스트용) @Transactional(readOnly = true) public UserInfoResponse getUserInfo(Long id) { - User user = userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found")); + User user = userRepository.findById(id).orElseThrow(() -> new OuchException(CommonErrorCode.MEMBER_NOT_FOUND)); return userConverter.convertToUserInfoResponse(user); } + //유저 탈퇴(비활성화) @Transactional public void deactivateUser(Long userId) { User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("User not found")); + .orElseThrow(() -> new OuchException(CommonErrorCode.MEMBER_NOT_FOUND)); User deactivatedUser = user.toBuilder() .status(UserStatus.INACTIVE) @@ -44,38 +42,6 @@ public void deactivateUser(Long userId) { userRepository.save(deactivatedUser); } - - @Transactional - public void deleteUser(Long id) { - User user = userRepository.findById(id).orElseThrow(() -> new RuntimeException("User not found")); - userRepository.delete(user); - } - - @Transactional(readOnly = true) - public MypageUserInfoResponse myPageGetUserInfo(Long userId) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("User not found")); - return userConverter.convertToMypageUserInfoResponse(user); - } - - @Transactional - public void myPageUpdateUserInfo(Long userId, MypageUserInfoUpdateRequest request) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("User not found")); - - Nation wantedNation = nationRepository.findById(request.getNationId()) - .orElseThrow(() -> new RuntimeException("Nation not found")); - - User updatedUser = user.toBuilder() - .nickname(request.getNickname()) - .phoneNumber(request.getPhoneNumber()) - .gender(request.getGender()) - .email(request.getEmail()) - .nation(wantedNation) - .build(); - - userRepository.save(updatedUser); - } } diff --git a/src/main/java/com/onebridge/ouch/web/controller/LanguageController.java b/src/main/java/com/onebridge/ouch/web/controller/LanguageController.java index fe78c1e..aef6706 100644 --- a/src/main/java/com/onebridge/ouch/web/controller/LanguageController.java +++ b/src/main/java/com/onebridge/ouch/web/controller/LanguageController.java @@ -26,6 +26,7 @@ public class LanguageController { private final LanguageService languageService; + /* @PostMapping public ResponseEntity> addLanguage(@Valid @RequestBody LanguageDto languageDto) { Long languageId = languageService.addLanguage(languageDto); @@ -44,6 +45,7 @@ public ResponseEntity> deleteLanguage(@PathVariable("languageI languageService.deleteLanguage(id); return ResponseEntity.ok(ApiResponse.successWithNoData()); } + */ @GetMapping // 전체 언어 목록 조회 public ResponseEntity>> getAllLanguages() { diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index bc3214d..68a72f6 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -21,4 +21,11 @@ openai: api-key: ${OPENAI_API_KEY} jwt: - secret: ${JWT_SECRET} \ No newline at end of file + secret: ${JWT_SECRET} + +# spring actuator 활용한 도커 헬스체크용 +management: + endpoints: + web: + exposure: + include: health \ No newline at end of file