Add Custom Control on Customer's Form and Do Real Time Data Exchange (POS to HQ)

 ADD CUSTOM CONTROL ON CUSTOMER'S FORM

How to add custom control on Customer's form and do Real-Time Data Exchange: Data Exchange from POS form to HQ with Real-Time Service

This blog has complete guide that how we can add custom control on customer's form and add data into it then push data from form to the table's custom field with real time service.

Before that we have to learn that how we can configure the scale unit project into our vm for the customization of CPOS. For that purpose, please have a look into this blog.

Your Guide to Efficiently Setting Up Dynamics 365 Commerce Cloud POS (dynamicscommerce.blogspot.com)

Now you have to get knowledge about the Real-Time Data Exchange. For that I wrote a blog, please have a look into it you will get understanding.

Extend Data Exchange - Real Time Service 


Add Custom Control on Customer's Form

To add custom control on customer's form we have to write two classes:

  • .html
  • .ts
In Scale Unit solution under the POS project, we will find a folder with name ViewExtensions.
Under that folder we have to create folder with name CustomerAddEdit.
Now create a .html file with name CustomFieldsSection.html and add custom control code in it.

Code for CustomFieldsSection.html class:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <!-- Note: The element id is different than the id generated by the POS extensibility framework. This 'template' id is not used by the POS extensibility framework. -->

    <div id="Contoso_Pos_Extensibility_Samples_CustomFieldsSection" class="height100Percent" >
        <div class="gutter20x20"></div>
        <div id="Contoso_Pos_Extensibility_Samples_SSN" class="width300 grow col">
            <label for="SSN">SSN</label>
            <input type="text" id="IntSSN" name="SSN"/>
        </div>
    </div>
</body>
</html>


Now we have to create .ts class with same name CustomFieldsSection.ts and add code in it for custom control to get on the form.

Code for CustomFieldsSection.ts class:

import {
    CustomerAddEditCustomControlBase,
    ICustomerAddEditCustomControlState,
    ICustomerAddEditCustomControlContext,
    CustomerAddEditCustomerUpdatedData
} from "PosApi/Extend/Views/CustomerAddEditView";
import { ObjectExtensions } from "PosApi/TypeExtensions";
import { ProxyEntities } from "PosApi/Entities";
import * as Controls from "PosApi/Consume/Controls";

export default class CustomFieldsSection extends CustomerAddEditCustomControlBase {
    public ssn: string;
    public customerIsPerson: boolean;

    public dataList: Controls.IDataList<ProxyEntities.Customer>;
    public readonly title: string;

    private static readonly TEMPLATE_ID: string = "Contoso_Pos_Extensibility_Samples_CustomFieldsSection";
    private _state: ICustomerAddEditCustomControlState;


    constructor(id: string, context: ICustomerAddEditCustomControlContext)
    {
        super(id, context);

        this.ssn = "";
        this.customerIsPerson = false;

        this.customerUpdatedHandler = (data: CustomerAddEditCustomerUpdatedData) => {
            this.customerIsPerson = data.customer.CustomerTypeValue == ProxyEntities.CustomerType.Person ? true : false;
        };
    }

    /**
     * Binds the control to the specified element.
     * @param {HTMLElement} element The element to which the control should be bound.
     */
    public onReady(element: HTMLElement): void
    {
        let templateElement: HTMLElement = document.getElementById(CustomFieldsSection.TEMPLATE_ID);
        let templateClone: Node = templateElement.cloneNode(true);
        element.appendChild(templateClone);



    /**
     * Initializes the control.
     * @param {ICustomerDetailCustomControlState} state The initial state of the page used to initialize the control.
     */
    public init(state: ICustomerAddEditCustomControlState): void
    {
        this._state = state;
        if (!this._state.isSelectionMode) {
            this.isVisible = true;
            this.customerIsPerson = state.customer.CustomerTypeValue === ProxyEntities.CustomerType.Person ? true : false;
        }
    }


    /**
     * Gets the property value from the property bag, by its key. Optionally creates the property value on the bag, if it does not exist.
     */
    private _addOrUpdateExtensionProperty(key: string, newValue: ProxyEntities.CommercePropertyValue): void
    {
        let customer: ProxyEntities.Customer = this.customer;
        let extensionProperty: ProxyEntities.CommerceProperty =
            Commerce.ArrayExtensions.firstOrUndefined(customer.ExtensionProperties, (property: ProxyEntities.CommerceProperty) => {
                return property.Key === key;
            });

        if (ObjectExtensions.isNullOrUndefined(extensionProperty)) {
            let newProperty: ProxyEntities.CommerceProperty = {
                Key: key,
                Value: newValue
            };

            if (ObjectExtensions.isNullOrUndefined(customer.ExtensionProperties)) {
                customer.ExtensionProperties = [];
            }

            customer.ExtensionProperties.push(newProperty);
        } else {
            extensionProperty.Value = newValue;
        }

        this.customer = customer;
    }
}


Now register the classes into manifest.json file.

Code to be added in manifest class:


        "CustomerAddEditView": {
          "controlsConfig": {
            "customControls": [
              {
                "controlName": "CustomFieldsSection",
                "htmlPath": "ViewExtensions/CustomerAddEdit/CustomFieldsSection.html",
                "modulePath": "ViewExtensions/CustomerAddEdit/CustomFieldsSection"
              }
            ]
          }
        }




  • Build the project 
  • Copy .dll from K:\"Your ScaleUnit ProjectName"\src\ScaleUnitSample\CommerceRuntime\bin\Debug\netstandard2.0\CommerceRuntime.dll
  • Paste the copied .dll to K:\RetailServer\WebRoot\bin\Ext
  • Add a line of code in CommerceRuntime.Ext.config file in K:\RetailServer\WebRoot\bin\Ext
  • Copy the package of scale unit project from K:\"Your ScaleUnit ProjectName"\src\ScaleUnitSample\ScaleUnit\bin\Debug\netstandard2.0\CloudScaleUnitExtensionPackage\RetailCloudPOS\Code\Extensions\Contoso.Commerce
  • Paste the copied package into K:\RetailCloudPos\WebRoot\Extensions
  • Refresh the POS, now you will see the custom control on the customer's creation form.





Get value from Custom Control and do real-time syncing with HQ

Now we have to get data from custom control and save that data on the table through real-time service.
For that purpose, we have to write a couple of lines to save the data in extension properties of the Customer's Entity and then we will get that from Extension properties to table on real-time.
So, add some lines of code on the Previously created class, i.e. CustomFieldsSection.ts to add value on the extension properties.
Write these lines under the onReady method of the class:


let intDataInput: HTMLInputElement = element.querySelector("#IntSSN") as HTMLInputElement;
intDataInput.onchange = () => { this.updateExtensionField(intDataInput.value); };


create a new method in the same class:


    public updateExtensionField(ssnValue: string): void
    {
        this._addOrUpdateExtensionProperty("ssn", <ProxyEntities.CommercePropertyValue>{ StringValue: ssnValue });
    }

Now we have to do real-time data exchange for that, please have a look into this blog.


we have to do some changes into the class that we will discuss here.
Please replace code of 'ContosoRetailTransactionServiceSample_Extension' class.

Code for class 'ContosoRetailTransactionServiceSample_Extension':

[ExtensionOf(classStr(RetailTransactionServiceEx))]
final class ContosoRetailTransactionServiceSample_Extension
{
    public static container Hello(AccountNum accountNumber, str SSN)
    {
        CustTable custTable;
        DirPartyTable dirPartyTable;
        container result = [false, ''];
    
        if (accountNumber)
        {
            custTable = CustTable::find(accountNumber, true);
            if (custTable)
            { 
                ttsbegin;
                custTable.SSN = SSN;//'RealTime';
                custTable.update();
                ttscommit;
                
                result = [true, 'Success!', strFmt("Hello %1 !", custTable.AccountNum)];
            }
            else
            {
                result = [false, 'Customer not found'];
            }
        }
        else
        {
            result = [false, 'accountNumber is null.'];
        }
    
        return result;
    }

}


Also replace the code for trigger 'CustomerServiceTrigger'.

Code for trigger to be replaced:


using System;
using System.Collections.Generic;
using System.Text;

namespace Contoso.Commerce.Runtime.NonTransactionalLoyaltyPointsSample
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using Microsoft.Dynamics.Commerce.Runtime.DataServices.Messages;
    using Microsoft.Dynamics.Commerce.Runtime;
    using Microsoft.Dynamics.Commerce.Runtime.Messages;
    using Microsoft.Dynamics.Commerce.Runtime.RealtimeServices.Messages;
    using Microsoft.Dynamics.Commerce.Runtime.Framework.Exceptions;
    using Microsoft.Dynamics.Commerce.Runtime.DataModel;
    using System.Runtime.Serialization;
    using Contoso.Commerce.Runtime.DocumentProvider.EpsonFP90IIISample.DocumentBuilders;
    using Microsoft.Dynamics.Commerce.Runtime.Data;
    using Microsoft.Dynamics.Commerce.Runtime.DataAccess.SqlServer;

    class CustomerServiceTrigger : IRequestTriggerAsync
    {
        /// <summary>
        /// Gets the supported requests for this trigger.
        /// </summary>
        public IEnumerable<Type> SupportedRequestTypes
        {
            get
            {
                return new[] { typeof(NewCustomerRealtimeRequest) };
            }
        }

        /// <summary>
        /// Post trigger code to post loyalty reward points for non-transactional activity.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="response">The response.</param>
        public async Task OnExecuted(Request request, Response response)
        {
            try
            {
                var SearchCustomersRequest  = (NewCustomerRealtimeRequest)request;
                var customer = (Customer)SearchCustomersRequest.CustomerToSave;

                string ssn = "";
                ICollection<CommerceProperty> custext = customer.ExtensionProperties;

                foreach (var item in custext)
                {
                    if (item.Key == "ssn")
                    {
                        ssn = item.Value.StringValue.ToString();
                        break;
                    }
                }


                InvokeExtensionMethodRealtimeRequest extensionRequest = new InvokeExtensionMethodRealtimeRequest("Hello", customer.AccountNumber, ssn);
                InvokeExtensionMethodRealtimeResponse response1 = await request.RequestContext.ExecuteAsync<InvokeExtensionMethodRealtimeResponse>(extensionRequest).ConfigureAwait(false);
                ReadOnlyCollection<object> results = response1.Result;

            }
            catch (HeadquarterTransactionServiceException exception)
            {
            }
        }
        /// <summary>
        /// Pre trigger code.
        /// </summary>
        /// <param name="request">The request.</param>
        public async Task OnExecuting(Request request)
        {
            // It's only stub to handle async signature 
            await Task.CompletedTask;
        }
    }
}


By this you will achieve the real-time data exchange on customer's creation form with custom control.
Add new values on customer's creation form on POS.


Save the customer. Copy the Customer Account number after saving.



Now check the customer account on the All customers form on HQ.



Now we can see that the real time service is working with the custom control on the creation of customers.



Update the existing record of Customer for Custom Control on Real-Time

To update the existing record of Customer for Custom Control we have to write code on the CRT project.
Firstly, we have to create a stored procedure on our DB for updating the custom field on both the Channel and HQ tables.

Query to create stored procedure:

CREATE PROCEDURE [ext].[UPDATECUSTOMEREXTENEDPROPERTIES] @AccountNum nvarchar(255), @SSN nvarchar(255)

AS
BEGIN
    Update ax.CUSTTABLE Set SSN = @SSN Where ACCOUNTNUM = @AccountNum
    Update dbo.CUSTTABLE Set SSN = @SSN Where ACCOUNTNUM = @AccountNum
END
GO

  • Open CommerceRuntimeSamples solution from K:\RetailSDK\SampleExtensions\CommerceRuntime\CommerceRuntimeSamples.sln.
  • Search for 'Runtime.Extensions.EmailPreferenceSample' project.
  • In the project you will find a class with name 'CreateOrUpdateCustomerDataRequestHandler.cs'.

Add this code into the class:

namespace Contoso
{
    namespace Commerce.Runtime.EmailPreferenceSample
    {
        using System.Collections.Generic;
        using System.Threading.Tasks;
        using System.Transactions;
        using Microsoft.Dynamics.Commerce.Runtime;
        using Microsoft.Dynamics.Commerce.Runtime.Data;
        using Microsoft.Dynamics.Commerce.Runtime.DataAccess.SqlServer;
        using Microsoft.Dynamics.Commerce.Runtime.DataModel;
        using Microsoft.Dynamics.Commerce.Runtime.DataServices.Messages;
        using Microsoft.Dynamics.Commerce.Runtime.Messages;

        /// <summary>
        /// Create or update customer data request handler.
        /// </summary>
        public sealed class CreateOrUpdateCustomerDataRequestHandler : SingleAsyncRequestHandler<CreateOrUpdateCustomerDataRequest>
        {
            /// <summary>
            /// Executes the workflow to create or update a customer.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>The response.</returns>
            protected override async Task<Response> Process(CreateOrUpdateCustomerDataRequest request)
            {
                ThrowIf.Null(request, "request");

                using (var databaseContext = new SqlServerDatabaseContext(request.RequestContext))
                {
                    // Execute original functionality to save the customer.
                    var response = await this.ExecuteNextAsync<SingleEntityDataServiceResponse<Customer>>(request).ConfigureAwait(false);

                    if (!request.Customer.ExtensionProperties.IsNullOrEmpty())
                    {

                        string ssn = "";
                        var custExt = request.Customer.ExtensionProperties;
                        
                        foreach (var item in custExt)
                        {
                            if (item.Key == "ssn")
                            {
                                ssn = item.Value.StringValue.ToString();
                                break;
                            }
                        }


                        ParameterSet parameters = new ParameterSet();
                        parameters.Add("AccountNum", request.Customer.AccountNumber);// response.Entity.AccountNumber);
                        parameters.Add("SSN", ssn);
                        await databaseContext.ExecuteStoredProcedureNonQueryAsync("[ext].[UPDATECUSTOMEREXTPROPERTIES]", parameters, resultSettings: null).ConfigureAwait(true);
                    }

                    return response;
                }
            }
        }
    }
}

  • Build the project.
  • Copy the .dll of the project from K:\RetailSDK\SampleExtensions\CommerceRuntime\Extensions.EmailPreferenceSample\bin\Debug\netstandard2.0\Contoso.Commerce.Runtime.EmailPreferenceSample.dll.
  • Paste the copied .dll to K:\RetailServer\WebRoot\bin\Ext
  • Add a line of code in CommerceRuntime.Ext.config file in K:\RetailServer\WebRoot\bin\Ext

Code:

<add source="type" value="Contoso.Commerce.Runtime.EmailPreferenceSample.CreateOrUpdateCustomerDataRequestHandler, Contoso.Commerce.Runtime.EmailPreferenceSample" />

Refresh the POS and update any of the customer record the updated record will be populated into the tables on Real-Time.





Update the record


Record will be updated on real time






Read the value of Custom Control on loading of Customer's Form

Now the last part is that we must write the value of custom control on every customer's record according to the account number.
For that, we must write the code for two services on CRT.
  • Open CommerceRuntimeSamples solution from K:\RetailSDK\SampleExtensions\CommerceRuntime\CommerceRuntimeSamples.sln.
  • Search for 'Runtime.Extensions.EmailPreferenceSample' project.
  • In the project you will find a class with name 'GetCustomerTriggers.cs'.

Add the code to the class:

namespace Contoso
{
    namespace Commerce.Runtime.EmailPreferenceSample
    {
        using System;
        using System.Collections.Generic;
        using System.Threading.Tasks;
        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;

        /// <summary>
        /// Class that implements a post trigger for the GetCustomerDataRequest request type.
        /// </summary>
        public class GetCustomerTriggers : IRequestTriggerAsync
        {
            /// <summary>
            /// Gets the supported requests for this trigger.
            /// </summary>
            public IEnumerable<Type> SupportedRequestTypes
            {
                get
                {
                    return new[] { typeof(GetCustomerDataRequest) ,
                                   typeof(GetCustomersDataRequest) }; 
                                   //typeof(GetSimpleCustomerDataRequest),
                                   //typeof(GetSimpleCustomersDataRequest)};
                }
            }

            /// <summary>
            /// Post trigger code to retrieve extension properties.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <param name="response">The response.</param>
            public async Task OnExecuted(Request request, Response response)
            {
                ThrowIf.Null(request, "request");
                ThrowIf.Null(response, "response");

switch (request)

                {

                    case GetCustomerDataRequest getCustomerDataRequests:

                        var custom = ((SingleEntityDataServiceResponse<Customer>)response).Entity;

                        if (custom != null)

                        {

                            var query = new SqlPagedQuery(QueryResultSettings.SingleRecord)

                            {

                                DatabaseSchema = "ax",

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

                                From = "CustTable",

                                Where = "ACCOUNTNUM = @accountNum"

                            };



                            query.Parameters["@accountNum"] = custom.AccountNumber;

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

                            {

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

                                ExtensionsEntity extensions = extensionsResponse.FirstOrDefault();



                                var emailOptIn = extensions != null ? extensions.GetProperty("ssn") : null;

                                if (emailOptIn != null)

                                {

                                    //customer.SetProperty("EMAILOPTIN", emailOptIn);

                                    custom.ExtensionProperties.Add(new CommerceProperty() { Key = "ssn", Value = emailOptIn.ToString() });

                                }

                            }

                        }

                        break;

                    case GetCustomersDataRequest getCustomersDataRequests:

                        var customers = (EntityDataServiceResponse<Customer>)response;

                        PagedResult<Customer> customer = customers.PagedEntityCollection;



                        foreach (Customer item in customer)

                        {

                            var query = new SqlPagedQuery(QueryResultSettings.SingleRecord)

                            {

                                DatabaseSchema = "ax",

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

                                From = "CustTable",

                                Where = "ACCOUNTNUM = @accountNum"

                            };



                            query.Parameters["@accountNum"] = item.AccountNumber;

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

                            {

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

                                ExtensionsEntity extensions = extensionsResponse.FirstOrDefault();



                                var emailOptIn = extensions != null ? extensions.GetProperty("ssn") : null;

                                if (emailOptIn != null)

                                {

                                    item.ExtensionProperties.Add(new CommerceProperty() { Key = "ssn", Value = emailOptIn.ToString() });

                                }

                            }

                        }

                        break;


                    default:

                        break;

                }
            }

            /// <summary>
            /// Pre trigger code.
            /// </summary>
            /// <param name="request">The request.</param>
            public async Task OnExecuting(Request request)
            {
                // It's only stub to handle async signature 
                await Task.CompletedTask;
            }
        }
    }
}

  • Build the project.
  • Copy the .dll of the project from K:\RetailSDK\SampleExtensions\CommerceRuntime\Extensions.EmailPreferenceSample\bin\Debug\netstandard2.0\Contoso.Commerce.Runtime.EmailPreferenceSample.dll.
  • Paste the copied .dll to K:\RetailServer\WebRoot\bin\Ext
  • Add a line of code in CommerceRuntime.Ext.config file in K:\RetailServer\WebRoot\bin\Ext

Code:

<add source="type" value="Contoso.Commerce.Runtime.EmailPreferenceSample.GetCustomerTriggers, Contoso.Commerce.Runtime.EmailPreferenceSample" />


Also add this couple of lines 'CustomFieldsSection.ts' class under the OnReady Method


        let sampleExtensionPropertyValue: string;
        if (!ObjectExtensions.isNullOrUndefined(this.customer.ExtensionProperties))
        {
            let SampleCommerceProperties: ProxyEntities.CommerceProperty[] = this.customer.ExtensionProperties.filter(
                (extensionProperty: ProxyEntities.CommerceProperty) => { 
                return extensionProperty.Key === "ssn";
            });
            sampleExtensionPropertyValue = SampleCommerceProperties.length > 0 ? SampleCommerceProperties[0].Value.StringValue: "";
            //sampleExtensionPropertyValue = "Ext Value";
        }
        else
        {
            //intDataInput.value = "Fixed SSN";
            sampleExtensionPropertyValue = "";
        }
           intDataInput.value = sampleExtensionPropertyValue;


The Whole class code for the 'CustomFieldsSection.ts' will be look like this:

import {
    CustomerAddEditCustomControlBase,
    ICustomerAddEditCustomControlState,
    ICustomerAddEditCustomControlContext,
    CustomerAddEditCustomerUpdatedData
} from "PosApi/Extend/Views/CustomerAddEditView";
import { ObjectExtensions } from "PosApi/TypeExtensions";
import { ProxyEntities } from "PosApi/Entities";
import * as Controls from "PosApi/Consume/Controls";

export default class CustomFieldsSection extends CustomerAddEditCustomControlBase {
    public ssn: string;
    public customerIsPerson: boolean;

    public dataList: Controls.IDataList<ProxyEntities.Customer>;
    public readonly title: string;

    private static readonly TEMPLATE_ID: string = "Contoso_Pos_Extensibility_Samples_CustomFieldsSection";
    private _state: ICustomerAddEditCustomControlState;


    constructor(id: string, context: ICustomerAddEditCustomControlContext)
    {
        super(id, context);

        this.ssn = "";
        this.customerIsPerson = false;

        this.customerUpdatedHandler = (data: CustomerAddEditCustomerUpdatedData) => {
            this.customerIsPerson = data.customer.CustomerTypeValue == ProxyEntities.CustomerType.Person ? true : false;
        };
    }

    /**
     * Binds the control to the specified element.
     * @param {HTMLElement} element The element to which the control should be bound.
     */
    public onReady(element: HTMLElement): void
    {
        let templateElement: HTMLElement = document.getElementById(CustomFieldsSection.TEMPLATE_ID);
        let templateClone: Node = templateElement.cloneNode(true);
        element.appendChild(templateClone);


        let intDataInput: HTMLInputElement = element.querySelector("#IntSSN") as HTMLInputElement;
        intDataInput.onchange = () => { this.updateExtensionField(intDataInput.value); };
      
        let sampleExtensionPropertyValue: string;
        if (!ObjectExtensions.isNullOrUndefined(this.customer.ExtensionProperties))
        {
            let SampleCommerceProperties: ProxyEntities.CommerceProperty[] = this.customer.ExtensionProperties.filter(
                (extensionProperty: ProxyEntities.CommerceProperty) => { 
                return extensionProperty.Key === "ssn";
            });
            sampleExtensionPropertyValue = SampleCommerceProperties.length > 0 ? SampleCommerceProperties[0].Value.StringValue: "";
            //sampleExtensionPropertyValue = "Ext Value";
        }
        else
        {
            //intDataInput.value = "Fixed SSN";
            sampleExtensionPropertyValue = "";
        }
           intDataInput.value = sampleExtensionPropertyValue;
    }

    /**
     * Initializes the control.
     * @param {ICustomerDetailCustomControlState} state The initial state of the page used to initialize the control.
     */
    public init(state: ICustomerAddEditCustomControlState): void
    {
        this._state = state;
        if (!this._state.isSelectionMode) {
            this.isVisible = true;
            this.customerIsPerson = state.customer.CustomerTypeValue === ProxyEntities.CustomerType.Person ? true : false;
        }
    }

    public updateExtensionField(ssnValue: string): void
    {
        this._addOrUpdateExtensionProperty("ssn", <ProxyEntities.CommercePropertyValue>{ StringValue: ssnValue });
    }


    /**
     * Gets the property value from the property bag, by its key. Optionally creates the property value on the bag, if it does not exist.
     */
    private _addOrUpdateExtensionProperty(key: string, newValue: ProxyEntities.CommercePropertyValue): void
    {
        let customer: ProxyEntities.Customer = this.customer;
        let extensionProperty: ProxyEntities.CommerceProperty =
            Commerce.ArrayExtensions.firstOrUndefined(customer.ExtensionProperties, (property: ProxyEntities.CommerceProperty) => {
                return property.Key === key;
            });

        if (ObjectExtensions.isNullOrUndefined(extensionProperty)) {
            let newProperty: ProxyEntities.CommerceProperty = {
                Key: key,
                Value: newValue
            };

            if (ObjectExtensions.isNullOrUndefined(customer.ExtensionProperties)) {
                customer.ExtensionProperties = [];
            }

            customer.ExtensionProperties.push(newProperty);
        } else {
            extensionProperty.Value = newValue;
        }

        this.customer = customer;
    }
}



  • Build the project 
  • Copy .dll from K:\"Your ScaleUnit ProjectName"\src\ScaleUnitSample\CommerceRuntime\bin\Debug\netstandard2.0\CommerceRuntime.dll
  • Paste the copied .dll to K:\RetailServer\WebRoot\bin\Ext
  • Add a line of code in CommerceRuntime.Ext.config file in K:\RetailServer\WebRoot\bin\Ext
  • Copy the package of scale unit project from K:\"Your ScaleUnit ProjectName"\src\ScaleUnitSample\ScaleUnit\bin\Debug\netstandard2.0\CloudScaleUnitExtensionPackage\RetailCloudPOS\Code\Extensions\Contoso.Commerce
  • Paste the copied package into K:\RetailCloudPos\WebRoot\Extensions
  • Refresh the POS, now you will see the value of custom control on the customer's update form.


On loading of the form, the value of the custom control will be populated if it exists.














Comments

Popular Posts