How To Add & Store A Field In Odoo POS
A Point of Sale in a shop is a place where items are sold to customers by the sellers. POS refers to 'point of sale', which, as the name suggests, means a stock and sales control system.
Point of Sale transactions is the transactions made by the customers every time they buy something from a shop.
Odoo POS is a very great and interactive POS setup for any shop. Odoo POS is listed as one of the smartest interfaces provided by any ERP system. The setup is easy to use and provides almost all POS features.
Odoo provides us the convenience of customizing the flow according to our preferences. The Odoo backend setup comprises of Python and Javascript code.
The front end is designed using XML and Bootstrap libraries. We can easily customize Odoo and all the business modules provided by Odoo according to our preferences.
In this blog, we are going to discuss how we can customize the Odoo POS according to our preferences.
Subscribe for Odoo tips, technical insights, and more!
Sometimes while creating order in POS, we need to add some extra info to the order and save in the record so we can check the info later. We can add a simple text field that can be opened as a popup. We can add a button to the interface for adding this popup.
In this case, we’ll try to add a popup note field to the POS interface and we can use this field value and store it in the record/order in the backend.
1) Firstly inherit qweb template for adding a button.
Here we have inherited POS payment screen and added a button with Popup Note name.
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<-- Here we have extend PaymentScreenWidget -->
<t t-extend="PaymentScreenWidget" t-as="CustomPaymentScreenWidget">
<--And here we have append our button in the div class-->
<t t-jquery="div[class='payment-buttons']" t-operation="append">
<button t-attf-class="button pos_payment_method"style="width:320px;">
<span>Popup Note</span>
</button>
</t>
</t>
</templates>
2) Now mention this xml in manifest file.
# -*- coding: utf-8 -*-
{
'name': 'Popup Note In POS Screen',
'version': '13.0',
'summary': '',
'sequence': 30,
'description': """ """,
'website': 'www.kanakinfosystems.com',
'author': 'Kanak Infosystems LLP',
'images': [],
'depends': ['base', 'point_of_sale'],
'data': [],
'qweb': ['static/src/xml/pos.xml'],
'installable': True,
'application': True,
'auto_install': False,
}
3) Now you can see your button.
4) Create a new template for popup note and we are creating in the same file (pos.xml).
?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
➡ This is the extended template
<t t-extend="PaymentScreenWidget" t-as="CustomPaymentScreenWidget">
<t t-jquery="div[class='payment-buttons']" t-operation="append">
<button t-attf-class="button pos_payment_method"style="width:320px;">
<span>Popup Note</span>
</button>
</t>
</t>
➡ This is your new template from here
➡ And this is the template name and you can give any name
<t t-name="PopupNote">
<div role="dialog" class="modal-dialog">
<div class="popup popup-textinput">
<--This is the header -->
<header class="title">
<t t-esc=" widget.options.title || '' " />
</header>
<--This is the input field-->
<input type='text' class="popup_note"name="popup_note"></input>
➡ This is the footer and we have added confirm button and cancel button
<div class="footer">
<div class="button confirm">
Confirm
</div>
<div class="button cancel">
Cancel
</div>
</div>
</div>
</div>
</t>
</templates>
5) Create a js file and create a widget.
➡ Here is the module_name.js_file_name
odoo.define('poppup_note.pos', function(require) {
"use strict";
➡ Here we have defined some variable and assigned some js file (like this- require ('module_name.js_file_name')) so that we can include and extend some method
var core = require('web.core');
var models = require('point_of_sale.models');
var screens = require('point_of_sale.screens');
var gui = require('point_of_sale.gui');
var PopupWidget = require('point_of_sale.popups');
var PaymentScreenWidget = screens.PaymentScreenWidget;
var PosBaseWidget = require('point_of_sale.BaseWidget');
var BarcodeEvents = require('barcodes.BarcodeEvents').BarcodeEvents;
var time = require('web.time');
var QWeb = core.qweb;
var _t = core._t;
➡ Here we have extended our new widget in the PopupWidget.
var PopupNote = PopupWidget.extend({
<--This is the template name-->
template: 'PopupNote',
show: function(options) {
options = options || {};
this._super(options);
this.renderElement();
},
<--This is the confirm method-->
click_confirm: function() {
var value = this.$('input,textarea').val();
➡ When we will click on confirm button then it will close automatically popup note
this.gui.close_popup();
if (this.options.confirm) {
this.options.confirm.call(this, value);
}
},
});
gui.define_popup({ name: 'popup_note', widget: PopupNote });
➡ Now, we need to include the custom widget in the PaymentScreenWidget
PaymentScreenWidget.include({
➡ We have to override this method from the point_of_sale module for the payment screen so that we can input char in our input filed.
Note – If you add any input field inside pos product screen then you don’t override this method.
init: function(parent, options) {
var self = this;
this._super(parent, options);
this.pos.bind('change:selectedOrder', function() {
this.renderElement();
this.watch_order_changes();
}, this);
this.watch_order_changes();
this.inputbuffer = "";
this.firstinput = true;
this.decimal_point = _t.database.parameters.decimal_point;
// This is a keydown handler that prevents backspace from
// doing a back navigation. It also makes sure that keys that
// do not generate a keypress in Chrom{e,ium} (eg. delete,
// backspace, ...) get passed to the keypress handler.
this.keyboard_keydown_handler = function(event) {
if (event.keyCode === 8 || event.keyCode === 46) { // Backspace and Delete
➡ We have commented out this element so that after writing any char we can delete it by backspace
// event.preventDefault();
// These do not generate keypress events in
// Chrom{e,ium}. Even if they did, we just called
// preventDefault which will cancel any keypress that
// would normally follow. So we call keyboard_handler
// explicitly with this keydown event.
self.keyboard_handler(event);
}
};
// This keyboard handler listens for keypress events. It is
// also called explicitly to handle some keydown events that
// do not generate keypress events.
this.keyboard_handler = function(event) {
// On mobile Chrome BarcodeEvents relies on an invisible
// input being filled by a barcode device. Let events go
// through when this input is focused.
if (BarcodeEvents.$barcodeInput && BarcodeEvents.$barcodeInput.is(":focus")) {
return;
}
var key = '';
if (event.type === "keypress") {
if (event.keyCode === 13) { // Enter
self.validate_order();
} else if (event.keyCode === 190 || // Dot
event.keyCode === 110 || // Decimal point (numpad)
event.keyCode === 188 || // Comma
event.keyCode === 46) { // Numpad dot
key = self.decimal_point;
} else if (event.keyCode >= 48 && event.keyCode <= 57) { // Numbers
key = '' + (event.keyCode - 48);
} else if (event.keyCode === 45) { // Minus
key = '-';
} else if (event.keyCode === 43) { // Plus
key = '+';
}
} else { // keyup/keydown
if (event.keyCode === 46) { // Delete
key = 'CLEAR';
} else if (event.keyCode === 8) { // Backspace
key = 'BACKSPACE';
}
}
➡ And this one we have commented out so that we can input any char or word
// self.payment_input(key);
// event.preventDefault();
};
this.pos.bind('change:selectedClient', function() {
self.customer_changed();
}, this);
},
renderElement: function() {
var self = this;
this._super();
➡ Here, we have to define button id
this.$('.popup_notes').click(function() {
➡ Here, we have defined another method when we will click on the button then, it will call this method
self.get_select_data();
});
},
get_select_data: function() {
➡ Here, we have defined a variable and assigned this and you can get the value of the current class by using this.
var self = this;
➡ Here, we have to define the widget name('popup_note') which we have created.
self.gui.show_popup('popup_note', {
title: _t('Popup Note'),
confirm: function() {
➡ Here, we have called get_order() method and we have defined two methods in order set and get
var order = self.pos.get_order();
➡ Here we have passed a value of input value inside set_note_value
order.set_note_value(document.getElementsByName("popup_note")[0].value)
},
cance: function() {},
});
},
});
var _super_order = models.Order.prototype;
models.Order = models.Order.extend({
➡ Here we have inherited this method and defined a variable with a note value.
initialize: function(attr, options) {
this.note_value = false;
_super_order.initialize.apply(this, arguments);
},
set_note_value: function(note_value) {
this.note_value = note_value;
},
get_note_value: function() {
return this.note_value;
},
export_as_JSON: function() {
var json = _super_order.export_as_JSON.apply(this, arguments);
var order = this.pos.get('selectedOrder');
if (order) {
➡ Here we are getting value by set method and get method which we have to defined above side
json.field_input_value = this.note_value;
}
return json
},
});
});
6) Now add this js file in point_of_sale.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
➡ Here we have inherited the assets template of point_of_sale module
<template id="assets" inherit_id="point_of_sale.assets">
<xpath expr="." position="inside">
➡ Here we have defined path in src- /module_name/static/src/js_filename
<script type="text/javascript" src="/popup_note/static/src/js/pos.js"></script>
</xpath>
</template>
</odoo>
Note – Don't forget to mention this inside manifest.py file.
7) After doing this, you can see your popup note.
Click on this button.
Now you can see your popup note
8) Store value in the pos.order.
For storing value we need to add a field in the pos order.
Here we have added a new field with the Input Field Value name
Note – If you don’t know how to add a field in the existing form view, then you can check out our blog: How To Add Fields In Form View In Odoo
Now we need to inherit a method of python file(point_of_sale) for storing value.
@api.model
def _order_fields(self, ui_order):
➡ Here we have called the super method for inheriting method
➡ Here we have assigned input field value inside the custom field, which we have added in the pos.order
res['input_field_value'] = ui_order['field_input_value'] if ui_order['field_input_value'] else False
return res
Now you can see your stored value
After validating, you can see
Conclusion
So, by following these simple steps we can add a popup field to the POS interface and save its value in the record.
The coding for the POS and its customization involves basic knowledge of Python, Javascript, and Xml. If you are not familiar with the coding basics of these, the customization could cause you a little trouble.
But no need to worry, you can contact us and we’ll provide you full support. We can customize your POS according to your needs and will make all the changes that you want.
If you want to make any changes to the POS receipt generated by Odoo, you can check this blog: How To Customize POS Receipt In Odoo
Code Download from GitHub
Get in touch with us!
Your email address will not be published.