diff --git a/CHANGELOG.md b/CHANGELOG.md index 5204e35417f154199d654e48221e2921e9319a01..84023af56a1de3ed0ec527354c1cb53701f107e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ### Added - New features that have been added. - MYD-168/create sale session +- MYD-173/get all sessions ### Changed - Changes in existing functionality. +- MYD-173/change in existing classes ### Deprecated - Soon-to-be removed features. diff --git a/src/main/java/com/marketingconfort/mydressin/controllers/CartController.java b/src/main/java/com/marketingconfort/mydressin/controllers/CartController.java index acc6f833c050ce3ee9759ca33dd8eeba9351a9c5..2ec3a28a1c3c7dc5c3d3868327d6f6a26a1212e7 100644 --- a/src/main/java/com/marketingconfort/mydressin/controllers/CartController.java +++ b/src/main/java/com/marketingconfort/mydressin/controllers/CartController.java @@ -1,6 +1,7 @@ package com.marketingconfort.mydressin.controllers; import com.marketingconfort.mydressin.common.cart.dtos.ProductStockDTO; +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockRequestDTO; import com.marketingconfort.mydressin.dtos.CartDTO; import com.marketingconfort.mydressin.dtos.LocalStorageRequest; import com.marketingconfort.mydressin.exceptions.CartNotFoundException; @@ -12,7 +13,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; -import java.util.Map; @RestController @RequestMapping(value = "/api/cart", method = RequestMethod.OPTIONS) @@ -23,15 +23,15 @@ public class CartController { private final ProductStockService productStockService; private final CartService cartService; - @PostMapping("/check-stock") - public ResponseEntity<List<ProductStockDTO>> checkProductStockForIds(@RequestBody Map<Long, Long> productQuantities) { - List<ProductStockDTO> productStockDTOs = productStockService.checkProductStockForIds(productQuantities); + @PostMapping("/checkProductsStock") + public ResponseEntity<List<ProductStockDTO>> checkProductStockForIds(@RequestBody List<ProductStockRequestDTO> productStockRequestDTOS) { + List<ProductStockDTO> productStockDTOs = productStockService.checkProductStockForIds(productStockRequestDTOS); return ResponseEntity.ok(productStockDTOs); } - @GetMapping("/check-stock/{id}/{quantityToAdd}") - public ResponseEntity<ProductStockDTO> checkStock(@PathVariable Long id, @PathVariable Long quantityToAdd) { - ProductStockDTO productStockDTO = productStockService.checkStock(id, quantityToAdd); + @PostMapping("/checkProductStock") + public ResponseEntity<ProductStockDTO> checkStock(@RequestBody ProductStockRequestDTO productStockRequestDTO) { + ProductStockDTO productStockDTO = productStockService.checkStock(productStockRequestDTO); return ResponseEntity.ok(productStockDTO); } diff --git a/src/main/java/com/marketingconfort/mydressin/controllers/SaleSessionController.java b/src/main/java/com/marketingconfort/mydressin/controllers/SaleSessionController.java index 2fe070464f5f2a3a11dda33d757de0f780969ba7..3e6453c899a35568e97d91daa20dd055289689be 100644 --- a/src/main/java/com/marketingconfort/mydressin/controllers/SaleSessionController.java +++ b/src/main/java/com/marketingconfort/mydressin/controllers/SaleSessionController.java @@ -1,7 +1,12 @@ package com.marketingconfort.mydressin.controllers; import com.marketingconfort.mydressin.common.cart.models.SaleSession; +import com.marketingconfort.mydressin.common.cart.models.SessionOrder; import com.marketingconfort.mydressin.dtos.SaleSessionDTO; +import com.marketingconfort.mydressin.dtos.SessionRequest; +import com.marketingconfort.mydressin.exceptions.CartNotFoundException; +import com.marketingconfort.mydressin.exceptions.ProductOutOfStockException; +import com.marketingconfort.mydressin.exceptions.SaleSessionNotFoundException; import com.marketingconfort.mydressin.services.SaleSessionService; import lombok.AllArgsConstructor; import org.springframework.http.HttpStatus; @@ -23,5 +28,9 @@ public class SaleSessionController { return new ResponseEntity<>(createdSaleSession, HttpStatus.CREATED); } - + @GetMapping("/saleSessions") + public ResponseEntity<List<SaleSessionDTO>> getAllSaleSessions() { + List<SaleSessionDTO> saleSessions = saleSessionService.getAllSaleSessions(); + return new ResponseEntity<>(saleSessions, HttpStatus.OK); + } } diff --git a/src/main/java/com/marketingconfort/mydressin/dtos/ItemCartDTO.java b/src/main/java/com/marketingconfort/mydressin/dtos/ItemCartDTO.java index 6eeae88123bd2749f0a2757c93d238baa4f6eb39..27c3388f8d1cad6167946c01b31164d63e31be0d 100644 --- a/src/main/java/com/marketingconfort/mydressin/dtos/ItemCartDTO.java +++ b/src/main/java/com/marketingconfort/mydressin/dtos/ItemCartDTO.java @@ -3,6 +3,7 @@ package com.marketingconfort.mydressin.dtos; import com.marketingconfort.mydressin.common.cart.dtos.ProductCartDTO; +import com.marketingconfort.mydressin.common.cart.enumurations.ItemSource; import com.marketingconfort.mydressin.common.stockmanagement.enumurations.ProductType; import lombok.Getter; import lombok.Setter; @@ -17,5 +18,5 @@ public class ItemCartDTO { private Long productId; private double totalPrice; private ProductCartDTO product; - private String source; + private ItemSource source; } diff --git a/src/main/java/com/marketingconfort/mydressin/dtos/SaleSessionDTO.java b/src/main/java/com/marketingconfort/mydressin/dtos/SaleSessionDTO.java index c4c6c5f4a70524b72955cc0b185445c5498e79c3..c66bdf2dac71f7dacd03ec3de8b655eef77aaf94 100644 --- a/src/main/java/com/marketingconfort/mydressin/dtos/SaleSessionDTO.java +++ b/src/main/java/com/marketingconfort/mydressin/dtos/SaleSessionDTO.java @@ -14,7 +14,10 @@ public class SaleSessionDTO { private LocalDateTime lastModification; private LiveType type; private long live; - private long paidProductNumber; + private long paidProductsNumber; private long clientsNumber; + private long deletedProductsNumber; + private long consultedProductsNumber; + } diff --git a/src/main/java/com/marketingconfort/mydressin/dtos/SessionRequest.java b/src/main/java/com/marketingconfort/mydressin/dtos/SessionRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..b0a1764572b62cff751a14002093876cd8cb5eee --- /dev/null +++ b/src/main/java/com/marketingconfort/mydressin/dtos/SessionRequest.java @@ -0,0 +1,13 @@ +package com.marketingconfort.mydressin.dtos; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class SessionRequest { + private Long clientId; + private Long productId; + private Long sessionId; + private Long quantity; +} diff --git a/src/main/java/com/marketingconfort/mydressin/exceptions/ProductOutOfStockException.java b/src/main/java/com/marketingconfort/mydressin/exceptions/ProductOutOfStockException.java new file mode 100644 index 0000000000000000000000000000000000000000..d0ba08468c14bbb0dc651efd028cc71547e32c3f --- /dev/null +++ b/src/main/java/com/marketingconfort/mydressin/exceptions/ProductOutOfStockException.java @@ -0,0 +1,7 @@ +package com.marketingconfort.mydressin.exceptions; + +public class ProductOutOfStockException extends RuntimeException { + public ProductOutOfStockException(String message) { + super(message); + } +} diff --git a/src/main/java/com/marketingconfort/mydressin/exceptions/SaleSessionExpiredException.java b/src/main/java/com/marketingconfort/mydressin/exceptions/SaleSessionExpiredException.java new file mode 100644 index 0000000000000000000000000000000000000000..f40f357f72380807589bb9685229d5b16b307112 --- /dev/null +++ b/src/main/java/com/marketingconfort/mydressin/exceptions/SaleSessionExpiredException.java @@ -0,0 +1,12 @@ +package com.marketingconfort.mydressin.exceptions; + +public class SaleSessionExpiredException extends RuntimeException { + + public SaleSessionExpiredException(String message) { + super(message); + } + + public SaleSessionExpiredException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/main/java/com/marketingconfort/mydressin/mappers/ItemCartMapper.java b/src/main/java/com/marketingconfort/mydressin/mappers/ItemCartMapper.java index 3eef6e6dad5f327bbad750bef13cb27bf4313d85..f08337cc13718af3b208e7e472958da98bec7c6b 100644 --- a/src/main/java/com/marketingconfort/mydressin/mappers/ItemCartMapper.java +++ b/src/main/java/com/marketingconfort/mydressin/mappers/ItemCartMapper.java @@ -15,7 +15,7 @@ public class ItemCartMapper { itemCartDTO.setId(itemCart.getId()); itemCartDTO.setProductId(itemCart.getProductId()); itemCartDTO.setQuantity(itemCart.getQuantity()); - itemCartDTO.setSource(itemCart.getSource()); + //itemCartDTO.setSource(itemCart.getSource()); if (itemCart.getProduct() != null) { itemCartDTO.setProduct( itemCart.getProduct()); } diff --git a/src/main/java/com/marketingconfort/mydressin/repositories/SessionOrderRepository.java b/src/main/java/com/marketingconfort/mydressin/repositories/SessionOrderRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..27b40b094e893097b0e4297a1a36214edbc0c723 --- /dev/null +++ b/src/main/java/com/marketingconfort/mydressin/repositories/SessionOrderRepository.java @@ -0,0 +1,10 @@ +package com.marketingconfort.mydressin.repositories; + +import com.marketingconfort.mydressin.common.cart.models.SessionOrder; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SessionOrderRepository extends JpaRepository<SessionOrder,Long> { + +} diff --git a/src/main/java/com/marketingconfort/mydressin/services/CartServiceImp.java b/src/main/java/com/marketingconfort/mydressin/services/CartServiceImp.java index f3a7bd49997018ab0e4fdd3a1318b02376e1a839..a5c8bdb7049635744fb70652890bcaca0e639203 100644 --- a/src/main/java/com/marketingconfort/mydressin/services/CartServiceImp.java +++ b/src/main/java/com/marketingconfort/mydressin/services/CartServiceImp.java @@ -2,6 +2,7 @@ package com.marketingconfort.mydressin.services; import com.marketingconfort.mydressin.common.cart.dtos.ProductStockDTO; +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockRequestDTO; import com.marketingconfort.mydressin.common.cart.enumurations.Status; import com.marketingconfort.mydressin.common.cart.models.Cart; import com.marketingconfort.mydressin.common.cart.models.ItemCart; @@ -66,15 +67,15 @@ public class CartServiceImp implements CartService { return null; } List<String> messages = new ArrayList<>(); - Map<Long, Long> productQuantities = collectProductQuantities(cart); + List<ProductStockRequestDTO> productStockRequestDTOS= collectProductQuantities(cart); - if (productQuantities != null) { + if (productStockRequestDTOS!= null) { // Create a map for quick lookup of item carts by product ID Map<Long, ItemCart> itemCartMap = cart.getItems().stream() .collect(Collectors.toMap(ItemCart::getProductId, itemCart -> itemCart)); // Check stock for all products in the cart - List<ProductStockDTO> stockResults = productStockService.checkProductStockForIds(productQuantities); + List<ProductStockDTO> stockResults = productStockService.checkProductStockForIds(productStockRequestDTOS); stockResults .forEach(stockResult -> { @@ -96,18 +97,17 @@ public class CartServiceImp implements CartService { return cart; } - private Map<Long, Long> collectProductQuantities(Cart cart) { + private List<ProductStockRequestDTO> collectProductQuantities(Cart cart) { if (cart.getItems() == null) { - return null; + return Collections.emptyList(); } return cart.getItems().stream() - .collect(Collectors.toMap( - ItemCart::getProductId, - ItemCart::getQuantity - )); + .map(item -> new ProductStockRequestDTO(item.getProductId(), item.getQuantity(), item.getSource())) + .collect(Collectors.toList()); } + @Override public CartDTO reload(Long clientId) { Cart cart = cartRepository.findByClientIdAndStatus(clientId, Status.open) diff --git a/src/main/java/com/marketingconfort/mydressin/services/ItemCartServiceImp.java b/src/main/java/com/marketingconfort/mydressin/services/ItemCartServiceImp.java index 4b7c6ac21883b5e9460e26d7be00f4bede687380..5e60f8289f36a4cf6f633f869b2bbf2fe364cee1 100644 --- a/src/main/java/com/marketingconfort/mydressin/services/ItemCartServiceImp.java +++ b/src/main/java/com/marketingconfort/mydressin/services/ItemCartServiceImp.java @@ -3,6 +3,9 @@ package com.marketingconfort.mydressin.services; import com.marketingconfort.mydressin.common.cart.dtos.ProductStockDTO; + +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockRequestDTO; +import com.marketingconfort.mydressin.common.cart.enumurations.ItemSource; import com.marketingconfort.mydressin.common.cart.models.Cart; import com.marketingconfort.mydressin.common.cart.models.ItemCart; import com.marketingconfort.mydressin.dtos.CartDTO; @@ -66,7 +69,8 @@ public class ItemCartServiceImp implements ItemCartService { } cart.getInfos().clear(); cart = cartService.updateCartWithStockAvailability(cart); - ProductStockDTO stockResult = productStockService.checkStock(productId, quantity); + ProductStockRequestDTO productStockRequestDTO=new ProductStockRequestDTO(productId,quantity, ItemSource.WEB); + ProductStockDTO stockResult = productStockService.checkStock(productStockRequestDTO); if (!stockResult.isAvailable()) { cart.getInfos().add(stockResult.getProductDTO().getName() + " non disponible"); @@ -122,7 +126,10 @@ public class ItemCartServiceImp implements ItemCartService { } else { if (quantity > itemCart.getQuantity()) { Long quantityToAdd = quantity - itemCart.getQuantity(); - ProductStockDTO stockResult = productStockService.checkStock(itemCart.getProductId(), quantityToAdd); + + ProductStockRequestDTO productStockRequestDTO=new ProductStockRequestDTO(itemCart.getProductId(),quantityToAdd, ItemSource.WEB); + + ProductStockDTO stockResult = productStockService.checkStock(productStockRequestDTO); if (!stockResult.isAvailable()) { Message = "Le produit" + " " + stockResult.getProductDTO().getName() + " " + "n'est pas disponible en quantité suffisante."; diff --git a/src/main/java/com/marketingconfort/mydressin/services/ProductStockService.java b/src/main/java/com/marketingconfort/mydressin/services/ProductStockService.java index 49f2cd6d23a7cfe3e6231fa010d863a24228cb19..8f1ff4600a2736a9e737281c11fd240429b4c929 100644 --- a/src/main/java/com/marketingconfort/mydressin/services/ProductStockService.java +++ b/src/main/java/com/marketingconfort/mydressin/services/ProductStockService.java @@ -1,12 +1,12 @@ package com.marketingconfort.mydressin.services; import com.marketingconfort.mydressin.common.cart.dtos.ProductStockDTO; +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockRequestDTO; import java.util.List; -import java.util.Map; public interface ProductStockService { - List<ProductStockDTO> checkProductStockForIds(Map<Long, Long> productQuantities); - ProductStockDTO checkStock(Long id, Long quantityToAdd); + List<ProductStockDTO> checkProductStockForIds(List<ProductStockRequestDTO> productStockRequestDTOS); + ProductStockDTO checkStock(ProductStockRequestDTO productStockRequestDTO); } diff --git a/src/main/java/com/marketingconfort/mydressin/services/ProductStockServiceImp.java b/src/main/java/com/marketingconfort/mydressin/services/ProductStockServiceImp.java index 004503dc788cc0da5e37a215635d5c026cb43266..6d141bc1de3a9db24ac6a0596fdd1d55a55a5748 100644 --- a/src/main/java/com/marketingconfort/mydressin/services/ProductStockServiceImp.java +++ b/src/main/java/com/marketingconfort/mydressin/services/ProductStockServiceImp.java @@ -1,6 +1,10 @@ package com.marketingconfort.mydressin.services; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.marketingconfort.mydressin.common.cart.dtos.ProductStockDTO; + +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockRequestDTO; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpEntity; @@ -10,7 +14,6 @@ import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; -import java.util.Map; @Service public class ProductStockServiceImp implements ProductStockService { @@ -24,19 +27,25 @@ public class ProductStockServiceImp implements ProductStockService { } @Override - public List<ProductStockDTO> checkProductStockForIds(Map<Long, Long> productQuantities) { + public List<ProductStockDTO> checkProductStockForIds(List<ProductStockRequestDTO> productStockRequestDTOS) { ResponseEntity<List<ProductStockDTO>> responseEntity = restTemplate.exchange( - productStockServiceUrl, + productStockServiceUrl+ "/checkProductsStock", HttpMethod.POST, - new HttpEntity<>(productQuantities), + new HttpEntity<>(productStockRequestDTOS), new ParameterizedTypeReference<>() {} ); return responseEntity.getBody(); } @Override - public ProductStockDTO checkStock(Long id, Long quantityToAdd) { - String url = productStockServiceUrl + "/" + id + "/" + quantityToAdd; - return restTemplate.getForObject(url, ProductStockDTO.class); + public ProductStockDTO checkStock(ProductStockRequestDTO productStockRequestDTO) { + String url = productStockServiceUrl + "/checkProductStock"; + try { + ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, productStockRequestDTO, String.class); + return new ObjectMapper().readValue(responseEntity.getBody(), ProductStockDTO.class); + } catch (JsonProcessingException e) { + throw new RuntimeException("Failed to parse JSON response", e); + } } + } diff --git a/src/main/java/com/marketingconfort/mydressin/services/SaleSessionService.java b/src/main/java/com/marketingconfort/mydressin/services/SaleSessionService.java index ee56517830b2e7f33fb3229bc3e19b95a09212fe..9d4e71147ab1c46d13731e86defd5f7ba9a0a2f0 100644 --- a/src/main/java/com/marketingconfort/mydressin/services/SaleSessionService.java +++ b/src/main/java/com/marketingconfort/mydressin/services/SaleSessionService.java @@ -1,10 +1,16 @@ package com.marketingconfort.mydressin.services; import com.marketingconfort.mydressin.common.cart.models.SaleSession; + +import com.marketingconfort.mydressin.common.cart.models.SessionOrder; import com.marketingconfort.mydressin.dtos.SaleSessionDTO; +import com.marketingconfort.mydressin.dtos.SessionRequest; +import com.marketingconfort.mydressin.exceptions.SaleSessionExpiredException; import java.util.List; public interface SaleSessionService { SaleSessionDTO createSaleSession(SaleSession saleSession); + List<SaleSessionDTO> getAllSaleSessions(); + } diff --git a/src/main/java/com/marketingconfort/mydressin/services/SaleSessionServiceImp.java b/src/main/java/com/marketingconfort/mydressin/services/SaleSessionServiceImp.java index ebda4389bacce623d2557d2334df64a26ff57e82..8a21a17fc578fb4ef468f7f72db4418a40c08311 100644 --- a/src/main/java/com/marketingconfort/mydressin/services/SaleSessionServiceImp.java +++ b/src/main/java/com/marketingconfort/mydressin/services/SaleSessionServiceImp.java @@ -1,20 +1,44 @@ package com.marketingconfort.mydressin.services; +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockDTO; +import com.marketingconfort.mydressin.common.cart.dtos.ProductStockRequestDTO; +import com.marketingconfort.mydressin.common.cart.enumurations.ItemCartStatus; +import com.marketingconfort.mydressin.common.cart.enumurations.ItemSource; +import com.marketingconfort.mydressin.common.cart.enumurations.OrderStatus; +import com.marketingconfort.mydressin.common.cart.models.Cart; +import com.marketingconfort.mydressin.common.cart.models.ItemCart; import com.marketingconfort.mydressin.common.cart.models.SaleSession; + +import com.marketingconfort.mydressin.common.cart.models.SessionOrder; import com.marketingconfort.mydressin.dtos.SaleSessionDTO; +import com.marketingconfort.mydressin.dtos.SessionRequest; +import com.marketingconfort.mydressin.exceptions.CartNotFoundException; +import com.marketingconfort.mydressin.exceptions.ProductOutOfStockException; +import com.marketingconfort.mydressin.exceptions.SaleSessionExpiredException; +import com.marketingconfort.mydressin.exceptions.SaleSessionNotFoundException; import com.marketingconfort.mydressin.mappers.SaleSessionMapper; import com.marketingconfort.mydressin.repositories.SaleSessionRepository; +import com.marketingconfort.mydressin.repositories.SessionOrderRepository; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; @AllArgsConstructor @Service -public class SaleSessionServiceImp implements SaleSessionService{ +public class SaleSessionServiceImp implements SaleSessionService { private final SaleSessionRepository saleSessionRepository; private final SaleSessionMapper saleSessionMapper; + private final ItemCartService itemCartService; + private final CartService cartService; + private final ProductStockService productStockService; + private final SessionOrderRepository orderRepository; + @Override public SaleSessionDTO createSaleSession(SaleSession saleSession) { @@ -22,5 +46,44 @@ public class SaleSessionServiceImp implements SaleSessionService{ return saleSessionMapper.toDTO(savedSaleSession); } + @Override + public List<SaleSessionDTO> getAllSaleSessions() { + return saleSessionRepository.findAll().stream() + .map(this::getSessionStatistics) + .collect(Collectors.toList()); + } + public SaleSessionDTO getSessionStatistics(SaleSession saleSession) { + List<SessionOrder> orders = saleSession.getOrders(); + + + Set<Long> uniqueClientIds = orders.stream() + .map(SessionOrder::getClientId) + .collect(Collectors.toSet()); + int numberOfClients = uniqueClientIds.size(); + + + long numberOfPaidProducts = orders.stream() + .filter(order -> order.getItemCart().getStatus() == ItemCartStatus.PAYER) + .mapToLong(order -> order.getItemCart().getQuantity()) + .sum(); + + long numberOfDeletedProducts = orders.stream() + .filter(order -> order.getItemCart().getStatus() == ItemCartStatus.SUPPRIMER) + .mapToLong(order -> order.getItemCart().getQuantity()) + .sum(); + + long numberOfConsultedProducts = orders.stream() + .filter(order -> order.getItemCart().getStatus() == ItemCartStatus.CONSULTER) + .mapToLong(order -> order.getItemCart().getQuantity()) + .sum(); + + SaleSessionDTO saleSessionDTO=saleSessionMapper.toDTO(saleSession); + saleSessionDTO.setClientsNumber(numberOfClients); + saleSessionDTO.setPaidProductsNumber(numberOfPaidProducts); + saleSessionDTO.setDeletedProductsNumber(numberOfDeletedProducts); + saleSessionDTO.setConsultedProductsNumber(numberOfConsultedProducts); + + return saleSessionDTO; + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 526375ae2a1e793669e0a672661a1457c1723cd4..ab90609f4e01bd962086739851cacd9c615351eb 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -33,7 +33,7 @@ spring: product: stock: service: - url: https://mydressin-stock-management-service.mc-test.xyz/api/stock/products/checkStock + url: http://localhost:8080/api/stock/products promoCode: service: