How to Search Custom Field from Customer and Num Pad in Dynamics 365 Retail & Commerce POS

 

Microsoft Dynamics 365 

Retail & Commerce

POS (Point of Sales)

How to Search Custom Field from Customer and Num Pad


Pre-Requisite

          You must have a custom field in the channel table.

            If you want to add a custom field. Please follow the link

https://sajidshaikhblog.blogspot.com/2023/08/how-to-extend-customer-list-view-adding.html

Commerce Runtime (CRT)

K:\RetailSDK\SampleExtensions\CommerceRuntime

 

Development

Open the commerce runtime project from the above source and select set as the startup project Runtime.Extensions.CustomerSearchSample

              

 

Create a new class with the name of CustomerSearchRequestHandler.cs. Because this class is not part of the project, you must create a file manually.

Code - CustomerSearchRequestHandler.cs

using Microsoft.Dynamics.Commerce.Runtime;

using Microsoft.Dynamics.Commerce.Runtime.Data;

using Microsoft.Dynamics.Commerce.Runtime.DataModel;

using Microsoft.Dynamics.Commerce.Runtime.DataServices.Messages;

using Microsoft.Dynamics.Commerce.Runtime.Messages;

using Microsoft.Dynamics.Commerce.Runtime.DataAccess.SqlServer;

using System;

using System.Collections.Generic;

 

namespace Contoso.Commerce.Runtime.CustomerSearchSample

{

    public sealed class CustomerSearchRequestHandler : SingleRequestHandler<CustomersSearchRequest, CustomersSearchResponse> //SingleAsyncRequestHandler<CustomersSearchRequest>//

    {

        /// <summary>

        /// Executes the workflow to retrieve customer information.

        /// </summary>

        /// <param name="request">The request.</param>

        /// <returns>The response.</returns>

        protected override CustomersSearchResponse Process(CustomersSearchRequest request)

        {

            ThrowIf.Null(request, "request");

            ThrowIf.Null(request.Criteria, "request.Criteria");

 

            // Execute custom customer search logic here.

            CustomersSearchResponse externalResponse = this.ExternalCustomerSearch(request);

            return new CustomersSearchResponse(externalResponse.Customers.AsPagedResult());

        }

 

        public CustomersSearchResponse ExternalCustomerSearch(CustomersSearchRequest request)

        {

            List<CustomerSearchResult> customerSearchResult = new List<CustomerSearchResult>();

            var databaseContext = new DatabaseContext(request.RequestContext);

            ParameterSet configurationDataParameters = new ParameterSet

            {

                ["@RefNoExt"] = request.Criteria.Keyword

            };

 

            //Get tender type Id for tokenized tender line from database.

            var externalConfigDataset = databaseContext

                    .ExecuteQueryDataSet("SELECT PARTY from ax.CUSTTABLE where RefNoExt = @RefNoExt", configurationDataParameters);

 

            if (externalConfigDataset.Tables[0].Rows.Count > 0)

            {

                CustomerSearchResult customersearchobj = new CustomerSearchResult()

                {

                    PartyId = Convert.ToInt64(externalConfigDataset.Tables[0].Rows[0][0]),

                };

                customerSearchResult.Add(customersearchobj);

            }

 

            //Filter AccountNum

            ParameterSet internalconfigurationDataParameters = new ParameterSet

            {

                ["@AccountNum"] = "%" + request.Criteria.Keyword + "%"

            };

 

            var internalConfigDataset = databaseContext

                    .ExecuteQueryDataSet("SELECT PARTY from ax.CUSTTABLE where AccountNum Like @AccountNum", internalconfigurationDataParameters);

 

            if (internalConfigDataset.Tables[0].Rows.Count > 0)

            {

                for (int i = 0; i < internalConfigDataset.Tables[0].Rows.Count; i++)

                {

                    CustomerSearchResult customersearchobj = new CustomerSearchResult()

                    {

                        PartyId = Convert.ToInt64(internalConfigDataset.Tables[0].Rows[i][0]),

                    };

                    customerSearchResult.Add(customersearchobj);

                }

            }

           

 

            if (customerSearchResult.Count == 0 && request.Criteria.DataLevel == CommerceEntityDataLevel.Complete)

            {

                using (var databaseContext2 = new SqlServerDatabaseContext(request.RequestContext))

                {

                   

                    Customer customer = new Customer();

                    customer.FirstName = request.Criteria.Keyword;

                    customer.LastName = "";

                    customer.Name = customer.FirstName + " " + customer.LastName;

                    customer.CustomerType = CustomerType.Person;

                    customer.CustomerTypeValue = 1;

                    customer.CurrencyCode = request.RequestContext.GetChannelConfiguration().Currency;

                    customer.Language = request.RequestContext.GetChannelConfiguration().DefaultLanguageId;

 

                    var getCustomerCreateRequest = new CreateCustomerRequest();

                    getCustomerCreateRequest.NewCustomer = customer;

                    var getCustomerCreateResponse = request.RequestContext.Execute<CreateCustomerResponse>(getCustomerCreateRequest);

                    if (getCustomerCreateResponse.CreatedCustomer != null)

                    {

                        //customer.ExtensionProperties.Add(new CommerceProperty() { Key = "BoardingPass", Value = request.Criteria.Keyword });

 

                        ParameterSet parameters = new ParameterSet();

                        parameters.Add("RecId", getCustomerCreateResponse.CreatedCustomer.RecordId);

                        parameters.Add("RefNoExt", request.Criteria.Keyword);

                        databaseContext2.ExecuteStoredProcedureNonQuery("[ext].UPDATECUSTOMEREXTENEDPROPERTIES", parameters);

 

                        CustomerSearchResult customersearchobj = new CustomerSearchResult()

                        {

                            PartyId = Convert.ToInt64(getCustomerCreateResponse.CreatedCustomer.DirectoryPartyRecordId)

                        };

                        customerSearchResult.Add(customersearchobj);

                    }

                }

            }

 

            var getGlobalCustomersDataRequest = new GetGlobalCustomersByCustomerSearchResultsDataRequest(customerSearchResult);

            var getGlobalCustomersDataResponse = request.RequestContext.ExecuteAsync<EntityDataServiceResponse<GlobalCustomer>>(getGlobalCustomersDataRequest);

            PagedResult<GlobalCustomer> customers = getGlobalCustomersDataResponse.Result.PagedEntityCollection;

 

            foreach (GlobalCustomer i in customers)

            {

                using (var databaseContext1 = new DatabaseContext(request.RequestContext))

                {

                    ParameterSet configurationDataParameters1 = new ParameterSet

                    {

                        ["@AccountNum"] = i.AccountNumber

                    };

 

                    var configurationDataSet = databaseContext1

                        .ExecuteQueryDataSet("SELECT RefNoExt from ax.CUSTTABLE where AccountNum = @AccountNum", configurationDataParameters1);

 

                    if (configurationDataSet.Tables[0].Rows.Count > 0 && configurationDataSet.Tables[0].Rows[0][0] != null)

                    {

                        i.ExtensionProperties.Add(new CommerceProperty() { Key = "RefNoExt", Value = configurationDataSet.Tables[0].Rows[0][0].ToString() });

                    }

                    else

                    {

                        i.ExtensionProperties.Add(new CommerceProperty() { Key = "RefNoExt", Value = "" });

                    }

                }

            }

            return new CustomersSearchResponse(customers);

        }

    }

}

 

This class will be modified with this code

 

Code - CustomerSearchByFieldsServiceRequestHandler.cs

 

 

namespace Contoso

{

    namespace Commerce.Runtime.CustomerSearchSample

    {

        using System;

        using System.Collections.Generic;

        using System.Linq;

        using System.Threading.Tasks;

        using Microsoft.Dynamics.Commerce.Runtime;

        using Microsoft.Dynamics.Commerce.Runtime.DataModel;

        using Microsoft.Dynamics.Commerce.Runtime.Services.Messages;

        using Microsoft.Dynamics.Commerce.Runtime.DataServices.Messages;

        using Microsoft.Dynamics.Commerce.Runtime.Messages;

        using Microsoft.Dynamics.Commerce.Runtime.Data;

      

        /// <summary>

        /// Custom customer search by fields service request handler.

        /// </summary>

        public sealed class CustomerSearchByFieldsServiceRequestHandler : SingleAsyncRequestHandler<CustomerSearchByFieldsServiceRequest>

        {

            /// <summary>

            /// Executes the workflow to retrieve customer information.

            /// </summary>

            /// <param name="request">The request.</param>

            /// <returns>The response.</returns>

            protected override async Task<Response> Process(CustomerSearchByFieldsServiceRequest request)

            {

                ThrowIf.Null(request, "request");

                ThrowIf.Null(request.SearchByFieldCriteria, "request.SearchByFieldCriteria");

                if (request.SearchByFieldCriteria.Criteria.IsNullOrEmpty())

                {

                    throw new ArgumentException("request.Criteria.Criteria can't be empty.");

                }

 

                // Execute the original customer search logic here.

                var getCustomerSearchResultsDataRequest = new GetCustomerSearchResultsDataRequest(request.SearchByFieldCriteria, request.QueryResultSettings);

                var getCustomerSearchResultsDataResponse = await request.RequestContext.ExecuteAsync<EntityDataServiceResponse<CustomerSearchResult>>(getCustomerSearchResultsDataRequest).ConfigureAwait(false);

                PagedResult<CustomerSearchResult> originalSearchResults = getCustomerSearchResultsDataResponse.PagedEntityCollection;

 

                // Execute the custom customer search logic here.

                var customSearchResultsawait = await this.ExternalCustomerSearch(request.SearchByFieldCriteria, request).ConfigureAwait(false);

                PagedResult<CustomerSearchResult> customSearchResults = customSearchResultsawait;

 

                // Merge the search results.

                IEnumerable<CustomerSearchResult> mergedSearchResults = originalSearchResults.Union(customSearchResults).OrderByDescending(c => c.SearchRanking);

 

                // Get the global customer data for the customer search results.

                var getGlobalCustomersDataRequest = new GetGlobalCustomersByCustomerSearchResultsDataRequest(mergedSearchResults);

                var getGlobalCustomersDataResponse = await request.RequestContext.ExecuteAsync<EntityDataServiceResponse<GlobalCustomer>>(getGlobalCustomersDataRequest).ConfigureAwait(false);

                PagedResult<GlobalCustomer> customers = getGlobalCustomersDataResponse.PagedEntityCollection;

 

                foreach (GlobalCustomer i in customers)

                {

                    var query = new SqlPagedQuery(QueryResultSettings.SingleRecord)

                    {

                        DatabaseSchema = "ax",

                        Select = new ColumnSet(new string[] { "RefNoExt" }),

                        From = "CustTable",

                        Where = "AccountNum = @AccountNum"

                    };

 

                    query.Parameters["@AccountNum"] = i.AccountNumber;

 

                    using (var databaseContext = new DatabaseContext(request.RequestContext))

                    {

                        var extensionResponse = await databaseContext.ReadEntityAsync<ExtensionsEntity>(query).ConfigureAwait(false);

                        ExtensionsEntity extensions = extensionResponse.FirstOrDefault();

 

                        var boardingPass = extensions != null ? extensions.GetProperty("RefNoExt") : null;

                        if (boardingPass != null)

                        {

                            i.ExtensionProperties.Add(new CommerceProperty() { Key = "RefNoExt", Value = boardingPass.ToString() });

                        }

                        else

                        {

                            i.ExtensionProperties.Add(new CommerceProperty() { Key = "RefNoExt", Value = "" });

                        }

                    }

                }

 

                return new CustomerSearchByFieldsServiceResponse(customers);

            }

 

            /// <summary>

            /// A placeholder method that represents a call to an external service or a custom implementation

            /// of customer search.

            /// </summary>

            /// <param name="criteria">The criteria containing which customer fields to search.</param>

            /// <returns>The response.</returns>

            //private PagedResult<CustomerSearchResult> ExternalCustomerSearch(CustomerSearchByFieldCriteria criteria, CustomerSearchByFieldsServiceRequest request)

            private async Task<PagedResult<CustomerSearchResult>> ExternalCustomerSearch(CustomerSearchByFieldCriteria criteria, CustomerSearchByFieldsServiceRequest request)

            {

                // This sample method will only append an additional customer search result if the search criteria contains

                string externalSearchKeyword = "";

                List<CustomerSearchResult> customerSearchResult = new List<CustomerSearchResult>();

                if (string.IsNullOrEmpty(externalSearchKeyword))

                {

                    string removeSteric = criteria?.Criteria?.FirstOrDefault()?.SearchTerm.Replace("*", "");

                    string removeSlash = removeSteric.Substring(1, removeSteric.Length - 1);

                    externalSearchKeyword = removeSlash.Replace("\\", "").Replace("\"", "");

 

                    var query = new SqlPagedQuery(QueryResultSettings.SingleRecord)

                    {

                        DatabaseSchema = "ax",

                        Select = new ColumnSet(new string[] { "PARTY" }),

                        From = "CustTable",

                        Where = "RefNoExt = @RefNoExt"

                    };

 

                    query.Parameters["@RefNoExt"] = externalSearchKeyword;

 

                    using (var databaseContext = new DatabaseContext(request.RequestContext))

                    {

                        var extensionResponse = await databaseContext.ReadEntityAsync<ExtensionsEntity>(query).ConfigureAwait(false);

                        ExtensionsEntity extensions = extensionResponse.FirstOrDefault();

 

                        var party = extensions != null ? extensions.GetProperty("PARTY") : null;

                        if (party != null)

                        {

                            CustomerSearchResult customersearchobj = new CustomerSearchResult()

                            {

                                PartyId = Convert.ToInt64(party),

                            };

                            customerSearchResult.Add(customersearchobj);

                        }

                    }

                }

 

                return customerSearchResult.AsPagedResult();

            }

        }

    }

}

 

Build the project Runtime.Extensions.CustomerSearchSample.

  Copy dll from

K:\RetailSDK\SampleExtensions\CommerceRuntime\Extensions.CustomerSearchSample\bin\Debug\netstandard2.0

 

Paste dll to

K:\RetailServer\WebRoot\bin\Ext

 

 

Now refresh, log in and search your custom field data

 

 

 

Now go to the transaction screen and search

 

 

Video Link

https://youtu.be/v9Ct0p08Ur8


 

The End

Comments

Popular posts from this blog

How to Add Custom Control in Customer with Custom Field & Add/Update Data in D365 Commerce POS

How to Extend Customer List View adding Custom Field on Dynamics 365 Retail & Commerce POS