Rodney Elpidio Enciso Arias 7 gadi atpakaļ
revīzija
180b103c29

+ 135 - 0
README.rst

@@ -0,0 +1,135 @@
+=====================
+POS Select Cashier v8
+=====================
+This project aims to change POS cashier easily
+
+
+Contact
+=======
+
+- Blog: www.xubi.me_
+- Linkedin: binhnguyenxuan_
+- Skype: **xubi.uit**
+- Email: **kid.uit.1412@gmail.com**
+
+.. _www.xubi.me: http://www.xubi.me
+.. _binhnguyenxuan: https://www.linkedin.com/in/binhnguyenxuan
+
+Installation
+============
+Installation process is at present stage only possible in manual way.
+Then go to you odoo webinterface to the module section and start "Update module list". Then look for the "POS Select Cashier" in Apps (module list) and install.
+I hope you enjoy checking out what all you can do with this application.
+
+
+Prerequisite
+============
+Before installing the module make sure that the you have configured an addon path for custom addons. In a Linux system the parameter in the config file usually looks similar as the following example:
+specify additional addons paths (separated by commas)
+addons_path = /opt/odoo/odoo-server/addons, /opt/odoo/custom/addons
+In this case you have to install the modules into /opt/odoo/custom/addons. At the present stage on dependency could not automatically resolved so you have to install one extra module that vertical community depends on.
+
+Usage
+=====
+Maybe images in github do not fit with the Odoo apps, so you can check: https://apps.odoo.com/apps/modules/8.0/pos_select_cashier/ for more details.
+Thank you.
+
+|
+With this module, you just need open POS session by only *one user* but you **can use by other users**
+
+
+Configuration
+=============
+
+Config **Default Point of Sale** for each user who is the cashier
+
+|
+.. figure:: config_default.jpg
+   :alt: Default Point of Sale
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+**Select Cashier** will be the default screen at begining
+
+|
+.. figure:: default_screen.jpg
+   :alt: Default Screen
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+**Company Logo** and **Cashier Info** (*name and avatar*) displayed at the right top of the screen. Click on **Cashier Name** to change cashier
+
+|
+.. figure:: logo_cashier_avatar.jpg
+   :alt: Change cashier
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+**Sale Man** will be change as your select
+
+|
+.. figure:: saleman.jpg
+   :alt: Change Saleman
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+
+Working on all of devices
+
+|
+.. figure:: device.jpg
+   :alt: iPhone working
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+|
+.. figure:: device_2.jpg
+   :alt: iPad working
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+
+Require password when change cashier
+------------------------------------
+
+**Config required password** when change cashier
+
+|
+.. figure:: config_required_pass.jpg
+   :alt: Config required password
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+**Set password** for cashier
+
+|
+.. figure:: set_password.jpg
+   :alt: Set password
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|
+
+**Required password screen** display whenever click on cashier name
+
+|
+.. figure:: required_sceen.jpg
+   :alt: Required password screen
+   :scale: 80 %
+   :align: center
+   :figclass: text-center
+|

+ 25 - 0
__init__.py

@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    POS Select Cashier
+#    Copyright (C) 2016- XUBI.ME (http://www.xubi.me)
+#    @author binhnguyenxuan (https://www.linkedin.com/in/binhnguyenxuan)
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    
+#
+##############################################################################
+
+import controllers
+import models

BIN
__init__.pyc


+ 42 - 0
__openerp__.py

@@ -0,0 +1,42 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    POS Select Cashier
+#    Copyright (C) 2016- XUBI.ME (http://www.xubi.me)
+#    @author binhnguyenxuan (https://www.linkedin.com/in/binhnguyenxuan)
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    
+#
+##############################################################################
+{
+    'name': 'POS Select Cashier',
+    'summary': 'Changing POS cashier easily',
+    'version': '8.0.1.0',
+    'category': 'Point Of Sale',
+    'author': "binhnguyenxuan (www.xubi.me)",
+    'website': 'http://www.xubi.me',
+    'license': 'AGPL-3',
+    'depends': [
+        'point_of_sale',
+    ],
+    'data': [
+        'views/pos_config_views.xml',
+        'views/res_users_views.xml',
+        'templates/templates.xml',
+    ],
+    'qweb': ['static/src/xml/*.xml'],
+    'installable': True,
+    'application': True,
+}

+ 22 - 0
controllers/__init__.py

@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    POS Select Cashier
+#    Copyright (C) 2016- XUBI.ME (http://www.xubi.me)
+#    @author binhnguyenxuan (https://www.linkedin.com/in/binhnguyenxuan)
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    
+#
+##############################################################################

BIN
controllers/__init__.pyc


+ 25 - 0
models/__init__.py

@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    POS Select Cashier
+#    Copyright (C) 2016- XUBI.ME (http://www.xubi.me)
+#    @author binhnguyenxuan (https://www.linkedin.com/in/binhnguyenxuan)
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    
+#
+##############################################################################
+
+import pos_config
+import res_users

BIN
models/__init__.pyc


+ 30 - 0
models/pos_config.py

@@ -0,0 +1,30 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    POS Select Cashier
+#    Copyright (C) 2016- XUBI.ME (http://www.xubi.me)
+#    @author binhnguyenxuan (https://www.linkedin.com/in/binhnguyenxuan)
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    
+#
+##############################################################################
+
+from openerp import models, fields, api
+
+
+class pos_config(models.Model):
+    _inherit = 'pos.config'
+
+    required_password = fields.Boolean('Password Required', default=False, help="Required password when change cashier on POS screen")

BIN
models/pos_config.pyc


+ 30 - 0
models/res_users.py

@@ -0,0 +1,30 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    POS Select Cashier
+#    Copyright (C) 2016- XUBI.ME (http://www.xubi.me)
+#    @author binhnguyenxuan (https://www.linkedin.com/in/binhnguyenxuan)
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#    
+#
+##############################################################################
+
+from openerp import models, fields, api
+
+
+class res_users(models.Model):
+    _inherit = 'res.users'
+    
+    cashier_password = fields.Char(string="Cashier Password", default="000000")

BIN
models/res_users.pyc


BIN
static/description/config_default.jpg


BIN
static/description/config_required_pass.jpg


BIN
static/description/default_screen.jpg


BIN
static/description/device.jpg


BIN
static/description/device_2.jpg


BIN
static/description/icon.png


BIN
static/description/logo_cashier_avatar.jpg


BIN
static/description/required_sceen.jpg


BIN
static/description/saleman.jpg


BIN
static/description/set_password.jpg


+ 210 - 0
static/src/css/pos.css

@@ -0,0 +1,210 @@
+
+/* SELECT CASHIER SCREEN */
+
+
+/* Custom, iPhone Retina */ 
+@media only screen and (min-width : 320px) {
+	.pos-select-cashier {
+	    width: 100%;
+	    position: absolute;
+	    top: -51px;
+	    bottom: 0;
+	    background: #bdc3c7;
+	    display:flex;
+	    justify-content:center;
+	    align-items:center;
+	    z-index: 1;
+	}
+	
+	 .select-wrapper {
+	    width: 100%;
+   		height: 100%;
+   		margin: 0 auto;
+	}
+	
+	.select-title {
+		text-align: center;
+		padding: 40px 0;
+		font-size: 65px;
+		font-weight: bold;
+		color: #ecf0f1;
+		text-transform: uppercase;
+		background: #1abc9c;
+	}
+	
+	
+	.select-wrapper-item {
+		max-height: 80%;
+		overflow-y: auto;
+		overflow-x: hidden;
+	    width: 90%;
+    	margin: 40px auto;
+	}
+	
+	.cashier-item:nth-child(odd) {
+    	margin-right: 5%;
+	}
+
+}
+
+.cashier-item,
+.cashier-item-image,
+.cashier-item-info {
+	display: inline-block;
+	float: left;
+}
+
+.cashier-item {
+	height: 120px;
+	margin-bottom: 15px;
+    border-radius: 10px;
+    cursor: pointer;
+    width: 47%;
+	
+}
+
+.cashier-item-image {
+	width: 120px;
+	height: 120px;
+}
+
+.cashier-item-image img {
+	width: 100%;
+	height: auto;
+	max-height: 100%;
+	border-top-left-radius: 8px;
+    border-bottom-left-radius: 8px;
+}
+
+.cashier-item-info {
+	height: 120px;
+	width: 60%;
+	color: #ecf0f1;
+	padding: 0 10px 0 10px;
+}
+
+.cashier-name {
+	display:flex;
+	justify-content:center;
+	align-items:center;
+	width:100%;
+	height: 100%;
+	font-size: 30px;
+    text-align: center;
+    overflow: hidden;
+}
+
+.pos .pos-branding {
+	width: 300px;
+}
+
+.pos .pos-rightheader {
+	left: 300px !important;
+}
+
+.pos .pos-branding .username {
+    margin-left: 10px;
+    margin-right: 10px;
+    float: left;
+    overflow: hidden;
+    width: 110px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display:inline-block;
+}
+
+.pos .pos-logo {
+	float: left;
+	max-height: 100%;
+    margin-left: 0px;
+    max-width: 100px;
+    height: auto;
+    over-flow: hidden;
+}
+
+.cashier-display {
+    display: inline-block;
+    float: right;
+    cursor: pointer;
+    max-width: 180px;
+    overflow: hidden;	
+}
+
+.cashier-avatar {
+    width: auto;
+    height: 48px;
+    float: left;
+}
+
+/*
+	Show password
+*/
+.popup-password-confirm {
+	width: 270px !important;
+	height: 490px !important;
+	padding: 0px !important;
+	margin-top: 0px !important;
+	top: 20px !important;
+	left: 55% !important;
+	border-top-left-radius: 10px !important;
+    border-top-right-radius: 10px !important;
+}
+
+.popup-password-confirm .message {
+    text-align: center;
+    padding: 10px 0;
+    font-size: 25px;
+    font-weight: bold;
+    color: #ecf0f1;
+    text-transform: uppercase;
+    background: #1abc9c;
+    border-top-left-radius: 10px;
+    border-top-right-radius: 10px;
+}
+
+.popup-password-confirm .content {
+	padding: 10px;
+}
+
+.popup-password-confirm .numpad {
+    padding: 8px;
+}
+
+.popup-password-confirm table.table-numpad {
+    border-color: #ccc;
+}
+
+.popup-password-confirm table.table-numpad td {
+    padding: 16px;
+    font-size: 28px;
+    width: 40px;
+    height: 40px;
+    cursor: pointer;
+}
+
+.popup-password-confirm table.table-numpad td:hover {
+    background: #1abc9c;
+    color: #FFF;
+}
+
+.popup-password-confirm #password_content {
+    width: 190px;
+    height: 40px;
+    border: 2px solid #DDD;
+    border-radius: 5px;
+    display: inline-block;
+    margin-bottom: 5px;
+    font-size: 20px;
+    padding: 0 15px;
+    outline: none;
+}
+
+.popup-password-confirm #password_content:focus {
+	border: 2px solid #1abc9c;
+}
+
+.popup-password-confirm .button {
+	margin-right: 11px !important;
+    width: 115px !important;
+    font-size: 16px !important;
+}

+ 54 - 0
static/src/js/db.js

@@ -0,0 +1,54 @@
+
+function openerp_pos_select_cashier_db(instance, module){ //module = openerp.point_of_sale;
+    var QWeb = instance.web.qweb,
+    _t = instance.web._t;
+    
+    module.PosDB.include({
+    	init: function(options){
+			this._super();
+			// Cashier
+			this.cashiers = {}
+			this.cashier_by_id = {};
+			// required password
+			this.required_password = false;
+    	},
+
+    	set_cashier: function(users) {
+        	this.cashiers = users;
+        	var self = this;
+        	_.each(users, function(user) {
+        		self.cashier_by_id[user.id] = {
+        			image: user.image_small,
+        			name: user.name,
+        			id: user.id,
+        			cashier_password: user.cashier_password || '',
+        		}
+        	});
+        },
+
+        get_cashier: function(id) {
+        	if (typeof(id) == 'undefined') {
+        		return this.cashiers;
+        	}
+        	return this.cashier_by_id[id] || {};
+        },
+        
+        set_required_password: function(config) {
+        	this.required_password = config.required_password || false;
+        },
+        
+        get_required_password: function(config) {
+        	return this.required_password;
+        },
+        
+        get_cashier_password: function(cashier_id) {
+        	var cashier = this.get_cashier(cashier_id);
+        	
+        	if (_.isEmpty(cashier)) {
+        		return false;
+        	} else {
+        		return cashier.cashier_password;
+        	}
+        }
+    });
+}

+ 18 - 0
static/src/js/main.js

@@ -0,0 +1,18 @@
+
+openerp.pos_select_cashier = function(instance) {
+
+    instance.pos_select_cashier = {};
+
+    var module = openerp.point_of_sale;
+    
+    openerp_pos_select_cashier_db(instance,module);         // import db.js
+
+    openerp_pos_select_cashier_models(instance,module);     // import pos_restaurant_menu_models.js
+
+    openerp_pos_select_cashier_screens(instance,module);	   // import pos_select_cashier_screens.js
+    
+    openerp_pos_select_cashier_widgets(instance,module);    // import pos_select_cashier_widgets.js
+    
+};
+
+    

+ 37 - 0
static/src/js/models.js

@@ -0,0 +1,37 @@
+function openerp_pos_select_cashier_models(instance, module){ //module = openerp.point_of_sale;
+    var QWeb = instance.web.qweb;
+	var _t = instance.web._t;
+    
+    var PosModelSuper = module.PosModel;
+    module.PosModel = module.PosModel.extend({
+        
+        models: (function() {
+			
+        	var base_posmodel_model = module.PosModel.prototype.models;
+			
+			base_posmodel_model.push(
+				 // get users (cashier belong to current pos config)
+	            {
+	            	model: 'res.users',
+	            	fields: ['id', 'image_small', 'name', 'ean13', 'cashier_password'],
+	            	domain: function(self){ 
+	            		return [['pos_config','=', self.pos_session.config_id[0]]]; 
+	            	},
+	            	loaded: function(self, users){
+	            		self.users = users;
+						self.db.set_cashier(users);
+	                },
+	            },{
+	                model: 'pos.config',
+	                fields: ['required_password'],
+	                domain: function(self){ return [['id','=', self.pos_session.config_id[0]]]; },
+	                loaded: function(self,configs){
+	                    self.db.set_required_password(configs[0]);
+	                },
+	            }
+	            
+			);
+			return base_posmodel_model;
+		})(),
+    });
+}

+ 142 - 0
static/src/js/screens.js

@@ -0,0 +1,142 @@
+
+function openerp_pos_select_cashier_screens(instance, module){ //module = openerp.point_of_sale;
+    var QWeb = instance.web.qweb,
+    _t = instance.web._t;
+    
+    module.CashierSelectionScreenWidget = module.ScreenWidget.extend({
+		template: 'CashierSelectionScreenWidget',
+		back_screen: 'products', // TODO: remove by default screen
+		init: function(parent, options){
+			this.options = options || [];
+			this.parent = parent || {}
+            this._super(parent, options);
+        },
+
+        show_leftpane: false,
+        
+        show: function() {
+        	this._super();
+        	var self = this;
+        	
+        	this.$('.cashier-item').on('click', function(e) {
+        		e.stopPropagation();
+        		self.select_cashier(this);
+        	});
+        	// After load we reset the default screen
+        	this.pos_widget.screen_selector.default_screen = this.back_screen;
+        },
+        
+        back: function() {
+            this.pos_widget.screen_selector.set_current_screen(this.back_screen);
+        },
+        
+        color_random_generator: function() {
+        	return "#" + Math.random().toString(16).slice(2, 8).toUpperCase();
+        },
+        
+        select_cashier: function(target) {
+        	var self = this;
+        	
+        	var required_password = self.pos.db.get_required_password();
+        	var cashier_id = $(target).data('cashier-id');
+    		cashier_id = parseInt(cashier_id);
+        	if (required_password) {
+        		self.pos_widget.screen_selector.show_popup('password_confirm',{
+                    message: _t('password'),
+                    confirm: function(password){
+                        self.check_cashier_password(cashier_id, password);
+                    },
+                });
+        	} else {
+        		self.select_cashier_by_id(cashier_id);
+        	}
+        },
+        
+        check_cashier_password: function(cashier_id, password) {
+        	var self = this,
+        	input_password = self.pos.db.get_cashier_password(cashier_id);
+        	
+        	if (input_password === password) {
+        		self.select_cashier_by_id(cashier_id);
+        		self.pos_widget.screen_selector.close_popup();
+        	} else {
+        		alert('Wrong pass!');
+        	}
+        },
+        
+        select_cashier_by_id: function(cashier_id) {
+        	var self = this;
+        	this.pos.cashier = this.pos.db.get_cashier(cashier_id);
+    		this.pos_widget.username = new module.UsernameWidget(self.parent, self.pos.cashier);
+    		this.pos_widget.username.replace($('.cashier-display'));
+            
+    		this.back();
+        }
+	});
+    
+    module.PasswordConfirmPopupWidget = module.PopUpWidget.extend({
+        template: 'PasswordConfirmPopupWidget',
+        show: function(options){
+            var self = this;
+            this._super();
+
+            this.message = options.message || '';
+            this.renderElement();
+            
+            this.$('.button.cancel').click(function(){
+                self.pos_widget.screen_selector.close_popup();
+                if( options.cancel ){
+                    options.cancel.call(self);
+                }
+            });
+
+            this.$('.button.confirm').click(function(){
+                self.button_confirm(options);
+            });
+            
+            this.$('td.number-char').click(function(e){
+            	self.numpad_char(this);
+            });
+            
+            this.$('td.number-clear').click(function(e){
+            	self.numpad_clear();
+            });
+
+			this.$('td.numpad-backspace').click(function(e){
+				self.numpad_backspace();
+			});
+			
+			self.$('#password_content').focus();
+        },
+        
+        numpad_backspace: function() {
+        	var self = this;
+        	var pass = self.$('#password_content').val();
+			if (pass.length > 0) {
+				self.$('#password_content').val(pass.slice(0, -1));
+			}
+			self.$('#password_content').focus();
+        },
+        
+        numpad_clear: function() {
+        	this.$('#password_content').val('').focus();
+        },
+        
+        numpad_char: function(target) {
+        	var self = this,
+        	char = $(target).html(),
+        	pass = self.$('#password_content').val();
+			
+        	pass += char;
+        	self.$('#password_content').val(pass).focus();
+        },
+        
+        button_confirm: function(options) {
+        	if (options.confirm) {
+        		var self = this,
+            	pass = self.$('#password_content').val();
+            	options.confirm.call(self, pass);
+            }
+        }
+    });
+}

+ 61 - 0
static/src/js/widgets.js

@@ -0,0 +1,61 @@
+function openerp_pos_select_cashier_widgets(instance, module){ //module = openerp.point_of_sale;
+    var QWeb = instance.web.qweb;
+	var _t = instance.web._t;
+	
+	module.PosWidget = module.PosWidget.extend({
+		//Overload Section
+        build_widgets: function(){
+            this._super();
+            
+            this.selectcashier = new module.CashierSelectionScreenWidget(this, this.pos.db.cashiers);
+            this.selectcashier.appendTo(this.$('.screens'));
+            
+            // Add new screen select cashier, set default screen = selectcashier
+            // After load select cashier screen, reset the default screen for native function
+            this.screen_selector.screen_set['selectcashier'] = this.selectcashier;
+            this.screen_selector.default_screen = 'selectcashier';
+            
+            /**
+             * Regis password confirm popup
+             */
+            this.password_confirm_popup = new module.PasswordConfirmPopupWidget(this,{});
+            this.password_confirm_popup.appendTo(this.$el);
+            
+            this.screen_selector.popup_set['password_confirm'] = this.password_confirm_popup;
+            // Hide the popup because all pop up are displayed at the
+            // beginning by default
+            this.password_confirm_popup.hide();
+            
+        },
+	});
+	
+	module.UsernameWidget.include({
+        renderElement: function(){
+            var self = this;
+            this._super();
+            this.$el.click(function(){
+            	self.show_select_cashier_screen();
+            });
+        },
+        get_image: function(){
+            var user;
+            user = this.pos.cashier || false;
+            if(user){
+                return user.image;
+            }else{
+                return "";
+            }
+        },
+        
+        show_select_cashier_screen: function() {
+        	/**
+        	 * Check current screen is receipt or not?
+        	 * for make sure selectedOrder was destroyed -> cart clear
+        	 */
+        	var current_screen = this.pos_widget.screen_selector.get_current_screen();
+        	if (current_screen !== 'receipt') {
+        		this.pos_widget.screen_selector.set_current_screen('selectcashier');
+        	}
+        }
+	});
+}

+ 95 - 0
static/src/xml/pos.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<template>
+
+	<t t-name="CashierSelectionScreenWidget">
+		<div class="pos-select-cashier">
+			<div class="select-wrapper">
+				<div class="select-title">
+					Select cashier
+				</div>
+				<div class="select-wrapper-item">
+					<t t-call="CashierSelectionItem" />
+				</div>
+			</div>
+		</div>
+	</t>
+
+	<t t-name="CashierSelectionItem">
+		<t t-foreach="widget.options" t-as="cashier">
+			<div class="cashier-item" t-att-data-cashier-id="cashier.id" t-att-style="'background: ' + widget.color_random_generator()">
+				<div class="cashier-item-image">
+					<img t-att-src="'data:image/png;base64,' + cashier.image_small" />
+				</div>
+				<div class="cashier-item-info">
+					<div class="cashier-name">
+						<span t-esc="cashier.name" />
+					</div>
+				</div>
+			</div>
+		</t>
+	</t>
+
+	<t t-extend="UsernameWidget">
+		<t t-jquery=".username" t-operation="replace">
+			<div class="cashier-display">
+				<img class="cashier-avatar" t-att-src="'data:image/png;base64,' + widget.get_image()" />
+				<span class="username">
+					<t t-esc="widget.get_name()" />
+				</span>
+			</div>
+		</t>
+	</t>
+	
+	<t t-extend="PosWidget">
+    	<t t-jquery=".placeholder-UsernameWidget" t-operation="replace" />
+        <t t-jquery=".pos-branding" t-operation="append">
+        	<span class="placeholder-UsernameWidget"></span>
+        </t>
+    </t>
+    
+    <t t-name="PasswordConfirmPopupWidget">
+        <div class="modal-dialog">
+            <div class="popup popup-password-confirm">
+                <div class="message"><t t-esc=" widget.message || 'Pin Code' " /></div>
+                <div class="content">
+                	<input id="password_content" type="password" />
+                	<div class="numpad">
+                		<table class="table-numpad" border="1">
+                		<tbody>
+                			<tr>
+                				<td class="number-char">1</td>
+                				<td class="number-char">2</td>
+                				<td class="number-char">3</td>
+                			</tr>
+                			<tr>
+                				<td class="number-char">4</td>
+                				<td class="number-char">5</td>
+                				<td class="number-char">6</td>
+                			</tr>
+                			<tr>
+                				<td class="number-char">7</td>
+                				<td class="number-char">8</td>
+                				<td class="number-char">9</td>
+                			</tr>
+                			<tr>
+                				<td class="number-clear">AC</td>
+                				<td class="number-char">0</td>
+                				<td class="numpad-backspace"><img height="21" src="/point_of_sale/static/src/img/backspace.png" width="24" /></td>
+                			</tr>
+                		</tbody>
+                	</table>
+                	</div>
+                </div>
+                <div class="footer">
+                    <div class="button confirm">
+                        Confirm 
+                    </div>
+                    <div class="button cancel">
+                        Cancel 
+                    </div>
+                </div>
+            </div>
+        </div>
+    </t>
+	
+</template>

+ 25 - 0
templates/templates.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<openerp>
+    <data>
+
+        <template id="index" name="select_cashier_module_index index"
+                  inherit_id="point_of_sale.index">
+            <xpath expr="//link[@id='pos-stylesheet']" position="after">
+                <link rel="stylesheet" href="/pos_select_cashier/static/src/css/pos.css"/>
+            </xpath>
+
+        </template>
+
+      	<template id="assets_backend" name="select_cashier_module assets"
+                  inherit_id="web.assets_backend">
+            <xpath expr="//script[last()]" position="after">
+            	<script type="text/javascript" src="/pos_select_cashier/static/src/js/db.js"></script>
+                <script type="text/javascript" src="/pos_select_cashier/static/src/js/models.js"></script>
+                <script type="text/javascript" src="/pos_select_cashier/static/src/js/screens.js"></script>
+                <script type="text/javascript" src="/pos_select_cashier/static/src/js/widgets.js"></script>
+            	<script type="text/javascript" src="/pos_select_cashier/static/src/js/main.js"></script>
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 21 - 0
views/pos_config_views.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<openerp>
+    <data>
+    
+    	<record id="view_pos_config_form" model="ir.ui.view">
+            <field name="name">pos.config.form.view.inherit</field>
+            <field name="model">pos.config</field>
+            <field name="inherit_id" ref="point_of_sale.view_pos_config_form"/>
+            <field name="arch" type="xml">
+            	<xpath expr="//sheet/group[last()]" position="after">
+            		<group string="Select Cashier" col="1">
+            			<group col="4">
+                            <field name="required_password" />
+                        </group>
+                    </group>
+            	</xpath>
+            </field>
+       </record>
+    
+    </data>
+</openerp>

+ 16 - 0
views/res_users_views.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+
+    <record id="res_users_form_view" model="ir.ui.view">
+        <field name="name">res.users.form.view</field>
+        <field name="model">res.users</field>
+        <field name="inherit_id" ref="point_of_sale.res_users_form_view" />
+        <field name="arch" type="xml">
+        	<xpath expr="//notebook/page/group/field[@name='ean13']" position="after">
+        		<field name="cashier_password" />
+        	</xpath>
+        </field>
+    </record>
+    </data>
+</openerp>