cancel
Showing results for 
Search instead for 
Did you mean: 

Example for a Quick service Plugin CCO

0 Kudos
1,572

Hey is there an Example for a plugin working in the Quick service Mode. we need to access the UDF on the line level in the receipt and to prompt a validation for it, also we need to access the voucher data, if there is an example or sample documentation it will help alot

Accepted Solutions (1)

Accepted Solutions (1)

R_Zieschang
Contributor
0 Kudos

Dear m.metwaly,

please use the following classes and methods in the PluginAt annotation for the new UI Stack:

@PluginAt(pluginClass = ReceiptPosService.class, method = "postReceipt", where = POSITION.BEFORE)

@PluginAt(pluginClass = ReceiptPosService.class, method = "addSalesItem", where = POSITION.BEFORE)

In the args array all the needed entities should be available.

Regards

Robert

0 Kudos

rzieschang Many thanks , also if i have the following code what is the alternative JS for New UI to do the same function :

var originAddNewSalesItem = addNewSalesItem;

addNewSalesItem = function (rowid, materialId, amount, unitOfMeasure, materialUsed, additionalParams) {

if (materialId) {

var result = materialId.split("\?");

if (result.length > 1) {

materialId = result[0];

amount = result[1];

}

}

originAddNewSalesItem(rowid, materialId, amount, unitOfMeasure, materialUsed, additionalParams);

};

Answers (7)

Answers (7)

0 Kudos

rzieschang thanks alot for the guidance , they are very clear samples appreciate you support

R_Zieschang
Contributor
0 Kudos

Dear m.metwaly,

in your js code, you can use the backendPluginEvent to push Events to your plugin backend rather than using the PluginServlet (which is still possible but this is more convenient imho).

this.pluginService.backendPluginEvent('MY_PLUGIN_EVENT', {
    'myData': 'data'
});

In your backend you need to override the handleEvent Method from the EventChannelListener like this:

BroadcasterHolder.INSTANCE.addEventChannelListener(new UIEventChannelListener() {
  @Override
  public void handleEvent(String eventId, JSONObject payload) {
    if(StringUtils.equals(eventId, "MY_PLUGIN_EVENT")) {
      System.out.println(payload.getString("myData"));
    }
  }
}

For a generic InputDialog you just push an event to the Eventbus and send some configuration along:

const inputModel = new cco.InputModel();
this.eventBus.push('SHOW_GENERIC_INPUT', {
            'configuration': [
                new cco.GenericInputConfiguration('This is the text', '0', 'CenteredLabel'),
                new cco.GenericInputConfiguration('Please enter a value', '1', 'Input', inputModel),                                
            ],
            'title': 'This is the title',
            'callback': (positive) => {
                if (positive) {
                    console.log('OK Pressed. Value is: ' + inputModel.getValue());
                }else {
					console.log('X or cancel pressed');
                }
            }
        });

hth

Robert

AaronMendieta
Participant
0 Kudos

Hi @Robert Zieschang

I'm trying to catch SALESITEM_ADD event data in my backend (Retail UI),

however, when I want to implement the EventChannelListener script you shared I'm getting the next:

I still don't get the reason of the error, the structure and syntaxis are the same and I have already imported all necessary packages (the script is declared in my main class).

Could you please help me to understand the reason for the issue or tell me if there is another way to catch the event when debugging (using @PluginAt does not seem to work anymore with Retail UI)?

Thanks in advance for your attention, best regards!

R_Zieschang
Contributor
0 Kudos

Hi pamt,

the BroadcasterHolder is a singleton class, so you can't just add this anywhere in your code. What you do here is basically the following, the BroadcasterHolder holds a list of implementations of the UIEventChannelListener interface. This interface defines the handleEvent method. With the block of the mentioned code you are adding a new event listener to the BroadcasterHolder singleton class and give the implementation inline.
You could also define a separate class, implement the interface and have a very short "adding" procedure. But because I need to keep it simple in my blog posts I choose this way.

So to get going:

Override the startup method of the abstract BasePlugin class (this one should be your main plugin class) and then add this whole block of code within your startup method.

Should look something like this:

    @Override
    public void startup() {
        super.startup(); 
BroadcasterHolder.INSTANCE.addEventChannelListener(new UIEventChannelListener() { @Override
public void handleEvent(String eventId, JSONObject payload)
{ // do stuff with the event } } }

Hope that helps

Regards
Robert

AaronMendieta
Participant
0 Kudos

Hi Robert

Thanks in advance for your willingness to help and for taking the time to answer, I do appreciate it.

Your previous comment helped me to succeed in catching the event I was interested in, however, I have noticed the next.

1.- Compare to the Old Retail (using PluginServlet I was able to catch the event before the sales item was added to the receipt), in the New Retail UI, the addition of the item happens before (Item is already shown in the receipt) I can catch the event and that is something I am asked to avoid.


-1.1 Do you know if there is any other way to catch the event before the addition happens?
-1.1 Is this the expected behavior of the system (I am working with FP13)?


2.- I am able to modify the quantity of the added Item via backend, then I update my receipt and refresh my UI, however, something curious happens, the modification works perfectly while I am debugging but once I stop, the quantity differs from what is expected.

-2.1 Have you ever experienced something similar?

-2.2 Do you have any clue of what could be the reason that only while debugging scripts run as they are expected?

Thanks again and best regards Robert!

0 Kudos

rzieschang many thanks for the last piece of code it worked very smoothly , one last thing i hope to get your support on , i have a dialog box in the retail mode that capture data and store it in a UDF , i need to know how this will be managed in the New UI (Quick Service Mode) the code is as below

$( "#dialog-confirm" ).dialog({resizable: false,height: "auto",width: 400,modal: true,

buttons: { Ok: function()

{ imeiNo=$('#txtimei').val();

showInProgressDialog();

$.ajax(

{"url" : "PluginServlet?action=getIMEIInfo&imeiNo=" + imeiNo+ "&materialId=" + materialId,

"dataType" : "JSON",

"type" : "GET"}).

success(function(data) {

hideInProgressDialog();

console.log(data);

if (data["status"] === "success" && data["action"] != "imei") {

originAddNewSalesItem(rowid, materialId, amount,unitOfMeasure,materialUsed,additionalParams);

}

}).fail(function() {hideInProgressDialog();});

$( "#dialog-confirm" ).dialog( "close" );

},Cancel: function() {

$( "#dialog-confirm" ).dialog( "close" );

}

}

});

R_Zieschang
Contributor
0 Kudos

Dear m.metwaly,

with the new UI Stack written with Angular in Typescript, you can't monkey patch js methods like in your example. From 2.0 FP08 onwards you have the option to subscribe to the eventbus. In the eventbus all the UI components are publishing events e.g. the adding of a sales item, adding of a payment item etc.

Create a js file:

Plugin.MyPlugin = class MyPlugin {
  constructor(pluginService, eventBus) {
    this.pluginService = pluginService;
    this.eventBus = eventBus;
    this.init();
  }

  init() {
    this.eventBus.subscribe({
      'handleEvent': (event) => { console.log(event); }
     });
  }
};
 

Now when your plugin is loaded open the google developer console (Press F12) and identifiy the event you want manipulate (I currently don't know which event is for adding a sales item). In the payload of every event you may find everything you need (e.g. when adding a sales item there will be the sales item entity in the payload section of the event).

hth

Robert

R_Zieschang
Contributor
0 Kudos

Dear m.metwaly,

can you please tell me which Exits or which methods via PluginAt annotation you hooked in? With the new UI some of the methods for posting receipts etc. changed.


Regards

Robert

Thanks @rzieschang if there is a document or a full sample for the new UI it will be great this will save time for asking alot of questions , and if there is a document or a link to explore the new UI Methods i will be greatfull , if not i will share my code sample but this will mean i will need your support every time i get stuck 🙂

0 Kudos

Dear rzieschang below sample of the code used in the new UI

@PluginAt(pluginClass=IReceiptManager.class, method="dirtyStore", where=POSITION.BEFORE)

public void performReceiptValidation(Object proxy, Object[] args, StackTraceElement callStack) throws BreakExecutionException{

}

@PluginAt(pluginClass=IReceiptManager.class, method="addSalesItems", where=POSITION.BEFORE)

public void performReceiptaddSaleItems(Object proxy, Object[] args, StackTraceElement callStack) throws BreakExecutionException{

}

the debugger passed by them

Arne_Timmermann
Contributor
0 Kudos

Hey Mohamad,

check out this blog series written by my colleague https://blogs.sap.com/2018/10/16/sap-customer-checkout-plugin-development-part-i/ , maybe this will help you!

Kind regards,

Arne

0 Kudos

I checked it I need to do the same in the Kiosk Mode, not the retail

R_Zieschang
Contributor
0 Kudos

Dear m.metwaly,

what is it you want to achieve? Based on the Value in the UDF the cashier needs to prompt something? Is this validation needed when the sales item is added or when the receipt is going to be posted?

Regards
Robert

i need to generate automatic Vouchers when selling certain items in the Kiosk Mode ( Quick service) , i tried to make the plugin it works in the Retail Mode but not working in the Kiosk Mode , when tried to debug it works totally different and didn't catch the events