Hi Mina
Do you just have to add an operation that does the same as SetQuantity?
To add the operation ID with its factory, handler and request/response code follow the steps in this link: docs.microsoft.com/.../add-pos-operations
For the SetQuantity itself:
To get your current cartline, the POS SampleExtensions have a CartViewController in ViewEstensions/Cart which logic you can use . SaveDatatoSelectedCartLineHandler shows you how to call it.
In my case, I copied the CartViewController and placed it inside my extension because I added logic to also get the actual cartline, not just the ID.
In your typeScript file, add the following where the you just add your cartviewcontroller.
import { ExtensionOperationRequestType, ExtensionOperationRequestHandlerBase } from "PosApi/Create/Operations";
import { ClientEntities, ProxyEntities } from "PosApi/Entities";
import CartViewController from "../../CustomControlExtensions/Cart/CartViewDetailsController";
import { SetCartLineQuantityOperationResponse } from "PosApi/Consume/Cart";
import { ObjectExtensions, StringExtensions } from "PosApi/TypeExtensions";
My case is different because I had to also add a custom request/response because I needed to pull more information from the channel DB after the initial quantity was entered. So the export class is on my custom handler and it extends "ExtensionOperationRequestHandlerBase<TResponse>"
Just below the signature of my export default class I have the following variables defined:
private cart: ProxyEntities.Cart = null;
private cartLine: ProxyEntities.CartLine = null;
private enteredQty: number = 0;
private isReturn: boolean = false;
private originalQty: number = 0;
/*
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.");
MessageService.ShowMessage(this, this.context.resources.getString("tmc_38"), this.context.resources.getString("tmc_39"));
return Promise.resolve(null);
}
if (ObjectExtensions.isNullOrUndefined(CartViewController.selectedCartLine)) {
return Promise.resolve(null);
}
this.cartLine = CartViewController.selectedCartLine;
// Need to make sure the quantity is always positive, function Return transaction or return item will deal with the sign
if (this.cartLine.Quantity < 0) {
this.isReturn = true;
}
else {
this.isReturn = false;
}
this.originalQty = Math.abs(this.cartLine.Quantity);
return this.SetQtyRequest(sqRequest, this.originalQty);
});
*/
The reason why I only take the absolute value of the quantity is because one enters only a positive quantity on the number pad.
After getting the current cart and it line's quantity, I call my custom method SetQtyRequest and I pass in my custom executeASync. You will have a different one depending on your logic.
Inside my custom method I create the number pad on the fly:
let dialogOptions: ClientEntities.Dialogs.INumericInputDialogOptions = {
title: this.context.resources.getString("tmc_1"), // "Change Quantity",
subTitle: " ",
numPadLabel: this.context.resources.getString("tmc_2"), //"Quantity",
defaultNumber: _lineQty.toString()
};
let showInputDialog: Commerce.ShowNumericInputDialogClientRequest<Commerce.ShowNumericInputDialogClientResponse> = new Commerce.ShowNumericInputDialogClientRequest(dialogOptions);
return this.context.runtime.executeAsync(showInputDialog)
.then((showNumericDialogResult: ClientEntities.ICancelableDataResult<Commerce.ShowNumericInputDialogClientResponse>): any => {
this.enteredQty = parseFloat(showNumericDialogResult.data.result.value);
this.EnteredQty will contain the number the user entered.
I had some extra code after the above to call the channel DB if certain conditions were met, however you should be able to after the enteredQty was populated, do the following:
let setQtyResponse: Promise<ClientEntities.ICancelableDataResult<TResponse>>;
setQtyResponse = this._saveQtyToCartline(this.cartLine.LineId, this.enteredQty, request.correlationId, this.cart);
return setQtyResponse;
}).catch((reason: any): any => {
MessageService.ShowMessage(this, this.context.resources.getString("tmc_40"), JSON.stringify(reason));
return Promise.resolve();
});
SaveQtyToCartLine method calls then the standard repsonse of SetQuantity to populate the line quantity with the value entered by the user using your operationId:
private _saveQtyToCartline(cartLineId: string, qtySelection: number, correlationId: string, cart: ProxyEntities.Cart):
any {
if (this.isReturn) {
qtySelection = qtySelection * -1;
}
let saveRequest: Commerce.SetCartLineQuantityOperationRequest<SetCartLineQuantityOperationResponse> =
new Commerce.SetCartLineQuantityOperationRequest<SetCartLineQuantityOperationResponse>
(correlationId, cartLineId, qtySelection);
this.context.runtime.executeAsync(saveRequest);
let refreshCartLineRequest: Commerce.RefreshCartClientRequest<Commerce.RefreshCartClientResponse>
= new Commerce.RefreshCartClientRequest<Commerce.RefreshCartClientResponse>();
return this.context.runtime.executeAsync(refreshCartLineRequest)
.then((result: ClientEntities.ICancelableDataResult<Commerce.RefreshCartClientResponse>): any => {
if (!result.canceled) {
this.context.logger.logInformational("TMC Set quantity on Cart updated successfully!!!");
}
});
}
I hope the above will give you an idea on how to create your own operationId but uses the standard SetCartLineQuantityOperationRequest/SetCartLineQuantityOperationResponse to update the cart line with the quantity from your custom number dialog