Skip to content

Commit 9fa839b

Browse files
committed
add recipe import from FoodSafety API
1 parent 246382b commit 9fa839b

8 files changed

Lines changed: 412 additions & 6 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.webservice.algorithmchef.client;
2+
3+
import com.webservice.algorithmchef.dto.recipe.CookRcpResponse;
4+
import org.springframework.beans.factory.annotation.Value;
5+
import org.springframework.stereotype.Service;
6+
import org.springframework.web.client.RestTemplate;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import java.util.Optional;
11+
12+
@Service
13+
public class FoodSafetyApiClient {
14+
15+
private final RestTemplate restTemplate;
16+
17+
public FoodSafetyApiClient(RestTemplate restTemplate) {
18+
this.restTemplate = restTemplate;
19+
}
20+
21+
@Value("${foodsafety.cookrcp.base-url}")
22+
private String baseUrl;
23+
24+
@Value("${foodsafety.cookrcp.service-key}")
25+
private String serviceKey;
26+
27+
@Value("${foodsafety.cookrcp.svc-no}")
28+
private String svcNo;
29+
30+
public int getTotalCount() {
31+
String url = String.format("%s/%s/%s/json/1/1",
32+
baseUrl, serviceKey, svcNo);
33+
34+
CookRcpResponse res = restTemplate.getForObject(url, CookRcpResponse.class);
35+
36+
if (res == null || res.getCOOKRCP01() == null) return 0;
37+
38+
try {
39+
return Integer.parseInt(res.getCOOKRCP01().getTotalCount());
40+
} catch (Exception e) {
41+
return 0;
42+
}
43+
}
44+
45+
public List<CookRcpResponse.Item> fetchRange(int start, int end) {
46+
String url = String.format("%s/%s/%s/json/%d/%d",
47+
baseUrl, serviceKey, svcNo, start, end);
48+
49+
CookRcpResponse res = restTemplate.getForObject(url, CookRcpResponse.class);
50+
51+
return Optional.ofNullable(res)
52+
.map(CookRcpResponse::getCOOKRCP01)
53+
.map(CookRcpResponse.Body::getRow)
54+
.orElse(List.of());
55+
}
56+
57+
public List<CookRcpResponse.Item> fetchAll() {
58+
int total = getTotalCount();
59+
if (total <= 0) return List.of();
60+
61+
int pageSize = 200;
62+
List<CookRcpResponse.Item> all = new ArrayList<>(total);
63+
64+
for (int start = 1; start <= total; start += pageSize) {
65+
int end = Math.min(start + pageSize - 1, total);
66+
all.addAll(fetchRange(start, end));
67+
}
68+
69+
return all;
70+
}
71+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.webservice.algorithmchef.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.web.client.RestTemplate;
6+
7+
@Configuration
8+
public class RestTemplateConfig {
9+
10+
@Bean
11+
public RestTemplate restTemplate() {
12+
return new RestTemplate();
13+
}
14+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.webservice.algorithmchef.controller;
2+
3+
import com.webservice.algorithmchef.service.RecipeImportService;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.RequestMapping;
6+
import org.springframework.web.bind.annotation.RestController;
7+
8+
@RestController
9+
@RequestMapping("/admin")
10+
public class RecipeImportController {
11+
12+
private final RecipeImportService recipeImportService;
13+
14+
public RecipeImportController(RecipeImportService recipeImportService) {
15+
this.recipeImportService = recipeImportService;
16+
}
17+
18+
@GetMapping("/import/foodsafety")
19+
public String importFromFoodSafety() {
20+
recipeImportService.importAllFromFoodSafety();
21+
return "import started";
22+
}
23+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package com.webservice.algorithmchef.dto.recipe;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Objects;
9+
10+
@JsonIgnoreProperties(ignoreUnknown = true)
11+
public class CookRcpResponse {
12+
13+
@JsonProperty("COOKRCP01")
14+
private Body cookrcp01;
15+
16+
public Body getCOOKRCP01() {
17+
return cookrcp01;
18+
}
19+
20+
@JsonIgnoreProperties(ignoreUnknown = true)
21+
public static class Body {
22+
23+
@JsonProperty("total_count")
24+
private String totalCount;
25+
26+
@JsonProperty("row")
27+
private List<Item> row;
28+
29+
public String getTotalCount() {
30+
return totalCount;
31+
}
32+
33+
public List<Item> getRow() {
34+
// NPE 방지용
35+
return row == null ? List.of() : row;
36+
}
37+
}
38+
39+
@JsonIgnoreProperties(ignoreUnknown = true)
40+
public static class Item {
41+
42+
@JsonProperty("RCP_NM")
43+
private String name;
44+
45+
@JsonProperty("RCP_SEQ")
46+
private String recipeIdRaw;
47+
48+
49+
@JsonProperty("RCP_PARTS_DTLS")
50+
private String parts;
51+
52+
@JsonProperty("ATT_FILE_NO_MAIN")
53+
private String imageUrl;
54+
55+
@JsonProperty("INFO_ENG")
56+
private String infoEng;
57+
58+
@JsonProperty("HASH_TAG")
59+
private String hashTag;
60+
61+
@JsonProperty("RCP_WAY2")
62+
private String way;
63+
64+
@JsonProperty("RCP_PAT2")
65+
private String category;
66+
67+
@JsonProperty("MANUAL01") private String manual01;
68+
@JsonProperty("MANUAL02") private String manual02;
69+
@JsonProperty("MANUAL03") private String manual03;
70+
@JsonProperty("MANUAL04") private String manual04;
71+
@JsonProperty("MANUAL05") private String manual05;
72+
@JsonProperty("MANUAL06") private String manual06;
73+
@JsonProperty("MANUAL07") private String manual07;
74+
@JsonProperty("MANUAL08") private String manual08;
75+
@JsonProperty("MANUAL09") private String manual09;
76+
@JsonProperty("MANUAL10") private String manual10;
77+
@JsonProperty("MANUAL11") private String manual11;
78+
@JsonProperty("MANUAL12") private String manual12;
79+
@JsonProperty("MANUAL13") private String manual13;
80+
@JsonProperty("MANUAL14") private String manual14;
81+
@JsonProperty("MANUAL15") private String manual15;
82+
@JsonProperty("MANUAL16") private String manual16;
83+
@JsonProperty("MANUAL17") private String manual17;
84+
@JsonProperty("MANUAL18") private String manual18;
85+
@JsonProperty("MANUAL19") private String manual19;
86+
@JsonProperty("MANUAL20") private String manual20;
87+
88+
89+
public String getName() {
90+
return name;
91+
}
92+
93+
public String getParts() {
94+
return parts;
95+
}
96+
97+
public String getDescription() {
98+
return parts;
99+
}
100+
101+
public String getImageUrl() {
102+
return imageUrl;
103+
}
104+
105+
public String getInfoEng() {
106+
return infoEng;
107+
}
108+
109+
public Double getKcal() {
110+
if (infoEng == null) return null;
111+
try {
112+
String n = infoEng.replaceAll("[^0-9.]", "");
113+
return n.isEmpty() ? null : Double.valueOf(n);
114+
} catch (Exception e) {
115+
return null;
116+
}
117+
}
118+
119+
public Double getKcalOrNull() {
120+
return getKcal();
121+
}
122+
123+
public String getHashTag() {
124+
return hashTag;
125+
}
126+
127+
public String getWay() {
128+
return way;
129+
}
130+
131+
public String getCategory() {
132+
return category;
133+
}
134+
135+
public String getType() {
136+
if (category != null && !category.isBlank()) return category;
137+
if (way != null && !way.isBlank()) return way;
138+
return "기타";
139+
}
140+
141+
public String getInstructions() {
142+
List<String> steps = new ArrayList<>();
143+
144+
for (String s : List.of(
145+
manual01, manual02, manual03, manual04, manual05,
146+
manual06, manual07, manual08, manual09, manual10,
147+
manual11, manual12, manual13, manual14, manual15,
148+
manual16, manual17, manual18, manual19, manual20
149+
)) {
150+
if (s == null) continue;
151+
152+
String t = s
153+
.replace("\r\n", "\n")
154+
.replace("\\n", "\n")
155+
.replaceAll("[ \t]+", " ")
156+
.trim();
157+
158+
if (!t.isEmpty()) {
159+
steps.add(t);
160+
}
161+
}
162+
163+
return String.join("\n", steps);
164+
}
165+
}
166+
}

src/main/java/com/webservice/algorithmchef/model/Recipe.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ public class Recipe {
3535

3636
@Lob
3737
private String description;
38-
39-
@Lob
40-
@Column(nullable = false)
41-
private String instructions;
42-
43-
private String imageUrl;
38+
39+
@Lob
40+
@Column(nullable = false, columnDefinition = "LONGTEXT")
41+
private String instructions;
42+
43+
@Lob
44+
@Column(columnDefinition = "TEXT")
45+
private String neededIngredients;
46+
47+
private String imageUrl;
4448

4549
@Column(nullable = false)
4650
private String type;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.webservice.algorithmchef.repository;
2+
3+
import com.webservice.algorithmchef.model.Recipe;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
import java.util.Optional;
7+
8+
public interface RecipeRepository extends JpaRepository<Recipe, Long> {
9+
10+
Optional<Recipe> findByName(String name);
11+
12+
boolean existsByName(String name);
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.webservice.algorithmchef.service;
2+
3+
import org.springframework.boot.CommandLineRunner;
4+
import org.springframework.stereotype.Component;
5+
6+
@Component("recipeDataInitializer")
7+
public class RecipeDataInitializer implements CommandLineRunner {
8+
9+
private final RecipeImportService importService;
10+
11+
public RecipeDataInitializer(RecipeImportService importService) {
12+
this.importService = importService;
13+
}
14+
15+
@Override
16+
public void run(String... args) throws Exception {
17+
System.out.println("[INIT] import start");
18+
importService.importAllFromFoodSafety();
19+
System.out.println("[INIT] import complete");
20+
}
21+
}

0 commit comments

Comments
 (0)