Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

Commit

Permalink
#91 Implement full product draft conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
PapaBravo committed Jun 5, 2020
1 parent f94108a commit 20d2ac3
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 33 deletions.
2 changes: 0 additions & 2 deletions src/main/java/com/diconiumwvv/storesservice/WebConfig.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.diconiumwvv.storesservice;

import com.diconiumwvv.storesservice.products.ProductDraftDTOToProductDraftConverter;
import com.diconiumwvv.storesservice.products.ProductProjectionToProductDTOConverter;
import com.diconiumwvv.storesservice.stores.dtos.StoreDraftDTOToStoreDraftConverter;
import com.diconiumwvv.storesservice.stores.dtos.StoreToStoreDTOConverter;
Expand All @@ -14,7 +13,6 @@ public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new ProductProjectionToProductDTOConverter());
registry.addConverter(new ProductDraftDTOToProductDraftConverter());
registry.addConverter(new StoreToStoreDTOConverter());
registry.addConverter(new StoreDraftDTOToStoreDraftConverter());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.diconiumwvv.storesservice.products;

import com.diconiumwvv.storesservice.products.dtos.ProductDraftDTO;
import io.sphere.sdk.channels.Channel;
import io.sphere.sdk.models.DefaultCurrencyUnits;
import io.sphere.sdk.models.LocalizedString;
import io.sphere.sdk.models.ResourceIdentifier;
import io.sphere.sdk.products.*;
import org.springframework.stereotype.Service;

import java.text.Normalizer;
import java.util.Locale;

@Service
public class ProductCTConverter {

static Locale userLocale = Locale.GERMANY;

ProductVariantDraft convertVariantDraftWithPrice(ProductDraftDTO productDraftDTO, Channel store) {
return ProductVariantDraftBuilder.of()
.price(
PriceDraft.of(
productDraftDTO.getPrice().getValue(),
DefaultCurrencyUnits.EUR // TODO read currency unit from input?
).withChannel(store)
)
.build();
}


LocalizedString buildSlug(LocalizedString productName, Channel store) {
String defaultLocaleName = productName.get(userLocale);
String defaultLocaleSlug = store.getKey() + "_" + defaultLocaleName;
String normalizedSlug = normalizeString(defaultLocaleSlug);
return LocalizedString.of(userLocale, normalizedSlug);
}

private String normalizeString(String original) {
String normalized = Normalizer.normalize(original, Normalizer.Form.NFD);
normalized = normalized.replaceAll("[^a-zA-Z_\\-]", "");
return normalized.toLowerCase();
}

public ProductDraft convert(ProductDraftDTO productDraftDTO, Channel store, String productTypeKey) {
return ProductDraftBuilder.of(
ResourceIdentifier.ofKey(productTypeKey),
productDraftDTO.getName(),
buildSlug(productDraftDTO.getName(), store),
convertVariantDraftWithPrice(productDraftDTO, store)
).build();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ public ProductDTO getProductById(@ApiParam(value = "id", required = true, exampl
public ProductDTO createProduct(
@ApiParam(
value = "id",
name = "Store ID",
name = "id",
example = "ddf24dc6-1a2d-4391-8f34-c5c322b21c1e")
@PathVariable String id,
@RequestBody ProductDraftDTO productDraftDTO
) throws InterruptedException, ExecutionException, SbhException {
return productsService.createProduct(productDraftDTO);
return productsService.createProduct(productDraftDTO, id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.diconiumwvv.storesservice.exceptions.SbhException;
import com.diconiumwvv.storesservice.products.dtos.ProductDTO;
import com.diconiumwvv.storesservice.products.dtos.ProductDraftDTO;
import com.diconiumwvv.storesservice.stores.StoresService;
import io.sphere.sdk.channels.Channel;
import io.sphere.sdk.client.BlockingSphereClient;
import io.sphere.sdk.products.Product;
import io.sphere.sdk.products.ProductDraft;
Expand Down Expand Up @@ -33,6 +35,12 @@ public class ProductsService {
@Resource
private ConversionService conversionService;

@Resource
private ProductCTConverter productCTConverter;

@Resource
private StoresService storesService;


public ProductProjection getProductByID(String productId) {
return client.executeBlocking(ProductProjectionByIdGet.ofCurrent(productId));
Expand All @@ -53,18 +61,27 @@ public List<ProductProjection> getProductsByStore(String storeId) {
return pagedQueryResult.getResults();
}

public ProductDTO createProduct(final ProductDraftDTO productDraftDTO) throws SbhException, ExecutionException, InterruptedException {
log.info("About to create a new product {}", productDraftDTO.getName());
public ProductDTO createProduct(final ProductDraftDTO productDraftDTO, final String channelId)
throws SbhException, ExecutionException, InterruptedException {
log.info("About to create a new product {} {}", productDraftDTO.getName(), channelId);

if (channelId == null || productDraftDTO.getName() == null) {
throw new SbhException("Product incomplete. Could not create product.");
}

Channel store = storesService.getStoreForID(channelId);
if (store == null) {
throw new SbhException("Store for your product is not available.");
}

ProductDraft productDraft = conversionService.convert(productDraftDTO, ProductDraft.class);
ProductDraft productDraft = productCTConverter.convert(productDraftDTO, store, "default-product-type");
if (productDraft == null) {
throw new SbhException("Product draft could not be converted.");
}

Product product = client.execute(ProductCreateCommand.of(productDraft)).toCompletableFuture().get();
Product publishedProduct = client.execute(ProductUpdateCommand.of(product, Publish.of())).toCompletableFuture().get();

// TODO: combine product with store
return conversionService.convert(publishedProduct.toProjection(ProductProjectionType.CURRENT), ProductDTO.class);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.diconiumwvv.storesservice.products.dtos;

import io.sphere.sdk.models.LocalizedString;
import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class ProductDraftDTO {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.diconiumwvv.storesservice.products;

import com.diconiumwvv.storesservice.products.dtos.PriceDTO;
import com.diconiumwvv.storesservice.products.dtos.ProductDraftDTO;
import io.sphere.sdk.channels.Channel;
import io.sphere.sdk.json.SphereJsonUtils;
import io.sphere.sdk.models.LocalizedString;
import io.sphere.sdk.products.ProductDraft;
import io.sphere.sdk.products.ProductVariantDraft;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.util.Locale;

import static org.assertj.core.api.Assertions.assertThat;

public class ProductCTConverterTest {

private static final String DEFAULT_PRODUCT_KEY = "Default-Product-Key";
private static final Locale TEST_LOCALE = Locale.GERMANY;

private static final String PRODUCT_NAME = "Product Name";
private static final String PRODUCT_DESCRIPTION = "Product Description";
private static final String STORE_KEY = "test-channel-key";
private static final String STORE_ID = "test-channel-id";

private final ProductCTConverter productCTConverter = new ProductCTConverter();

private Channel testStore;

@BeforeEach
void setUp() {
testStore = setUpTestStore();
}

private Channel setUpTestStore() {

return SphereJsonUtils.readObject("{\n" +
" \"id\": \"" + STORE_ID + "\",\n" +
" \"key\": \"" + STORE_KEY + "\"\n" +
"}", Channel.typeReference());
}

private ProductDraftDTO buildProductDraft(String productName, String productDescription) {
return ProductDraftDTO.builder()
.name(LocalizedString.of(TEST_LOCALE, productName))
.description(LocalizedString.of(TEST_LOCALE, productDescription))
.price(PriceDTO.builder().value(BigDecimal.TEN).currencyCode("EUR").build())
.build();
}

@Test
void convertProductDraft() {
final ProductDraftDTO testDraft = buildProductDraft(PRODUCT_NAME, PRODUCT_DESCRIPTION);

ProductDraft convertedProductDraft = productCTConverter.convert(testDraft, testStore, DEFAULT_PRODUCT_KEY);
ProductVariantDraft masterVariant = convertedProductDraft.getMasterVariant();

assertThat(convertedProductDraft).isNotNull();
assertThat(convertedProductDraft.getProductType().getKey()).isEqualTo(DEFAULT_PRODUCT_KEY);
assertThat(convertedProductDraft.getSlug().get(TEST_LOCALE)).contains(STORE_KEY);

assertThat(masterVariant).isNotNull();
assertThat(masterVariant.getPrices()).isNotNull();
assertThat(masterVariant.getPrices().get(0)).isNotNull();
assertThat(masterVariant.getPrices().get(0).getChannel()).isNotNull();
assertThat(masterVariant.getPrices().get(0).getChannel().getId()).isEqualTo(STORE_ID);


}

@Test
void normalizeNameForSlug() {
final ProductDraftDTO testDraft = buildProductDraft("name%with+special?CHARACTERS&", PRODUCT_DESCRIPTION);
ProductDraft convertedProductDraft = productCTConverter.convert(testDraft, testStore, DEFAULT_PRODUCT_KEY);

// test for product name normalization
String createdSlug = convertedProductDraft.getSlug().get(TEST_LOCALE);
assertThat(createdSlug).doesNotContain("%");
assertThat(createdSlug).doesNotContain("+");
assertThat(createdSlug).doesNotContain("?");
assertThat(createdSlug).doesNotContain("&");
assertThat(createdSlug).contains("special");
assertThat(createdSlug).contains("characters");
assertThat(createdSlug).contains(STORE_KEY.toLowerCase());
}
}

0 comments on commit 20d2ac3

Please sign in to comment.