Update code, add API
This commit is contained in:
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
13
.idea/compiler.xml
generated
Normal file
13
.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="excel-access-migration" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
20
.idea/jarRepositories.xml
generated
Normal file
20
.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/misc.xml
generated
Normal file
12
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" project-jdk-name="24" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -193,6 +193,7 @@ public class MainController implements Initializable {
|
||||
|
||||
// Display INSERT statements for Склад
|
||||
appendLog("=== ВСТАВКА ДАННЫХ В ТАБЛИЦУ СКЛАД ===");
|
||||
appendLog("ВНИМАНИЕ: ID товара получается через API запросы к dsol_factory");
|
||||
for (String statement : sqlResult.getSkladInsertStatements()) {
|
||||
appendLog(statement);
|
||||
}
|
||||
|
||||
56
src/main/java/com/excelaccess/service/ApiDebugTest.java
Normal file
56
src/main/java/com/excelaccess/service/ApiDebugTest.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.excelaccess.service;
|
||||
|
||||
import com.excelaccess.model.ApiConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Отладочный класс для тестирования API с реальными данными
|
||||
*/
|
||||
public class ApiDebugTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiDebugTest.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Создаем конфигурацию API на основе ваших логов
|
||||
ApiConfig apiConfig = new ApiConfig();
|
||||
apiConfig.setBaseUrl("http://dsol-factory.ulan:9000"); // реальный URL
|
||||
apiConfig.setApiGetLabelId("instruments/api/get_label/");
|
||||
|
||||
// Создаем API сервис
|
||||
ApiService apiService = new ApiService(apiConfig);
|
||||
|
||||
// Тестируем с реальными данными из ваших логов
|
||||
testProduct(apiService, "Заказные интегральные микросхемы в корпусе с кристаллом",
|
||||
"А6 эт.2", "Заказные интегральные микросхемы в корпусе с кристаллом по договору SBR028-2505220027/024/67 от 06.06.25",
|
||||
"микросхема", "DS-DD-001197");
|
||||
|
||||
testProduct(apiService, "Микросхема 3DV7 512Gbit",
|
||||
"Сапфир субсидия эт 3 Тех.оснастка", "Микросхема 3DV7 512Gbit",
|
||||
"Микросхема", "DS-DD-001198");
|
||||
}
|
||||
|
||||
private static void testProduct(ApiService apiService, String name, String nameUpd, String project, String category, String article) {
|
||||
logger.info("=== TESTING PRODUCT: {} ===", name);
|
||||
|
||||
ApiService.ProductSearchData testProduct = new ApiService.ProductSearchData(
|
||||
name, // name
|
||||
nameUpd, // name_upd
|
||||
project, // project
|
||||
category, // category
|
||||
article, // article
|
||||
1, // count
|
||||
null, // upd
|
||||
null // date
|
||||
);
|
||||
|
||||
try {
|
||||
Integer productId = apiService.getProductId(testProduct);
|
||||
logger.info("RESULT: Product ID = {}", productId);
|
||||
} catch (Exception e) {
|
||||
logger.error("ERROR: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
logger.info("=== END TEST ===\n");
|
||||
}
|
||||
}
|
||||
93
src/main/java/com/excelaccess/service/ApiParsingTest.java
Normal file
93
src/main/java/com/excelaccess/service/ApiParsingTest.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.excelaccess.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Тест парсинга реального ответа API
|
||||
*/
|
||||
public class ApiParsingTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiParsingTest.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Реальный ответ API из curl запроса
|
||||
String apiResponse = "{\n" +
|
||||
" \"state\": 200,\n" +
|
||||
" \"data\": {\n" +
|
||||
" \"id\": 34539,\n" +
|
||||
" \"name_1\": \"Трасса Р110(В)-3-DB9(В)-05\",\n" +
|
||||
" \"name_2\": \"Трасса Р110(В)-3-DB9(В)-05\",\n" +
|
||||
" \"cipher\": \"СЧ ОКР МБС Энергия этап 2.1 \",\n" +
|
||||
" \"type\": \"Кабель\",\n" +
|
||||
" \"article\": \"DS-CB-000528\",\n" +
|
||||
" \"count\": 4,\n" +
|
||||
" \"upd\": \"УПД УТ-1759 08.10.25\",\n" +
|
||||
" \"date\": \"16.10.2025\",\n" +
|
||||
" \"cell_num\": null\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
testParsing(apiResponse);
|
||||
}
|
||||
|
||||
private static void testParsing(String responseBody) {
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
logger.info("Testing API response parsing...");
|
||||
logger.info("Response: {}", responseBody);
|
||||
|
||||
JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
logger.info("Parsed JSON structure: {}", rootNode.toPrettyString());
|
||||
|
||||
// Ищем ID в различных возможных полях ответа
|
||||
String[] possibleIdFields = {"id", "product_id", "item_id", "label_id", "ID", "label", "labelId"};
|
||||
|
||||
// Сначала проверяем объект data (основной формат API)
|
||||
if (rootNode.has("data")) {
|
||||
logger.info("Searching for ID in 'data' object...");
|
||||
JsonNode dataNode = rootNode.get("data");
|
||||
|
||||
if (dataNode.isObject()) {
|
||||
logger.info("Data is object: {}", dataNode.toPrettyString());
|
||||
for (String field : possibleIdFields) {
|
||||
JsonNode node = dataNode.get(field);
|
||||
logger.info("Checking field '{}' in data object: {}", field, node);
|
||||
if (node != null && !node.isNull()) {
|
||||
if (node.isNumber()) {
|
||||
int id = node.asInt();
|
||||
logger.info("Found numeric ID {} in data field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
logger.info("✅ SUCCESS: Found valid ID {} in data.{}", id, field);
|
||||
return;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in data field '{}': {}", field, id);
|
||||
}
|
||||
} else if (node.isTextual()) {
|
||||
try {
|
||||
int id = Integer.parseInt(node.asText());
|
||||
logger.info("Found string ID {} in data field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
logger.info("✅ SUCCESS: Found valid ID {} in data.{}", id, field);
|
||||
return;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in data field '{}': {}", field, id);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Не удалось преобразовать ID в число: {}", node.asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn("❌ No valid ID found in response");
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error parsing API response: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
357
src/main/java/com/excelaccess/service/ApiService.java
Normal file
357
src/main/java/com/excelaccess/service/ApiService.java
Normal file
@@ -0,0 +1,357 @@
|
||||
package com.excelaccess.service;
|
||||
|
||||
import com.excelaccess.model.ApiConfig;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ApiService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiService.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ApiConfig apiConfig;
|
||||
|
||||
public ApiService(ApiConfig apiConfig) {
|
||||
this.apiConfig = apiConfig;
|
||||
this.httpClient = HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(30))
|
||||
.build();
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает ID товара через API запрос
|
||||
*
|
||||
* @param productData данные товара для поиска
|
||||
* @return ID товара или null если не найден
|
||||
*/
|
||||
public Integer getProductId(ProductSearchData productData) {
|
||||
if (!isApiConfigured()) {
|
||||
logger.warn("API не настроен, пропускаем получение ID товара");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.debug("Поиск ID товара для: {}", productData.getName());
|
||||
|
||||
// Формируем URL для API запроса
|
||||
String apiUrl = buildApiUrl(productData);
|
||||
logger.info("API URL: {}", apiUrl);
|
||||
logger.info("Searching for product with data: {}", productData);
|
||||
|
||||
// Формируем данные для POST запроса
|
||||
String postData = buildPostData(productData);
|
||||
logger.info("POST data: {}", postData);
|
||||
logger.info("Equivalent curl command (with swapped name fields):");
|
||||
logger.info("curl -X POST {} -d \"{}\"", apiUrl, postData.replace("&", "\" -d \""));
|
||||
logger.info("Note: name and name_upd fields are swapped in API request");
|
||||
|
||||
// Создаем HTTP запрос
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(apiUrl))
|
||||
.timeout(Duration.ofSeconds(30))
|
||||
.header("Content-Type", "application/x-www-form-urlencoded")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(postData))
|
||||
.build();
|
||||
|
||||
// Выполняем запрос
|
||||
HttpResponse<String> response = httpClient.send(request,
|
||||
HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
logger.info("API Response status: {}", response.statusCode());
|
||||
logger.info("API Response body: {}", response.body());
|
||||
logger.info("API Response headers: {}", response.headers().map());
|
||||
|
||||
if (response.statusCode() == 200) {
|
||||
return parseProductId(response.body());
|
||||
} else {
|
||||
logger.warn("API запрос завершился с ошибкой: {} - {}",
|
||||
response.statusCode(), response.body());
|
||||
|
||||
// Проверяем, есть ли ошибка в JSON ответе
|
||||
try {
|
||||
JsonNode errorNode = objectMapper.readTree(response.body());
|
||||
if (errorNode.has("error")) {
|
||||
logger.error("API Error: {}", errorNode.get("error").asText());
|
||||
}
|
||||
if (errorNode.has("state") && errorNode.get("state").asInt() != 200) {
|
||||
logger.error("API State: {}", errorNode.get("state").asInt());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Could not parse error response as JSON");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Ошибка при получении ID товара для '{}': {}",
|
||||
productData.getName(), e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, настроен ли API
|
||||
*/
|
||||
public boolean isApiConfigured() {
|
||||
return apiConfig != null
|
||||
&& apiConfig.getBaseUrl() != null
|
||||
&& !apiConfig.getBaseUrl().trim().isEmpty()
|
||||
&& apiConfig.getApiGetLabelId() != null
|
||||
&& !apiConfig.getApiGetLabelId().trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует URL для API запроса (без параметров для POST)
|
||||
*/
|
||||
private String buildApiUrl(ProductSearchData productData) {
|
||||
StringBuilder url = new StringBuilder(apiConfig.getBaseUrl());
|
||||
|
||||
// Добавляем endpoint если base_url не заканчивается на /
|
||||
if (!apiConfig.getBaseUrl().endsWith("/")) {
|
||||
url.append("/");
|
||||
}
|
||||
url.append(apiConfig.getApiGetLabelId());
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует данные для POST запроса
|
||||
*/
|
||||
private String buildPostData(ProductSearchData productData) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
|
||||
// Обязательные поля (всегда отправляем, даже если пустые)
|
||||
// Поменяли местами: name_upd -> name, name -> name_upd
|
||||
params.put("name", productData.getNameUpd() != null ? productData.getNameUpd() : "");
|
||||
params.put("name_upd", productData.getName() != null ? productData.getName() : "");
|
||||
params.put("project", productData.getProject() != null ? productData.getProject() : "");
|
||||
params.put("category", productData.getCategory() != null ? productData.getCategory() : "");
|
||||
params.put("article", productData.getArticle() != null ? productData.getArticle() : "");
|
||||
params.put("count", String.valueOf(productData.getCount()));
|
||||
params.put("upd", productData.getUpd() != null ? productData.getUpd() : "");
|
||||
|
||||
// Опциональные поля
|
||||
if (productData.getDate() != null) {
|
||||
params.put("date", productData.getDate().format(DateTimeFormatter.ofPattern("dd.MM.yyyy")));
|
||||
}
|
||||
|
||||
// Формируем строку для application/x-www-form-urlencoded
|
||||
StringBuilder postData = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
if (!first) {
|
||||
postData.append("&");
|
||||
}
|
||||
postData.append(entry.getKey()).append("=")
|
||||
.append(java.net.URLEncoder.encode(entry.getValue(), java.nio.charset.StandardCharsets.UTF_8));
|
||||
first = false;
|
||||
}
|
||||
|
||||
return postData.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Парсит ответ API и извлекает ID товара
|
||||
*/
|
||||
private Integer parseProductId(String responseBody) {
|
||||
try {
|
||||
logger.info("Parsing API response: {}", responseBody);
|
||||
|
||||
JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
logger.info("Parsed JSON structure: {}", rootNode.toPrettyString());
|
||||
|
||||
// Ищем ID в различных возможных полях ответа
|
||||
String[] possibleIdFields = {"id", "product_id", "item_id", "label_id", "ID", "label", "labelId"};
|
||||
|
||||
// Сначала проверяем объект data (основной формат API)
|
||||
if (rootNode.has("data")) {
|
||||
logger.info("Searching for ID in 'data' object...");
|
||||
JsonNode dataNode = rootNode.get("data");
|
||||
|
||||
if (dataNode.isObject()) {
|
||||
logger.info("Data is object: {}", dataNode.toPrettyString());
|
||||
for (String field : possibleIdFields) {
|
||||
JsonNode node = dataNode.get(field);
|
||||
logger.info("Checking field '{}' in data object: {}", field, node);
|
||||
if (node != null && !node.isNull()) {
|
||||
if (node.isNumber()) {
|
||||
int id = node.asInt();
|
||||
logger.info("Found numeric ID {} in data field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
return id;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in data field '{}': {}", field, id);
|
||||
}
|
||||
} else if (node.isTextual()) {
|
||||
try {
|
||||
int id = Integer.parseInt(node.asText());
|
||||
logger.info("Found string ID {} in data field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
return id;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in data field '{}': {}", field, id);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Не удалось преобразовать ID в число: {}", node.asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (dataNode.isArray() && dataNode.size() > 0) {
|
||||
logger.info("Data is array with {} elements", dataNode.size());
|
||||
// Берем первый элемент массива
|
||||
JsonNode firstItem = dataNode.get(0);
|
||||
logger.info("First array element: {}", firstItem.toPrettyString());
|
||||
for (String field : possibleIdFields) {
|
||||
JsonNode node = firstItem.get(field);
|
||||
logger.info("Checking field '{}' in array element: {}", field, node);
|
||||
if (node != null && !node.isNull()) {
|
||||
if (node.isNumber()) {
|
||||
int id = node.asInt();
|
||||
logger.info("Found numeric ID {} in array field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
return id;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in array field '{}': {}", field, id);
|
||||
}
|
||||
} else if (node.isTextual()) {
|
||||
try {
|
||||
int id = Integer.parseInt(node.asText());
|
||||
logger.info("Found string ID {} in array field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
return id;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in array field '{}': {}", field, id);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Не удалось преобразовать ID в число: {}", node.asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Если ID не найден в data, ищем в корневом объекте
|
||||
logger.info("Searching for ID in root object...");
|
||||
for (String field : possibleIdFields) {
|
||||
JsonNode node = rootNode.get(field);
|
||||
logger.info("Checking field '{}': {}", field, node);
|
||||
if (node != null && !node.isNull()) {
|
||||
if (node.isNumber()) {
|
||||
int id = node.asInt();
|
||||
logger.info("Found numeric ID {} in field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
return id;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in field '{}': {}", field, id);
|
||||
}
|
||||
} else if (node.isTextual()) {
|
||||
try {
|
||||
int id = Integer.parseInt(node.asText());
|
||||
logger.info("Found string ID {} in field '{}'", id, field);
|
||||
if (id > 0) {
|
||||
return id;
|
||||
} else {
|
||||
logger.warn("ID is 0 or negative in field '{}': {}", field, id);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Не удалось преобразовать ID в число: {}", node.asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Проверяем все поля в корневом объекте для отладки
|
||||
logger.info("All fields in root object:");
|
||||
rootNode.fieldNames().forEachRemaining(fieldName -> {
|
||||
JsonNode fieldValue = rootNode.get(fieldName);
|
||||
logger.info(" {}: {} (type: {})", fieldName, fieldValue, fieldValue.getNodeType());
|
||||
});
|
||||
|
||||
logger.warn("ID товара не найден в ответе API: {}", responseBody);
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Ошибка при парсинге ответа API: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Данные товара для поиска через API
|
||||
*/
|
||||
public static class ProductSearchData {
|
||||
private String name;
|
||||
private String nameUpd;
|
||||
private String project;
|
||||
private String category;
|
||||
private String article;
|
||||
private Integer count;
|
||||
private String upd;
|
||||
private LocalDate date;
|
||||
|
||||
// Конструкторы
|
||||
public ProductSearchData() {}
|
||||
|
||||
public ProductSearchData(String name, String nameUpd, String project,
|
||||
String category, String article, Integer count,
|
||||
String upd, LocalDate date) {
|
||||
this.name = name;
|
||||
this.nameUpd = nameUpd;
|
||||
this.project = project;
|
||||
this.category = category;
|
||||
this.article = article;
|
||||
this.count = count;
|
||||
this.upd = upd;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
|
||||
public String getNameUpd() { return nameUpd; }
|
||||
public void setNameUpd(String nameUpd) { this.nameUpd = nameUpd; }
|
||||
|
||||
public String getProject() { return project; }
|
||||
public void setProject(String project) { this.project = project; }
|
||||
|
||||
public String getCategory() { return category; }
|
||||
public void setCategory(String category) { this.category = category; }
|
||||
|
||||
public String getArticle() { return article; }
|
||||
public void setArticle(String article) { this.article = article; }
|
||||
|
||||
public Integer getCount() { return count; }
|
||||
public void setCount(Integer count) { this.count = count; }
|
||||
|
||||
public String getUpd() { return upd; }
|
||||
public void setUpd(String upd) { this.upd = upd; }
|
||||
|
||||
public LocalDate getDate() { return date; }
|
||||
public void setDate(LocalDate date) { this.date = date; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ProductSearchData{name='%s', nameUpd='%s', project='%s', category='%s', article='%s', count=%d, upd='%s', date=%s}",
|
||||
name, nameUpd, project, category, article, count, upd, date);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/main/java/com/excelaccess/service/ApiServiceTest.java
Normal file
59
src/main/java/com/excelaccess/service/ApiServiceTest.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.excelaccess.service;
|
||||
|
||||
import com.excelaccess.model.ApiConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Тестовый класс для проверки API интеграции
|
||||
* Этот класс можно использовать для тестирования API запросов
|
||||
*/
|
||||
public class ApiServiceTest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiServiceTest.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Создаем тестовую конфигурацию API
|
||||
ApiConfig apiConfig = new ApiConfig();
|
||||
apiConfig.setBaseUrl("https://api.example.com");
|
||||
apiConfig.setApiGetLabelId("products/search");
|
||||
|
||||
// Создаем API сервис
|
||||
ApiService apiService = new ApiService(apiConfig);
|
||||
|
||||
// Проверяем конфигурацию
|
||||
if (apiService.isApiConfigured()) {
|
||||
logger.info("API service is properly configured");
|
||||
} else {
|
||||
logger.warn("API service is not configured");
|
||||
}
|
||||
|
||||
// Создаем тестовые данные товара
|
||||
ApiService.ProductSearchData testProduct = new ApiService.ProductSearchData(
|
||||
"Тестовый товар", // name
|
||||
"Поставщик товара", // name_upd
|
||||
"Тестовый проект", // project
|
||||
"Категория", // category
|
||||
"ART-001", // article
|
||||
10, // count
|
||||
"INV-12345", // upd
|
||||
java.time.LocalDate.now() // date
|
||||
);
|
||||
|
||||
logger.info("Testing API request with product data: {}", testProduct);
|
||||
|
||||
try {
|
||||
// Выполняем тестовый запрос
|
||||
Integer productId = apiService.getProductId(testProduct);
|
||||
|
||||
if (productId != null) {
|
||||
logger.info("Successfully retrieved product ID: {}", productId);
|
||||
} else {
|
||||
logger.warn("Product ID not found for test product");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error during API test: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,16 @@ public class MigrationService {
|
||||
// Generate SQL statements
|
||||
SqlGeneratorService sqlGeneratorService = new SqlGeneratorService();
|
||||
sqlGeneratorService.setIdCurator(config.getSettings().getIdCurator());
|
||||
|
||||
// Настраиваем API сервис если он доступен
|
||||
if (config.getDsolFactory() != null) {
|
||||
ApiService apiService = new ApiService(config.getDsolFactory());
|
||||
sqlGeneratorService.setApiService(apiService);
|
||||
logger.info("API service configured for product ID lookup");
|
||||
} else {
|
||||
logger.warn("API configuration not found, product IDs will be NULL");
|
||||
}
|
||||
|
||||
SqlGeneratorService.SqlGenerationResult sqlResult = sqlGeneratorService.generateSqlQueries(
|
||||
analysisResult.getProductCards(), analysisResult.getTransactions());
|
||||
|
||||
|
||||
@@ -14,11 +14,16 @@ public class SqlGeneratorService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SqlGeneratorService.class);
|
||||
|
||||
private int idCurator = 1; // Default value
|
||||
private ApiService apiService;
|
||||
|
||||
public void setIdCurator(int idCurator) {
|
||||
this.idCurator = idCurator;
|
||||
}
|
||||
|
||||
public void setApiService(ApiService apiService) {
|
||||
this.apiService = apiService;
|
||||
}
|
||||
|
||||
public SqlGenerationResult generateSqlQueries(List<ProductCard> productCards, List<Transaction> transactions) {
|
||||
logger.info("Generating SQL queries for {} product cards and {} transactions",
|
||||
productCards.size(), transactions.size());
|
||||
@@ -42,6 +47,7 @@ public class SqlGeneratorService {
|
||||
List<String> statements = new ArrayList<>();
|
||||
|
||||
statements.add("-- Вставка данных в таблицу Склад");
|
||||
statements.add("-- Получение ID товара через API запросы");
|
||||
|
||||
for (int i = 0; i < productCards.size(); i++) {
|
||||
ProductCard card = productCards.get(i);
|
||||
@@ -52,10 +58,23 @@ public class SqlGeneratorService {
|
||||
|
||||
logger.debug("Generating SQL for product card {}: {}", i, card.getName());
|
||||
|
||||
// Получаем ID товара через API
|
||||
Integer productId = getProductIdFromApi(card);
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("INSERT INTO Склад ([Наименование], [Наименование у поставщика], [Проект], [Местоположение], [Категория], [Артикул], [Примечание]) VALUES (");
|
||||
sql.append(escapeString(truncateString(card.getName(), 255))).append(", ");
|
||||
sql.append("INSERT INTO Склад ([ID Товара], [Наименование], [Наименование у поставщика], [Проект], [Местоположение], [Категория], [Артикул], [Примечание]) VALUES (");
|
||||
|
||||
if (productId != null) {
|
||||
sql.append(productId).append(", ");
|
||||
logger.debug("Using API product ID {} for product: {}", productId, card.getName());
|
||||
} else {
|
||||
sql.append("NULL, ");
|
||||
logger.warn("Product ID not found via API for: {}", card.getName());
|
||||
}
|
||||
|
||||
// Поменяли местами: Наименование и Наименование у поставщика
|
||||
sql.append(escapeString(truncateString(card.getSupplierName(), 255))).append(", ");
|
||||
sql.append(escapeString(truncateString(card.getName(), 255))).append(", ");
|
||||
sql.append(escapeString(truncateString(card.getProject(), 255))).append(", ");
|
||||
sql.append(escapeString(truncateString(card.getLocation(), 255))).append(", ");
|
||||
sql.append(escapeString(truncateString(card.getCategory(), 255))).append(", ");
|
||||
@@ -67,7 +86,6 @@ public class SqlGeneratorService {
|
||||
logger.debug("Added SQL statement for product card: {}", card.getName());
|
||||
}
|
||||
|
||||
|
||||
return statements;
|
||||
}
|
||||
|
||||
@@ -161,6 +179,53 @@ public class SqlGeneratorService {
|
||||
return str.substring(0, maxLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает ID товара через API запрос
|
||||
*/
|
||||
private Integer getProductIdFromApi(ProductCard card) {
|
||||
if (apiService == null || !apiService.isApiConfigured()) {
|
||||
logger.warn("API service not configured, skipping product ID lookup for: {}", card.getName());
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.info("=== API LOOKUP START ===");
|
||||
logger.info("Product name: {}", card.getName());
|
||||
logger.info("Supplier name: {}", card.getSupplierName());
|
||||
logger.info("Project: {}", card.getProject());
|
||||
logger.info("Category: {}", card.getCategory());
|
||||
logger.info("Article: {}", card.getArticleNumbers());
|
||||
|
||||
// Создаем данные для поиска товара
|
||||
ApiService.ProductSearchData searchData = new ApiService.ProductSearchData(
|
||||
card.getName(), // name
|
||||
card.getSupplierName(), // name_upd
|
||||
card.getProject(), // project
|
||||
card.getCategory(), // category
|
||||
card.getArticleNumbers(), // article
|
||||
1, // count (по умолчанию 1, так как в карточке товара нет количества)
|
||||
"", // upd (пустая строка вместо null)
|
||||
null // date (дата - нет в карточке товара)
|
||||
);
|
||||
|
||||
logger.info("Searching for product ID with data: {}", searchData);
|
||||
Integer productId = apiService.getProductId(searchData);
|
||||
|
||||
if (productId != null && productId > 0) {
|
||||
logger.info("✅ Found product ID {} for: {}", productId, card.getName());
|
||||
} else {
|
||||
logger.warn("❌ Product ID not found or is 0 for: {} (returned: {})", card.getName(), productId);
|
||||
}
|
||||
|
||||
logger.info("=== API LOOKUP END ===");
|
||||
return productId;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("❌ Error getting product ID for '{}': {}", card.getName(), e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SqlGenerationResult {
|
||||
private List<String> skladInsertStatements;
|
||||
private List<String> transactionsInsertStatements;
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
<appender-ref ref="FILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="com.excelaccess.service.ApiService" level="INFO" additivity="false">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="net.ucanaccess" level="WARN" additivity="false">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
"id_curator": 1
|
||||
},
|
||||
"dsol_factory": {
|
||||
"base_url": "",
|
||||
"api_get_label_id": ""
|
||||
"base_url": "http://dsol-factory.ulan:9000",
|
||||
"api_get_label_id": "instruments/api/get_label/"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user