You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
11 KiB
313 lines
11 KiB
/* Copyright 2015 igallyamov <https://github.com/igallyamov>
|
|
Copyright 2016 ufaks <https://github.com/ufaks>
|
|
Copyright 2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
|
|
Copyright 2019 Kolushov Alexandr <https://it-projects.info/team/kolushovalexandr>
|
|
Copyright 2019 ssaid <https://github.com/ssaid>
|
|
Copyright 2019 raulovallet <https://github.com/raulovallet>
|
|
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). */
|
|
/* eslint-disable complexity */
|
|
odoo.define("pos_keyboard.pos", function(require) {
|
|
"use strict";
|
|
|
|
var core = require("web.core");
|
|
var gui = require("point_of_sale.gui");
|
|
var models = require("point_of_sale.models");
|
|
var screens = require("point_of_sale.screens");
|
|
var PopupWidget = require("point_of_sale.popups");
|
|
|
|
gui.Gui.prototype.popup_classes
|
|
.filter(function(c) {
|
|
return c.name === "password";
|
|
})[0]
|
|
.widget.include({
|
|
init: function(parent, args) {
|
|
this._super(parent, args);
|
|
this.popup_type = "password";
|
|
},
|
|
});
|
|
|
|
PopupWidget.include({
|
|
keypad_action: function(data) {
|
|
var type = this.pos.keypad.type;
|
|
if (data.type === type.numchar) {
|
|
this.click_keyboard(data.val);
|
|
} else if (data.type === type.backspace) {
|
|
this.click_keyboard("BACKSPACE");
|
|
} else if (data.type === type.enter) {
|
|
// Some pop-ups might throw an error due to lack of some income data
|
|
try {
|
|
return this.click_confirm();
|
|
} catch (error) {
|
|
return;
|
|
}
|
|
} else if (data.type === type.escape) {
|
|
this.click_cancel();
|
|
}
|
|
},
|
|
click_keyboard: function(value) {
|
|
if (typeof this.inputbuffer === "undefined") {
|
|
return;
|
|
}
|
|
var newbuf = this.gui.numpad_input(this.inputbuffer, value, {
|
|
firstinput: this.firstinput,
|
|
});
|
|
|
|
this.firstinput = newbuf.length === 0;
|
|
|
|
var $value = this.$(".value");
|
|
if (newbuf !== this.inputbuffer) {
|
|
this.inputbuffer = newbuf;
|
|
$value.text(this.inputbuffer);
|
|
}
|
|
if (this.popup_type === "password" && newbuf) {
|
|
$value.text($value.text().replace(/./g, "•"));
|
|
}
|
|
},
|
|
show: function(options) {
|
|
this._super(options);
|
|
this.$("input,textarea").focus();
|
|
},
|
|
});
|
|
|
|
screens.NumpadWidget.include({
|
|
keypad_action: function(data) {
|
|
var type = this.pos.keypad.type;
|
|
if (data.type === type.numchar) {
|
|
this.state.appendNewChar(data.val);
|
|
} else if (data.type === type.bmode) {
|
|
this.state.changeMode(data.val);
|
|
} else if (data.type === type.sign) {
|
|
this.clickSwitchSign();
|
|
} else if (data.type === type.backspace) {
|
|
this.clickDeleteLastChar();
|
|
}
|
|
},
|
|
});
|
|
|
|
screens.PaymentScreenWidget.include({
|
|
show: function() {
|
|
this._super();
|
|
this.pos.keypad.disconnect();
|
|
},
|
|
hide: function() {
|
|
this._super();
|
|
this.pos.keypad.connect();
|
|
},
|
|
});
|
|
|
|
// This module mimics a keypad-only cash register. Use connect() and
|
|
// disconnect() to activate and deactivate it.
|
|
var Keypad = core.Class.extend({
|
|
init: function(attributes) {
|
|
this.pos = attributes.pos;
|
|
/* This.pos_widget = this.pos.pos_widget;*/
|
|
this.type = {
|
|
numchar: "number, dot",
|
|
bmode: "quantity, discount, price",
|
|
sign: "+, -",
|
|
backspace: "backspace",
|
|
enter: "enter",
|
|
escape: "escape",
|
|
};
|
|
this.data = {
|
|
// Type: undefined,
|
|
// val: undefined
|
|
};
|
|
delete this.action_callback;
|
|
this.active = false;
|
|
},
|
|
|
|
save_callback: function() {
|
|
this.saved_callback_stack.push(this.action_callback);
|
|
},
|
|
|
|
restore_callback: function() {
|
|
if (this.saved_callback_stack.length > 0) {
|
|
this.action_callback = this.saved_callback_stack.pop();
|
|
}
|
|
},
|
|
|
|
set_action_callback: function(callback) {
|
|
this.action_callback = callback;
|
|
},
|
|
|
|
// Remove action callback
|
|
reset_action_callback: function() {
|
|
delete this.action_callback;
|
|
},
|
|
|
|
// Starts catching keyboard events and tries to interpret keystrokes,
|
|
// calling the callback when needed.
|
|
connect: function() {
|
|
var self = this;
|
|
if (self.active) {
|
|
return;
|
|
}
|
|
// --- additional keyboard ---//
|
|
// KeyCode: + or - (Keypad '+')
|
|
var KC_PLU = 107;
|
|
// KeyCode: Quantity (Keypad '/')
|
|
var KC_QTY = 111;
|
|
// KeyCode: Price (Keypad '*')
|
|
var KC_AMT = 106;
|
|
// KeyCode: Discount Percentage [0..100] (Keypad '-')
|
|
var KC_DISC = 109;
|
|
// --- basic keyboard --- //
|
|
// KeyCode: sign + or - (Keypad 's')
|
|
var KC_PLU_1 = 83;
|
|
// KeyCode: Quantity (Keypad 'q')
|
|
var KC_QTY_1 = 81;
|
|
// KeyCode: Price (Keypad 'p')
|
|
var KC_AMT_1 = 80;
|
|
// KeyCode: Discount Percentage [0..100] (Keypad 'd')
|
|
var KC_DISC_1 = 68;
|
|
|
|
// KeyCode: Backspace (Keypad 'backspace')
|
|
var KC_BACKSPACE = 8;
|
|
// KeyCode: Enter (Keypad 'enter')
|
|
var KC_ENTER = 13;
|
|
// KeyCode: Escape (Keypad 'esc')
|
|
var KC_ESCAPE = 27;
|
|
var kc_lookup = {
|
|
48: "0",
|
|
49: "1",
|
|
50: "2",
|
|
51: "3",
|
|
52: "4",
|
|
53: "5",
|
|
54: "6",
|
|
55: "7",
|
|
56: "8",
|
|
57: "9",
|
|
80: "p",
|
|
83: "s",
|
|
68: "d",
|
|
190: ".",
|
|
81: "q",
|
|
96: "0",
|
|
97: "1",
|
|
98: "2",
|
|
99: "3",
|
|
100: "4",
|
|
101: "5",
|
|
102: "6",
|
|
103: "7",
|
|
104: "8",
|
|
105: "9",
|
|
106: "*",
|
|
107: "+",
|
|
109: "-",
|
|
110: ".",
|
|
111: "/",
|
|
};
|
|
|
|
// Usb keyboard keyup event
|
|
var rx = /INPUT|SELECT|TEXTAREA/i;
|
|
var ok = false;
|
|
var timeStamp = 0;
|
|
$("body").on("keyup", "", function(e) {
|
|
var statusHandler =
|
|
!rx.test(e.target.tagName) ||
|
|
e.target.disabled ||
|
|
e.target.readOnly;
|
|
if (statusHandler) {
|
|
var is_number = false;
|
|
var type = self.type;
|
|
var buttonMode = {
|
|
qty: "quantity",
|
|
disc: "discount",
|
|
price: "price",
|
|
};
|
|
var token = e.keyCode;
|
|
if (
|
|
(token >= 96 && token <= 105) ||
|
|
token === 110 ||
|
|
(token >= 48 && token <= 57) || token === 190
|
|
) {
|
|
self.data.type = type.numchar;
|
|
self.data.val = kc_lookup[token];
|
|
is_number = true;
|
|
ok = true;
|
|
} else if (token === KC_PLU || token === KC_PLU_1) {
|
|
self.data.type = type.sign;
|
|
ok = true;
|
|
} else if (token === KC_QTY || token === KC_QTY_1) {
|
|
self.data.type = type.bmode;
|
|
self.data.val = buttonMode.qty;
|
|
ok = true;
|
|
} else if (token === KC_AMT || token === KC_AMT_1) {
|
|
self.data.type = type.bmode;
|
|
self.data.val = buttonMode.price;
|
|
ok = true;
|
|
} else if (token === KC_DISC || token === KC_DISC_1) {
|
|
self.data.type = type.bmode;
|
|
self.data.val = buttonMode.disc;
|
|
ok = true;
|
|
} else if (token === KC_BACKSPACE) {
|
|
self.data.type = type.backspace;
|
|
ok = true;
|
|
} else if (token === KC_ENTER) {
|
|
self.data.type = type.enter;
|
|
ok = true;
|
|
} else if (token === KC_ESCAPE) {
|
|
self.data.type = type.escape;
|
|
ok = true;
|
|
} else {
|
|
delete self.data.type;
|
|
delete self.data.val;
|
|
ok = false;
|
|
}
|
|
|
|
if (is_number) {
|
|
if (timeStamp + 50 > new Date().getTime()) {
|
|
ok = false;
|
|
}
|
|
}
|
|
|
|
timeStamp = new Date().getTime();
|
|
|
|
setTimeout(function() {
|
|
if (ok) {
|
|
self.action_callback(self.data);
|
|
}
|
|
}, 50);
|
|
}
|
|
});
|
|
self.active = true;
|
|
},
|
|
|
|
// Stops catching keyboard events
|
|
disconnect: function() {
|
|
$("body").off("keyup", "");
|
|
this.active = false;
|
|
},
|
|
});
|
|
|
|
var _super_posmodel = models.PosModel.prototype;
|
|
models.PosModel = models.PosModel.extend({
|
|
initialize: function(session, attributes) {
|
|
var self = this;
|
|
this.keypad = new Keypad({pos: this});
|
|
_super_posmodel.initialize.call(this, session, attributes);
|
|
this.ready.then(function() {
|
|
self.keypad.set_action_callback(function(data) {
|
|
var current_screen = self.gui.current_screen;
|
|
var current_popup = self.gui.current_popup;
|
|
|
|
if (current_popup) {
|
|
current_popup.keypad_action(data);
|
|
} else if (
|
|
current_screen.numpad &&
|
|
current_screen.numpad.keypad_action
|
|
) {
|
|
current_screen.numpad.keypad_action(data);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
});
|
|
|
|
return {
|
|
Keypad: Keypad,
|
|
};
|
|
});
|