fix: use plain String for PS multilingual fields; add Dolibarr diagnostic endpoint
PS WebService GET responses return name/description as plain strings, not language-array objects. Using List<LangValue> caused Jackson to throw HttpMessageConversionException on every getProductByReference call. Also adds GET /api/sync/diagnostics/dolibarr to verify Dolibarr connectivity and product count from the Railway environment. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
806497b24d
commit
96d75b324a
|
|
@ -1,6 +1,8 @@
|
|||
package com.teterialosjuanjos.tfg.sync_service.api.controller;
|
||||
|
||||
import com.teterialosjuanjos.tfg.sync_service.api.dto.SyncTriggerResponse;
|
||||
import com.teterialosjuanjos.tfg.sync_service.integration.dolibarr.DolibarrClient;
|
||||
import com.teterialosjuanjos.tfg.sync_service.integration.dolibarr.dto.DolibarrProductDto;
|
||||
import com.teterialosjuanjos.tfg.sync_service.sync.OrderSyncService;
|
||||
import com.teterialosjuanjos.tfg.sync_service.sync.ProductSyncService;
|
||||
import com.teterialosjuanjos.tfg.sync_service.sync.StockSyncService;
|
||||
|
|
@ -8,10 +10,14 @@ import com.teterialosjuanjos.tfg.sync_service.sync.SyncResult;
|
|||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* REST endpoints for manually triggering synchronization flows.
|
||||
* Useful in development (where scheduling is disabled) and for on-demand resync in production.
|
||||
|
|
@ -25,6 +31,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
@RequiredArgsConstructor
|
||||
public class SyncController {
|
||||
|
||||
private final DolibarrClient dolibarrClient;
|
||||
private final ProductSyncService productSyncService;
|
||||
private final StockSyncService stockSyncService;
|
||||
private final OrderSyncService orderSyncService;
|
||||
|
|
@ -47,6 +54,14 @@ public class SyncController {
|
|||
return toResponse("ORDER_PULL", orderSyncService.synchronize());
|
||||
}
|
||||
|
||||
@Operation(summary = "Diagnostic: list products returned by Dolibarr API (verifies connectivity)")
|
||||
@GetMapping("/diagnostics/dolibarr")
|
||||
public Map<String, Object> dolibarrDiagnostics() {
|
||||
List<DolibarrProductDto> products = dolibarrClient.getProducts();
|
||||
List<String> refs = products.stream().map(DolibarrProductDto::ref).toList();
|
||||
return Map.of("count", products.size(), "refs", refs);
|
||||
}
|
||||
|
||||
private static SyncTriggerResponse toResponse(String syncType, SyncResult result) {
|
||||
return new SyncTriggerResponse(
|
||||
syncType,
|
||||
|
|
|
|||
|
|
@ -209,9 +209,9 @@ public class PrestashopClient {
|
|||
// PS WebService requires XML body for writes; output_format=JSON only affects the response.
|
||||
|
||||
private String toProductXml(PrestashopProductDto dto) {
|
||||
String name = firstLangValue(dto.name());
|
||||
String description = firstLangValue(dto.description());
|
||||
String descShort = firstLangValue(dto.descriptionShort());
|
||||
String name = dto.name() != null ? dto.name() : "";
|
||||
String description = dto.description() != null ? dto.description() : "";
|
||||
String descShort = dto.descriptionShort() != null ? dto.descriptionShort() : "";
|
||||
String slug = toSlug(dto.reference());
|
||||
|
||||
StringBuilder sb = new StringBuilder(512);
|
||||
|
|
@ -260,12 +260,6 @@ public class PrestashopClient {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String firstLangValue(List<PrestashopProductDto.LangValue> langs) {
|
||||
if (langs == null || langs.isEmpty()) return "";
|
||||
String v = langs.get(0).value();
|
||||
return v != null ? v : "";
|
||||
}
|
||||
|
||||
/** Generates a URL-safe slug from any string (used for PS link_rewrite). */
|
||||
private static String toSlug(String text) {
|
||||
if (text == null || text.isBlank()) return "product";
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ import java.util.List;
|
|||
/**
|
||||
* Represents a PrestaShop product.
|
||||
*
|
||||
* <p>Multilingual fields (name, description) are returned as arrays of {@link LangValue}
|
||||
* objects, one per configured shop language.</p>
|
||||
* <p>The PS WebService GET response (both list and single) returns multilingual fields
|
||||
* ({@code name}, {@code description}, {@code description_short}) as plain {@link String}
|
||||
* values — NOT as language-array objects. The XML request bodies we send for create/update
|
||||
* wrap these strings inside {@code <language id="1">} elements.</p>
|
||||
*
|
||||
* <p>Response wrappers ({@link ListResponse}, {@link SingleResponse}) match the JSON envelope
|
||||
* PrestaShop adds around resources: {@code {"products":[...]}} and {@code {"product":{...}}}.</p>
|
||||
|
|
@ -25,15 +27,11 @@ public record PrestashopProductDto(
|
|||
/** "1" = active, "0" = inactive */
|
||||
String active,
|
||||
@JsonProperty("id_category_default") String idCategoryDefault,
|
||||
List<LangValue> name,
|
||||
List<LangValue> description,
|
||||
@JsonProperty("description_short") List<LangValue> descriptionShort
|
||||
String name,
|
||||
String description,
|
||||
@JsonProperty("description_short") String descriptionShort
|
||||
) {
|
||||
|
||||
/** One language entry for a multilingual field, e.g. {@code {"id":"1","value":"Name"}}. */
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record LangValue(String id, String value) {}
|
||||
|
||||
/** Envelope for {@code GET /api/products?display=full} */
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record ListResponse(List<PrestashopProductDto> products) {}
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ public class ProductSyncService {
|
|||
src.price(),
|
||||
active,
|
||||
categoryId,
|
||||
List.of(new PrestashopProductDto.LangValue("1", label)),
|
||||
List.of(new PrestashopProductDto.LangValue("1", description)),
|
||||
List.of(new PrestashopProductDto.LangValue("1", ""))
|
||||
label,
|
||||
description,
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue