Point of Sale (POS) is one of the best and most important modules of Odoo ERP. A web-based application should always be attractive and easy to use. As we know, Odoo is a user-friendly ERP with an attractive user interface. Additionally, JavaScript plays a key role in ensuring a user-friendly interface for this ERP. We know that the version Odoo15 uses a web library called Odoo Web Library (OWL), a modern UI framework that inherits ideas from React and Vue.
To know more about OWL, refer to the link below: Introduction to Odoo OWL Framework.
For adding a button in POS, we are using the OWL FRAMEWORK, and also we have to create a new module in the custom folder.
Here we are going to discuss adding buttons in three different areas of POS those are, Product Screen, Systray & Payment Screen.
Let’s see how this works.
Showing below is the module files:
The files inside static>src are included under the assets of POS, So we have to add files in the manifest file shown below:
“assets”: {
‘web.assets_backend’: [‘pos_custom_buttons/static/src/js/product_screen_button.js’,
‘pos_custom_buttons/static/src/js/systray_button.js’,
‘pos_custom_buttons/static/src/js/payment_screen_button.js’],
‘web.assets_qweb’: {
[‘pos_custom_buttons/static/src/xml/product_screen_button_view.xml’,
‘pos_custom_buttons/static/src/xml/systray_button_view.xml’,
‘pos_custom_buttons/static/src/xml/payment_screen_button_view.xml’,]
},
After Adding in the manifest file you have to create corresponding JS & XML files.
Product Screen
To add a button to the Product Screen you have to add the below code into a created XML file in static > src > XML.
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="CustomDemoButtons" owl="1">
<span class="control-button" t-att-class="is_available()? 'highlight' : ''">
<i class="fa fa-ban" aria-hidden="true"></i>
<span> </span>
<span>Click me!!!</span>
</span>
</t>
</templates>
After adding the button, we have to add the JS file. And in the JS file we have to define the module using odoo.define and also define the required screens.
odoo.define('pos_custom_buttons.DemoButton', function(require) {
'use strict';
const { Gui } = require('point_of_sale.Gui');
const PosComponent = require('point_of_sale.PosComponent');
const { posbus } = require('point_of_sale.utils');
const ProductScreen = require('point_of_sale.ProductScreen');
const { useListener } = require('web.custom_hooks');
const Registries = require('point_of_sale.Registries');
const PaymentScreen = require('point_of_sale.PaymentScreen');
Above mentioned code is the required screen to add a button to the Product Screen.
The full code is shown below:
odoo.define('pos_custom_buttons.DemoButton', function(require) {
'use strict';
const { Gui } = require('point_of_sale.Gui');
const PosComponent = require('point_of_sale.PosComponent');
const { posbus } = require('point_of_sale.utils');
const ProductScreen = require('point_of_sale.ProductScreen');
const { useListener } = require('web.custom_hooks');
const Registries = require('point_of_sale.Registries');
const PaymentScreen = require('point_of_sale.PaymentScreen');
class CustomDemoButtons extends PosComponent {
constructor() {
super(...arguments);
useListener('click', this.onClick);
}
is_available() {
const order = this.env.pos.get_order();
return order
}
onClick() {
Gui.showPopup("ErrorPopup", {
title: this.env._t('Payment Screen Custom Button Clicked'),
body: this.env._t('Welcome to OWL'),
});
}
}
CustomDemoButtons.template = 'CustomDemoButtons';
ProductScreen.addControlButton({
component: CustomDemoButtons,
condition: function() {
return this.env.pos;
},
});
Registries.Component.add(CustomDemoButtons);
return CustomDemoButtons;
});
In the above code, we added a class named CustomDemoButtons and also added a function named onClick(). It is that when we click on the button then a popup error message will appear. You can customize the onClick() function as per your logic. The next line of code is for adding the button to the Product Screen. If you complete these steps and add files in the manifest file properly, it will work well. The below screenshot shows the workflow and functioning of the custom button we have added in POS.
In the below image, you can see the button “Click me!!!” button is shown.
When we click on the button, then this pop-up will be shown.
Systray
Here, we are going to discuss adding a button on the systray near orders.
For adding a button we have to create with a template name, and also add the template name in the inherited view.
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="CustomDemoButtons" owl="1">
<div class="ticket-button" t-att-class="{ highlight: props.isTicketScreenShown }" t-on-click="onClick">
<div class="with-badge" t-att-badge="count">
<i class="fa fa-diamond" aria-hidden="true"></i>
</div>
<div>Click me!!!</div>
</div>
</t>
<t t-inherit="point_of_sale.Chrome" t-inherit-mode="extension">
<xpath expr="//TicketButton" position="before">
<CustomDemoButtons isTicketScreenShown="isTicketScreenShown"/>
</xpath>
<xpath expr="//TicketButton" position="after">
<CustomDemoButtons isTicketScreenShown="isTicketScreenShown" t-if="env.isMobile"/>
</xpath>
</t>
</templates>
To add buttons, we have to create a button with a template and add the template name in the inherited view. Once you have defined the button structure, then we can add this button by inheriting the default template and adding our template “CustomDemoButtons” through xpath.
After adding buttons we have to add the corresponding JS file to configure the button.
odoo.define('pos_custom_buttons.CustomDemoButtons', function(require) {
'use strict';
const { Gui } = require('point_of_sale.Gui');
const PosComponent = require('point_of_sale.PosComponent');
const { posbus } = require('point_of_sale.utils');
const ProductScreen = require('point_of_sale.ProductScreen');
const { useListener } = require('web.custom_hooks');
const Registries = require('point_of_sale.Registries');
class CustomDemoButtons extends PosComponent {
onClick() {
Gui.showPopup("ErrorPopup", {
title: this.env._t('Custom Ticket Button Clicked'),
body: this.env._t('Welcome to OWL'),
});
}
}
CustomDemoButtons.template = 'CustomDemoButtons';
Registries.Component.add(CustomDemoButtons);
return CustomDemoButtons;
});
Here also you can add your own logic in the onClick() function. we can see how this works after completing the following steps.
Here we can see the button “Click me!!!” is shown near orders on the Systray. When we click on the button it will show an error popup.
Payment Screen
Finally, we are going to discuss adding a button to the Payment Screen.
For that, we have to add an XML file for the button. To add the button to the Payment Screen we have to inherit the template and add our button to it.
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-inherit="point_of_sale.PaymentScreen" t-inherit-mode="extension">
<xpath expr="//div[hasclass('payment-controls')]" position="inside">
<div>
<div id="my_button" class="button js_invoice"
t-on-click="IsCustomButton">
<i class="fa fa-spinner fa-spin" /> Click me!!!
</div>
</div>
</xpath>
</t>
</templates>
Here we can see t-on-click="IsCustomButton" is a function to be added to the JS file. And we just inherited the Payment Screen template and added it to the division payment-controls. We know that Payment Screen is the default class in Odoo15 so we have to just inherit the required class in JS which means, We just need to inherit the predefined class PaymentScreen.
odoo.define('pos_custom_buttons.PaymentScreenButton', function(require) {
'use strict';
const { Gui } = require('point_of_sale.Gui');
const PosComponent = require('point_of_sale.PosComponent');
const { posbus } = require('point_of_sale.utils');
const ProductScreen = require('point_of_sale.ProductScreen');
const { useListener } = require('web.custom_hooks');
const Registries = require('point_of_sale.Registries');
const PaymentScreen = require('point_of_sale.PaymentScreen');
const CustomButtonPaymentScreen = (PaymentScreen) =>
class extends PaymentScreen {
constructor() {
super(...arguments);
}
IsCustomButton() {
// click_invoice
Gui.showPopup("ErrorPopup", {
title: this.env._t('Payment Screen Custom Button Clicked'),
body: this.env._t('Welcome to OWL'),
});
}
};
Registries.Component.extend(PaymentScreen, CustomButtonPaymentScreen);
return CustomButtonPaymentScreen;
});
You can also write your own logic inside the button click function. After completing these steps the output in the Payment Screen is as shown below.
By clicking on the “Click me!!!” button it will show an error popup shown below.
Also, you can add the button wherever you need to, only by choosing the place and giving the XPath.
After completing all these steps check whether the file path given inside the manifest file and just upgrade the module. Also, ensure that these three buttons are working properly.This is how we add buttons to POS using OWL in Odoo15. lso Read Related Module: How to Add Custom Screens in Odoo 15 PoS.