Skip to main content



No record found.

Dynamics 365 Community / Forums / Commerce forum / How to add the quantit...
Commerce forum

How to add the quantity multiples of D365 into CloudPOS

Posted on by 1,423

In D365 finance and operations under released products there are order defaults for multiples. In D365 if a product is set up to have sales order multiples of 5 for instance, it will default 5 when that product is added to a sales order line. If the user change the quantity to 7 for instance, it will ask the user if they want to round up to 10.

We have custom that replaces the standard in that we have 3 buttons: round up, round down and override. So in the above example the user will be asked if they want to round down to 5, round up to 10 or override and stay on 7.

Although Retail has the table InventItemSales in the channel DB, it never passed to the channel DB the MultipleQty field.

I have added a CDX change that added in the [ext] schema the missing field and added it to the subjob 1040. so the channel DB is populated correctly with the value.

I then added a CRT custom and use trigger SaveCartVersionedDataRequest as the supported request type. On its OnExecuted, I then added logic to populate the extension property of salesLine on the cart with the multipleQty. I used this trigger because my research I came across this link that indicated that it is the trigger that is fired when an item is added to a cart line.

I may have to switch it over to OnExecuting instead of OnExecuted here. Will have to see when it is called.

We do not want to apply the multiple quantity when the line is created. We want it to stay with the default of 1. However when the item is flagged to be "KeyInQuantity" it pops up the Set Quantity dialog. And when the user click on change quantity, it opens a Change Quantity dialog. It is on these 2 dialogs that I need to apply the multiples when the item is flagged to be KeyInQuantity. This flag I found on entity ProductRules.

Apparently I can only extend a trigger on the POS side if it is in Pos.Api under Extend. There is no quantity trigger currently available for extension.

I also have to have a message dialog box that can take 3 buttons and not only 2 like the standard message dialog. This link uses the standard message box, but it has only 2 buttons and I need 3:

I looked at this link as well:

Where do I start with the POS side? Any suggestions to help me figure out this one, will be much appreciated.

I need to be able to create a dialog box that has 3 buttons

I need to be able to call it , lets say after the standard Set Quantity and Change Quantity dialog boxes

And I need to then update the quantity on the cart line in the transaction page with this new quantity

(By the way, the Commerce forum  - Retail forum seems to have undergone a name change - has no Development and Customization filter anymore, just General)

  • Retha Profile Picture
    Retha 1,423 on at
    RE: How to add the quantity multiples of D365 into CloudPOS

    Just an update, one cannot use "RetailSDK\POS\Extensions\SampleExtensions\Operations\SaveDataToSelectedCartLine" as a way to update the quantity on the cart line.

    With Microsoft's help I was able to get my custom operation ID to update the cartline by using:


    // Line id can obtained from the cart line.

    let qty: number = <quantity selected> ;

           let request: SetCartLineQuantityOperationRequest<SetCartLineQuantityOperationResponse> =

               new SetCartLineQuantityOperationRequest<SetCartLineQuantityOperationResponse>

                   ("Set quantity", "lineId", qty);



    Just make sure the quantity selected on the listInputDialog is returned as a string and then use ParseFloat on it else the above will give errors indicating that SetCarlLineQuanittyOperationRequest looks for it in a different format.

  • Retha Profile Picture
    Retha 1,423 on at
    RE: How to add the quantity multiples of D365 into CloudPOS

    How can I get my code to save the changed quantity to the cart line? I cannot use SetCartLineQuantityOperation Request/Response pair. It wants to run the 105 operation. I have created a custom operation with ID 4002 which I added to the buttonsGrid in the Head Quarters.

    When I click on my new button, it brings up the number dialog and I type in the quantity. then when it sees there is a multiple quantity, it brings up the rounding dialog. then it returns the value I selected for the rounding. however it doesn't want to save the quantity to the line.


    import { ExtensionOperationRequestType, ExtensionOperationRequestHandlerBase } from "PosApi/Create/Operations";

    import TMCSetQtyOperationResponse from "./TMCSetQtyOperationResponse";

    import TMCSetQtyOperationRequest from "./TMCSetQtyOperationRequest";

    import { ClientEntities, ProxyEntities } from "PosApi/Entities";

    import CartViewController from "../../CustomControlExtensions/Cart/CartViewDetailsController";

    import { ObjectExtensions} from "PosApi/TypeExtensions";

    import { MessageService } from "../../Controls/Dialogs/MessageBox/MessageBoxService";

    import { StoreOperations } from "../../DataServices/DataServiceRequests.g";

    import MultiplesListDialog from "../../Controls/Dialogs/MultiplesListDialog";

    export default class TMCSetQtyOperationRequestHandler<TResponse extends TMCSetQtyOperationResponse> extends ExtensionOperationRequestHandlerBase<TResponse> {

       private cart: ProxyEntities.Cart = null;

       private cartLine: ProxyEntities.CartLine = null;

       private enteredQty: number = 0;


        * Gets the supported request type.

        * @return {RequestType<TResponse>} The supported request type.


       public supportedRequestType(): ExtensionOperationRequestType<TResponse> {

           return TMCSetQtyOperationRequest;


       public executeAsync(sqRequest: TMCSetQtyOperationRequest<TResponse>): Promise<ClientEntities.ICancelableDataResult<TResponse>> {

           this.context.logger.logInformational("Log message from TMCSetQtyOperationRequestHandler executeAsync().", this.context.logger.getNewCorrelationId());

           //Fetch Current cart

           return this.getCurrentCart()

               .then((): any => {

                   if (ObjectExtensions.isNullOrUndefined(this.cart)) { // return if cart not found

                       MessageService.ShowMessage(this, "Cart not found", "Current cart cannot be found. Cannot continue.");

                       return Promise.resolve(null);


                   if (ObjectExtensions.isNullOrUndefined(CartViewController.selectedCartLine)) {

                       return Promise.resolve(null);


                   this.cartLine = CartViewController.selectedCartLine;

                   return this.SetQtyRequest(sqRequest, this.cartLine.Quantity);



       public getCurrentCart(): Promise<ProxyEntities.Cart> {

           return this.context.runtime.executeAsync(new Commerce.GetCurrentCartClientRequest<Commerce.GetCurrentCartClientResponse>())

               .then((getCurrentCartResponse: ClientEntities.ICancelableDataResult<Commerce.GetCurrentCartClientResponse>): Promise<ProxyEntities.Cart> => {

                   if (!(getCurrentCartResponse.canceled || ObjectExtensions.isNullOrUndefined( {

                       this.cart =;

                       return Promise.resolve(this.cart);


                   return Promise.resolve(null);



       public SetQtyRequest(request: TMCSetQtyOperationRequest<TResponse>, _lineQty: number): Promise<ClientEntities.ICancelableDataResult<TResponse>> {

           let dialogOptions: ClientEntities.Dialogs.INumericInputDialogOptions = {

               title: this.context.resources.getString("tmc_1"),

               subTitle: " ",

               numPadLabel: this.context.resources.getString("tmc_2"),

               defaultNumber: _lineQty.toString()


           let showInputDialog: Commerce.ShowNumericInputDialogClientRequest<Commerce.ShowNumericInputDialogClientResponse> = new Commerce.ShowNumericInputDialogClientRequest(dialogOptions);

           //return this.ExecuteAsync(showInputDialog)

           return this.context.runtime.executeAsync(showInputDialog)

               .then((showNumericDialogResult: ClientEntities.ICancelableDataResult<Commerce.ShowNumericInputDialogClientResponse>): any => {

                   this.enteredQty = parseFloat(;

                   let mResponse: Promise<ClientEntities.ICancelableDataResult<StoreOperations.GetMultiplesActionResponse>>;

                   let multiRequest: StoreOperations.GetMultiplesActionRequest<StoreOperations.GetMultiplesActionResponse> =

                       new StoreOperations.GetMultiplesActionRequest(this.cartLine.ItemId, this.cartLine.UnitOfMeasureSymbol, this.cartLine.ProductId, this.enteredQty);

                   mResponse = this.context.runtime.executeAsync<StoreOperations.GetMultiplesActionResponse>(multiRequest);

                   return mResponse;


               .then((response: ClientEntities.ICancelableDataResult<StoreOperations.GetMultiplesActionResponse>):

                   Promise<ClientEntities.ICancelableDataResult<number>> => {

                   let mqResult: Promise<ClientEntities.ICancelableDataResult<number>>;

                   if ( != null) {

                       var result =;

                       var vMqty = result[0];

                       if (vMqty > 1) {

                           mqResult =, result, this.enteredQty, this.cartLine.UnitOfMeasureSymbol);



                   return mqResult;


               .then((dialogResult: ClientEntities.ICancelableDataResult<number>): Promise<ClientEntities.ICancelableDataResult<TResponse>> => {

                   if (!dialogResult.canceled) {

                       this.enteredQty =;


                   this.cartLine.Quantity = this.enteredQty;

                   return Promise.resolve(<ClientEntities.ICancelableDataResult<TResponse>>{

                       canceled: false,

                       data: new TMCSetQtyOperationResponse(this.cart)






    When I step through the code I can see that cart that is passed in to TMCSetQtyOperationResponse, has my line and the quantity is that of what I added to the line. It just doesn't save it and I do not see an error in the event viewer.

    I used "RetailSDK\POS\Extensions\SampleExtensions\Operations\SaveDataToSelectedCartLine" as an example. However in this example they assign extension properties to the cartLine. I do not want to update extension properties, I want to update the quantity.

    Can anybody please look at my code and tell me what I'm missing.

    Thank you.

  • Retha Profile Picture
    Retha 1,423 on at
    RE: How to add the quantity multiples of D365 into CloudPOS

    I was able for it to close the multiples dialog now. but it doesn't want to update the quantity on the line. It just state that the request is invalid.

  • Retha Profile Picture
    Retha 1,423 on at
    RE: How to add the quantity multiples of D365 into CloudPOS

    Hi Ram,

    I am still working on this ticket of mine.

    For now I have passed in hard coded values to use to get the POS side to work.

    I have added a trigger on the PostOperationTrigger and make sure the operationCalled is SetQuantity.

    It triggers my dialog after I entered the quantity and when I select a list item on the listInputDialog, it changes the quantity on the cart line but it doesn't close the listInputdialog. I have to click twice on the 

    It also uses the quantity on the cartline and not the quantity I just entered in Setquantity dialog box. 

    So PostOperationTrigger won't work

  • Verified answer
    ram shenkar Profile Picture
    ram shenkar 515 on at
    RE: How to add the quantity multiples of D365 into CloudPOS

    You can get the selected line using "CartViewController" as per the documentation. Refer that "cartviewcontroller" in your custom typescript file and you will get selectedCartLineId

    If you want some data from the channel database and no suitable CRT request found where you can attach the attributes, you have to design end to end flow of service like CRT -> retail server -> typescript proxy -> consume in POS. Refer store hour sample for an end to end implementation.

  • Retha Profile Picture
    Retha 1,423 on at
    RE: How to add the quantity multiples of D365 into CloudPOS

    Hi Ram, how can I get the selected cart line?

    Also, although  SaveCartVersionedDataRequest in the CRT, is called when a product is added to a line or when the quantity is changed, it only allows me to add extension properties to ActiveSalesLines on the cart. Nothing for the current line.

    Is there another CRT trigger that I can call that can do a round trip to the channel DB to pull the multiple quantity for the SetQuantity retail operation?

    I did look at  "DialogSampleModule", and it derive from ITemplatedDialogOption which in the end only allow for 2 buttons. So I will go for your suggestion of ListInputdialog when I get there.

    However currently my CRT change to get the multipleQty is not for the selected cartline, and I have no idea how to get the selected cart line on POS to use PostOperationTrigger and how to do a CRT call from within POS to do the round trip to the channel DB

  • Verified answer
    ram shenkar Profile Picture
    ram shenkar 515 on at
    RE: How to add the quantity multiples of D365 into CloudPOS


    If I understood correctly, you want to show a dialog with 3 choices and that too only if sales line quantity is change(set/updated).

    You mentioned is correct there is no trigger as of now pre/after quantity change is sales line. If a user is updating quantity by using the 'set quantity' then yes you can perform your logic in PostOperationTrigger. Make sure to add logic only for the operation type as " SetQuantity = 105"

    Now, regarding the second issue that you want to show three buttons on a dialog box. It can be achieved in different ways

    - You can use "ListInputDialog" and add your three options as choices (preferred option in your scenario)

    - You can refer to "DialogSampleModule" in SampleExtensions and customize your dialog box up to any level.

    You can update quantity on cart line easily with "SetCartLineQuantityOperationRequest"

    I think the quantity change trigger may be a challenge here. If the operation trigger doesn't work for you, then best will be to reach out to Microsoft and raise extensibility requests.

Helpful resources

Quick Links

Replay now available! Dynamics 365 Community Call (CRM Edition)

Catch up on the first D365 Community Call held on 7/10

Community Spotlight of the Month

Kudos to Saurav Dhyani!

Congratulations to the June Top 10 community leaders!

These stars go above and beyond . . .


André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 288,459 Super User

Martin Dráb Profile Picture

Martin Dráb 225,783 Super User

nmaenpaa Profile Picture

nmaenpaa 101,148


Featured topics

Product updates

Dynamics 365 release plans