Sitecore Commerce Connect – Teil 3: Klassifizierungen synchronisieren

Im letzten Teil dieser Serie ging es um die Synchronisation von Produkten. Das Ziel dieses Blog-Artikels ist es auch Klassifizierungen unidirektional aus dem Sitecore heraus mit dem externen Commerce System (kurz ECS, in unserem Fall Hybris) zu synchronisieren und den Produkten zuzuordnen.

Klassifizierungen sind im Projekt individuell definierbare Spezifikationen zur Beschreibung von Produkten. Die sog. Classifications in Sitecore können über eine Parent-Verknüpfung (ExternalParentID) beliebig geschachtelt werden, die erste Ebene ist aber immer eine Gruppe, eine sog. ClassificationGroup.
ClassificationRepo

Synchronisation Klassifizierungen

Um Klassifizierungen zu synchronisieren muss zunächst die Pipeline ’synchronizeClassifications‘ der Sitecore.Commerce.Products.config erweitert werden:

Pipeline synchronizeClassifications

.config

<!-- SYNCHRONIZE CLASSIFICATIONS -->
<commerce.synchronizeProducts.synchronizeClassifications>
	<processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ReadSitecoreClassifications, Sitecore.Commerce">
		<patch:delete />
	</processor>
	<processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ResolveClassificationsChanges, Sitecore.Commerce">
		<patch:delete />
	</processor>
	<processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.SaveClassificationsToExternalCommerceSystem, Sitecore.Commerce" >
		<patch:delete />
	</processor>
	<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications.ReadClassifications, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type='Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ReadExternalCommerceSystemClassifications, Sitecore.Commerce']" />
	<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications.ReadClassificationGroups, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type='Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ReadExternalCommerceSystemClassifications, Sitecore.Commerce']" />
</commerce.synchronizeProducts.synchronizeClassifications>

Processor ReadClassificationGroups

using System.Collections.Generic;
using System.Linq;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Entities.Products;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications
{
	/// <summary>
	/// commerce.synchronizeProducts.synchronizeClassifications
	/// </summary>
	public class ReadClassificationGroups : PipelineProcessor<ServicePipelineArgs>
	{
		public override void Process(ServicePipelineArgs args)
		{
			var request = args.Request as SynchronizationRequest;
			var groups = request.Properties["ClassificationGroups"] as List<ClassificationGroup>; //integration guide (page 9)
			groups = groups ?? new List<ClassificationGroup>();

			//get groups from ECS
			IEnumerable<ExternalCategoryGroup> categoryGroups = ClassificationConnector.Load(request.Language);

			//convert and add to commerce connect list
			groups.AddRange(from @group in categoryGroups
			 select new ClassificationGroup
			 {
				 ExternalId = @group.Code,
				 Name = @group.Name
			 });

			//persist for next processor
			request.Properties["ClassificationGroups"] = groups;
		}
	}
}

Processor ReadClassifications

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Entities.Products;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications
{
	/// <summary>
	/// commerce.synchronizeProducts.synchronizeClassifications
	/// </summary>
	public class ReadClassifications : PipelineProcessor<ServicePipelineArgs>
	{
		public override void Process(ServicePipelineArgs args)
		{
			var request = args.Request as SynchronizationRequest;
			var groups = request.Properties["ClassificationGroups"] as List<ClassificationGroup>; ////integration guide (page 9)
			groups = groups != null ? groups : new List<ClassificationGroup>();

			foreach (ClassificationGroup group in groups)
			{
				var classifications = new List<Classification>();

				//get categories from ECS
				foreach (ExternalCategory externalCategory in ClassificationConnector.Load(group.ExternalId, request.Language)) //TBD
				{
					//convert to commerce connect classification
					var classification = new Classification();
					classification.ExternalId = externalCategory.Code;
					classification.Name = externalCategory.Name;
					classifications.Add(classification);

					//...with sub-classifications
					HandleSubCategories(externalCategory, classifications);
				}
				group.Classifications = new ReadOnlyCollection<Classification>(classifications);
			}

			//persist for next processor
			request.Properties["ClassificationGroups"] = groups;
		}

		private static void HandleSubCategories(ExternalCategory parentCategory, List<Classification> allClassifications)
		{
			if (parentCategory.Categories != null)
			{
				foreach (var category in parentCategory.Categories)
				{
					var classification = new Classification();
					classification.ExternalId = category.Code;
					classification.Name = category.Name;
					classification.ExternalParentId = parentCategory.Code;

					allClassifications.Add(classification);
					HandleSubCategories(category, allClassifications);
				}
			}
		}
	}
}

Klassifizierungen Produkten zuordnen

Anschließend müssen die Klassifizierungen nur noch den Produkten zugeordnet werden. Und auch dafür muss wieder eine Pipeline der Sitecore.Commerce.Products.config erweitert werden:

Pipeline synchronizeProductClassifications

.config

<!-- SYNCHRONIZE PRODUCT CLASSIFICATIONS
	This pipeline is responsible for synchronizing and updating the references between a given product and associated classifications and categories within.
	It’s assumed that classifications are already synchronized and present in CMS.
	The references to categories are stored directly on the main product item. -->
<commerce.synchronizeProducts.synchronizeProductClassifications>
	<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products.ReadProductClassifications, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type='Sitecore.Commerce.Pipelines.Products.SynchronizeProductClassifications.ReadExternalCommerceSystemProductClassifications, Sitecore.Commerce']" />
</commerce.synchronizeProducts.synchronizeProductClassifications>

Processor ReadProductClassifications

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Entities.Products;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products
{
	/// <summary>
	/// commerce.synchronizeProducts.synchronizeProductClassifications
	/// </summary>
	public class ReadProductClassifications : ReadProduct
	{
		public override void Process(ServicePipelineArgs args)
		{
			var request = args.Request as SynchronizeProductRequest;
			var product = request.Properties["Product"] as Product;
			var groups = request.Properties["ClassificationGroups"] as List<ClassificationGroup>;
			groups = groups != null ? groups : new List<ClassificationGroup>();

			//get product from ECS
			ExternalProduct externalProduct = ProductConnector.Load(request.Language, product.ExternalId); //tbd
			if (externalProduct != null && IsProductValidForImport(externalProduct))
			{
				//convert to commerce connect product classification groups and classifications
				foreach (ExternalCategoryGroup externalCategoryGroup in externalProduct.CategoryGroups)
				{
					ClassificationGroup group = new ClassificationGroup();
					group.ExternalId = externalCategoryGroup.Code;
					group.Name = externalCategoryGroup.Name;

					IEnumerable<Classification> classifications = from externalCategory in externalCategoryGroup.Categories
					 select new Classification
					 {
						 ExternalId = externalCategory.Code,
						 Name = externalCategory.Name
					 };
					group.Classifications = new ReadOnlyCollection<Classification>(classifications.ToList());

					groups.Add(group);
				}
			}

			//persist for next processor
			request.Properties["ClassificationGroups"] = groups;
		}
	}
}

Resumé

Mein erster Eindruck:

  • Es gibt viel Dokumentation, aber z.B. zum Thema Zuordnung von Klassifikationen zu Produkten konnte ich nichts finden. Da habt ihr es jetzt ja besser ;) Häufig war dann doch dotPeek mein bester Freund.
  • Der Differenzabgleich funktionierte problemlos, Mehrsprachigkeit war im Kontext der Zuordnung von Klassifizierungen zu Produkten noch etwas holprig, da sollte ein zweiter Blick erfolgen.

Wenn ihr mehr zum Sitecore Commerce Connect wissen wollt, dann schaut mal hier:

Über Friederike Heinze

Friederike Heinze arbeitet im Team Solution Architecture bei comspace. Im Projekt ist sie für eine Überführung von Anforderungen in technische Lösungen verantwortlich. Als Sitecore Expertin beobachtet sie Neuentwicklungen und Veränderungen auch über ein Projekt hinaus.
Artikel teilen:

Verwandte Themen

Trackbacks/ Pingbacks

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.