From 9fd11219afaf97bbcf7eaccd57289d446e9cb759 Mon Sep 17 00:00:00 2001 From: luklpz Date: Sun, 17 May 2026 18:07:42 +0200 Subject: [PATCH] feat: add DELETE /api/mappings/products/{id} for broken mapping cleanup Deletes the PS product via Webservice and removes the local mapping. Use this to clean up incomplete PS products (missing ps_product_shop entry) that block re-creation on next sync. Co-Authored-By: Claude Sonnet 4.6 --- .../api/controller/MappingController.java | 30 ++++++++++++++++--- .../prestashop/PrestashopClient.java | 12 ++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/api/controller/MappingController.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/api/controller/MappingController.java index 189ff60..56ba84b 100644 --- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/api/controller/MappingController.java +++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/api/controller/MappingController.java @@ -2,14 +2,16 @@ package com.teterialosjuanjos.tfg.sync_service.api.controller; import com.teterialosjuanjos.tfg.sync_service.api.dto.OrderMappingResponse; import com.teterialosjuanjos.tfg.sync_service.api.dto.ProductMappingResponse; +import com.teterialosjuanjos.tfg.sync_service.integration.prestashop.PrestashopClient; +import com.teterialosjuanjos.tfg.sync_service.integration.prestashop.exception.PrestashopApiException; import com.teterialosjuanjos.tfg.sync_service.mapping.*; 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.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; import java.util.List; @@ -17,6 +19,7 @@ import java.util.List; * REST endpoints for inspecting the Dolibarr ↔ PrestaShop ID mappings stored locally. */ @Tag(name = "Mappings", description = "Inspect Dolibarr ↔ PrestaShop ID mappings") +@Slf4j @RestController @RequestMapping("/api/mappings") @RequiredArgsConstructor @@ -24,6 +27,7 @@ public class MappingController { private final ProductMappingRepository productMappingRepository; private final OrderMappingRepository orderMappingRepository; + private final PrestashopClient prestashopClient; @Operation(summary = "List product mappings, optionally filtered by sync status") @GetMapping("/products") @@ -36,6 +40,24 @@ public class MappingController { return mappings.stream().map(MappingController::toProductResponse).toList(); } + @Operation(summary = "Delete a product mapping and its corresponding PS product. Use to clean up broken/stale mappings before re-syncing.") + @DeleteMapping("/products/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteProductMapping(@PathVariable Long id) { + ProductMapping mapping = productMappingRepository.findById(id) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Mapping not found: " + id)); + if (mapping.getPrestashopId() != null) { + try { + prestashopClient.deleteProduct(mapping.getPrestashopId()); + log.info("Deleted PS product id={} (sku={})", mapping.getPrestashopId(), mapping.getSku()); + } catch (PrestashopApiException e) { + log.warn("Could not delete PS product id={}: {} — removing mapping anyway", mapping.getPrestashopId(), e.getMessage()); + } + } + productMappingRepository.delete(mapping); + log.info("Deleted product mapping id={} sku={}", id, mapping.getSku()); + } + @Operation(summary = "List order mappings") @GetMapping("/orders") public List getOrderMappings() { diff --git a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java index e8c2815..7397f23 100644 --- a/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java +++ b/sync-service/src/main/java/com/teterialosjuanjos/tfg/sync_service/integration/prestashop/PrestashopClient.java @@ -115,6 +115,18 @@ public class PrestashopClient { return getProductByReference(dto.reference()).orElse(null); } + /** Permanently deletes a product from PrestaShop by its internal ID. */ + public void deleteProduct(Integer id) { + log.debug("Deleting PrestaShop product id={}", id); + restClient.delete() + .uri(u -> u.path("/products/{id}") + .queryParam("ws_key", wsKey) + .queryParam("output_format", "JSON") + .build(id)) + .retrieve() + .toBodilessEntity(); + } + /** Updates an existing product by its PrestaShop internal ID. */ public void updateProduct(Integer id, PrestashopProductDto dto) { log.debug("Updating PrestaShop product id={}", id);