Home Blog How To Add And Store A Field In Odoo POS
How To Add And Store A Field In Odoo POS

How To Add & Store A Field In Odoo POS

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 frontend 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.

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.

How To Add and Store A Field In Odoo POS

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.

How To Add and Store A Field In Odoo POS
# -*- 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.

How To Add and Store A Field In Odoo POS

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">
How To Add and Store A Field In Odoo POS
How To Add and Store A Field In Odoo POS

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 point_of_sale module for 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 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 current class by using this.

var self = this;

Here we have to define 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 define a variable with 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 define above side

                json.field_input_value = this.note_value;
            }
            return json
        },
    });
});

6) Now add this js file in point_of_sale.

How To Add and Store A Field In Odoo POS
<?xml version="1.0" encoding="utf-8"?>
<odoo>

Here we have inherited 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.

How To Add and Store A Field In Odoo POS

Now you can see your popup note

How To Add and Store A Field In Odoo POS

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 Input Field Value name


Note – If you don’t know how to add a field in existing form view then you can check out our blog: How To Add Fields In Form View In Odoo

How To Add and Store A Field In Odoo POS

Now we need to inherit a method of python file(point_of_sale) for storing value.

How To Add and Store A Field In Odoo POS
@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

How To Add and Store A Field In Odoo POS
How To Add and Store A Field In Odoo POS
How To Add and Store A Field In Odoo POS
Odoo CMS - a big picture

After validating you can see 

How To Add and Store A Field In Odoo POS

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

Odoo CMS - a big picture