From cb229668936991a73cb01a85d3e86e01fc4da1ef Mon Sep 17 00:00:00 2001 From: ji-young Date: Fri, 4 Apr 2025 17:46:14 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=88=98=EC=A0=95=20=ED=9B=84=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ChartController.java | 1 - .../controller/UserController.java | 70 ++++++++++++----- .../esginsightboard/dto/EsgChartDataDto.java | 65 ---------------- .../dto/UserUpdateRequest.java | 17 +++++ .../gyeoul/esginsightboard/entity/User.java | 8 +- .../repository/ChartRepository.java | 24 ------ .../service/ChartDataService.java | 4 + .../esginsightboard/service/ChartService.java | 75 ------------------- .../esginsightboard/service/UserService.java | 24 +++++- 9 files changed, 98 insertions(+), 190 deletions(-) delete mode 100644 src/main/java/dev/gyeoul/esginsightboard/controller/ChartController.java delete mode 100644 src/main/java/dev/gyeoul/esginsightboard/dto/EsgChartDataDto.java create mode 100644 src/main/java/dev/gyeoul/esginsightboard/dto/UserUpdateRequest.java delete mode 100644 src/main/java/dev/gyeoul/esginsightboard/repository/ChartRepository.java delete mode 100644 src/main/java/dev/gyeoul/esginsightboard/service/ChartService.java diff --git a/src/main/java/dev/gyeoul/esginsightboard/controller/ChartController.java b/src/main/java/dev/gyeoul/esginsightboard/controller/ChartController.java deleted file mode 100644 index 8b13789..0000000 --- a/src/main/java/dev/gyeoul/esginsightboard/controller/ChartController.java +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java b/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java index 8be22b6..5eef7e1 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java +++ b/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java @@ -56,7 +56,7 @@ public class UserController { }) public ResponseEntity signup(@Valid @RequestBody SignupRequest request) { UserDto userDto = userService.signup(request); - return ResponseEntity.status(HttpStatus.CREATED).body(userDto); + return ResponseEntity.status(HttpStatus.CREATED).body(userDto); // HTTP 201 Created 상태코드로 생성된 사용자 정보 반환 } /** @@ -76,8 +76,8 @@ public ResponseEntity signup(@Valid @RequestBody SignupRequest request) @ApiResponse(responseCode = "401", description = "이메일 또는 비밀번호가 일치하지 않음") }) public ResponseEntity login(@RequestBody LoginRequest request) { - LoginResponse response = userService.login(request); - return ResponseEntity.ok(response); + LoginResponse response = userService.login(request); // 서비스 계층에 로그인 요청을 위임하여 처리 + return ResponseEntity.ok(response); // 로그인 성공 시 200 OK + JWT 포함된 응답 반환 } /** @@ -98,14 +98,17 @@ public ResponseEntity login(@RequestBody LoginRequest request) { @ApiResponse(responseCode = "401", description = "인증 실패 또는 토큰 없음") }) public ResponseEntity getMyInfo(HttpServletRequest request) { + // JWT 인증 필터에서 사용자 정보를 request attribute로 설정했다고 가정 UserDto user = (UserDto) request.getAttribute("user"); + + // 사용자 정보가 존재하면 200 ok, 없으면 401 Unauthorized 반환 if (user != null) { return ResponseEntity.ok(user); } else { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } } - + /** * API 테스트를 위한 테스트 토큰 발급 API * @@ -124,14 +127,14 @@ public ResponseEntity getMyInfo(HttpServletRequest request) { public ResponseEntity> generateTestToken( @Parameter(description = "테스트 토큰에 사용할 이메일", example = "test@example.com") @RequestParam(defaultValue = "test@example.com") String email) { + + String token = jwtTokenUtil.generateTestToken(email); // 1. 테스트용 JWT 토큰 생성 + Date expiryDate = jwtTokenUtil.getExpirationDateFromToken(token); // 2. 만료일 추출 + + Map response = createTestTokenResponse(token, email, expiryDate); // 3. 응답 데이터 구성 + log.info("테스트 토큰 발급: {}, 만료일: {}", email, expiryDate); // 4. 로그 기록 - String token = jwtTokenUtil.generateTestToken(email); - Date expiryDate = jwtTokenUtil.getExpirationDateFromToken(token); - - Map response = createTestTokenResponse(token, email, expiryDate); - log.info("테스트 토큰 발급: {}, 만료일: {}", email, expiryDate); - - return ResponseEntity.ok(response); + return ResponseEntity.ok(response); // 5. 응답 반환 } /** @@ -140,17 +143,20 @@ public ResponseEntity> generateTestToken( private Map createTestTokenResponse(String token, String email, Date expiryDate) { Map response = new HashMap<>(); Map tokenInfo = new HashMap<>(); - - tokenInfo.put("token", token); - tokenInfo.put("type", "Bearer"); - tokenInfo.put("expiryDate", expiryDate); - - response.put("success", true); + + // JWT 토큰 정보 구성 + tokenInfo.put("token", token); // JWT 문자열 + tokenInfo.put("type", "Bearer"); // 토큰 타입 명시 (OAuth2 등에서 사용) + tokenInfo.put("expiryDate", expiryDate); // 만료일 정보 + + // 최종 응답 객체 구성 + response.put("success", true); // 처리 성공 여부 response.put("message", "테스트 토큰이 발급되었습니다"); - response.put("tokenInfo", tokenInfo); + response.put("tokenInfo", tokenInfo); // 위에서 구성한 토큰 정보 Map // Swagger UI 사용법 response.put("swaggerUsage", "Swagger UI 우측 상단의 'Authorize' 버튼을 클릭하고, 발급된 토큰을 입력하세요. (Bearer 접두사 없이)"); + // cURL 명령 예시 포함 response.put("curlExample", "curl -X GET 'http://localhost:8080/api/users/me' -H 'Authorization: Bearer " + token + "'"); return response; @@ -179,13 +185,39 @@ public ResponseEntity> tokenTest(HttpServletRequest request) UserDto user = (UserDto) request.getAttribute("user"); response.put("authenticated", user != null); + // 사용자 정보가 존재하면 세부 정보 반환 if (user != null) { response.put("userInfo", extractUserInfo(user)); } + // 응답 반환 return ResponseEntity.ok(response); } - + + // 마이페이지 회원정보 저장 API + @PutMapping("/update") + @Operation( + summary = "사용자 정보 수정", + description = "마이페이지에서 사용자 정보를 수정합니다." + ) + @SecurityRequirement(name = "bearerAuth") + public ResponseEntity updateUser( + @RequestBody @Valid UserUpdateRequest request, HttpServletRequest req) { + // JWT 필터를 통해 주입된 현재 사용자 정보 꺼내기 + UserDto currentUser = (UserDto) req.getAttribute("user"); + + // 인증되지 않은 경우 401 반환 + if (currentUser == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + // 서비스 계층에 사용자 ID와 수정 요청을 넘겨 DB 반영 수행 + userService.updateUser(currentUser.getId(), request); + + // 성공적으로 수정된 경우, 원래 요청 객체를 그대로 반환 + return ResponseEntity.ok(request); + } + /** * 사용자 정보에서 필요한 정보만 추출하는 메서드 */ diff --git a/src/main/java/dev/gyeoul/esginsightboard/dto/EsgChartDataDto.java b/src/main/java/dev/gyeoul/esginsightboard/dto/EsgChartDataDto.java deleted file mode 100644 index c3c4047..0000000 --- a/src/main/java/dev/gyeoul/esginsightboard/dto/EsgChartDataDto.java +++ /dev/null @@ -1,65 +0,0 @@ -package dev.gyeoul.esginsightboard.dto; - -import dev.gyeoul.esginsightboard.entity.EsgInputValue; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import lombok.*; - -import java.util.Map; - -//@Data // @Getter + Setter + ToString + equals -@Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class EsgChartDataDto { - // ESG 카테고리: "E", "S", "G" - @NotBlank(message = "카테고리 코드는 필수입니다.") - private String category; - - // 차트 제목 - @NotBlank(message = "차트 제목은 필수입니다.") - private String chartTitle; - - // ESG 지표 이름 (ex. 원재료) - @NotBlank(message = "지표 선택 필수입니다.") - private String indicatorCode; - - // 지표별 상세 입력값 (key-value 구조) - @NotEmpty(message = "지표 입력값은 비어 있을 수 없습니다.") - private Map indicatorInputs; - - private String unit; // 데이터 단위 (예: "kWh", "tCO2eq") - -// private Long companyId; - - public static EsgChartDataDto fromEntity(EsgInputValue entity) { - return EsgChartDataDto.builder() - .category(entity.getIndicator().getCategory().getCategory()) // E, S, G - .chartTitle(entity.getIndicator().getIndicatorTitle()) // 지표 제목 - .indicatorCode(entity.getIndicator().getIndicatorCode()) // 지표 코드 - .indicatorInputs(Map.of( - "numericValue", entity.getNumericValue() != null ? entity.getNumericValue().toString() : "", - "textValue", entity.getTextValue() != null ? entity.getTextValue() : "" - )) - .unit(entity.getUnit()) -// .companyId(entity.getCompany().getId()) - .build(); - } - - // 생성자 -// public EsgChartDataDto(String category, String chartTitle, String indicatorCode, Map indicatorInputs, Long companyId) { -// String trimmedCode = category.trim().toUpperCase(); -// -// // 직접 검증: E, S, G 중 하나인지 확인 -// if (!Set.of("E", "S", "G").contains(trimmedCode)) { -// throw new IllegalArgumentException("카테고리 코드는 E, S, G 중 하나여야 합니다."); -// } -// this.category = category; -// this.chartTitle = chartTitle; -// this.indicatorCode = indicatorCode; -// this.indicatorInputs = indicatorInputs; -// this.unit = indicatorInputs.get("unit"); -// this.companyId = companyId; -// } -} diff --git a/src/main/java/dev/gyeoul/esginsightboard/dto/UserUpdateRequest.java b/src/main/java/dev/gyeoul/esginsightboard/dto/UserUpdateRequest.java new file mode 100644 index 0000000..9a4ac4f --- /dev/null +++ b/src/main/java/dev/gyeoul/esginsightboard/dto/UserUpdateRequest.java @@ -0,0 +1,17 @@ +package dev.gyeoul.esginsightboard.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserUpdateRequest { + private String name; + private String email; + private String password; // optional + private String phoneNumber; +} diff --git a/src/main/java/dev/gyeoul/esginsightboard/entity/User.java b/src/main/java/dev/gyeoul/esginsightboard/entity/User.java index 868e2cf..cda5c76 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/entity/User.java +++ b/src/main/java/dev/gyeoul/esginsightboard/entity/User.java @@ -1,10 +1,7 @@ package dev.gyeoul.esginsightboard.entity; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; @@ -20,6 +17,7 @@ @Entity @Table(name = "users") @Getter +@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) // JPA에 필요한 기본 생성자를 protected로 제한 public class User implements UserDetails { @@ -165,4 +163,4 @@ public boolean isCredentialsNonExpired() { public boolean isEnabled() { return this.enabled; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/dev/gyeoul/esginsightboard/repository/ChartRepository.java b/src/main/java/dev/gyeoul/esginsightboard/repository/ChartRepository.java deleted file mode 100644 index c1b10f2..0000000 --- a/src/main/java/dev/gyeoul/esginsightboard/repository/ChartRepository.java +++ /dev/null @@ -1,24 +0,0 @@ -package dev.gyeoul.esginsightboard.repository; - -import dev.gyeoul.esginsightboard.dto.EsgChartDataDto; -import org.springframework.stereotype.Repository; - -import java.util.ArrayList; -import java.util.List; - -@Repository -public class ChartRepository { - - // 임시 저장소 (DB 대체용) - private final List chartDataStore = new ArrayList<>(); - - // 차트 데이터 저장 - public void save(EsgChartDataDto dto) { - chartDataStore.add(dto); - } - - // 전체 저장 데이터 반환 (옵션) - public List findAll() { - return chartDataStore; - } -} diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/ChartDataService.java b/src/main/java/dev/gyeoul/esginsightboard/service/ChartDataService.java index 4226127..d2d870b 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/ChartDataService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/ChartDataService.java @@ -7,6 +7,7 @@ import dev.gyeoul.esginsightboard.repository.ChartDataRepository; import dev.gyeoul.esginsightboard.repository.UserRepository; import lombok.RequiredArgsConstructor; +//import org.apache.catalina.User; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,6 +21,9 @@ public class ChartDataService { private final ChartDataRepository chartDataRepository; private final UserRepository userRepository; +// @Transactional +// public User findUser() + // ✅ 차트 데이터 저장 (DTO 적용) @Transactional public ChartDataDto saveChartData(ChartDataDto dto, UserDto userDto) { diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/ChartService.java b/src/main/java/dev/gyeoul/esginsightboard/service/ChartService.java deleted file mode 100644 index 777bffa..0000000 --- a/src/main/java/dev/gyeoul/esginsightboard/service/ChartService.java +++ /dev/null @@ -1,75 +0,0 @@ -package dev.gyeoul.esginsightboard.service; - -import dev.gyeoul.esginsightboard.dto.EsgChartDataDto; -import dev.gyeoul.esginsightboard.dto.UserDto; -import dev.gyeoul.esginsightboard.entity.*; -import dev.gyeoul.esginsightboard.repository.*; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.time.LocalDate; -import java.util.Map; - -// 사용자가 입력한 차트 로직을 처리하는 서비스 -@Service -@RequiredArgsConstructor // 생성자 주입을 자동으로 처리해주는 롬복 어노테이션 -public class ChartService { - - private final EsgCategoryRepository categoryRepository; - private final EsgIndicatorRepository indicatorRepository; - private final EsgInputValueRepository inputValueRepository; -// private final CompanyRepository companyRepository; - private final UserRepository userRepository; - - // 차트 데이터 저장 메서드 - public void saveChartData(EsgChartDataDto chartDto, UserDto user) { - - // 1. 카테고리 조회 (예: "E", "S", "G") - EsgCategory category = categoryRepository.findByCategory(chartDto.getCategory()) - .orElseThrow(() -> new IllegalArgumentException("잘못된 카테고리 코드입니다.")); - - // 2. 지표 조회 - EsgIndicator indicator = indicatorRepository.findByIndicatorCode(chartDto.getIndicatorCode()) - .orElseThrow(() -> new IllegalArgumentException("잘못된 카테고리 코드입니다.")); - - // 3. 사용자 조회 - User userId = userRepository.findById(user.getId()) - .orElseThrow(() -> new IllegalStateException("회사를 찾을 수 없습니다.")); - - // 4. 연도별 입력값 Map 순회 저장 - for (Map.Entry entry : chartDto.getIndicatorInputs().entrySet()) { - String period = entry.getKey(); // 예: "2024" - String value = entry.getValue(); // 예: "123.45" 또는 "사용량 증가" - - Double numericValue = null; - try { - // 문자열을 숫자로 변환 시도 - numericValue = Double.parseDouble(value); - } catch (NumberFormatException ignored) { - // 숫자가 아닌 경우(null 유지), 예: "증가함", "없음" 등 - } - - // 연도를 기준으로 보고 기간 설정 (1월 1일 ~ 12월 31일) - LocalDate startDate = LocalDate.of(Integer.parseInt(period), 1, 1); - LocalDate endDate = LocalDate.of(Integer.parseInt(period), 12, 31); - - // EsqInputValue 엔티티 생성 - EsgInputValue inputValue = new EsgInputValue( - indicator, // 연결된 지표 - userId, // 연결된 회사 - numericValue, // 숫자형 값 (null 가능) - value, // 원래의 문자열 값 - chartDto.getUnit(), // 단위 (예: "톤", "kWh") - startDate, // 보고 시작일 - endDate // 보고 종료일 - ); - - EsgInputValue saved = inputValueRepository.save(inputValue); -// savedDtos.add(EsgInputValueDto.from(saved)); - - // DB에 저장 -// inputValueRepository.save(inputValue); - } -// return saveDtos; - } -} diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java index 0dbff51..20ef193 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java @@ -17,6 +17,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import dev.gyeoul.esginsightboard.dto.UserUpdateRequest; import java.util.Optional; @@ -68,7 +69,7 @@ public UserDto signup(SignupRequest request) { * @return 찾거나 생성된 회사 엔티티 */ private Company findOrCreateCompany(SignupRequest request) { - // 회사 코드로 회사 정보 조회 + // 회사 코드로 회사 정보 조회12 Optional existingCompany = companyRepository.findByBusinessNumber(request.getCompanyCode()); // 존재하면 기존 회사 정보 반환 @@ -197,4 +198,25 @@ public Optional getUserByEmail(String email) { return userRepository.findByEmail(email) .map(UserDto::fromEntity); } + + // 사용자 데이터 업데이트 + @Transactional + public void updateUser(Long userId, UserUpdateRequest request) { + // 1. 사용자 ID로 기존 사용자 조회 (없으면 예외 발생) + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("User not found with id: " + userId)); + + // 2. 필드 수정 + user.setName(request.getName()); + user.setEmail(request.getEmail()); + user.setPhoneNumber(request.getPhoneNumber()); + + // 3. 비밀번호가 전달된 경우에만 수정 (공란이면 무시) + if (request.getPassword() != null && !request.getPassword().isBlank()) { + String encoderPassword = passwordEncoder.encode(request.getPassword()); + user.setPassword(encoderPassword); + } +// // 저장 (JPA 엔티티 변경 감지 dirty checking) +// return UserDto.toEntity(user); + } } \ No newline at end of file From 1807851fb5bbbb324bfa279e508fd1c71e5bb3dd Mon Sep 17 00:00:00 2001 From: ji-young Date: Sat, 5 Apr 2025 18:02:29 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=ED=9A=8C=EC=82=AC=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=ED=9B=84=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserController.java | 31 ++++++++++++++++++- .../dto/CompanyUpdateRequest.java | 17 ++++++++++ .../esginsightboard/service/UserService.java | 20 +++++++++--- 3 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 src/main/java/dev/gyeoul/esginsightboard/dto/CompanyUpdateRequest.java diff --git a/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java b/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java index 5eef7e1..22cdd88 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java +++ b/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java @@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import java.util.Date; @@ -194,7 +195,13 @@ public ResponseEntity> tokenTest(HttpServletRequest request) return ResponseEntity.ok(response); } - // 마이페이지 회원정보 저장 API + /** + * 마이페이지 회원정보 저장 API + * + * @param request 사용자가 보낸 회원정보 수정 요청 (이름, 이메일, 비밀번호, 전화번호) + * @param req HTTP 요청 객체 (JWT 토큰 검증 결과 포함) + * @return 수정 성공 시 요청 내용을 그대로 반환 (HTTP 200), 인증 실패 시 401 반환 + */ @PutMapping("/update") @Operation( summary = "사용자 정보 수정", @@ -218,6 +225,28 @@ public ResponseEntity updateUser( return ResponseEntity.ok(request); } + // 회사 정보 수정 + @PutMapping("/update-company") + @Operation( + summary = "회사 정보 수정", + description = "마이페이지에서 회사 정보 수정" + ) + @SecurityRequirement(name = "bearerAuth") + public ResponseEntity updateCompany( + @RequestBody CompanyUpdateRequest request, + HttpServletRequest req + ) { + UserDto currentUser = (UserDto) req.getAttribute("user"); + + if(currentUser == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + userService.updateCompany(currentUser.getCompanyId(), request); + return ResponseEntity.ok(request); + } + + /** * 사용자 정보에서 필요한 정보만 추출하는 메서드 */ diff --git a/src/main/java/dev/gyeoul/esginsightboard/dto/CompanyUpdateRequest.java b/src/main/java/dev/gyeoul/esginsightboard/dto/CompanyUpdateRequest.java new file mode 100644 index 0000000..2b5def2 --- /dev/null +++ b/src/main/java/dev/gyeoul/esginsightboard/dto/CompanyUpdateRequest.java @@ -0,0 +1,17 @@ +package dev.gyeoul.esginsightboard.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CompanyUpdateRequest { + private String companyName; + private String ceoName; + private String companyCode; + private String companyPhoneNumber; +} diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java index 20ef193..ff6c0d8 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java @@ -1,9 +1,6 @@ package dev.gyeoul.esginsightboard.service; -import dev.gyeoul.esginsightboard.dto.LoginRequest; -import dev.gyeoul.esginsightboard.dto.LoginResponse; -import dev.gyeoul.esginsightboard.dto.SignupRequest; -import dev.gyeoul.esginsightboard.dto.UserDto; +import dev.gyeoul.esginsightboard.dto.*; import dev.gyeoul.esginsightboard.entity.Company; import dev.gyeoul.esginsightboard.entity.User; import dev.gyeoul.esginsightboard.exception.UserAlreadyExistsException; @@ -17,7 +14,6 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import dev.gyeoul.esginsightboard.dto.UserUpdateRequest; import java.util.Optional; @@ -219,4 +215,18 @@ public void updateUser(Long userId, UserUpdateRequest request) { // // 저장 (JPA 엔티티 변경 감지 dirty checking) // return UserDto.toEntity(user); } + + // 회사 데이터 업데이트 + @Transactional + public void updateCompany(Long userId, CompanyUpdateRequest request) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("User not found with id: " + userId)); + + user.setCompanyName(request.getCompanyName()); + user.setCeoName(request.getCeoName()); + user.setCompanyCode(request.getCompanyCode()); + user.setCompanyPhoneNumber(request.getCompanyPhoneNumber()); + + userRepository.save(user); + } } \ No newline at end of file From c1ce8a0cf4c0facc9381275ca87a35a0b820d7fb Mon Sep 17 00:00:00 2001 From: Gyeoul Date: Sun, 6 Apr 2025 00:19:02 +0900 Subject: [PATCH 3/7] fix: Update User Entity --- .../config/UserDataInitializer.java | 16 +- .../gyeoul/esginsightboard/dto/UserDto.java | 32 +-- .../esginsightboard/entity/Company.java | 210 ++---------------- .../gyeoul/esginsightboard/entity/User.java | 29 +-- .../repository/CompanyRepository.java | 38 +--- .../service/CsvImportService.java | 2 +- .../esginsightboard/service/UserService.java | 18 +- 7 files changed, 61 insertions(+), 284 deletions(-) diff --git a/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java b/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java index e56ff8e..494cdba 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java +++ b/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java @@ -1,5 +1,6 @@ package dev.gyeoul.esginsightboard.config; +import dev.gyeoul.esginsightboard.entity.Company; import dev.gyeoul.esginsightboard.entity.User; import dev.gyeoul.esginsightboard.repository.UserRepository; import dev.gyeoul.esginsightboard.util.JwtTokenUtil; @@ -24,14 +25,16 @@ public CommandLineRunner initUsers() { return args -> { // 테스트 계정이 없을 경우에만 생성 if (!userRepository.existsByEmail("admin@example.com")) { + Company company = Company.builder() + .name("ESG 인사이트") + .companyCode("ESG") + .companyPhoneNumber("010-1234-5678") + .build(); User admin = User.builder() .email("admin@example.com") .password(passwordEncoder.encode("admin123")) .name("관리자") - .department("경영지원팀") - .position("ESG 담당자") - .companyName("ESG 인사이트") - .phoneNumber("010-1234-5678") + .company(company) .accountNonExpired(true) .accountNonLocked(true) .credentialsNonExpired(true) @@ -44,10 +47,7 @@ public CommandLineRunner initUsers() { .email("user@example.com") .password(passwordEncoder.encode("user123")) .name("사용자") - .department("ESG팀") - .position("팀원") - .companyName("ESG 인사이트") - .phoneNumber("010-8765-4321") + .company(company) .accountNonExpired(true) .accountNonLocked(true) .credentialsNonExpired(true) diff --git a/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java b/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java index 83ba20d..e17f5b3 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java +++ b/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java @@ -1,5 +1,6 @@ package dev.gyeoul.esginsightboard.dto; +import dev.gyeoul.esginsightboard.entity.Company; import dev.gyeoul.esginsightboard.entity.User; import lombok.AllArgsConstructor; import lombok.Builder; @@ -26,7 +27,7 @@ public class UserDto { private Long companyId; private LocalDateTime createdAt; private LocalDateTime updatedAt; - + /** * User 엔티티를 UserDto로 변환합니다. */ @@ -34,40 +35,39 @@ public static UserDto fromEntity(User user) { if (user == null) { return null; } - + return UserDto.builder() .id(user.getId()) .email(user.getEmail()) .name(user.getName()) - .department(user.getDepartment()) - .position(user.getPosition()) - .companyName(user.getCompanyName()) - .ceoName(user.getCeoName()) - .companyCode(user.getCompanyCode()) - .companyPhoneNumber(user.getCompanyPhoneNumber()) + .companyName(user.getCompany().getCompanyName()) + .ceoName(user.getCompany().getCeoName()) + .companyCode(user.getCompany().getCompanyCode()) + .companyPhoneNumber(user.getCompany().getCompanyPhoneNumber()) .phoneNumber(user.getPhoneNumber()) .companyId(user.getCompany() != null ? user.getCompany().getId() : null) .createdAt(user.getCreatedAt()) .updatedAt(user.getUpdatedAt()) .build(); } - + /** * UserDto를 User 엔티티로 변환합니다. * 비밀번호 필드는 포함되지 않으므로 새로운 사용자 생성에는 사용할 수 없습니다. */ public User toEntity() { + Company company = Company.builder() + .companyName(this.companyName) + .ceoName(this.ceoName) + .companyCode(this.companyCode) + .companyPhoneNumber(this.companyPhoneNumber).build(); + return User.builder() .id(this.id) .email(this.email) .name(this.name) - .department(this.department) - .position(this.position) - .companyName(this.companyName) - .ceoName(this.ceoName) - .companyCode(this.companyCode) - .companyPhoneNumber(this.companyPhoneNumber) .phoneNumber(this.phoneNumber) + .company(company) .build(); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java b/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java index 26ab5c3..fba068c 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java +++ b/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java @@ -4,8 +4,6 @@ import lombok.*; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; /** @@ -27,8 +25,8 @@ @Entity @Table(name = "companies") @Getter +@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor @Builder public class Company { @@ -50,87 +48,21 @@ public class Company { */ @Column(nullable = false) private String name; - - /** - * 사업자등록번호 - *

- * 회사의 공식 사업자등록번호입니다. 고유한 값이어야 합니다. - * 형식: 000-00-00000 - *

- */ - @Column(unique = true) - private String businessNumber; - - /** - * 업종 - *

- * 회사의 주요 사업 영역 또는 업종을 나타냅니다. - * 예: "제조업", "서비스업", "금융업" 등 - *

- */ - @Column - private String industry; - - /** - * 산업 섹터 - *

- * 회사가 속한 산업 섹터를 나타냅니다. - * 예: "IT", "에너지", "헬스케어", "금융" 등 - *

- */ + + @Column - private String sector; - - /** - * 회사 설명 - *

- * 회사에 대한 간략한 소개 또는 설명입니다. - * 최대 1000자까지 저장할 수 있습니다. - *

- */ - @Column(length = 1000) - private String description; - - /** - * 웹사이트 URL - *

- * 회사의 공식 웹사이트 URL입니다. - * 예: "https://www.example.com" - *

- */ + private String companyName; // 회사명 + @Column - private String website; - - /** - * 직원 수 - *

- * 회사의 전체 직원 수를 나타냅니다. - *

- */ + private String ceoName; // 대표자명 + @Column - private Integer employeeCount; - - /** - * 연간 매출액 - *

- * 회사의 연간 매출액을 백만원 단위로 - 저장합니다. - * 예: 1000000은 10억원을 의미 - *

- */ + private String companyCode; // 회사 코드 + @Column - private Long annualRevenue; - - /** - * 이 회사와 연결된 GRI 데이터 항목 목록 (양방향 관계) - *

- * 회사에 속한 모든 GRI 데이터 항목을 조회할 수 있습니다. - * mappedBy 속성은 GriDataItem 엔티티의 company 필드가 이 관계의 주인임을 나타냅니다. - *

- */ - @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval = true) - private List griDataItems = new ArrayList<>(); - + private String companyPhoneNumber; // 회사 전화번호 + + /** * 엔티티 생성 일시 *

@@ -150,37 +82,19 @@ public class Company { */ @Column(nullable = false) private LocalDateTime updatedAt; - - /** - * Company 엔티티 생성을 위한 빌더 패턴 - *

- * 사용 예시: - *

-     * Company company = Company.builder()
-     *     .name("한국ESG주식회사")
-     *     .businessNumber("123-45-67890")
-     *     .industry("제조업")
-     *     .sector("에너지")
-     *     .employeeCount(1000)
-     *     .annualRevenue(50000L) // 5억원
-     *     .build();
-     * 
- *

- */ + @Builder - public Company(Long id, String name, String businessNumber, String industry, String sector, - String description, String website, Integer employeeCount, Long annualRevenue) { + public Company(Long id, String name, String companyName, String ceoName, String companyCode, String companyPhoneNumber, LocalDateTime createdAt, LocalDateTime updatedAt) { this.id = id; this.name = name; - this.businessNumber = businessNumber; - this.industry = industry; - this.sector = sector; - this.description = description; - this.website = website; - this.employeeCount = employeeCount; - this.annualRevenue = annualRevenue; + this.companyName = companyName; + this.ceoName = ceoName; + this.companyCode = companyCode; + this.companyPhoneNumber = companyPhoneNumber; + this.createdAt = createdAt; + this.updatedAt = updatedAt; } - + /** * 엔티티 생성 시 호출되어 생성 시간과 수정 시간을 현재 시간으로 설정 *

@@ -205,70 +119,7 @@ protected void onCreate() { protected void onUpdate() { this.updatedAt = LocalDateTime.now(); } - - /** - * 회사 정보 업데이트 - *

- * 회사의 기본 정보를 업데이트합니다. ID와 생성일은 변경되지 않습니다. - *

- * - * @param name 새 회사명 (null이면 변경 안 함) - * @param industry 새 업종 (null이면 변경 안 함) - * @param sector 새 섹터 (null이면 변경 안 함) - * @param description 새 설명 (null이면 변경 안 함) - * @param website 새 웹사이트 (null이면 변경 안 함) - * @param employeeCount 새 직원 수 (null이면 변경 안 함) - * @param annualRevenue 새 연간 매출액 (null이면 변경 안 함) - */ - public void update(String name, String industry, String sector, String description, - String website, Integer employeeCount, Long annualRevenue) { - if (name != null) this.name = name; - if (industry != null) this.industry = industry; - if (sector != null) this.sector = sector; - if (description != null) this.description = description; - if (website != null) this.website = website; - if (employeeCount != null) this.employeeCount = employeeCount; - if (annualRevenue != null) this.annualRevenue = annualRevenue; - } - - /** - * 사업자등록번호 업데이트 - *

- * 사업자등록번호는 중요한 식별 정보이므로 별도의 메서드로 관리합니다. - *

- * - * @param businessNumber 새 사업자등록번호 - */ - public void updateBusinessNumber(String businessNumber) { - this.businessNumber = businessNumber; - } - - /** - * GRI 데이터 항목 추가 - *

- * 이 회사에 GRI 데이터 항목을 추가하고 양방향 관계를 설정합니다. - *

- * - * @param griDataItem 추가할 GRI 데이터 항목 - */ - public void addGriDataItem(GriDataItem griDataItem) { - this.griDataItems.add(griDataItem); - griDataItem.setCompany(this); - } - - /** - * GRI 데이터 항목 제거 - *

- * 이 회사에서 GRI 데이터 항목을 제거하고 양방향 관계를 해제합니다. - *

- * - * @param griDataItem 제거할 GRI 데이터 항목 - */ - public void removeGriDataItem(GriDataItem griDataItem) { - this.griDataItems.remove(griDataItem); - griDataItem.setCompany(null); - } - + /** * 두 회사 객체가 동일한지 비교 * @@ -292,20 +143,5 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(id); } - - /** - * 회사 정보를 문자열로 표현 - * - * @return 회사 정보 문자열 - */ - @Override - public String toString() { - return "Company{" + - "id=" + id + - ", name='" + name + '\'' + - ", businessNumber='" + businessNumber + '\'' + - ", industry='" + industry + '\'' + - ", sector='" + sector + '\'' + - '}'; - } + } \ No newline at end of file diff --git a/src/main/java/dev/gyeoul/esginsightboard/entity/User.java b/src/main/java/dev/gyeoul/esginsightboard/entity/User.java index cda5c76..b4b119c 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/entity/User.java +++ b/src/main/java/dev/gyeoul/esginsightboard/entity/User.java @@ -33,25 +33,6 @@ public class User implements UserDetails { @Column(nullable = false) private String name; - - @Column - private String department; // 부서 - - @Column - private String position; // 직급/직책 - - @Column - private String companyName; // 회사명 - - @Column - private String ceoName; // 대표자명 - - @Column - private String companyCode; // 회사 코드 - - @Column - private String companyPhoneNumber; // 회사 전화번호 - @Column private String phoneNumber; // 개인 전화번호 @@ -85,21 +66,13 @@ public class User implements UserDetails { * User 엔티티 생성을 위한 빌더 패턴 구현 */ @Builder - public User(Long id, String email, String password, String name, String department, - String position, String companyName, String ceoName, String companyCode, - String companyPhoneNumber, String phoneNumber, Company company, + public User(Long id, String email, String password, String name, String phoneNumber, Company company, boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled) { this.id = id; this.email = email; this.password = password; this.name = name; - this.department = department; - this.position = position; - this.companyName = companyName; - this.ceoName = ceoName; - this.companyCode = companyCode; - this.companyPhoneNumber = companyPhoneNumber; this.phoneNumber = phoneNumber; this.company = company; this.accountNonExpired = accountNonExpired; diff --git a/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java b/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java index bd3b6bf..4b927d1 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java +++ b/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java @@ -19,7 +19,7 @@ public interface CompanyRepository extends JpaRepository { * @param name 회사명 * @return 회사명에 해당하는 회사 정보 */ - Optional findByName(String name); + Optional findByCompanyName(String name); /** * 회사명에 포함된 문자열로 회사를 검색 @@ -28,38 +28,8 @@ public interface CompanyRepository extends JpaRepository { * @return 검색 조건에 맞는 회사 목록 */ List findByNameContaining(String name); - - /** - * 사업자등록번호로 회사를 조회 - * - * @param businessNumber 사업자등록번호 - * @return 사업자등록번호에 해당하는 회사 정보 - */ - Optional findByBusinessNumber(String businessNumber); - - /** - * 업종으로 회사 목록을 조회 - * - * @param industry 업종명 - * @return 업종에 해당하는 회사 목록 - */ - List findByIndustry(String industry); - - /** - * 섹터로 회사 목록을 조회 - * - * @param sector 섹터명 - * @return 섹터에 해당하는 회사 목록 - */ - List findBySector(String sector); - - /** - * 사업자등록번호 존재 여부 확인 - * - * @param businessNumber 사업자등록번호 - * @return 존재 여부 - */ - boolean existsByBusinessNumber(String businessNumber); - Optional findByid(Long id); + + Optional findByCompanyCode(String code); + } \ No newline at end of file diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java b/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java index 98cc615..76f5c5c 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java @@ -132,7 +132,7 @@ public CsvUploadResponse processCsvFile(CsvUploadRequest request, UserDto user) } // 회사 존재 여부 확인 - Company company = companyRepository.findByName(user.getCompanyName()) + Company company = companyRepository.findByCompanyName(user.getCompanyName()) .orElseThrow(() -> new ResourceNotFoundException( "회사명 '" + user.getCompanyName() + "'에 해당하는 회사를 찾을 수 없습니다.")); diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java index ff6c0d8..42767d9 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java @@ -66,7 +66,7 @@ public UserDto signup(SignupRequest request) { */ private Company findOrCreateCompany(SignupRequest request) { // 회사 코드로 회사 정보 조회12 - Optional existingCompany = companyRepository.findByBusinessNumber(request.getCompanyCode()); + Optional existingCompany = companyRepository.findByCompanyCode(request.getCompanyCode()); // 존재하면 기존 회사 정보 반환 if (existingCompany.isPresent()) { @@ -76,7 +76,7 @@ private Company findOrCreateCompany(SignupRequest request) { // 존재하지 않으면 새로운 회사 정보 생성 및 저장 Company newCompany = Company.builder() .name(request.getCompanyName()) - .businessNumber(request.getCompanyCode()) + .companyCode(request.getCompanyCode()) .build(); return companyRepository.save(newCompany); @@ -106,10 +106,6 @@ private User createAndSaveUser(SignupRequest request, Company company) { .email(request.getEmail()) .password(passwordEncoder.encode(request.getPassword())) .name(request.getName()) - .companyName(request.getCompanyName()) - .ceoName(request.getCeoName()) - .companyCode(request.getCompanyCode()) - .companyPhoneNumber(request.getCompanyPhoneNumber()) .phoneNumber(request.getPhoneNumber()) .company(company) // 회사 엔티티 연결 .build(); @@ -222,10 +218,12 @@ public void updateCompany(Long userId, CompanyUpdateRequest request) { User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("User not found with id: " + userId)); - user.setCompanyName(request.getCompanyName()); - user.setCeoName(request.getCeoName()); - user.setCompanyCode(request.getCompanyCode()); - user.setCompanyPhoneNumber(request.getCompanyPhoneNumber()); + Company company = user.getCompany(); + + company.setCompanyName(request.getCompanyName()); + company.setCeoName(request.getCeoName()); + company.setCompanyCode(request.getCompanyCode()); + company.setCompanyPhoneNumber(request.getCompanyPhoneNumber()); userRepository.save(user); } From 80fadcce7eabbb5bd1adbb93731bf28c4a61886c Mon Sep 17 00:00:00 2001 From: Gyeoul Date: Sun, 6 Apr 2025 00:29:16 +0900 Subject: [PATCH 4/7] fix: Transient Instance Error Fix up --- .../esginsightboard/dto/GriDataItemDto.java | 6 ---- .../esginsightboard/entity/GriDataItem.java | 30 +++---------------- .../service/CsvImportService.java | 3 +- 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/src/main/java/dev/gyeoul/esginsightboard/dto/GriDataItemDto.java b/src/main/java/dev/gyeoul/esginsightboard/dto/GriDataItemDto.java index edb4476..080824d 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/dto/GriDataItemDto.java +++ b/src/main/java/dev/gyeoul/esginsightboard/dto/GriDataItemDto.java @@ -244,12 +244,6 @@ public static GriDataItemDto fromEntity(GriDataItem entity) { .createdAt(entity.getCreatedAt()) .updatedAt(entity.getUpdatedAt()); - // 회사 정보 설정 (null 체크) - if (entity.getCompany() != null) { - builder.companyId(entity.getCompany().getId()) - .companyName(entity.getCompany().getName()); - } - return builder.build(); } diff --git a/src/main/java/dev/gyeoul/esginsightboard/entity/GriDataItem.java b/src/main/java/dev/gyeoul/esginsightboard/entity/GriDataItem.java index 2215cc9..b3ddbfc 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/entity/GriDataItem.java +++ b/src/main/java/dev/gyeoul/esginsightboard/entity/GriDataItem.java @@ -201,17 +201,7 @@ public static VerificationStatus fromDisplayName(String displayName) { @Column(nullable = false) private String category; - /** - * 이 데이터가 속한 회사 (다대일 관계) - *

- * 하나의 회사는 여러 GRI 데이터 항목을 가질 수 있습니다. - * 이 관계는 지연 로딩(LAZY)으로 설정되어 있어, 필요할 때만 회사 정보를 불러옵니다. - *

- */ - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "company_id") - private Company company; - + /** * 엔티티 생성 일시 *

@@ -252,8 +242,8 @@ public static VerificationStatus fromDisplayName(String displayName) { public GriDataItem(Long id, String standardCode, String disclosureCode, String disclosureTitle, String disclosureValue, String description, Double numericValue, String unit, LocalDate reportingPeriodStart, LocalDate reportingPeriodEnd, - String verificationStatus, String verificationProvider, String category, - Company company) { + String verificationStatus, String verificationProvider, String category + ) { this.id = id; this.standardCode = standardCode; this.disclosureCode = disclosureCode; @@ -267,7 +257,6 @@ public GriDataItem(Long id, String standardCode, String disclosureCode, String d this.verificationStatus = verificationStatus != null ? verificationStatus : VerificationStatus.UNVERIFIED.getDisplayName(); this.verificationProvider = verificationProvider; this.category = category; - this.company = company; } /** @@ -295,18 +284,7 @@ protected void onUpdate() { this.updatedAt = LocalDateTime.now(); } - /** - * 회사 설정 메서드 - *

- * 이 메서드는 GRI 데이터 항목을 특정 회사와 연결할 때 사용합니다. - *

- * - * @param company 연결할 회사 엔티티 (null일 수 있음) - */ - public void setCompany(Company company) { - this.company = company; - } - + /** * 검증 상태 설정 메서드 *

diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java b/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java index 76f5c5c..ae9f673 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java @@ -226,8 +226,7 @@ private CsvUploadResponse processGriData(List> csvData, Long try { Map row = csvData.get(i); GriDataItem dataItem = convertRowToGriDataItem(row); - dataItem.setCompany(company); - + // 데이터베이스에 저장 griDataItemRepository.save(dataItem); processedCount++; From f00f025c750aa08679a218a509f2f7cf13ae134e Mon Sep 17 00:00:00 2001 From: Gyeoul Date: Sun, 6 Apr 2025 00:41:49 +0900 Subject: [PATCH 5/7] fix: Transient Instance Error Fix up --- .../gyeoul/esginsightboard/config/UserDataInitializer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java b/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java index 494cdba..e41d182 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java +++ b/src/main/java/dev/gyeoul/esginsightboard/config/UserDataInitializer.java @@ -3,6 +3,7 @@ import dev.gyeoul.esginsightboard.entity.Company; import dev.gyeoul.esginsightboard.entity.User; import dev.gyeoul.esginsightboard.repository.UserRepository; +import dev.gyeoul.esginsightboard.repository.CompanyRepository; import dev.gyeoul.esginsightboard.util.JwtTokenUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -17,6 +18,7 @@ public class UserDataInitializer { private final UserRepository userRepository; + private final CompanyRepository companyRepository; private final JwtTokenUtil jwtTokenUtil; private final PasswordEncoder passwordEncoder; @@ -30,6 +32,9 @@ public CommandLineRunner initUsers() { .companyCode("ESG") .companyPhoneNumber("010-1234-5678") .build(); + + company = companyRepository.save(company); + User admin = User.builder() .email("admin@example.com") .password(passwordEncoder.encode("admin123")) From c3fb06b827535f5cd1686d15c80e24170b523d1a Mon Sep 17 00:00:00 2001 From: Gyeoul Date: Sun, 6 Apr 2025 00:51:49 +0900 Subject: [PATCH 6/7] fix: Update Company Entity Field --- src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java | 4 ++-- .../java/dev/gyeoul/esginsightboard/entity/Company.java | 7 +------ .../esginsightboard/repository/CompanyRepository.java | 2 +- .../gyeoul/esginsightboard/service/CsvImportService.java | 2 +- .../dev/gyeoul/esginsightboard/service/UserService.java | 2 +- 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java b/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java index e17f5b3..3564d1a 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java +++ b/src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java @@ -40,7 +40,7 @@ public static UserDto fromEntity(User user) { .id(user.getId()) .email(user.getEmail()) .name(user.getName()) - .companyName(user.getCompany().getCompanyName()) + .companyName(user.getCompany().getName()) .ceoName(user.getCompany().getCeoName()) .companyCode(user.getCompany().getCompanyCode()) .companyPhoneNumber(user.getCompany().getCompanyPhoneNumber()) @@ -57,7 +57,7 @@ public static UserDto fromEntity(User user) { */ public User toEntity() { Company company = Company.builder() - .companyName(this.companyName) + .name(this.companyName) .ceoName(this.ceoName) .companyCode(this.companyCode) .companyPhoneNumber(this.companyPhoneNumber).build(); diff --git a/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java b/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java index fba068c..d3effea 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java +++ b/src/main/java/dev/gyeoul/esginsightboard/entity/Company.java @@ -49,10 +49,6 @@ public class Company { @Column(nullable = false) private String name; - - @Column - private String companyName; // 회사명 - @Column private String ceoName; // 대표자명 @@ -84,10 +80,9 @@ public class Company { private LocalDateTime updatedAt; @Builder - public Company(Long id, String name, String companyName, String ceoName, String companyCode, String companyPhoneNumber, LocalDateTime createdAt, LocalDateTime updatedAt) { + public Company(Long id, String name, String ceoName, String companyCode, String companyPhoneNumber, LocalDateTime createdAt, LocalDateTime updatedAt) { this.id = id; this.name = name; - this.companyName = companyName; this.ceoName = ceoName; this.companyCode = companyCode; this.companyPhoneNumber = companyPhoneNumber; diff --git a/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java b/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java index 4b927d1..814e083 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java +++ b/src/main/java/dev/gyeoul/esginsightboard/repository/CompanyRepository.java @@ -19,7 +19,7 @@ public interface CompanyRepository extends JpaRepository { * @param name 회사명 * @return 회사명에 해당하는 회사 정보 */ - Optional findByCompanyName(String name); + Optional findByName(String name); /** * 회사명에 포함된 문자열로 회사를 검색 diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java b/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java index ae9f673..ac3cfc2 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/CsvImportService.java @@ -132,7 +132,7 @@ public CsvUploadResponse processCsvFile(CsvUploadRequest request, UserDto user) } // 회사 존재 여부 확인 - Company company = companyRepository.findByCompanyName(user.getCompanyName()) + Company company = companyRepository.findByName(user.getCompanyName()) .orElseThrow(() -> new ResourceNotFoundException( "회사명 '" + user.getCompanyName() + "'에 해당하는 회사를 찾을 수 없습니다.")); diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java index 42767d9..ea17a13 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java @@ -220,7 +220,7 @@ public void updateCompany(Long userId, CompanyUpdateRequest request) { Company company = user.getCompany(); - company.setCompanyName(request.getCompanyName()); + company.setName(request.getCompanyName()); company.setCeoName(request.getCeoName()); company.setCompanyCode(request.getCompanyCode()); company.setCompanyPhoneNumber(request.getCompanyPhoneNumber()); From 9b8c45eb1856de7263ba25a1849ee4d4708cb046 Mon Sep 17 00:00:00 2001 From: ji-young Date: Sun, 6 Apr 2025 02:24:06 +0900 Subject: [PATCH 7/7] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EB=B0=8F=20?= =?UTF-8?q?=ED=9A=8C=EC=82=AC=20=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=A1=9C=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../esginsightboard/controller/UserController.java | 2 +- .../gyeoul/esginsightboard/service/UserService.java | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java b/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java index 22cdd88..dc7f85d 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java +++ b/src/main/java/dev/gyeoul/esginsightboard/controller/UserController.java @@ -15,9 +15,9 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import java.util.Date; diff --git a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java index ea17a13..92158b9 100644 --- a/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java +++ b/src/main/java/dev/gyeoul/esginsightboard/service/UserService.java @@ -214,17 +214,15 @@ public void updateUser(Long userId, UserUpdateRequest request) { // 회사 데이터 업데이트 @Transactional - public void updateCompany(Long userId, CompanyUpdateRequest request) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("User not found with id: " + userId)); - - Company company = user.getCompany(); + public void updateCompany(Long companyId, CompanyUpdateRequest request) { + Company company = companyRepository.findById(companyId) + .orElseThrow(() -> new IllegalArgumentException("User not found with id: " + companyId)); company.setName(request.getCompanyName()); company.setCeoName(request.getCeoName()); company.setCompanyCode(request.getCompanyCode()); company.setCompanyPhoneNumber(request.getCompanyPhoneNumber()); - userRepository.save(user); + companyRepository.save(company); } } \ No newline at end of file