Step 8: Implementing the Processor Classes
For each pair of entities that you need to synchronize, you need to create a processor class. For details about processor classes, see Processor Classes.
Implementing the Processor Classes
- For each pair of entities that you need to synchronize, in the Visual Studio
project of the extension library, create a processor class that derives from the
PX.Commerce.Core.IProcessor interface and,
optionally, the PX.Commerce.Core.BCProcessorSingleBase<TGraph,
TEntityBucket, TPrimaryMapped> abstract class. In this example,
you are creating the
WooCustomerProcessor
class. - Assign the BCProcessor and
BCProcessorRealtime attributes to the class and define
the methods that perform the synchronization of the entities. The following code
shows the implementation for the example in this chapter.Tip:You can see this code on GitHub.
using PX.Commerce.Core; using PX.Commerce.Core.API; using PX.Commerce.Objects; using PX.Data; using PX.Objects.AR; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace WooCommerceTest { [BCProcessor(typeof(WooCommerceConnector), BCEntitiesAttribute.Customer, 20, BCCaptions.Customer, IsInternal = false, Direction = SyncDirection.Import, PrimaryDirection = SyncDirection.Import, PrimarySystem = PrimarySystem.Extern, PrimaryGraph = typeof(PX.Objects.AR.CustomerMaint), ExternTypes = new Type[] { typeof(CustomerData) }, LocalTypes = new Type[] { typeof(PX.Commerce.Core.API.Customer) }, AcumaticaPrimaryType = typeof(PX.Objects.AR.Customer), AcumaticaPrimarySelect = typeof(PX.Objects.AR.Customer.acctCD), URL = "user-edit.php?user_id={0}" )] [BCProcessorRealtime(PushSupported = false, HookSupported = false)] public class WooCustomerProcessor : BCProcessorSingleBase<WooCustomerProcessor, WooCustomerEntityBucket, MappedCustomer>, IProcessor { public WooRestClient client; protected CustomerDataProvider customerDataProvider; //protected List<Country> countries; public CommerceHelper helper = PXGraph.CreateInstance<CommerceHelper>(); #region Constructor public override void Initialise(IConnector iconnector, ConnectorOperation operation) { base.Initialise(iconnector, operation); client = WooCommerceConnector.GetRestClient( GetBindingExt<BCBindingWooCommerce>()); customerDataProvider = new CustomerDataProvider(client); } #endregion #region Import public override async Task MapBucketImport(WooCustomerEntityBucket bucket, IMappedEntity existing, CancellationToken cancellationToken = default) { MappedCustomer customerObj = bucket.Customer; PX.Commerce.Core.API.Customer customerImpl = customerObj.Local = new PX.Commerce.Core.API.Customer(); customerImpl.Custom = GetCustomFieldsForImport(); customerImpl.CustomerName = GetBillingCustomerName(customerObj.Extern). ValueField(); customerImpl.AccountRef = APIHelper.ReferenceMake(customerObj.Extern.Id, GetBinding().BindingName).ValueField(); customerImpl.CustomerClass = customerObj.LocalID == null || existing?.Local == null ? GetBindingExt<BCBindingExt>().CustomerClassID?.ValueField() : null; //Primary Contact customerImpl.PrimaryContact = GetPrimaryContact(customerObj.Extern); customerImpl.MainContact = SetBillingContact(customerObj.Extern); customerImpl.ShippingAddressOverride = true.ValueField(); customerImpl.ShippingContactOverride = true.ValueField(); customerImpl.ShippingContact = SetShippingContact(customerObj.Extern); BCBindingExt bindingExt = GetBindingExt<BCBindingExt>(); if (bindingExt.CustomerClassID != null) { CustomerClass customerClass = PXSelect<CustomerClass, Where<CustomerClass.customerClassID, Equal<Required<CustomerClass.customerClassID>>>>. Select(this, bindingExt.CustomerClassID); if (customerClass != null) { customerClass.ShipVia.ValueField(); } } } public virtual Contact GetPrimaryContact(CustomerData customer) { var contact = new Contact(); contact.FirstName = !string.IsNullOrWhiteSpace(customer.FirstName) && string.IsNullOrWhiteSpace(customer.LastName) ? string.Empty.ValueField() : customer.FirstName.ValueField(); contact.LastName = !string.IsNullOrWhiteSpace(customer.LastName) ? customer.LastName.ValueField() : !string.IsNullOrWhiteSpace(customer.FirstName) && string.IsNullOrWhiteSpace(customer.LastName) ? customer.FirstName.ValueField() : customer.Username.ValueField(); contact.Email = customer.Email.ValueField(); return contact; } public virtual Contact SetBillingContact(CustomerData customerObj) { Contact contactImpl = new Contact(); contactImpl.DisplayName = GetBillingCustomerName(customerObj). ValueField(); contactImpl.Attention = $"{customerObj.Billing?.FirstName} { customerObj.Billing?.LastName}".ValueField(); ; contactImpl.FullName = GetBillingCustomerName(customerObj).ValueField(); contactImpl.FirstName = customerObj.Billing?.FirstName.ValueField(); contactImpl.LastName = customerObj.Billing.LastName.ValueField(); contactImpl.Email = customerObj.Billing.Email.ValueField(); contactImpl.Address = MapAddress(customerObj.Billing); contactImpl.Active = true.ValueField(); contactImpl.Phone1 = customerObj.Billing?.Phone.ValueField(); contactImpl.Phone1Type = PhoneTypes.Business1.ValueField(); return contactImpl; } public virtual Contact SetShippingContact(CustomerData customerObj) { Contact contactImpl = new Contact(); contactImpl.DisplayName = GetShippingCustomerName(customerObj). ValueField(); contactImpl.Attention = $"{customerObj.Shipping?.FirstName} { customerObj.Shipping?.LastName}".ValueField(); contactImpl.FullName = GetShippingCustomerName(customerObj).ValueField(); contactImpl.FirstName = customerObj.Shipping?.FirstName.ValueField(); contactImpl.LastName = customerObj.Shipping.LastName.ValueField(); contactImpl.Address = MapAddress(customerObj.Shipping); contactImpl.Active = true.ValueField(); return contactImpl; } public virtual string GetBillingCustomerName(CustomerData data) { return !string.IsNullOrWhiteSpace(data.Billing.Company) ? data.Billing.Company : string.IsNullOrWhiteSpace($"{data.Billing?.FirstName} { data.Billing?.LastName}") ? data.Username : $"{ data.Billing?.FirstName} {data.Billing?.LastName}"; } public virtual string GetShippingCustomerName(CustomerData data) { return !string.IsNullOrWhiteSpace(data.Shipping?.Company) ? data.Shipping.Company : $"{data.Shipping?.FirstName} {data.Shipping?.LastName}"; } public virtual Address MapAddress(CustomerAddressData addressObj) { var address = new Address(); address.AddressLine1 = addressObj.Address1.ValueField(); address.AddressLine2 = addressObj.Address2.ValueField(); address.City = addressObj.City.ValueField(); address.PostalCode = addressObj.PostalCode.ValueField(); if (!string.IsNullOrWhiteSpace(addressObj.Country)) { var selectedCountry = addressObj.Country; if (selectedCountry != null) { address.Country = addressObj.Country.ValueField(); if (!string.IsNullOrWhiteSpace(addressObj.State)) { address.State = addressObj.State.ValueField(); } } } return address; } public override async Task<PullSimilarResult<MappedCustomer>> PullSimilar( IExternEntity entity, CancellationToken cancellationToken = default) { var uniqueField = string.IsNullOrWhiteSpace( ((CustomerData)entity)?.Billing.Email) ? ((CustomerData)entity)?.Email : ((CustomerData)entity)?.Billing.Email; if (uniqueField == null) return null; List<MappedCustomer> result = new List<MappedCustomer>(); foreach (PX.Objects.AR.Customer item in helper.CustomerByEmail.Select( uniqueField)) { PX.Commerce.Core.API.Customer data = new PX.Commerce.Core.API.Customer() { SyncID = item.NoteID, SyncTime = item.LastModifiedDateTime }; result.Add(new MappedCustomer(data, data.SyncID, data.SyncTime)); } if (result == null || result?.Count == 0) return null; return new PullSimilarResult<MappedCustomer>() { UniqueField = uniqueField, Entities = result }; } public override async Task<PullSimilarResult<MappedCustomer>> PullSimilar( ILocalEntity entity, CancellationToken cancellationToken = default) { var uniqueField = ((PX.Commerce.Core.API.Customer)entity)?. MainContact?.Email?.Value; if (uniqueField == null) return null; IEnumerable<CustomerData> datas = customerDataProvider.GetAll(null); if (datas == null) return null; return new PullSimilarResult<MappedCustomer>() { UniqueField = uniqueField, Entities = datas.Select( data => new MappedCustomer(data, data.Id.ToString(), data.DateModified.ToDate())) }; } public override async Task SaveBucketImport(WooCustomerEntityBucket bucket, IMappedEntity existing, string operation, CancellationToken cancellationToken = default) { MappedCustomer obj = bucket.Customer; PX.Commerce.Core.API.Customer impl = cbapi.Put(obj.Local, obj.LocalID); obj.AddLocal(impl, impl.SyncID, impl.SyncTime); UpdateStatus(obj, operation); } #endregion #region Export public override async Task MapBucketExport(WooCustomerEntityBucket bucket, IMappedEntity existing, CancellationToken cancellationToken = default) { } public override async Task SaveBucketExport(WooCustomerEntityBucket bucket, IMappedEntity existing, string operation, CancellationToken cancellationToken = default) { } #endregion #region Pull public override async Task<MappedCustomer> PullEntity(Guid? localID, Dictionary<string, object> externalInfo, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } public override async Task<MappedCustomer> PullEntity(string externID, string externalInfo, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } public override async Task FetchBucketsForImport(DateTime? minDateTime, DateTime? maxDateTime, PXFilterRow[] filters, CancellationToken cancellationToken = default) { IEnumerable<CustomerData> customers = customerDataProvider.GetAll(null); foreach (CustomerData data in customers) { WooCustomerEntityBucket bucket = CreateBucket(); MappedCustomer mapped = bucket.Customer = bucket.Customer.Set( data, data.Id.ToString(), data.LastName, data.DateModified.ToDate()); EnsureStatus(mapped, SyncDirection.Import); } } public override async Task FetchBucketsForExport(DateTime? minDateTime, DateTime? maxDateTime, PXFilterRow[] filters, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } public override async Task<EntityStatus> GetBucketForImport( WooCustomerEntityBucket bucket, BCSyncStatus syncstatus, CancellationToken cancellationToken = default) { CustomerData data = client.Get<CustomerData>( string.Format("/customers/{0}", syncstatus.ExternID)); MappedCustomer obj = bucket.Customer = bucket.Customer.Set(data, data.Id.ToString(), data.LastName, data.DateModified.ToDate()); EntityStatus status = EnsureStatus(obj, SyncDirection.Import); return status; } public override async Task<EntityStatus> GetBucketForExport( WooCustomerEntityBucket bucket, BCSyncStatus bcstatus, CancellationToken cancellationToken = default) { PX.Commerce.Core.API.Customer impl = cbapi.GetByID<PX.Commerce.Core.API.Customer>(bcstatus.LocalID, GetCustomFieldsForExport()); if (impl == null) return EntityStatus.None; bucket.Customer = bucket.Customer.Set(impl, impl.SyncID, impl.SyncTime); EntityStatus status = EnsureStatus(bucket.Customer, SyncDirection.Export); return status; } #endregion } public static class PhoneTypes { public static string Business1 = "B1"; } }
- Build the project.