CRM and CX Blogs by Members
Find insights on SAP customer relationship management and customer experience products in blog posts from community members. Post your own perspective today!
cancel
Showing results for 
Search instead for 
Did you mean: 
R_Zieschang
Contributor
Today I want to show you how you can modify the receipt component in SAP Customer Checkouts UI. Some of these requirements encountered me a couple of times over the last years and since FP11 you are now able to add, remove or modify columns with a plugin.

There is also an influencer ticket to have this configurable in the quick selection management in CCOm. So if you haven't voted already, please do so.

Customize options for receipt area

This blog post requires some knowledge of creating plugins for SAP Customer Checkout, so I won't go into these specific details. If you are new to this, please visit my 5 part blog series on CCO plugin development:

SAP Customer Checkout Plugin Development – Part I

So let's dive into. We all know (and probably love) the receipt component in SAP Customer Checkout .


In this plugin we are going to create, we want to modify the columns shown in the ui. We want to show the itemcode and also the unitprice. Furthermore, we want interact with a click event of the customer, when he clicks on the itemcode. For the sake of simplicity we are going to add a simple alertbox on this click event, but you could also send events in the eventbus or whatever your mind comes up with.

In addition to this, we want to enable the option, that the cashier can edit a sales items description within the current receipt. And yeah, it would be cool, if we can show the cashier, if a sales item is discountable or not. 🙂

So the goal is to let the receipt component looks like this:


 

So how do we achieve this? The UI coding of the quickservice ui now knows the same principle called "Plugin Exits" like we know from the java coding e.g.
@ListenToExit(exitName="BusinessOneServiceWrapper.beforePostInvoiceRequest")

But for our ui plugin we want to listen an exit called "ReceiptComponent.getColumnConfigProvider". We listen to this exit not in our java coding but rather in our javascript script, we inject with our cco plugin. This procedure on how to do this is explained in detail in my blog series.

What we need to do here is, to provide a new modified configuration for the receipt component. This means, we do not modify the receipt component by modifying tiny bits but rather we provide a complete configuration of the receipt component at once.

The model for the quantity column looks like this:
{
text: 'ID',
width: '17%',
type: 'component',
field: 'material.externalID',
id: 'externalId',
noAutoFontSize: true,
component: (cellValue, salesItem) => {
return {
'component': 'ContainerComponent',
'props': {
'margin': '5%',
'content': {
'component': 'ButtonComponent',
'props': {
'content': cellValue,
'btnPress': () => {
alert(cellValue);
},
'class': 'rowButton'
}
}
}
};
}
}

So we are setting some properties for this column like the text, the width, the field of the sales item and we can extend this with another component. In this example the externalId column will be treated as a button the cashier can click on. The value for the property "field" can be any field of the sales item data model.

This click event will be handled in 'btnPress'.

Further properties you can set is a formatter or an editor. Remember when you click on the quantity column in a receipt row? A small editor shows up to let the cashier add or substract items. See:


So we also need to provide this editor as a configuration. The configuration for the quantity column looks like this.
{
text: receiptComponent.TL('SALES_ITEM_QUANTITY'),
width: '15%',
type: 'decimal',
field: 'quantity',
id: 'quantity',
formatter: (cellValue, salesItem) =>
{
return cellValue === null ? null : formatters.decimal.formatType(cellValue, decimalTools.TYPE_QUANTITY);
},
editor: new cco.ColumnTextEditor(receiptComponent, 'quantity', receiptComponent.TL('ENTER_QUANTITY'), receiptComponent.globalInputStore, receiptComponent.eventBus, null, 'quantity', (model, column) =>
{
let salesItem = column.salesItem;

let fallbackInputModel = new cco.FallbackInputModel(column.text);

if (receiptComponent.validateQuantityForReturn && salesItem.status !== '1')
{
if (salesItem.quantity <= 0)
{
fallbackInputModel.setValidator(new cco.MinMaxNumberInputValidator(-salesItem.orderedQuantity, -1));
}
else if (salesItem.orderedQuantity > 0)
{
fallbackInputModel.setValidator(new cco.MinMaxNumberInputValidator(salesItem.orderedQuantity));
}
}
return fallbackInputModel;
}, (column) =>
{
return !column['salesItem']['voucher'] && !column['salesItem']['immutable'];
})
}

 

Like the column for the itemcode we are setting some properties like text (in this case translated with the translator), width etc. Also the formatter will be used to format the values of the quantities to the right format. Like I already mentioned, because we provide a full new configuration for the receipt component we also need to implement the editor as well.

The last "special" thing which differs from the standard of the receipt component will be the editor to change the sales item description within the receipt. Also we mark the sales item as discountable. The config for the material description column looks like this:
{
text: receiptComponent.TL('MATERIAL'),
width: 'auto',
type: 'text',
class: (value, salesItem) => {
return salesItem.material && salesItem.material.discountable ? 'discountableHighlight' : '';
},
field: 'description',
id: 'description',
editor: new cco.ColumnTextEditor(receiptComponent, 'description', receiptComponent.TL('DESCRIPTION'), receiptComponent.globalInputStore, receiptComponent.eventBus, null, 'description', (model, column) => {
let salesItem = column.salesItem;

let fallbackInputModel = new cco.FallbackInputModel(column.text);
return fallbackInputModel;
}, (column) => {
return !column['salesItem']['voucher'] && !column['salesItem']['immutable'];
}),
hints: true
}

We are using the class property (which actually sets the css class for this column) to identify if the salesItem is a discountable item and if so, the class discountableHighlight will be used for this row.

The editor field will be used to use the ColumnTextEditor to let the cashier edit the description of the sales item.

The remaining columns have standard behaviour, so I wont get into more details. The code is uploaded to github as always.

Please feel free to comment.

 

Happy coding!

Robert
12 Comments
raveedriaz
Explorer
0 Kudos
Hi,

It is really helpful in understanding the concept of how quick service UI work and also the features you have added will be of use surely.

I only have one question regarding this, what if I want to show data which is not in salesItemdata for example I want to show another price which I will be fetching through webservice from B1if.
R_Zieschang
Contributor
Hi raveedriaz,

you could send this additional price in an additional field of the material entity by extending the material sync scenarios. This way, you could easily show it with material.udfDecimal1 (I think).

When the price needs to be fetched right at the moment, when the article is added to the receipt, you could react on the SALESITEM_ADD event, make the call to the backend and retrieve the price.

To dynamically change properties of components you can look at the last part of my blogseries, where I introduced the dynamicProperties.

 

Regards

Robert
JoergAldinger
Active Contributor
0 Kudos
Hello Robert!

Thank you very much for this explanation. In our case the most requested columns are item code, unit of measurement and current stock. The first two are going to be easy with this, the last one I guess we have to try and do it in the way you suggested to Raveed, using an AdditionalField.

Thank you very much!

Joerg.
raveedriaz
Explorer
0 Kudos
Hi Robert,

One quick question, can we increase the width of receipt area (grid in which selected item's are shown).

Thanks.
R_Zieschang
Contributor
0 Kudos

Hi raveedriaz,

currently not. The size is fixed afaik. But also our customers requested this to be configurable.

Maybe this would be a good idea for an influence ticket. You have my vote on that. 🙂

https://influence.sap.com/sap/ino/#/campaign/1731/ideas

Regards

Robert

former_member333938
Participant
0 Kudos
Hello, rzieschang,

 

Question, could I add a checkboxComponent instead of a buttonComponent ?.

in case of "yes". Is there an example of how to do this?.

 

thanks in advance
0 Kudos

Hi,

It is really helpful in understanding the concept, thank you.

I only have one question regarding this,it's possible to change background color or line of receipt component ? I try different way but i did not succed..

thanks in advance.

R_Zieschang
Contributor
0 Kudos
Hi mehdi.selmani,

there is another UI exit you can use. It's called 'ReceiptComponent.getRowModelCustomizer'

Use my example plugin to add this exit as well. This exit will provide an object "rowModel" in which you can set row specific properties. E.g. the CSS class.

 

e.g.

 
[...]
'ReceiptComponent.getRowModelCustomizer': () => {
return this.getRowModelCustomizer();
}
[...]

getRowModelCustomizer() {
return (rowModel) => {
// do stuff
}
}

Regards
Robert
0 Kudos

HI rzieschang,

Thank you very much for your answer.
I have try this
...
	@CSSInject(targetScreen="NGUI")
public InputStream cssInject() {
return this.getClass().getClassLoader().getResourceAsStream("resources/receiptcomponentplugin.css");
}

	    		'ReceiptComponent.getRowModelCustomizer': () => {

return (rowModel) => {
console.log('////// test',rowModel.rowClass);
rowModel.rowClass = 'nwraw';

}


},
.nwraw {
background-color: #f30a0a; Doesn't work..
opacity: .85;
display: none; (It's Work but i try this only for exemple)
}
It's work for some modification, but for Background color doesn't work ...if you can help me...
thanks in advance.
Regards.
Mehdi SELMANI.
AaronMendieta
Participant
0 Kudos
Hi rzieschang

Do you if it is possible to show message boxes with a specified time of life?

In the Old UI, I used to achieve this by creating the next method, modifying the parameters, and calling it when necessary


Reading your blogs I found the next script example:
 this.eventBus.push('SHOW_MESSAGE_BOX', {
'title': this.translationStore.getTranslation('NO_OPEN_RECEIPT', this.user.getLanguageCode()),
'message': this.translationStore.getTranslation('NO_OPEN_RECEIPT', this.user.getLanguageCode())
});



I have looked for more details about this way of showing messages, however, I have not found a way to add a timing parameter.


Any guidance will be truly appreciated, thanks in advance for your attention and best regards!
AaronMendieta
Participant
0 Kudos
Hi rzieschang

Hoping you could see my comment and take the time to answer, thanks a lot in advance Robert!

 

I need to print in the Retail UI's Log (where the next message is displayed) some messages from the backend once a BreakExecutionException is triggered:

 


In Old UI I used to achieve this by using the next code lines:


LogGDT log = new LogGDT();
CLogUtils.addMessageToLog(log, LogItemSeverityCode.Error, "", "Message to print");
throw new BreakExecutionException(log);

-First I created LogGDT instance


-Then I use the method addMessageToLog from the package CLogUtil to assign to my LogGDT instance the required structure

-Finally I passed the log as the parameter for the Exception

 

However, I am getting the next output:

class com.sap.scco.util.types.LogGDT cannot be cast to class com.sap.scco.ap.pos.entity.ReceiptEntity (com.sap.scco.util.types.LogGDT and com.sap.scco.ap.pos.entity.ReceiptEntity are in unnamed module of loader 'app')

Seems like LogGDT is not compatible anymore.

Do you know what is the way to print messages in the current Retail UI log?


Any guidance or comments will be really appreciated, Best Regards!
0 Kudos
UP,

 

Hi rzieschang

Hoping you could see my comment and take the time to answer, thanks a lot in advance !

 

 

Mehdi SELMANI