-
Notifications
You must be signed in to change notification settings - Fork 5
feat[law-word]:법령 검색 기능 추가 #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| drop table ho; | ||
| drop table hang; | ||
| drop table jo; | ||
| drop table jang; | ||
| drop table law; | ||
| drop table precedent; | ||
|
|
||
| ALTER TABLE ho AUTO_INCREMENT = 1; | ||
| ALTER TABLE hang AUTO_INCREMENT = 1; | ||
| ALTER TABLE jo AUTO_INCREMENT = 1; | ||
| ALTER TABLE jang AUTO_INCREMENT = 1; | ||
| ALTER TABLE law AUTO_INCREMENT = 1; | ||
| ALTER TABLE precedent AUTO_INCREMENT = 1; |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,30 +5,22 @@ | |
| import com.ai.lawyer.domain.law.entity.Law; | ||
| import com.ai.lawyer.domain.law.service.LawService; | ||
| import com.ai.lawyer.global.dto.PageResponseDto; | ||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/law") | ||
| @RequestMapping("/api/law") | ||
| public class LawController { | ||
|
|
||
| private final LawService lawService; | ||
|
|
||
| // 법령 리스트 출력 | ||
| @GetMapping(value = "/list") | ||
| public ResponseEntity<?> list( | ||
| @RequestParam String query, | ||
| @RequestParam int page | ||
| ) throws Exception { | ||
| String lawList = lawService.getLawList(query, page); | ||
| return ResponseEntity.ok().body(lawList); | ||
| } | ||
|
|
||
|
|
||
| @GetMapping(value = "/list/save") | ||
| @Operation(summary = "키워드 관련 법령 데이터 저장(벡엔드 전용 API)", description = "벡엔드 데이터 저장용 API입니다") | ||
| public ResponseEntity<?> getStatisticsCard( | ||
| @RequestParam String query, | ||
| @RequestParam int page | ||
|
|
@@ -44,15 +36,8 @@ public ResponseEntity<?> getStatisticsCard( | |
| return ResponseEntity.ok().body("Success"); | ||
| } | ||
|
|
||
| @GetMapping("/{id}") | ||
| public ResponseEntity<Law> getFullLaw(@PathVariable Long id) { | ||
| Law law = lawService.getLawWithAllChildren(id); | ||
|
|
||
| return ResponseEntity.ok(law); | ||
| } | ||
|
|
||
|
|
||
| @PostMapping("/search") | ||
| @Operation(summary = "볍령 목록 검색 기능", description = "조건에 맞는 법령 목록을 가져옵니다") | ||
| public ResponseEntity<PageResponseDto> searchLaws(@RequestBody LawSearchRequestDto searchRequest) { | ||
| Page<LawsDto> laws = lawService.searchLaws(searchRequest); | ||
| PageResponseDto response = PageResponseDto.builder() | ||
|
|
@@ -64,4 +49,13 @@ public ResponseEntity<PageResponseDto> searchLaws(@RequestBody LawSearchRequestD | |
| .build(); | ||
| return ResponseEntity.ok(response); | ||
| } | ||
|
|
||
| @GetMapping("/{id}") | ||
| @Operation(summary = "볍령 상세 조회 기능", description = "법령 상세 데이터를 조회합니다 \n" + | ||
|
||
| "예시: /api/law/1") | ||
| public ResponseEntity<Law> getFullLaw(@PathVariable Long id) { | ||
| Law law = lawService.getLawWithAllChildren(id); | ||
|
|
||
| return ResponseEntity.ok(law); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||
| package com.ai.lawyer.domain.lawWord.controller; | ||||
|
|
||||
| import com.ai.lawyer.domain.lawWord.service.LawWordService; | ||||
| import com.ai.lawyer.domain.precedent.entity.Precedent; | ||||
|
||||
| import com.ai.lawyer.domain.precedent.entity.Precedent; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.ai.lawyer.domain.lawWord.entity; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| import jakarta.persistence.*; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.Builder; | ||
| import lombok.Data; | ||
| import lombok.NoArgsConstructor; | ||
|
|
||
| @Entity | ||
| @Data | ||
| @Builder | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| public class LawWord { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| @JsonIgnore | ||
| private Long id; | ||
|
|
||
| private String word; // 법률 용어 | ||
|
|
||
| @Lob | ||
| @Column(columnDefinition = "LONGTEXT") | ||
| private String definition; // 정의 | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.ai.lawyer.domain.lawWord.repository; | ||
|
|
||
| import com.ai.lawyer.domain.lawWord.entity.LawWord; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.stereotype.Repository; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| @Repository | ||
| public interface LawWordRepository extends JpaRepository<LawWord, Long> { | ||
| Optional<LawWord> findByWord(String word); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package com.ai.lawyer.domain.lawWord.service; | ||
|
|
||
| import com.ai.lawyer.domain.lawWord.entity.LawWord; | ||
| import com.ai.lawyer.domain.lawWord.repository.LawWordRepository; | ||
| import com.fasterxml.jackson.core.JsonProcessingException; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import lombok.AllArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.web.client.RestTemplate; | ||
|
|
||
| @Service | ||
| @AllArgsConstructor | ||
| public class LawWordService { | ||
|
|
||
| private final LawWordRepository lawWordRepository; | ||
|
|
||
| private final RestTemplate restTemplate = new RestTemplate(); | ||
| private final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
|
||
| public String findDefinition(String word) { | ||
| // 1) DB 확인 | ||
| return lawWordRepository.findByWord(word) | ||
| .map(LawWord::getDefinition) | ||
| .orElseGet(() -> { | ||
| try { | ||
| String url = "https://www.law.go.kr/DRF/lawService.do?OC=noheechul" | ||
| + "&target=lstrm&type=JSON&query=" + word; | ||
| String json = restTemplate.getForObject(url, String.class); | ||
| JsonNode rootNode = objectMapper.readTree(json); | ||
| // 오류 응답 처리 | ||
| if (rootNode.has("Law")) { | ||
| return rootNode.get("Law").asText(); | ||
| } | ||
| JsonNode serviceNode = rootNode.path("LsTrmService"); | ||
| JsonNode defNode = serviceNode.path("법령용어정의"); | ||
| String definition; | ||
| if (defNode.isArray() && defNode.size() > 0) { | ||
| // definition = defNode.get(0).asText().split("\\.",2)[0].trim(); | ||
| definition = defNode.get(0).asText().trim(); | ||
| } else { | ||
| // definition = defNode.asText().split("\\.",2)[0].trim(); | ||
| definition = defNode.asText().trim(); | ||
| } | ||
| LawWord entity = LawWord.builder() | ||
| .word(word) | ||
| .definition(definition) | ||
| .build(); | ||
| lawWordRepository.save(entity); | ||
| return definition; | ||
| } catch (Exception e) { | ||
| throw new RuntimeException("Failed to fetch definition", e); | ||
| } | ||
| }); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,17 @@ | ||
| package com.ai.lawyer.domain.precedent.dto; | ||
|
|
||
| import io.swagger.v3.oas.annotations.media.Schema; | ||
| import lombok.Data; | ||
|
|
||
| @Data | ||
| public class PrecedentSearchRequestDto { | ||
|
|
||
| @Schema(description = "검색 키워드", example = "노동") | ||
| private String keyword; // 검색 키워드 | ||
|
|
||
| @Schema(description = "페이지 번호 (0부터 시작)", example = "0") | ||
| private int pageNumber; // 페이지 번호 | ||
|
|
||
| @Schema(description = "페이지 크기", example = "10") | ||
| private int pageSize; // 페이지 크기 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,9 +6,11 @@ | |
| import com.ai.lawyer.domain.precedent.repository.PrecedentRepository; | ||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import jakarta.persistence.EntityManager; | ||
| import lombok.AllArgsConstructor; | ||
| import org.springframework.data.domain.Page; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
| import org.springframework.util.StringUtils; | ||
| import org.springframework.web.client.RestTemplate; | ||
| import org.springframework.web.util.UriComponentsBuilder; | ||
|
|
@@ -29,6 +31,8 @@ public class PrecedentService { | |
| private final String BASE_URL = "http://www.law.go.kr/DRF"; | ||
| private final String OC = "noheechul"; // 실제 OC로 변경 필요 | ||
| private final ObjectMapper objectMapper = new ObjectMapper(); | ||
| private final EntityManager entityManager; | ||
|
|
||
|
|
||
|
|
||
| /** | ||
|
|
@@ -159,25 +163,30 @@ public List<Precedent> getPrecedentDetails(List<String> precedentIds) throws Exc | |
| * @param precedents 저장할 Precedent 객체 리스트 | ||
| * @return 저장된 Precedent 객체 리스트 | ||
| */ | ||
| @Transactional | ||
| public List<Precedent> savePrecedents(List<Precedent> precedents) { | ||
| List<Precedent> savedPrecedents = new ArrayList<>(); | ||
|
|
||
| for (Precedent precedent : precedents) { | ||
| try { | ||
| // 중복 확인 (판례일련번호 기준) | ||
| if (!precedentRepository.existsByPrecedentNumber(precedent.getPrecedentNumber())) { | ||
| Precedent saved = precedentRepository.save(precedent); | ||
| savedPrecedents.add(saved); | ||
| System.out.println("Saved precedent: " + precedent.getPrecedentNumber()); | ||
| } else { | ||
| System.out.println("Already exists: " + precedent.getPrecedentNumber()); | ||
| } | ||
| } catch (Exception e) { | ||
| System.err.println("Error saving precedent " + precedent.getPrecedentNumber() + ": " + e.getMessage()); | ||
| } | ||
| } | ||
| // List<Precedent> savedPrecedents = new ArrayList<>(); | ||
| // | ||
| // for (Precedent precedent : precedents) { | ||
| // try { | ||
| // // 중복 확인 (판례일련번호 기준) | ||
| // if (!precedentRepository.existsByPrecedentNumber(precedent.getPrecedentNumber())) { | ||
| // Precedent saved = precedentRepository.save(precedent); | ||
| // savedPrecedents.add(saved); | ||
| // System.out.println("Saved precedent: " + precedent.getPrecedentNumber()); | ||
| // } else { | ||
| // System.out.println("Already exists: " + precedent.getPrecedentNumber()); | ||
| // } | ||
| // } catch (Exception e) { | ||
| // System.err.println("Error saving precedent " + precedent.getPrecedentNumber() + ": " + e.getMessage()); | ||
| // } | ||
| // } | ||
|
|
||
| precedentRepository.saveAll(precedents); | ||
| precedentRepository.flush(); // 즉시 DB 반영 | ||
| entityManager.clear(); // 영속성 컨텍스트 정리 | ||
|
|
||
| return savedPrecedents; | ||
| return precedents; | ||
|
Comment on lines
+185
to
+189
|
||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are typos in the Korean text. '볍령' should be '법령' in both operation summaries.