Skip to content

Commit

Permalink
Merge pull request #138 from commercetools/134-tax-category-cli
Browse files Browse the repository at this point in the history
#134 Add CLI logic options -s Tax Categories
  • Loading branch information
leungkinghin-ct authored Aug 12, 2020
2 parents 94034a0 + c1d881d commit 7453325
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
import static io.sphere.sdk.models.LocalizedString.ofEnglish;
import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;

import com.commercetools.project.sync.model.response.LastSyncCustomObject;
import com.commercetools.sync.commons.helpers.BaseSyncStatistics;
import com.commercetools.sync.products.helpers.ProductSyncStatistics;
import com.neovisionaries.i18n.CountryCode;
import io.sphere.sdk.cartdiscounts.CartDiscount;
import io.sphere.sdk.cartdiscounts.CartDiscountDraft;
import io.sphere.sdk.cartdiscounts.CartDiscountDraftBuilder;
Expand Down Expand Up @@ -56,6 +58,13 @@
import io.sphere.sdk.states.StateType;
import io.sphere.sdk.states.commands.StateCreateCommand;
import io.sphere.sdk.states.queries.StateQuery;
import io.sphere.sdk.taxcategories.TaxCategory;
import io.sphere.sdk.taxcategories.TaxCategoryDraft;
import io.sphere.sdk.taxcategories.TaxCategoryDraftBuilder;
import io.sphere.sdk.taxcategories.TaxRateDraft;
import io.sphere.sdk.taxcategories.TaxRateDraftBuilder;
import io.sphere.sdk.taxcategories.commands.TaxCategoryCreateCommand;
import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery;
import io.sphere.sdk.types.ResourceTypeIdsSetBuilder;
import io.sphere.sdk.types.Type;
import io.sphere.sdk.types.TypeDraft;
Expand Down Expand Up @@ -120,6 +129,21 @@ static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClie

sourceProjectClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join();

final TaxRateDraft taxRateDraft =
TaxRateDraftBuilder.of("Tax-Rate-Name-1", 0.3, false, CountryCode.DE).build();

final TaxCategoryDraft taxCategoryDraft =
TaxCategoryDraftBuilder.of(
"Tax-Category-Name-1", singletonList(taxRateDraft), "Tax-Category-Description-1")
.key(RESOURCE_KEY)
.build();

final TaxCategory taxCategory =
sourceProjectClient
.execute(TaxCategoryCreateCommand.of(taxCategoryDraft))
.toCompletableFuture()
.join();

final CategoryDraft categoryDraft =
CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts"))
.key(RESOURCE_KEY)
Expand All @@ -137,6 +161,7 @@ static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClie
ofEnglish("v-neck-tee"),
ProductVariantDraftBuilder.of().key(RESOURCE_KEY).sku(RESOURCE_KEY).build())
.state(state)
.taxCategory(taxCategory)
.key(RESOURCE_KEY)
.build();

Expand Down Expand Up @@ -368,6 +393,9 @@ private ZonedDateTime assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt(

assertLastSyncCustomObjectExists(
postTargetClient, sourceProjectKey, "stateSync", "runnerName");

assertLastSyncCustomObjectExists(
postTargetClient, sourceProjectKey, "taxCategorySync", "runnerName");
}
}
}
Expand Down Expand Up @@ -476,6 +504,17 @@ private static void assertAllResourcesAreSyncedToTarget(
.hasSize(1)
.hasOnlyOneElementSatisfying(type -> assertThat(type.getKey()).isEqualTo(RESOURCE_KEY));

final PagedQueryResult<TaxCategory> taxCategoryQueryResult =
targetClient
.execute(TaxCategoryQuery.of().withPredicates(QueryPredicate.of(queryPredicate)))
.toCompletableFuture()
.join();

assertThat(taxCategoryQueryResult.getResults())
.hasSize(1)
.hasOnlyOneElementSatisfying(
taxCategory -> assertThat(taxCategory.getKey()).isEqualTo(RESOURCE_KEY));

final PagedQueryResult<InventoryEntry> inventoryEntryQueryResult =
targetClient
.execute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents;
import static io.sphere.sdk.models.LocalizedString.ofEnglish;
import static java.util.Arrays.asList;
Expand Down Expand Up @@ -230,6 +231,7 @@ void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldExecuteAllSyncers() {

assertTypeSyncerLoggingEvents(syncerTestLogger, 0);
assertProductTypeSyncerLoggingEvents(syncerTestLogger, 2);
assertTaxCategorySyncerLoggingEvents(syncerTestLogger, 0);
assertCategorySyncerLoggingEvents(syncerTestLogger, 1);
assertProductSyncerLoggingEvents(syncerTestLogger, 1);
assertInventoryEntrySyncerLoggingEvents(syncerTestLogger, 0);
Expand All @@ -238,7 +240,7 @@ void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldExecuteAllSyncers() {
syncerTestLogger, 1); // 1 state is built-in and it will always be processed

// Every sync module is expected to have 2 logs (start and stats summary)
assertThat(syncerTestLogger.getAllLoggingEvents()).hasSize(14);
assertThat(syncerTestLogger.getAllLoggingEvents()).hasSize(16);

assertAllResourcesAreSyncedToTarget(postTargetClient);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents;
import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents;
import static io.sphere.sdk.models.LocalizedString.ofEnglish;
import static java.lang.String.format;
Expand Down Expand Up @@ -195,6 +196,7 @@ void run_WithAProductWith500DistinctReferences_ShouldSyncCorrectly() {

assertTypeSyncerLoggingEvents(syncerTestLogger, 0);
assertProductTypeSyncerLoggingEvents(syncerTestLogger, 1);
assertTaxCategorySyncerLoggingEvents(syncerTestLogger, 0);
assertCategorySyncerLoggingEvents(syncerTestLogger, 0);
assertProductSyncerLoggingEvents(syncerTestLogger, 501);
assertInventoryEntrySyncerLoggingEvents(syncerTestLogger, 0);
Expand All @@ -203,7 +205,7 @@ void run_WithAProductWith500DistinctReferences_ShouldSyncCorrectly() {
syncerTestLogger, 1); // 1 state is built-in and it cant be deleted

// Every sync module is expected to have 2 logs (start and stats summary)
assertThat(syncerTestLogger.getAllLoggingEvents()).hasSize(14);
assertThat(syncerTestLogger.getAllLoggingEvents()).hasSize(16);

assertAllResourcesAreSyncedToTarget(postTargetClient);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
import io.sphere.sdk.queries.QueryPredicate;
import io.sphere.sdk.states.commands.StateDeleteCommand;
import io.sphere.sdk.states.queries.StateQuery;
import io.sphere.sdk.taxcategories.commands.TaxCategoryDeleteCommand;
import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery;
import io.sphere.sdk.types.commands.TypeDeleteCommand;
import io.sphere.sdk.types.queries.TypeQuery;
import java.util.ArrayList;
Expand Down Expand Up @@ -141,6 +143,7 @@ private static void deleteProjectData(@Nonnull final SphereClient client) {
StateQuery.of().plusPredicates(QueryPredicate.of("builtIn=\"false\"")),
StateDeleteCommand::of);
queryAndExecute(client, TypeQuery.of(), TypeDeleteCommand::of);
queryAndExecute(client, TaxCategoryQuery.of(), TaxCategoryDeleteCommand::of);
deleteProductTypes(client);
}

Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/commercetools/project/sync/CliRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ final class CliRunner {
static final String SYNC_MODULE_OPTION_PRODUCT_SYNC = "products";
static final String SYNC_MODULE_OPTION_INVENTORY_ENTRY_SYNC = "inventoryEntries";
static final String SYNC_MODULE_OPTION_STATE_SYNC = "states";
static final String SYNC_MODULE_OPTION_TAX_CATEGORY_SYNC = "taxCategories";
static final String SYNC_MODULE_OPTION_ALL = "all";

static final String SYNC_MODULE_OPTION_DESCRIPTION =
format(
"Choose one of the following modules to run: \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\" or \"%s\".",
"Choose one of the following modules to run: \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\" or \"%s\".",
SYNC_MODULE_OPTION_TYPE_SYNC,
SYNC_MODULE_OPTION_PRODUCT_TYPE_SYNC,
SYNC_MODULE_OPTION_STATE_SYNC,
SYNC_MODULE_OPTION_TAX_CATEGORY_SYNC,
SYNC_MODULE_OPTION_CATEGORY_SYNC,
SYNC_MODULE_OPTION_CART_DISCOUNT_SYNC,
SYNC_MODULE_OPTION_PRODUCT_SYNC,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_PRODUCT_TYPE_SYNC;
import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_SHORT;
import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_STATE_SYNC;
import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_TAX_CATEGORY_SYNC;
import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_TYPE_SYNC;
import static io.sphere.sdk.utils.CompletableFutureUtils.exceptionallyCompletedFuture;
import static java.lang.String.format;
Expand All @@ -21,6 +22,7 @@
import com.commercetools.project.sync.product.ProductSyncer;
import com.commercetools.project.sync.producttype.ProductTypeSyncer;
import com.commercetools.project.sync.state.StateSyncer;
import com.commercetools.project.sync.taxcategory.TaxCategorySyncer;
import com.commercetools.project.sync.type.TypeSyncer;
import com.commercetools.sync.commons.BaseSync;
import com.commercetools.sync.commons.BaseSyncOptions;
Expand Down Expand Up @@ -78,6 +80,10 @@ CompletableFuture<Void> syncAll(
.toCompletableFuture());

return CompletableFuture.allOf(typeAndProductTypeAndStateSync.toArray(new CompletableFuture[0]))
.thenCompose(
ignored ->
TaxCategorySyncer.of(sourceClient, targetClient, clock)
.sync(runnerNameOptionValue, isFullSync))
.thenCompose(
ignored ->
CategorySyncer.of(sourceClient, targetClient, clock)
Expand Down Expand Up @@ -168,6 +174,8 @@ CompletionStage<Void> sync(
case SYNC_MODULE_OPTION_INVENTORY_ENTRY_SYNC:
return InventoryEntrySyncer.of(
sourceClientSupplier.get(), targetClientSupplier.get(), clock);
case SYNC_MODULE_OPTION_TAX_CATEGORY_SYNC:
return TaxCategorySyncer.of(sourceClientSupplier.get(), targetClientSupplier.get(), clock);
case SYNC_MODULE_OPTION_TYPE_SYNC:
return TypeSyncer.of(sourceClientSupplier.get(), targetClientSupplier.get(), clock);
case SYNC_MODULE_OPTION_STATE_SYNC:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ protected CompletionStage<List<TaxCategoryDraft>> transform(
@Nonnull
private static TaxCategoryDraft convertTaxCategoryToTaxCategoryDraft(
@Nonnull final TaxCategory taxCategory) {
List<TaxRateDraft> taxRateDrafts = null;
taxRateDrafts = convertTaxRateToTaxRateDraft(taxCategory.getTaxRates());
List<TaxRateDraft> taxRateDrafts = convertTaxRateToTaxRateDraft(taxCategory.getTaxRates());
return TaxCategoryDraftBuilder.of(
taxCategory.getName(), taxRateDrafts, taxCategory.getDescription())
.key(taxCategory.getKey())
Expand Down
64 changes: 63 additions & 1 deletion src/test/java/com/commercetools/project/sync/CliRunnerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.sphere.sdk.producttypes.queries.ProductTypeQuery;
import io.sphere.sdk.queries.PagedQueryResult;
import io.sphere.sdk.states.queries.StateQuery;
import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery;
import io.sphere.sdk.types.queries.TypeQuery;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
Expand Down Expand Up @@ -247,6 +248,58 @@ void run_AsProductFullSync_ShouldBuildSyncerAndExecuteSync() {
verify(syncerFactory, never()).syncAll(null, true);
}

@Test
void run_AsTaxCategoryDeltaSync_ShouldBuildSyncerAndExecuteSync() {
// preparation
final SphereClient sourceClient = mock(SphereClient.class);
when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo"));

final SphereClient targetClient = mock(SphereClient.class);
when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar"));

when(sourceClient.execute(any(ProductQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));

final SyncerFactory syncerFactory =
spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()));

stubClientsCustomObjectService(targetClient, ZonedDateTime.now());

// test
CliRunner.of().run(new String[] {"-s", "taxCategories"}, syncerFactory);

// assertions
verify(syncerFactory, times(1)).sync("taxCategories", null, false);
verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class));
verify(syncerFactory, never()).syncAll(null, false);
}

@Test
void run_AsTaxCategoryFullSync_ShouldBuildSyncerAndExecuteSync() {
// preparation
final SphereClient sourceClient = mock(SphereClient.class);
when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo"));

final SphereClient targetClient = mock(SphereClient.class);
when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar"));

when(sourceClient.execute(any(TaxCategoryQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));

final SyncerFactory syncerFactory =
spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()));

stubClientsCustomObjectService(targetClient, ZonedDateTime.now());

// test
CliRunner.of().run(new String[] {"-s", "taxCategories", "-f"}, syncerFactory);

// assertions
verify(syncerFactory, times(1)).sync("taxCategories", null, true);
verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class));
verify(syncerFactory, never()).syncAll(null, true);
}

@Test
void run_AsCartDiscountFullSync_ShouldBuildSyncerAndExecuteSync() {
// preparation
Expand Down Expand Up @@ -458,6 +511,8 @@ void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncers() {
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));
when(sourceClient.execute(any(StateQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));
when(sourceClient.execute(any(TaxCategoryQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));

stubClientsCustomObjectService(targetClient, ZonedDateTime.now());

Expand All @@ -471,6 +526,7 @@ void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncers() {
verify(syncerFactory, times(1)).syncAll(null, false);
verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class));
verify(sourceClient, times(1)).execute(any(TypeQuery.class));
verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class));
verify(sourceClient, times(1)).execute(any(CategoryQuery.class));
verify(sourceClient, times(1)).execute(any(ProductQuery.class));
verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class));
Expand Down Expand Up @@ -501,6 +557,8 @@ void run_WithSyncAsArgumentWithAllArgWithRunnerName_ShouldExecuteAllSyncers() {
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));
when(sourceClient.execute(any(StateQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));
when(sourceClient.execute(any(TaxCategoryQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));

stubClientsCustomObjectService(targetClient, ZonedDateTime.now());

Expand All @@ -514,6 +572,7 @@ void run_WithSyncAsArgumentWithAllArgWithRunnerName_ShouldExecuteAllSyncers() {
verify(syncerFactory, times(1)).syncAll("myRunner", false);
verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class));
verify(sourceClient, times(1)).execute(any(TypeQuery.class));
verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class));
verify(sourceClient, times(1)).execute(any(CategoryQuery.class));
verify(sourceClient, times(1)).execute(any(ProductQuery.class));
verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class));
Expand Down Expand Up @@ -544,6 +603,8 @@ void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncersInCorrectOrder() {
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));
when(sourceClient.execute(any(StateQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));
when(sourceClient.execute(any(TaxCategoryQuery.class)))
.thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty()));

stubClientsCustomObjectService(targetClient, ZonedDateTime.now());

Expand All @@ -561,11 +622,12 @@ void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncersInCorrectOrder() {
inOrder.verify(sourceClient).execute(any(ProductTypeQuery.class));
inOrder.verify(sourceClient).execute(any(TypeQuery.class));
inOrder.verify(sourceClient).execute(any(StateQuery.class));
inOrder.verify(sourceClient).execute(any(TaxCategoryQuery.class));
inOrder.verify(sourceClient).execute(any(CategoryQuery.class));
inOrder.verify(sourceClient).execute(any(ProductQuery.class));
inOrder.verify(sourceClient).execute(any(CartDiscountQuery.class));
inOrder.verify(sourceClient).execute(any(InventoryEntryQuery.class));

verifyInteractionsWithClientAfterSync(sourceClient, 7);
verifyInteractionsWithClientAfterSync(sourceClient, 8);
}
}
Loading

0 comments on commit 7453325

Please sign in to comment.