Skip to Content
Technical Articles

SAP Customer Checkout Plugin Development – Part II

Back to Part I

Part II: Create a backend Plugin

Welcome to the second part of this blog series. In this part we will add two plugin properties, one for a list of material Ids and the second one for storing a message, read them from the database and we will show the message to the user if a sales item is added which was configured in the list of material Ids.

Maybe you want to remind the cashier to ask for the customers id for certain sales items?

We will also learn how to debug our code and log messages to the cco log. So let us start.

I copied the plugin we created in the first part, renamed it as blogpluginpart2 in the pom.xml and set the package name accordingly.

Let’s dive in. The first thing we need to do is to override the persistPropertiesToDB() method and return true. This ensures, that CCO handles the persistence of our plugin properties. Open the App.java class, click in the source at the bottom and press Strg + Spacebar. A list of methods will appear that we can override. Select the persistPropertiesToDB() method.

This method should always return true.

The next method we need to override is the getPluginPropertyConfig() method. This method should return a Map<String,String> of our properties.

The key of the HashMap is the name of the plugin property and the value is the type of data which will be stored in this property. So use int for integers or e.g. a boolean will create a checkbox. For now we will use two string properties. The first property will save a comma separated list of material Ids and the second one is a message string, we will show to the cashier, if a new sales item is in the LIST_OF_MATERIALS.

Next thing to do is to let our plugin react when a new sales item is added to the receipt. The Customer Checkout API is aspect-oriented; means whenever SAP is adding so called exit-points to their methods in their classes their API is calling any plugin which has this particular exit-point as parameter in annotation.

So we will add a method checkSalesItem like this:

@PluginAt is the annotation. And we will set this annotation to be called when the addSalesItems Method (method=“addSalesItems“) in the IReceiptManager class (pluginClass=IReceiptManager.class) was executed (where=POSITION.AFTER).

So our method checkSalesItem is called, whenever a sales item was successfully added to the receipt.

In the array of objects (Object[] args) cco sends all necessary entities we need for our process. E.g. the receipt and the added salesItem.

If you want to know, which entities are stored in the array of objects, we will need to setup our debug environment. Double click on the line with the method head to set a break point.

Save your files and build your plugin. Copy the plugin in the plugin folder of your Customer Checkout installation and start cco. Go back to your eclipse and right click on your project folder. Choose Debug As and Debug Configurations….

On the left list look for Remote Java Application and select this entry. Now create a new configuration via click on the new button.

Set a name for your configuration and change the port to 4000 (this is the port we set in part 1 in the run.bat, remember?). Click Apply and Debug.

Login into your cco and add a sales item. Your eclipse should change it’s perspective to debug.

Confirm with yes. In the variables window you will now see the content of the args array.

Disconnect your debug session. We will now implement the checkSalesItem Method. The exitpoint for addSalesItems method of the IReceiptManager class at the POSITION.AFTER is called multiple times. To ensure, that we will only react on the last one, we will check, how many entries the args array has.

Our plugin only reacts if the args array has two entries. If so, we will retrieve the 0 and the 1 indexed entry and cast it to the right type.

Will get our plugin property LIST_OF_MATERIALS and will split the string into a string array. To comfortably check if the new sales item has a material Id we configured we will create a List<String> of this String array so that we are able to use the contains method.

After that we are calling a showMessageToUi method we will implement later. This method will given two strings. The message itself and a “type” of the message.

Whenever the plugin shows the message to the cashier it should also create a log entry. SAP Customer Checkout has everything you need to log your own error messages, exception stacktraces and so on. Simply add this to your global class members:

Now we can log our messages right into the cco logs (and of course the cco console) when we have to.

The last thing we are going to implement in this part is the showMessageToUi method. This method allows you to create simple notifications to the cashier right from your cco plugin.

The UIEventDispatcher takes the „SHOW_MESSAGE_DIALOG“ action as parameter and also a Map where we set the message, in id, the lifetime and the type.

Ok, build your plugin, copy the jar into your plugin folder and start cco! Go to your plugin configuration in your cco backend and set your properties.

Save these changes. SAP Customer Checkout caches the properties from every plugin at startup so if you change this, you should restart.

Now if we add sales items with the configures material Id, we should see the MESSAGE_FOR_CASHIER and also an entry in the console.

And of course, also in the customer checkout log.

 

That’s all for this part of the course. If you have any questions or feedback, please do not hesitate to get in touch with me.

The code of this parts plugin is hosted in gitlab: https://gitlab.com/ccoplugins/blogpluginpart2

Stay tuned for the next part, where we are implementing a plugin sync job to retrieve data from the b1i and we are implementing a way to send custom monitoring messages to CCOm.

9 Comments
You must be Logged on to comment or reply to a post.
  • Hi Robert,

     

    It looks like “UIEventDispatcher.INSTANCE.dispatchAction(“SHOW_MESSAGE_DIALOG”, null, dialogOptions);” allows to pass button and input fields to front end.

    Can you please give me an example or suggest where can I find info about this. I need to ask question on frontend and get manually inputted reply from user on back end.

     

    Thanks,

    Sergei

    • Hi Sergei,

       

      afaik there is no real API Documentation unfortunately. But take this example to create a small input dialog for the cashier.

      JSONObject dialogOptions = new JSONObject();
      dialogOptions.put(“message”, “Please insert some value here:”);
      dialogOptions.put(“id”, “DIALOG_CONFIG”);
      dialogOptions.put(“type”, “info”);
      dialogOptions.put(“input”, “true”);

      JSONObject btnOkConf = new JSONObject();
      btnOkConf.put(“type”, “good”);
      btnOkConf.put(“id”, “DIALOG_CONFIG_BTN_OK”);
      btnOkConf.put(“text”, “OK”);
      btnOkConf.put(“default”, “true”);

      JSONObject btnCancelConf = new JSONObject();
      btnCancelConf.put(“type”, “bad”);
      btnCancelConf.put(“id”, “DIALOG_CONFIG_BTN_CAN”);
      btnCancelConf.put(“text”, “Abort”);

      dialogOptions.put(“buttons”, new JSONObject[] {btnOkConf, btnCancelConf});

       

      Then implement a method to get the input value:

       

      @ListenToExit(exitName=”genericButtonCallback”)
      public void handleDialogInput(Object caller, Object[] args) {

      String inputVal= (String) args[2];

      }

       

      You may also need to check, if the args are for the right event.

       

      Let me know if this worked for you.

      Regards

      Robert

       

      • Hi Robert,

        Thank you very much. It works like charm. It looks like your code for JavaScript, I just tweaked a bit for Java syntax and it works 🙂

        Thanks,

        Sergei

        • Hi Tomorjin,

           

          do you need to print another receipt or just extend the existing templates?

          When you need to add additional infos to existing printjobs:

          annotate a method in your plugin:

          @ListenToExit(exitName=”BasePrintJobBuilder.mergeTemplateWithData”)

          You will get an array of objects iirc with the printtemplate, the entity which will be printed e.g. the receipt or the voucher. The first entry in the array is iirc an HashMap<String, Object> where you can put additional information like this:

          map.put(“MY_CUSTOM_FIELD”, “Hello my name is dr. greenthumb”);

           

          In the printtemplate you can access the text via ${MY_CUSTOM_FIELD}.

           

          When you need your own Printjob:

          You can implement your own printjob builder by extending the BasePrintJobBuilder class. When extending you need to implement certain methods which are mostly self explainatory.

           

          But I did not have the chance to implement a custom printjob in production.

           

          Regards

          Robert

          • Hi Tomorjin,

             

            I would suggest not to handle this in the afterReceiptPost.

            Extend the salesReceipt Printtemplate with the layout of your tax receipt. Add a check for a boolean variable (printTaxReceipt yes / no). Printtemplates are implemented via Apache Freemarker Syntax.
            https://freemarker.apache.org/

            Implement a method with the ListenToExit as mentioned above. Something like this:

             

            @ListenToExit(exitName="BasePrintJobBuilder.mergeTemplateWithData)
            public void mergePrintTemplateData(Object caller, Object[] args) {
            
            Map<String, Object> root = (Map<String,Object)args[0];
            
                if(args[2] instanceof ReceiptDTO) {
                    // further checks if tax receipt should be printed
                    root.put("taxReceiptPrint", "true");
                    root.put("var1", "Value1");
                    root.put("var2", "Value2");
                }
            }

             

            In your print template you can now use the variable taxReceiptPrint, var1, var2 to enrich your template with the values you need to print on your tax receipt.

            For multilanguage purposes you may need textblocks in the print template like this:

            <@translate key=”YOUR_TEXT_CODE”>

             

            Then goto your translationsfolder (normally cco/translations) where you find the translation property files.

            Open the file for the desired language. Insert:

            YOUR_TEXT_CODE=your desired text in the desired language

             

            Save it. And now your text should automatically be inserted in your printtemplate.

             

            If you need further assistance or if you are interested that I shall implement this feature please contact info@hokona.de.

             

            Julian Wehmann FYI

             

            Regards

            Robert