[MERGE] Bzr branch lp:~openerp-usertesting/openobject-addons/trunk-restaurant-wip-fva
This commit is contained in:
parent
53d807f8a7
commit
b021330f0e
|
@ -682,7 +682,7 @@ class Escpos:
|
|||
try:
|
||||
stylestack = StyleStack()
|
||||
serializer = XmlSerializer(self)
|
||||
root = ET.fromstring(xml)
|
||||
root = ET.fromstring(xml.encode('utf-8'))
|
||||
|
||||
self._raw(stylestack.to_escpos())
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ Main Features
|
|||
'wizard/pos_open_statement.xml',
|
||||
'wizard/pos_payment.xml',
|
||||
'wizard/pos_session_opening.xml',
|
||||
'views/templates.xml',
|
||||
'point_of_sale_report.xml',
|
||||
'point_of_sale_view.xml',
|
||||
'point_of_sale_data.xml',
|
||||
|
|
|
@ -12,47 +12,6 @@ from openerp.addons.web.controllers.main import module_boot, login_redirect
|
|||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
html_template = """<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenERP POS</title>
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||
<meta http-equiv="content-type" content="text/html, charset=utf-8" />
|
||||
|
||||
<meta name="viewport" content=" width=1024, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<link rel="shortcut icon" sizes="196x196" href="/point_of_sale/static/src/img/touch-icon-196.png">
|
||||
<link rel="shortcut icon" sizes="128x128" href="/point_of_sale/static/src/img/touch-icon-128.png">
|
||||
<link rel="apple-touch-icon" href="/point_of_sale/static/src/img/touch-icon-iphone.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/point_of_sale/static/src/img/touch-icon-ipad.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/point_of_sale/static/src/img/touch-icon-iphone-retina.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/point_of_sale/static/src/img/touch-icon-ipad-retina.png">
|
||||
|
||||
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/fonts/lato/stylesheet.css" />
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/fonts/font-awesome-4.0.3/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/css/pos.css" />
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/css/keyboard.css" />
|
||||
<script type="text/javascript" src="/web/js/web.assets_common"></script>
|
||||
<script type="text/javascript" src="/web/js/web.assets_backend"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
var s = new openerp.init(%(modules)s);
|
||||
%(init)s
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!--[if lte IE 8]>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
|
||||
<script>CFInstall.check({mode: "overlay"});</script>
|
||||
<![endif]-->
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
class PosController(http.Controller):
|
||||
|
||||
|
@ -62,14 +21,19 @@ class PosController(http.Controller):
|
|||
if not request.session.uid:
|
||||
return login_redirect()
|
||||
|
||||
r = html_template % {
|
||||
'modules': simplejson.dumps(module_boot(request.db)),
|
||||
'init': """
|
||||
var wc = new s.web.WebClient();
|
||||
wc.show_application = function(){
|
||||
wc.action_manager.do_action("pos.ui");
|
||||
};
|
||||
wc.appendTo($(document.body));
|
||||
"""
|
||||
}
|
||||
return r
|
||||
modules = simplejson.dumps(module_boot(request.db))
|
||||
init = """
|
||||
var wc = new s.web.WebClient();
|
||||
wc.show_application = function(){
|
||||
wc.action_manager.do_action("pos.ui");
|
||||
};
|
||||
wc.appendTo($(document.body));
|
||||
"""
|
||||
|
||||
html = request.registry.get('ir.ui.view').render(request.cr, request.session.uid,'point_of_sale.index',{
|
||||
'modules': modules,
|
||||
'init': init,
|
||||
})
|
||||
|
||||
return html
|
||||
|
||||
|
|
|
@ -88,7 +88,14 @@ class pos_config(osv.osv):
|
|||
'session_ids': fields.one2many('pos.session', 'config_id', 'Sessions'),
|
||||
'group_by' : fields.boolean('Group Journal Items', help="Check this if you want to group the Journal Items by Product while closing a Session"),
|
||||
'pricelist_id': fields.many2one('product.pricelist','Pricelist', required=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'barcode_product': fields.char('Product Barcodes', size=64, help='The pattern that identifies product barcodes'),
|
||||
'barcode_cashier': fields.char('Cashier Barcodes', size=64, help='The pattern that identifies cashier login barcodes'),
|
||||
'barcode_customer': fields.char('Customer Barcodes',size=64, help='The pattern that identifies customer\'s client card barcodes'),
|
||||
'barcode_price': fields.char('Price Barcodes', size=64, help='The pattern that identifies a product with a barcode encoded price'),
|
||||
'barcode_weight': fields.char('Weight Barcodes', size=64, help='The pattern that identifies a product with a barcode encoded weight'),
|
||||
'barcode_discount': fields.char('Discount Barcodes', size=64, help='The pattern that identifies a product with a barcode encoded discount'),
|
||||
'fidelity_id': fields.many2one('pos.fidelity','Fidelity Card', help='The type of fidelity card available for this point_of_sale'),
|
||||
}
|
||||
|
||||
def _check_cash_control(self, cr, uid, ids, context=None):
|
||||
|
@ -156,6 +163,12 @@ class pos_config(osv.osv):
|
|||
'iface_invoicing': True,
|
||||
'stock_location_id': _get_default_location,
|
||||
'company_id': _get_default_company,
|
||||
'barcode_product': '*',
|
||||
'barcode_cashier': '041*',
|
||||
'barcode_customer':'042*',
|
||||
'barcode_weight': '21xxxxxNNDDD',
|
||||
'barcode_discount':'22xxxxxxxxNN',
|
||||
'barcode_price': '23xxxxxNNNDD',
|
||||
}
|
||||
|
||||
def onchange_picking_type_id(self, cr, uid, ids, picking_type_id, context=None):
|
||||
|
@ -191,6 +204,23 @@ class pos_config(osv.osv):
|
|||
obj.sequence_id.unlink()
|
||||
return super(pos_config, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
class pos_fidelity(osv.osv):
|
||||
_name = 'pos.fidelity'
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Fidelity Card Name', size=32, select=1,
|
||||
required=True, help="An internal identification for the fidelity card configuration"),
|
||||
'fidpoints_currency': fields.float('Points per paid currency',help="How many fidelity points are given to the customer by sold currency"),
|
||||
'fidpoints_product': fields.float('Points per sold product',help="How many fidelity points are given to the customer by product sold"),
|
||||
'fidpoints_sale': fields.float('Points per sale',help="How many fidelity points are given to the customer for each sale"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'fidpoints_currency': 0,
|
||||
'fidpoints_product': 0,
|
||||
'fidpoints_sale': 0,
|
||||
}
|
||||
|
||||
class pos_session(osv.osv):
|
||||
_name = 'pos.session'
|
||||
_order = 'id desc'
|
||||
|
@ -241,6 +271,8 @@ class pos_session(osv.osv):
|
|||
'state' : fields.selection(POS_SESSION_STATE, 'Status',
|
||||
required=True, readonly=True,
|
||||
select=1),
|
||||
|
||||
'sequence_number': fields.integer('Order Sequence Number'),
|
||||
|
||||
'cash_control' : fields.function(_compute_cash_all,
|
||||
multi='cash',
|
||||
|
@ -303,6 +335,7 @@ class pos_session(osv.osv):
|
|||
'name' : '/',
|
||||
'user_id' : lambda obj, cr, uid, context: uid,
|
||||
'state' : 'opening_control',
|
||||
'sequence_number': 1,
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
|
@ -523,6 +556,26 @@ class pos_order(osv.osv):
|
|||
_description = "Point of Sale"
|
||||
_order = "id desc"
|
||||
|
||||
def _order_fields(self,ui_order):
|
||||
return {
|
||||
'name': ui_order['name'],
|
||||
'user_id': ui_order['user_id'] or False,
|
||||
'session_id': ui_order['pos_session_id'],
|
||||
'lines': ui_order['lines'],
|
||||
'pos_reference':ui_order['name'],
|
||||
'partner_id': ui_order['partner_id'] or False,
|
||||
'fidpoints': ui_order['fidpoints'],
|
||||
}
|
||||
|
||||
def _payment_fields(self,ui_paymentline):
|
||||
return {
|
||||
'amount': ui_paymentline['amount'] or 0.0,
|
||||
'payment_date': ui_paymentline['name'],
|
||||
'statement_id': ui_paymentline['statement_id'],
|
||||
'payment_name': ui_paymentline.get('note',False),
|
||||
'journal': ui_paymentline['journal_id'],
|
||||
}
|
||||
|
||||
def create_from_ui(self, cr, uid, orders, context=None):
|
||||
# Keep only new orders
|
||||
submitted_references = [o['data']['name'] for o in orders]
|
||||
|
@ -535,27 +588,21 @@ class pos_order(osv.osv):
|
|||
for tmp_order in orders_to_save:
|
||||
to_invoice = tmp_order['to_invoice']
|
||||
order = tmp_order['data']
|
||||
order_id = self.create(cr, uid, self._order_fields(order),context)
|
||||
|
||||
order_id = self.create(cr, uid, {
|
||||
'name': order['name'],
|
||||
'user_id': order['user_id'] or False,
|
||||
'session_id': order['pos_session_id'],
|
||||
'lines': order['lines'],
|
||||
'pos_reference':order['name'],
|
||||
'partner_id': order['partner_id'] or False
|
||||
}, context)
|
||||
for payments in order['statement_ids']:
|
||||
payment = payments[2]
|
||||
self.add_payment(cr, uid, order_id, {
|
||||
'amount': payment['amount'] or 0.0,
|
||||
'payment_date': payment['name'],
|
||||
'statement_id': payment['statement_id'],
|
||||
'payment_name': payment.get('note', False),
|
||||
'journal': payment['journal_id']
|
||||
}, context=context)
|
||||
self.add_payment(cr, uid, order_id, self._payment_fields(payments[2]), context=context)
|
||||
|
||||
session = self.pool.get('pos.session').browse(cr, uid, order['pos_session_id'], context=context)
|
||||
if session.sequence_number <= order['sequence_number']:
|
||||
session.write({'sequence_number': order['sequence_number'] + 1})
|
||||
session = self.pool.get('pos.session').browse(cr, uid, order['pos_session_id'], context=context)
|
||||
|
||||
if order['fidpoints'] and order['partner_id']:
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, order['partner_id'], context=context)
|
||||
partner.write({'fidpoints': partner['fidpoints'] + order['fidpoints']})
|
||||
|
||||
if order['amount_return']:
|
||||
session = self.pool.get('pos.session').browse(cr, uid, order['pos_session_id'], context=context)
|
||||
cash_journal = session.cash_journal_id
|
||||
if not cash_journal:
|
||||
cash_journal_ids = filter(lambda st: st.journal_id.type=='cash', session.statement_ids)
|
||||
|
@ -662,6 +709,8 @@ class pos_order(osv.osv):
|
|||
'statement_ids': fields.one2many('account.bank.statement.line', 'pos_statement_id', 'Payments', states={'draft': [('readonly', False)]}, readonly=True),
|
||||
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, states={'draft': [('readonly', False)]}, readonly=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Customer', change_default=True, select=1, states={'draft': [('readonly', False)], 'paid': [('readonly', False)]}),
|
||||
'sequence_number': fields.integer('Sequence Number', help='A session-unique sequence number for the order'),
|
||||
'fidpoints': fields.integer('Won Fidelity Points ', help='The Fidelity Points the client won with this order'),
|
||||
|
||||
'session_id' : fields.many2one('pos.session', 'Session',
|
||||
#required=True,
|
||||
|
@ -710,6 +759,8 @@ class pos_order(osv.osv):
|
|||
'name': '/',
|
||||
'date_order': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'nb_print': 0,
|
||||
'sequence_number': 1,
|
||||
'fidpoints': 0,
|
||||
'session_id': _default_session,
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
|
||||
'pricelist_id': _default_pricelist,
|
||||
|
|
|
@ -674,6 +674,17 @@
|
|||
<field name="receipt_header" placeholder="A custom receipt header message"/>
|
||||
<field name="receipt_footer" placeholder="A custom receipt header footage"/>
|
||||
</group>
|
||||
<group string="Fidelity Cards" col="4" >
|
||||
<field name="fidelity_id" />
|
||||
</group>
|
||||
<group string="Barcode Types" col="4">
|
||||
<field name="barcode_product" />
|
||||
<field name="barcode_cashier" />
|
||||
<field name="barcode_customer" />
|
||||
<field name="barcode_weight" />
|
||||
<field name="barcode_discount" />
|
||||
<field name="barcode_price" />
|
||||
</group>
|
||||
</sheet>
|
||||
|
||||
</form>
|
||||
|
@ -705,6 +716,60 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Fidelity Cards -->
|
||||
|
||||
<record model="ir.ui.view" id="view_pos_fidelity_form">
|
||||
<field name="name">pos.fidelity.form.view</field>
|
||||
<field name="model">pos.fidelity</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Fidelity Card">
|
||||
|
||||
<group col="2">
|
||||
<field name="name" />
|
||||
<field name="fidpoints_currency" />
|
||||
<field name="fidpoints_product" />
|
||||
<field name="fidpoints_sale" />
|
||||
</group>
|
||||
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_pos_fidelity_tree">
|
||||
<field name="name">pos.fidelity.form.view</field>
|
||||
<field name="model">pos.fidelity</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Fidelity Cards">
|
||||
<field name="name" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_pos_fidelity_form">
|
||||
<field name="name">Fidelity Cards</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">pos.fidelity</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a Fidelity Card System
|
||||
</p><p>
|
||||
Fidelity card system allows you customer to earn points
|
||||
and rewards when doing business at your shops.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
parent="point_of_sale.menu_point_config_product"
|
||||
action="action_pos_fidelity_form"
|
||||
id="menu_pos_fidelity"
|
||||
sequence="30"
|
||||
groups="point_of_sale.group_pos_manager" />
|
||||
|
||||
|
||||
<!-- Sessions -->
|
||||
|
||||
<act_window
|
||||
id="act_pos_config_sessions"
|
||||
|
|
|
@ -10,6 +10,7 @@ class res_users(osv.osv):
|
|||
_inherit = 'res.partner'
|
||||
_columns = {
|
||||
'ean13' : fields.char('EAN13', size=13, help="BarCode"),
|
||||
'fidpoints': fields.integer('Fidelity Points'),
|
||||
}
|
||||
|
||||
def _check_ean(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
<field name="ean13" />
|
||||
<button name="edit_ean" type="object" string="Edit" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="fidpoints" />
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
|
|
|
@ -303,24 +303,65 @@ td {
|
|||
}
|
||||
|
||||
.pos .order-button{
|
||||
color: #273072;
|
||||
height:27px;
|
||||
margin:3px;
|
||||
margin-right:0px;
|
||||
border: 1px solid #353A7E;
|
||||
background: #7f82ac;
|
||||
text-shadow: none;
|
||||
border-radius: 3px;
|
||||
color: #f0f0f0;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
height: 32px;
|
||||
padding: 4px 8px;
|
||||
margin: 3px;
|
||||
margin-bottom: 0px;
|
||||
margin-right: 2px;
|
||||
padding-top: 0px;
|
||||
background: #8b8b8b;
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
vertical-align: top;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
box-shadow: 0px -5px 10px -6px rgb(82,82,82) inset;
|
||||
cursor: pointer;
|
||||
min-width: 34px;
|
||||
}
|
||||
.pos .order-button.selected{
|
||||
font-weight: 900;
|
||||
background: #666997;
|
||||
color: rgb(236, 237, 255);
|
||||
background: #EEEEEE;
|
||||
color: rgb(75,75,75);
|
||||
height: 31px;
|
||||
border-bottom: solid 1px rgb(196, 196, 196);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.pos .order-button .order-sequence{
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.pos .order-button.selected .order-sequence{
|
||||
color: white;
|
||||
background: black;
|
||||
display: inline-block;
|
||||
line-height: 24px;
|
||||
min-width: 24px;
|
||||
border-radius: 12px;
|
||||
margin-right: 4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.pos .order-button.square{
|
||||
width: 32px;
|
||||
margin-left:4px;
|
||||
width: 34px;
|
||||
margin-left:1px;
|
||||
background: #5c5c5c;
|
||||
color: rgb(160,160,160);
|
||||
}
|
||||
.pos .order-button:not(.square) > .fa {
|
||||
font-size: 16px;
|
||||
vertical-align: middle;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.pos .order-button .order-sequence{
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.pos .order-selector {
|
||||
|
@ -420,6 +461,46 @@ td {
|
|||
background: #F0EEEE;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* ********* The control buttons ********* */
|
||||
|
||||
.pos .control-buttons {
|
||||
padding-top: 8px;
|
||||
}
|
||||
.pos .control-button {
|
||||
background: #e2e2e2;
|
||||
border: solid 1px #BEBEBE;
|
||||
display: inline-block;
|
||||
line-height: 38px;
|
||||
min-width: 38px;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
padding: 0px 10px;
|
||||
font-size: 18px;
|
||||
margin-left: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.pos .control-button .fa{
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.pos .control-button.highlight{
|
||||
background: #6EC89B;
|
||||
border: solid 1px #6EC89B;
|
||||
color: white;
|
||||
}
|
||||
.pos .control-button:active {
|
||||
background: #7F82AC;
|
||||
border: solid 1px #7F82AC;
|
||||
color: white;
|
||||
}
|
||||
.pos .control-button.disabled,
|
||||
.pos .control-button.disabled:active{
|
||||
background: #e2e2e2;
|
||||
border: solid 1px #BEBEBE;
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* ********* The paypad contains the payment buttons ********* */
|
||||
|
||||
|
@ -782,6 +863,78 @@ td {
|
|||
color: #5a5a5a;
|
||||
}
|
||||
|
||||
/* a) Generic Screen Layout Constructs */
|
||||
|
||||
.screen .screen-content{
|
||||
margin: 0px auto;
|
||||
max-width: 1024px;
|
||||
text-align: left;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.screen .top-content{
|
||||
position: absolute;
|
||||
left: 0px; top: 0px; right: 0px;
|
||||
height: 64px;
|
||||
border-bottom: dashed 1px rgb(215,215,215);
|
||||
text-align: center;
|
||||
}
|
||||
.screen .top-content .button {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
line-height: 32px;
|
||||
padding: 3px 13px;
|
||||
font-size: 20px;
|
||||
background: rgb(230, 230, 230);
|
||||
margin: 12px;
|
||||
border-radius: 3px;
|
||||
border: solid 1px rgb(209, 209, 209);
|
||||
cursor: pointer;
|
||||
}
|
||||
.screen .top-content .button.highlight{
|
||||
background: rgb(110,200,155);
|
||||
color: white;
|
||||
border: solid 1px rgb(110,200,155);
|
||||
}
|
||||
.screen .top-content .button.back {
|
||||
left: 0px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
.screen .top-content .button.next{
|
||||
right: 0px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.screen .left-content{
|
||||
position: absolute;
|
||||
left:0px; top: 64px; bottom: 0px;
|
||||
right:50%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
border-right: dashed 1px rgb(215,215,215);
|
||||
}
|
||||
.screen .right-content{
|
||||
position: absolute;
|
||||
right:0px; top: 64px; bottom: 0px;
|
||||
left:50%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.screen .centered-content{
|
||||
position: absolute;
|
||||
right:25%; top: 64px; bottom: 0px;
|
||||
left:25%;
|
||||
border-right: dashed 1px rgb(215,215,215);
|
||||
border-left: dashed 1px rgb(215,215,215);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.screen .full-content{
|
||||
position: absolute;
|
||||
right: 0%; top: 65px; bottom: 0px;
|
||||
left: 0%;
|
||||
}
|
||||
|
||||
/* a) Layout for the Product Screen */
|
||||
|
||||
.pos .screen .layout-table {
|
||||
|
@ -995,117 +1148,145 @@ td {
|
|||
|
||||
/* d) The Scale screen */
|
||||
|
||||
.pos .scale-screen .display{
|
||||
position:relative;
|
||||
width: 550px;
|
||||
height:190px;
|
||||
margin-top: 100px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.pos .scale-screen .product-picture {
|
||||
position: relative;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: float;
|
||||
float: right;
|
||||
margin: 5px;
|
||||
width: 180px;
|
||||
height:180px;
|
||||
line-height:180px;
|
||||
cursor:pointer;
|
||||
|
||||
background:#fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 2px rgb(228, 228, 228);
|
||||
}
|
||||
|
||||
.pos .scale-screen .product-picture img{
|
||||
max-width: 178px;
|
||||
max-height: 178px;
|
||||
vertical-align: middle;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.pos .scale-screen .product-picture .product-price{
|
||||
position: absolute;
|
||||
top:8px;
|
||||
right:8px;
|
||||
width:auto;
|
||||
height:auto;
|
||||
line-height:1;
|
||||
color:white;
|
||||
background: #7f82ac;
|
||||
padding: 4px 5px;
|
||||
border-radius: 3px;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.pos .scale-screen .product-name {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 210px;
|
||||
top: 10px;
|
||||
height: 50px;
|
||||
font-size: 36px;
|
||||
line-height: 50px;
|
||||
text-align: right;
|
||||
color: #8d8d8d;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.pos .scale-screen .weight{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 80px;
|
||||
height: 90px;
|
||||
bottom: 55px;
|
||||
right: 210px;
|
||||
padding: 6px;
|
||||
padding-right: 33px;
|
||||
padding-top: 11px;
|
||||
background: white;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 2px rgb(228, 228, 228) inset;
|
||||
}
|
||||
.pos .scale-screen .weight p{
|
||||
.pos .scale-screen .product-price{
|
||||
font-size: 25px;
|
||||
margin: 16px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
text-align:right;
|
||||
line-height: 90px;
|
||||
font-size: 56px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
margin-right: 18px;
|
||||
font-family: "Inconsolata";
|
||||
color: #6c6c6c;
|
||||
width: 40%;
|
||||
}
|
||||
.pos .scale-screen .computed-price{
|
||||
font-size: 25px;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
margin: 16px;
|
||||
margin-top: 0px;
|
||||
padding: 16px;
|
||||
background: white;
|
||||
width: 40%;
|
||||
border-radius: 3px;
|
||||
font-family: Inconsolata;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px 2px 0px rgb(210,210,210);
|
||||
box-shadow: 0px 2px 0px rgb(225,225,225) inset;
|
||||
float: right;
|
||||
}
|
||||
.pos .scale-screen .buy-product{
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
background: rgb(110,200,155);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
padding: 16px;
|
||||
margin: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* e) The Welcome Screen */
|
||||
.pos .goodbye-message{
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top:40%;
|
||||
width:500px;
|
||||
height:400px;
|
||||
margin-left: -250px;
|
||||
margin-top: -200px;
|
||||
padding:10px;
|
||||
padding-top:20px;
|
||||
text-align:center;
|
||||
font-size:20px;
|
||||
font-weight:bold;
|
||||
background-color: #F0EEEE;
|
||||
border: 1px solid #E0DDDD;
|
||||
.pos .scale-screen .weight{
|
||||
text-align: right;
|
||||
margin: 16px;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
padding-right: 30px;
|
||||
font-size: 56px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 10px 20px rgba(0,0,0,0.4);
|
||||
z-index:1150;
|
||||
font-family: Inconsolata;
|
||||
text-shadow: 0px 2px 0px rgb(210, 210, 210);
|
||||
box-shadow: 0px 2px 0px rgb(225,225,225) inset;
|
||||
}
|
||||
|
||||
|
||||
/* e) The Client List Screen */
|
||||
|
||||
.pos .clientlist-screen .client-list{
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
line-height: 40px;
|
||||
}
|
||||
.pos .clientlist-screen .client-list th,
|
||||
.pos .clientlist-screen .client-list td {
|
||||
padding: 0px 8px;
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr{
|
||||
transition: all 150ms linear;
|
||||
background: rgb(230,230,230);
|
||||
}
|
||||
.pos .clientlist-screen .client-list thead > tr,
|
||||
.pos .clientlist-screen .client-list tr:nth-child(even) {
|
||||
background: rgb(247,247,247);
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr.highlight{
|
||||
transition: all 150ms linear;
|
||||
background: rgb(110,200,155) !important;
|
||||
color: white;
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr.lowlight{
|
||||
transition: all 150ms linear;
|
||||
background: rgb(216, 238, 227);
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr.lowlight:nth-child(even){
|
||||
transition: all 150ms linear;
|
||||
background: rgb(227, 246, 237);
|
||||
}
|
||||
.pos .clientlist-screen .client-details{
|
||||
padding: 16px;
|
||||
border-bottom: solid 5px rgb(110,200,155);
|
||||
}
|
||||
.pos .clientlist-screen .client-picture{
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
border-radius: 32px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
float: left;
|
||||
margin-right: 16px;
|
||||
background: white;
|
||||
}
|
||||
.pos .clientlist-screen .client-picture > img{
|
||||
vertical-align: middle;
|
||||
max-height: 64px;
|
||||
}
|
||||
.pos .clientlist-screen .client-name{
|
||||
font-size: 32px;
|
||||
line-height: 64px;
|
||||
margin-bottom:16px;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-box{
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-left{
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-right{
|
||||
width: 50%;
|
||||
float: right;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail{
|
||||
line-height: 24px;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail > .label{
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
width: 64px;
|
||||
text-align: right;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail > .empty{
|
||||
opacity: 0.3;
|
||||
}
|
||||
.pos .clientlist-screen .searchbox{
|
||||
right: auto;
|
||||
margin-left: -90px;
|
||||
margin-top:8px;
|
||||
left: 50%;
|
||||
}
|
||||
.pos .clientlist-screen .searchbox input{
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
|
||||
/* ********* The OrderWidget ********* */
|
||||
|
||||
.pos .order-container{
|
||||
|
@ -1119,11 +1300,17 @@ td {
|
|||
.pos .order-scroller{
|
||||
width:100%;
|
||||
height:100%;
|
||||
overflow:hidden;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.pos .scrollable-y{
|
||||
overflow: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
-webkit-overflow-scrolling: touch !important;
|
||||
}
|
||||
|
||||
.pos .order{
|
||||
background: white;
|
||||
padding-bottom:15px;
|
||||
|
@ -1135,6 +1322,8 @@ td {
|
|||
font-size:16px;
|
||||
border-radius: 3px;
|
||||
border: solid 1px rgb(220,220,220);
|
||||
text-align: left;
|
||||
max-width: 500px;
|
||||
-webkit-transform: translate3d(0,0,0);
|
||||
}
|
||||
|
||||
|
@ -1172,6 +1361,25 @@ td {
|
|||
color:#999;
|
||||
}
|
||||
|
||||
.pos .order .summary .fidpoints{
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
padding: 10px;
|
||||
color: #6EC89B;
|
||||
background: rgba(110, 200, 155, 0.17);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.submit-kitchen-button {
|
||||
float: left;
|
||||
background: rgb(61, 235, 82);
|
||||
color: white;
|
||||
padding: 12px 20px;
|
||||
margin: 0px 15px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ********* The OrderLineWidget ********* */
|
||||
|
||||
.pos .order .orderline{
|
||||
|
@ -1231,6 +1439,50 @@ td {
|
|||
font-style:normal;
|
||||
}
|
||||
|
||||
/* ********* SplitBill ********* */
|
||||
|
||||
.splitbill-screen .order-info {
|
||||
text-align: center;
|
||||
margin-bottom:20px;
|
||||
padding: 20px 0px;
|
||||
font-size: 64px;
|
||||
color: #43996E;
|
||||
text-shadow: 0px 2px white, 0px 2px 2px rgba(0, 0, 0, 0.27);
|
||||
border-bottom: dashed 1px rgb(215,215,215);
|
||||
}
|
||||
.splitbill-screen .order .orderline.selected{
|
||||
background: rgb(110,200,155);
|
||||
color: white;
|
||||
-webkit-transition: background 250ms ease-in-out;
|
||||
-moz-transition: background 250ms ease-in-out;
|
||||
transition: background 250ms ease-in-out;
|
||||
cursor: default;
|
||||
}
|
||||
.splitbill-screen .order .orderline.partially.selected{
|
||||
background: rgb(136, 214, 176);
|
||||
}
|
||||
.splitbill-screen .order .orderline.selected .info-list {
|
||||
color: white;
|
||||
}
|
||||
.splitbill-screen .order .orderline.selected .info-list em{
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.splitbill-screen .paymentmethods {
|
||||
margin: 16px;
|
||||
}
|
||||
.splitbill-screen .paymentmethod {
|
||||
background: rgb(221, 221, 221);
|
||||
line-height: 40px;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 3px;
|
||||
font-size: 16px;
|
||||
border: solid 1px rgb(202, 202, 202);
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ********* The ActionBarWidget ********* */
|
||||
|
||||
.pos .pos-actionbar{
|
||||
|
@ -1408,6 +1660,11 @@ td {
|
|||
box-shadow: 0px 10px 20px rgba(0,0,0,0.4);
|
||||
z-index:1200;
|
||||
}
|
||||
.pos .popup .comment{
|
||||
font-weight: normal;
|
||||
font-size: 18px;
|
||||
margin: 0px 16px;
|
||||
}
|
||||
.pos .popup .footer{
|
||||
position:absolute;
|
||||
bottom:0;
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 8.7 KiB |
|
@ -21,6 +21,11 @@ function openerp_pos_db(instance, module){
|
|||
this.product_by_category_id = {};
|
||||
this.product_by_reference = {};
|
||||
|
||||
this.partners_sorted = [];
|
||||
this.partner_by_id = {};
|
||||
this.partner_by_ean13 = {};
|
||||
this.partner_search_string = "";
|
||||
|
||||
this.category_by_id = {};
|
||||
this.root_category_id = 0;
|
||||
this.category_products = {};
|
||||
|
@ -196,6 +201,60 @@ function openerp_pos_db(instance, module){
|
|||
}
|
||||
}
|
||||
},
|
||||
_partner_search_string: function(partner){
|
||||
var str = '' + partner.id + ':' + partner.name;
|
||||
if(partner.ean13){
|
||||
str += '|' + partner.ean13;
|
||||
}
|
||||
if(partner.address){
|
||||
str += '|' + partner.address;
|
||||
}
|
||||
return str + '\n';
|
||||
},
|
||||
add_partners: function(partners){
|
||||
for(var i = 0, len = partners.length; i < len; i++){
|
||||
var partner = partners[i];
|
||||
this.partner_by_id[partner.id] = partner;
|
||||
if(partner.ean13){
|
||||
this.partner_by_ean13[partner.ean13] = partner;
|
||||
}
|
||||
partner.address = (partner.street || '') +', '+
|
||||
(partner.zip || '') +' '+
|
||||
(partner.city || '') +', '+
|
||||
(partner.country_id[1] || '');
|
||||
this.partner_search_string += this._partner_search_string(partner);
|
||||
this.partners_sorted.push(partner);
|
||||
}
|
||||
},
|
||||
get_partner_by_id: function(id){
|
||||
return this.partner_by_id[id];
|
||||
},
|
||||
get_partner_by_ean13: function(ean13){
|
||||
return this.partner_by_ean13[ean13];
|
||||
},
|
||||
get_partners_sorted: function(){
|
||||
return this.partners_sorted;
|
||||
},
|
||||
search_partner: function(query){
|
||||
try {
|
||||
query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.');
|
||||
query = query.replace(' ','.+');
|
||||
var re = RegExp("([0-9]+):.*?"+query,"gi");
|
||||
}catch(e){
|
||||
return [];
|
||||
}
|
||||
var results = [];
|
||||
for(var i = 0; i < this.limit; i++){
|
||||
r = re.exec(this.partner_search_string);
|
||||
if(r){
|
||||
var id = Number(r[1]);
|
||||
results.push(this.get_partner_by_id(id));
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
/* removes all the data from the database. TODO : being able to selectively remove data */
|
||||
clear: function(stores){
|
||||
for(var i = 0, len = arguments.length; i < len; i++){
|
||||
|
@ -243,7 +302,13 @@ function openerp_pos_db(instance, module){
|
|||
* - a name, package or ean13 containing the query (case insensitive)
|
||||
*/
|
||||
search_product_in_category: function(category_id, query){
|
||||
var re = RegExp("([0-9]+):.*?"+query,"gi");
|
||||
try {
|
||||
query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.');
|
||||
query = query.replace(' ','.+');
|
||||
var re = RegExp("([0-9]+):.*?"+query,"gi");
|
||||
}catch(e){
|
||||
return [];
|
||||
}
|
||||
var results = [];
|
||||
for(var i = 0; i < this.limit; i++){
|
||||
r = re.exec(this.category_search_string[category_id]);
|
||||
|
|
|
@ -77,6 +77,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
|
||||
};
|
||||
|
||||
|
||||
// this object interfaces with the local proxy to communicate to the various hardware devices
|
||||
// connected to the Point of Sale. As the communication only goes from the POS to the proxy,
|
||||
// methods are used both to signal an event, and to fetch information.
|
||||
|
@ -362,28 +363,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
this.notifications[name].push(callback);
|
||||
},
|
||||
|
||||
//a product has been scanned and recognized with success
|
||||
// ean is a parsed ean object
|
||||
scan_item_success: function(ean){
|
||||
return this.message('scan_item_success',{ean: ean});
|
||||
},
|
||||
|
||||
// a product has been scanned but not recognized
|
||||
// ean is a parsed ean object
|
||||
scan_item_error_unrecognized: function(ean){
|
||||
return this.message('scan_item_error_unrecognized',{ean: ean});
|
||||
},
|
||||
|
||||
//the client is asking for help
|
||||
help_needed: function(){
|
||||
return this.message('help_needed');
|
||||
},
|
||||
|
||||
//the client does not need help anymore
|
||||
help_canceled: function(){
|
||||
return this.message('help_canceled');
|
||||
},
|
||||
|
||||
// returns the weight on the scale.
|
||||
scale_read: function(){
|
||||
var self = this;
|
||||
|
@ -411,71 +390,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
this.debug_weight = 0;
|
||||
},
|
||||
|
||||
|
||||
// the pos asks the client to pay 'price' units
|
||||
payment_request: function(price){
|
||||
var ret = new $.Deferred();
|
||||
this.paying = true;
|
||||
this.custom_payment_status = this.default_payment_status;
|
||||
return this.message('payment_request',{'price':price});
|
||||
},
|
||||
|
||||
payment_status: function(){
|
||||
if(this.bypass_proxy){
|
||||
this.bypass_proxy = false;
|
||||
return (new $.Deferred()).resolve(this.custom_payment_status);
|
||||
}else{
|
||||
return this.message('payment_status');
|
||||
}
|
||||
},
|
||||
|
||||
// override what the proxy says and accept the payment
|
||||
debug_accept_payment: function(){
|
||||
this.bypass_proxy = true;
|
||||
this.custom_payment_status = {
|
||||
status: 'paid',
|
||||
message: 'Successfull Payment, have a nice day',
|
||||
payment_method: 'AMEX',
|
||||
receipt_client: '<xml>bla</xml>',
|
||||
receipt_shop: '<xml>bla</xml>',
|
||||
};
|
||||
},
|
||||
|
||||
// override what the proxy says and reject the payment
|
||||
debug_reject_payment: function(){
|
||||
this.bypass_proxy = true;
|
||||
this.custom_payment_status = {
|
||||
status: 'error-rejected',
|
||||
message: 'Sorry you don\'t have enough money :(',
|
||||
};
|
||||
},
|
||||
// the client cancels his payment
|
||||
payment_cancel: function(){
|
||||
this.paying = false;
|
||||
this.custom_payment_status = 'waiting_for_payment';
|
||||
return this.message('payment_cancel');
|
||||
},
|
||||
|
||||
// called when the client logs in or starts to scan product
|
||||
transaction_start: function(){
|
||||
return this.message('transaction_start');
|
||||
},
|
||||
|
||||
// called when the clients has finished his interaction with the machine
|
||||
transaction_end: function(){
|
||||
return this.message('transaction_end');
|
||||
},
|
||||
|
||||
// called when the POS turns to cashier mode
|
||||
cashier_mode_activated: function(){
|
||||
return this.message('cashier_mode_activated');
|
||||
},
|
||||
|
||||
// called when the POS turns to client mode
|
||||
cashier_mode_deactivated: function(){
|
||||
return this.message('cashier_mode_deactivated');
|
||||
},
|
||||
|
||||
// ask for the cashbox (the physical box where you store the cash) to be opened
|
||||
open_cashbox: function(){
|
||||
return this.message('open_cashbox');
|
||||
|
@ -509,10 +423,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
return this.message('log',{'arguments': _.toArray(arguments)});
|
||||
},
|
||||
|
||||
// asks the proxy to print an invoice in pdf form ( used to print invoices generated by the server )
|
||||
print_pdf_invoice: function(pdfinvoice){
|
||||
return this.message('print_pdf_invoice',{pdfinvoice: pdfinvoice});
|
||||
},
|
||||
});
|
||||
|
||||
// this module interfaces with the barcode reader. It assumes the barcode reader
|
||||
|
@ -524,8 +434,8 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
'product',
|
||||
'cashier',
|
||||
'client',
|
||||
'discount',
|
||||
],
|
||||
|
||||
init: function(attributes){
|
||||
this.pos = attributes.pos;
|
||||
this.action_callback = {};
|
||||
|
@ -535,11 +445,56 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
|
||||
this.action_callback_stack = [];
|
||||
|
||||
this.weight_prefix_set = attributes.weight_prefix_set || {'21':''};
|
||||
this.discount_prefix_set = attributes.discount_prefix_set || {'22':''};
|
||||
this.price_prefix_set = attributes.price_prefix_set || {'23':''};
|
||||
this.cashier_prefix_set = attributes.cashier_prefix_set || {'041':''};
|
||||
this.client_prefix_set = attributes.client_prefix_set || {'042':''};
|
||||
this.add_barcode_patterns(attributes.patterns || {
|
||||
'product': ['xxxxxxxxxxxxx'],
|
||||
'cashier': ['041xxxxxxxxxx'],
|
||||
'client': ['042xxxxxxxxxx'],
|
||||
'weight': ['21xxxxxNNDDDx'],
|
||||
'discount': ['22xxxxxxxxNNx'],
|
||||
'price': ['23xxxxxNNNDDx'],
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
add_barcode_patterns: function(patterns){
|
||||
this.patterns = this.patterns || {};
|
||||
for(type in patterns){
|
||||
this.patterns[type] = this.patterns[type] || [];
|
||||
|
||||
var patternlist = patterns[type];
|
||||
if( typeof patternlist === 'string'){
|
||||
patternlist = patternlist.split(',');
|
||||
}
|
||||
for(var i = 0; i < patternlist.length; i++){
|
||||
var pattern = patternlist[i].trim().substring(0,12);
|
||||
if(!pattern.length){
|
||||
continue;
|
||||
}
|
||||
pattern = pattern.replace(/[x\*]/gi,'x');
|
||||
while(pattern.length < 12){
|
||||
pattern += 'x';
|
||||
}
|
||||
this.patterns[type].push(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
this.sorted_patterns = [];
|
||||
for (var type in this.patterns){
|
||||
var patterns = this.patterns[type];
|
||||
for(var i = 0; i < patterns.length; i++){
|
||||
var pattern = patterns[i];
|
||||
var score = 0;
|
||||
for(var j = 0; j < pattern.length; j++){
|
||||
if(pattern[j] != 'x'){
|
||||
score++;
|
||||
}
|
||||
}
|
||||
this.sorted_patterns.push({type:type, pattern:pattern,score:score});
|
||||
}
|
||||
}
|
||||
this.sorted_patterns.sort(function(a,b){
|
||||
return b.score - a.score;
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
@ -625,67 +580,84 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
// most importantly :
|
||||
// - code : the ean
|
||||
// - type : the type of the ean:
|
||||
// 'price' | 'weight' | 'unit' | 'cashier' | 'client' | 'discount' | 'error'
|
||||
// 'price' | 'weight' | 'product' | 'cashier' | 'client' | 'discount' | 'error'
|
||||
//
|
||||
// - prefix : the prefix that has ben used to determine the type
|
||||
// - id : the part of the ean that identifies something
|
||||
// - value : if the id encodes a numerical value, it will be put there
|
||||
// - unit : if the encoded value has a unit, it will be put there.
|
||||
// not to be confused with the 'unit' type, which represent an unit of a
|
||||
// unique product
|
||||
// - base_code : the ean code with all the encoding parts set to zero; the one put on
|
||||
// the product in the backend
|
||||
|
||||
parse_ean: function(ean){
|
||||
var self = this;
|
||||
var parse_result = {
|
||||
encoding: 'ean13',
|
||||
type:'unknown',
|
||||
prefix:'',
|
||||
type:'error',
|
||||
code:ean,
|
||||
base_code: ean,
|
||||
id:'',
|
||||
value: 0,
|
||||
unit: 'none',
|
||||
};
|
||||
|
||||
function match_prefix(prefix_set, type){
|
||||
for(prefix in prefix_set){
|
||||
if(ean.substring(0,prefix.length) === prefix){
|
||||
parse_result.prefix = prefix;
|
||||
parse_result.type = type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (!this.check_ean(ean)){
|
||||
return parse_result;
|
||||
}
|
||||
|
||||
if (!this.check_ean(ean)){
|
||||
parse_result.type = 'error';
|
||||
} else if( match_prefix(this.price_prefix_set,'price')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.base_code = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.value = Number(ean.substring(7,12))/100.0;
|
||||
parse_result.unit = 'euro';
|
||||
} else if( match_prefix(this.weight_prefix_set,'weight')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.value = Number(ean.substring(7,12))/1000.0;
|
||||
parse_result.base_code = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.unit = 'Kg';
|
||||
} else if( match_prefix(this.client_prefix_set,'client')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.unit = 'Kg';
|
||||
} else if( match_prefix(this.cashier_prefix_set,'cashier')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
} else if( match_prefix(this.discount_prefix_set,'discount')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.base_code = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.value = Number(ean.substring(7,12))/100.0;
|
||||
parse_result.unit = '%';
|
||||
} else {
|
||||
parse_result.type = 'unit';
|
||||
parse_result.prefix = '';
|
||||
parse_result.id = ean;
|
||||
function is_number(char){
|
||||
n = char.charCodeAt(0);
|
||||
return n >= 48 && n <= 57;
|
||||
}
|
||||
|
||||
function match_pattern(ean,pattern){
|
||||
for(var i = 0; i < pattern.length; i++){
|
||||
var p = pattern[i];
|
||||
var e = ean[i];
|
||||
if( is_number(p) && p !== e ){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function get_value(ean,pattern){
|
||||
var value = 0;
|
||||
var decimals = 0;
|
||||
for(var i = 0; i < pattern.length; i++){
|
||||
var p = pattern[i];
|
||||
var v = parseInt(ean[i]);
|
||||
if( p === 'N'){
|
||||
value *= 10;
|
||||
value += v;
|
||||
}else if( p === 'D'){
|
||||
decimals += 1;
|
||||
value += v * Math.pow(10,-decimals);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function get_basecode(ean,pattern){
|
||||
var base = '';
|
||||
for(var i = 0; i < pattern.length; i++){
|
||||
var p = pattern[i];
|
||||
var v = ean[i];
|
||||
if( p === 'x' || is_number(p)){
|
||||
base += v;
|
||||
}else{
|
||||
base += '0';
|
||||
}
|
||||
}
|
||||
return self.sanitize_ean(base);
|
||||
}
|
||||
|
||||
var patterns = this.sorted_patterns;
|
||||
|
||||
for(var i = 0; i < patterns.length; i++){
|
||||
if(match_pattern(ean,patterns[i].pattern)){
|
||||
parse_result.type = patterns[i].type;
|
||||
parse_result.value = get_value(ean,patterns[i].pattern);
|
||||
parse_result.base_code = get_basecode(ean,patterns[i].pattern);
|
||||
return parse_result;
|
||||
}
|
||||
}
|
||||
|
||||
return parse_result;
|
||||
},
|
||||
|
||||
|
@ -702,21 +674,18 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
}else if(this.pos.db.get_product_by_reference(code)){
|
||||
var parse_result = {
|
||||
encoding: 'reference',
|
||||
type: 'unit',
|
||||
type: 'product',
|
||||
code: code,
|
||||
prefix: '',
|
||||
};
|
||||
}else{
|
||||
var parse_result = {
|
||||
encoding: 'error',
|
||||
type: 'error',
|
||||
code: code,
|
||||
prefix: '',
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if(parse_result.type in {'unit':'', 'weight':'', 'price':''}){ //ean is associated to a product
|
||||
if(parse_result.type in {'product':'', 'weight':'', 'price':'', 'discount':''}){ //ean is associated to a product
|
||||
if(this.action_callback['product']){
|
||||
this.action_callback['product'](parse_result);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.pos_widget = attributes.pos_widget;
|
||||
|
||||
this.proxy = new module.ProxyDevice(this); // used to communicate to the hardware devices via a local proxy
|
||||
this.barcode_reader = new module.BarcodeReader({'pos': this, proxy:this.proxy}); // used to read barcodes
|
||||
this.barcode_reader = new module.BarcodeReader({'pos': this, proxy:this.proxy, patterns: {}}); // used to read barcodes
|
||||
this.proxy_queue = new module.JobQueue(); // used to prevent parallels communications to the proxy
|
||||
this.db = new module.PosDB(); // a local database used to search trough products and categories & store pending orders
|
||||
this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode
|
||||
|
@ -34,6 +34,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.company_logo = null;
|
||||
this.company_logo_base64 = '';
|
||||
this.currency = null;
|
||||
this.shop = null;
|
||||
this.company = null;
|
||||
this.user = null;
|
||||
this.users = [];
|
||||
|
@ -47,6 +48,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.units = [];
|
||||
this.units_by_id = {};
|
||||
this.pricelist = null;
|
||||
this.order_sequence = 1;
|
||||
this.fidelity = null;
|
||||
window.posmodel = this;
|
||||
|
||||
// these dynamic attributes can be watched for change by other models or widgets
|
||||
|
@ -118,6 +121,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.pos_widget.loading_message(_t('Loading')+' '+model,this._load_progress);
|
||||
return new instance.web.Model(model).query(fields).filter(domain).context(ctx).all()
|
||||
},
|
||||
|
||||
// loads all the needed data on the sever. returns a deferred indicating when all the data has loaded.
|
||||
load_server_data: function(){
|
||||
var self = this;
|
||||
|
@ -148,6 +152,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
var units_by_id = {};
|
||||
for(var i = 0, len = units.length; i < len; i++){
|
||||
units_by_id[units[i].id] = units[i];
|
||||
units[i].groupable = ( units[i].category_id[0] === 1 );
|
||||
units[i].is_unit = ( units[i].id === 1 );
|
||||
}
|
||||
self.units_by_id = units_by_id;
|
||||
|
||||
|
@ -155,9 +161,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
}).then(function(users){
|
||||
self.users = users;
|
||||
|
||||
return self.fetch('res.partner', ['name','ean13'], [['ean13', '!=', false]]);
|
||||
return self.fetch('res.partner', ['name','street','city','country_id','phone','zip','mobile','email','ean13','fidpoints']);
|
||||
}).then(function(partners){
|
||||
self.partners = partners;
|
||||
self.db.add_partners(partners);
|
||||
|
||||
return self.fetch('account.tax', ['name','amount', 'price_include', 'type']);
|
||||
}).then(function(taxes){
|
||||
|
@ -165,23 +172,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
|
||||
return self.fetch(
|
||||
'pos.session',
|
||||
['id', 'journal_ids','name','user_id','config_id','start_at','stop_at'],
|
||||
['id', 'journal_ids','name','user_id','config_id','start_at','stop_at','sequence_number'],
|
||||
[['state', '=', 'opened'], ['user_id', '=', self.session.uid]]
|
||||
);
|
||||
}).then(function(pos_sessions){
|
||||
self.pos_session = pos_sessions[0];
|
||||
|
||||
return self.fetch(
|
||||
'pos.config',
|
||||
['name','journal_ids','journal_id','pricelist_id',
|
||||
'iface_self_checkout', 'iface_led', 'iface_cashdrawer',
|
||||
'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan',
|
||||
'iface_vkeyboard','iface_print_via_proxy','iface_scan_via_proxy',
|
||||
'iface_cashdrawer','iface_invoicing','iface_big_scrollbars',
|
||||
'receipt_header','receipt_footer','proxy_ip',
|
||||
'state','sequence_id','session_ids'],
|
||||
[['id','=', self.pos_session.config_id[0]]]
|
||||
);
|
||||
return self.fetch('pos.config',[],[['id','=', self.pos_session.config_id[0]]]);
|
||||
}).then(function(configs){
|
||||
self.config = configs[0];
|
||||
self.config.use_proxy = self.config.iface_payment_terminal ||
|
||||
|
@ -189,6 +186,18 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
self.config.iface_print_via_proxy ||
|
||||
self.config.iface_scan_via_proxy ||
|
||||
self.config.iface_cashdrawer;
|
||||
|
||||
self.barcode_reader.add_barcode_patterns({
|
||||
'product': self.config.barcode_product,
|
||||
'cashier': self.config.barcode_cashier,
|
||||
'client': self.config.barcode_customer,
|
||||
'weight': self.config.barcode_weight,
|
||||
'discount': self.config.barcode_discount,
|
||||
'price': self.config.barcode_price,
|
||||
});
|
||||
return self.fetch('stock.location',[],[['id','=', self.config.stock_location_id[0]]]);
|
||||
}).then(function(shops){
|
||||
self.shop = shops[0];
|
||||
|
||||
return self.fetch('product.pricelist',['currency_id'],[['id','=',self.config.pricelist_id[0]]]);
|
||||
}).then(function(pricelists){
|
||||
|
@ -198,13 +207,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
}).then(function(currencies){
|
||||
self.currency = currencies[0];
|
||||
|
||||
/*
|
||||
return (new instance.web.Model('decimal.precision')).call('get_precision',[['Account']]);
|
||||
}).then(function(precision){
|
||||
self.accounting_precision = precision;
|
||||
console.log("PRECISION",precision);
|
||||
*/
|
||||
return self.fetch('product.packaging',['ean','product_tmpl_id']);
|
||||
return self.fetch('pos.fidelity',[],[['id','=',self.config.fidelity_id[0] || -1]]);
|
||||
}).then(function(fidelity){
|
||||
if(fidelity.length){
|
||||
self.fidelity = fidelity[0];
|
||||
}
|
||||
|
||||
return self.fetch('product.packaging',['ean','product_id']);
|
||||
}).then(function(packagings){
|
||||
self.db.add_packagings(packagings);
|
||||
|
||||
|
@ -292,7 +301,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
// this is called when an order is removed from the order collection. It ensures that there is always an existing
|
||||
// order and a valid selected order
|
||||
on_removed_order: function(removed_order,index,reason){
|
||||
if(reason === 'abandon' && this.get('orders').size() > 0){
|
||||
if( (reason === 'abandon' || removed_order.temporary) && this.get('orders').size() > 0){
|
||||
// when we intentionally remove an unfinished order, and there is another existing one
|
||||
this.set({'selectedOrder' : this.get('orders').at(index) || this.get('orders').last()});
|
||||
}else{
|
||||
|
@ -309,6 +318,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.set('selectedOrder', order);
|
||||
},
|
||||
|
||||
get_order: function(){
|
||||
return this.get('selectedOrder');
|
||||
},
|
||||
|
||||
//removes the current order
|
||||
delete_current_order: function(){
|
||||
this.get('selectedOrder').destroy({'reason':'abandon'});
|
||||
|
@ -497,6 +510,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
selectedOrder.addProduct(product, {price:parsed_code.value});
|
||||
}else if(parsed_code.type === 'weight'){
|
||||
selectedOrder.addProduct(product, {quantity:parsed_code.value, merge:false});
|
||||
}else if(parsed_code.type === 'discount'){
|
||||
selectedOrder.addProduct(product, {discount:parsed_code.value, merge:false});
|
||||
}else{
|
||||
selectedOrder.addProduct(product);
|
||||
}
|
||||
|
@ -504,6 +519,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
},
|
||||
});
|
||||
|
||||
var orderline_id = 1;
|
||||
|
||||
// An orderline represent one element of the content of a client's shopping cart.
|
||||
// An orderline contains a product, its quantity, its price, discount. etc.
|
||||
// An Order contains zero or more Orderlines.
|
||||
|
@ -519,6 +536,21 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.discountStr = '0';
|
||||
this.type = 'unit';
|
||||
this.selected = false;
|
||||
this.id = orderline_id++;
|
||||
},
|
||||
clone: function(){
|
||||
var orderline = new module.Orderline({},{
|
||||
pos: this.pos,
|
||||
order: null,
|
||||
product: this.product,
|
||||
price: this.price,
|
||||
});
|
||||
orderline.quantity = this.quantity;
|
||||
orderline.quantityStr = this.quantityStr;
|
||||
orderline.discount = this.discount;
|
||||
orderline.type = this.type;
|
||||
orderline.selected = false;
|
||||
return orderline;
|
||||
},
|
||||
// sets a discount [0,100]%
|
||||
set_discount: function(discount){
|
||||
|
@ -566,7 +598,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
},
|
||||
get_quantity_str_with_unit: function(){
|
||||
var unit = this.get_unit();
|
||||
if(unit && unit.name !== 'Unit(s)'){
|
||||
if(unit && !unit.is_unit){
|
||||
return this.quantityStr + ' ' + unit.name;
|
||||
}else{
|
||||
return this.quantityStr;
|
||||
|
@ -602,6 +634,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
can_be_merged_with: function(orderline){
|
||||
if( this.get_product().id !== orderline.get_product().id){ //only orderline of the same product can be merged
|
||||
return false;
|
||||
}else if(!this.get_unit() || !this.get_unit().groupable){
|
||||
return false;
|
||||
}else if(this.get_product_type() !== orderline.get_product_type()){
|
||||
return false;
|
||||
}else if(this.get_discount() > 0){ // we don't merge discounted orderlines
|
||||
|
@ -787,11 +821,33 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.selected_paymentline = undefined;
|
||||
this.screen_data = {}; // see ScreenSelector
|
||||
this.receipt_type = 'receipt'; // 'receipt' || 'invoice'
|
||||
this.temporary = attributes.temporary || false;
|
||||
this.sequence_number = this.pos.pos_session.sequence_number++;
|
||||
return this;
|
||||
},
|
||||
is_empty: function(){
|
||||
return (this.get('orderLines').models.length === 0);
|
||||
},
|
||||
generateUniqueId: function() {
|
||||
return new Date().getTime();
|
||||
},
|
||||
addOrderline: function(line){
|
||||
if(line.order){
|
||||
order.removeOrderline(line);
|
||||
}
|
||||
line.order = this;
|
||||
this.get('orderLines').add(line);
|
||||
this.selectLine(this.getLastOrderline());
|
||||
},
|
||||
getWonFidpoints: function(){
|
||||
if(!this.pos.fidelity){
|
||||
return 0;
|
||||
}else{
|
||||
return round_di(this.getTotalTaxIncluded() * this.pos.fidelity.fidpoints_currency +
|
||||
this.get('orderLines').models.length * this.pos.fidelity.fidpoints_product +
|
||||
this.pos.fidelity.fidpoints_sale,0);
|
||||
}
|
||||
},
|
||||
addProduct: function(product, options){
|
||||
options = options || {};
|
||||
var attr = JSON.parse(JSON.stringify(product));
|
||||
|
@ -805,6 +861,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
if(options.price !== undefined){
|
||||
line.set_unit_price(options.price);
|
||||
}
|
||||
if(options.discount !== undefined){
|
||||
line.set_discount(options.discount);
|
||||
}
|
||||
|
||||
var last_orderline = this.getLastOrderline();
|
||||
if( last_orderline && last_orderline.can_be_merged_with(line) && options.merge !== false){
|
||||
|
@ -818,6 +877,15 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.get('orderLines').remove(line);
|
||||
this.selectLine(this.getLastOrderline());
|
||||
},
|
||||
getOrderline: function(id){
|
||||
var orderlines = this.get('orderLines').models;
|
||||
for(var i = 0; i < orderlines.length; i++){
|
||||
if(orderlines[i].id === id){
|
||||
return orderlines[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getLastOrderline: function(){
|
||||
return this.get('orderLines').at(this.get('orderLines').length -1);
|
||||
},
|
||||
|
@ -950,6 +1018,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
var client = this.get('client');
|
||||
var cashier = this.pos.cashier || this.pos.user;
|
||||
var company = this.pos.company;
|
||||
var shop = this.pos.shop;
|
||||
var date = new Date();
|
||||
|
||||
return {
|
||||
|
@ -969,6 +1038,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
cashier: cashier ? cashier.name : null,
|
||||
header: this.pos.config.receipt_header || '',
|
||||
footer: this.pos.config.receipt_footer || '',
|
||||
fidpoints: this.getWonFidpoints(),
|
||||
precision: {
|
||||
price: 2,
|
||||
money: 2,
|
||||
|
@ -994,6 +1064,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
phone: company.phone,
|
||||
logo: this.pos.company_logo_base64,
|
||||
},
|
||||
shop:{
|
||||
name: shop.name,
|
||||
},
|
||||
currency: this.pos.currency,
|
||||
};
|
||||
},
|
||||
|
@ -1019,6 +1092,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
partner_id: this.get_client() ? this.get_client().id : false,
|
||||
user_id: this.pos.cashier ? this.pos.cashier.id : this.pos.user.id,
|
||||
uid: this.uid,
|
||||
sequence_number: this.sequence_number,
|
||||
fidpoints: this.getWonFidpoints(),
|
||||
};
|
||||
},
|
||||
getSelectedLine: function(){
|
||||
|
@ -1102,7 +1177,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
}
|
||||
},
|
||||
switchSign: function() {
|
||||
console.log('switchsing');
|
||||
var oldBuffer;
|
||||
oldBuffer = this.get('buffer');
|
||||
this.set({
|
||||
|
|
|
@ -29,12 +29,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
this.popup_set = options.popup_set || {};
|
||||
|
||||
this.default_client_screen = options.default_client_screen;
|
||||
this.default_cashier_screen = options.default_cashier_screen;
|
||||
this.default_screen = options.default_screen;
|
||||
|
||||
this.current_popup = null;
|
||||
|
||||
this.current_mode = options.default_mode || 'client';
|
||||
this.current_mode = options.default_mode || 'cashier';
|
||||
|
||||
this.current_screen = null;
|
||||
|
||||
|
@ -46,10 +45,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.popup_set[popup_name].hide();
|
||||
}
|
||||
|
||||
this.selected_order = this.pos.get('selectedOrder');
|
||||
this.selected_order.set_screen_data({
|
||||
client_screen: this.default_client_screen,
|
||||
cashier_screen: this.default_cashier_screen,
|
||||
this.pos.get('selectedOrder').set_screen_data({
|
||||
'screen': this.default_screen,
|
||||
});
|
||||
|
||||
this.pos.bind('change:selectedOrder', this.load_saved_screen, this);
|
||||
|
@ -59,12 +56,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.screen_set[screen_name] = screen;
|
||||
return this;
|
||||
},
|
||||
show_popup: function(name){
|
||||
show_popup: function(name,options){
|
||||
if(this.current_popup){
|
||||
this.close_popup();
|
||||
}
|
||||
this.current_popup = this.popup_set[name];
|
||||
this.current_popup.show();
|
||||
this.current_popup.show(options);
|
||||
},
|
||||
close_popup: function(){
|
||||
if(this.current_popup){
|
||||
|
@ -75,15 +72,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
load_saved_screen: function(){
|
||||
this.close_popup();
|
||||
|
||||
var selectedOrder = this.pos.get('selectedOrder');
|
||||
// this.set_current_screen(selectedOrder.get_screen_data('screen') || this.default_screen,null,'refresh');
|
||||
this.set_current_screen(this.default_screen,null,'refresh');
|
||||
|
||||
if(this.current_mode === 'client'){
|
||||
this.set_current_screen(selectedOrder.get_screen_data('client_screen') || this.default_client_screen,null,'refresh');
|
||||
}else if(this.current_mode === 'cashier'){
|
||||
this.set_current_screen(selectedOrder.get_screen_data('cashier_screen') || this.default_cashier_screen,null,'refresh');
|
||||
}
|
||||
this.selected_order = selectedOrder;
|
||||
},
|
||||
set_user_mode: function(user_mode){
|
||||
if(user_mode !== this.current_mode){
|
||||
|
@ -102,20 +94,21 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
}
|
||||
|
||||
this.close_popup();
|
||||
var selectedOrder = this.pos.get('selectedOrder');
|
||||
if(this.current_mode === 'client'){
|
||||
selectedOrder.set_screen_data('client_screen',screen_name);
|
||||
if(params){
|
||||
selectedOrder.set_screen_data('client_screen_params',params);
|
||||
}
|
||||
}else{
|
||||
selectedOrder.set_screen_data('cashier_screen',screen_name);
|
||||
if(params){
|
||||
selectedOrder.set_screen_data('cashier_screen_params',params);
|
||||
}
|
||||
|
||||
var order = this.pos.get('selectedOrder');
|
||||
var old_screen_name = order.get_screen_data('screen');
|
||||
|
||||
order.set_screen_data('screen',screen_name);
|
||||
|
||||
if(params){
|
||||
order.set_screen_data('params',params);
|
||||
}
|
||||
|
||||
if(screen && (refresh || screen !== this.current_screen)){
|
||||
if( screen_name !== old_screen_name ){
|
||||
order.set_screen_data('previous-screen',old_screen_name);
|
||||
}
|
||||
|
||||
if ( refresh || screen !== this.current_screen){
|
||||
if(this.current_screen){
|
||||
this.current_screen.close();
|
||||
this.current_screen.hide();
|
||||
|
@ -124,21 +117,21 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.current_screen.show();
|
||||
}
|
||||
},
|
||||
get_current_screen_param: function(param){
|
||||
var selected_order = this.pos.get('selectedOrder');
|
||||
if(this.current_mode === 'client'){
|
||||
var params = selected_order.get_screen_data('client_screen_params');
|
||||
}else{
|
||||
var params = selected_order.get_screen_data('cashier_screen_params');
|
||||
}
|
||||
if(params){
|
||||
return params[param];
|
||||
}else{
|
||||
return undefined;
|
||||
get_current_screen: function(){
|
||||
return this.pos.get('selectedOrder').get_screen_data('screen') || this.default_screen;
|
||||
},
|
||||
back: function(){
|
||||
var previous = this.pos.get('selectedOrder').get_screen_data('previous-screen');
|
||||
if(previous){
|
||||
this.set_current_screen(previous);
|
||||
}
|
||||
},
|
||||
get_current_screen_param: function(param){
|
||||
var params = this.pos.get('selectedOrder').get_screen_data('params');
|
||||
return params ? params[param] : undefined;
|
||||
},
|
||||
set_default_screen: function(){
|
||||
this.set_current_screen(this.current_mode === 'client' ? this.default_client_screen : this.default_cashier_screen);
|
||||
this.set_current_screen(this.default_screen);
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -157,25 +150,19 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
|
||||
barcode_product_screen: 'products', //if defined, this screen will be loaded when a product is scanned
|
||||
barcode_product_error_popup: 'error-product', //if defined, this popup will be loaded when there's an error in the popup
|
||||
|
||||
hotkeys_handlers: {},
|
||||
|
||||
// what happens when a product is scanned :
|
||||
// it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if
|
||||
// there's an error.
|
||||
// it will add the product to the order and go to barcode_product_screen.
|
||||
barcode_product_action: function(code){
|
||||
var self = this;
|
||||
if(self.pos.scan_product(code)){
|
||||
self.pos.proxy.scan_item_success(code);
|
||||
if(self.barcode_product_screen){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen);
|
||||
}
|
||||
}else{
|
||||
self.pos.proxy.scan_item_error_unrecognized(code);
|
||||
if(self.barcode_product_error_popup && self.pos_widget.screen_selector.get_user_mode() !== 'cashier'){
|
||||
self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup);
|
||||
}
|
||||
self.pos_widget.screen_selector.show_popup('error-barcode',code.code);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -189,12 +176,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
if(users[i].ean13 === code.code){
|
||||
this.pos.cashier = users[i];
|
||||
this.pos_widget.username.refresh();
|
||||
this.pos.proxy.cashier_mode_activated();
|
||||
this.pos_widget.screen_selector.set_user_mode('cashier');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.pos.proxy.scan_item_error_unrecognized(code);
|
||||
this.pos_widget.screen_selector.show_popup('error-barcode',code.code);
|
||||
return false;
|
||||
},
|
||||
|
||||
|
@ -203,30 +188,28 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
// - if there's a user with a matching ean, put it as the active 'client' and return true
|
||||
// - else : return false.
|
||||
barcode_client_action: function(code){
|
||||
var partners = this.pos.partners;
|
||||
for(var i = 0, len = partners.length; i < len; i++){
|
||||
if(partners[i].ean13 === code.code){
|
||||
this.pos.get('selectedOrder').set_client(partners[i]);
|
||||
this.pos_widget.username.refresh();
|
||||
this.pos.proxy.scan_item_success(code);
|
||||
return true;
|
||||
}
|
||||
var partner = this.pos.db.get_partner_by_ean13(code.code);
|
||||
if(partner){
|
||||
this.pos.get('selectedOrder').set_client(partner);
|
||||
this.pos_widget.username.refresh();
|
||||
return true;
|
||||
}
|
||||
this.pos.proxy.scan_item_error_unrecognized(code);
|
||||
this.pos_widget.screen_selector.show_popup('error-barcode',code.code);
|
||||
return false;
|
||||
//TODO start the transaction
|
||||
},
|
||||
|
||||
// what happens when a discount barcode is scanned : the default behavior
|
||||
// is to set the discount on the last order.
|
||||
barcode_discount_action: function(code){
|
||||
this.pos.proxy.scan_item_success(code);
|
||||
var last_orderline = this.pos.get('selectedOrder').getLastOrderline();
|
||||
if(last_orderline){
|
||||
last_orderline.set_discount(code.value)
|
||||
}
|
||||
},
|
||||
|
||||
// What happens when an invalid barcode is scanned : shows an error popup.
|
||||
barcode_error_action: function(code){
|
||||
this.pos_widget.screen_selector.show_popup('error-barcode',code.code);
|
||||
},
|
||||
// shows an action bar on the screen. The actionbar is automatically shown when you add a button
|
||||
// with add_action_button()
|
||||
show_action_bar: function(){
|
||||
|
@ -264,33 +247,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.hide_action_bar();
|
||||
}
|
||||
|
||||
// we add the help button by default. we do this because the buttons are cleared on each refresh so that
|
||||
// the button stay local to each screen
|
||||
this.pos_widget.left_action_bar.add_new_button({
|
||||
label: _t('Help'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
||||
click: function(){ self.help_button_action(); },
|
||||
});
|
||||
|
||||
var self = this;
|
||||
this.cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier';
|
||||
|
||||
this.pos_widget.set_numpad_visible(this.show_numpad && this.cashier_mode);
|
||||
this.pos_widget.set_numpad_visible(this.show_numpad);
|
||||
this.pos_widget.set_leftpane_visible(this.show_leftpane);
|
||||
this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !this.cashier_mode);
|
||||
this.pos_widget.set_cashier_controls_visible(this.cashier_mode);
|
||||
|
||||
if(this.cashier_mode && this.pos.config.iface_self_checkout){
|
||||
this.pos_widget.client_button.show();
|
||||
}else{
|
||||
this.pos_widget.client_button.hide();
|
||||
}
|
||||
if(this.cashier_mode){
|
||||
this.pos_widget.close_button.show();
|
||||
}else{
|
||||
this.pos_widget.close_button.hide();
|
||||
}
|
||||
|
||||
this.pos_widget.username.set_user_mode(this.pos_widget.screen_selector.get_user_mode());
|
||||
|
||||
this.pos.barcode_reader.set_action_callback({
|
||||
|
@ -298,6 +259,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
'product': self.barcode_product_action ? function(code){ self.barcode_product_action(code); } : undefined ,
|
||||
'client' : self.barcode_client_action ? function(code){ self.barcode_client_action(code); } : undefined ,
|
||||
'discount': self.barcode_discount_action ? function(code){ self.barcode_discount_action(code); } : undefined,
|
||||
'error' : self.barcode_error_action ? function(code){ self.barcode_error_action(code); } : undefined,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -308,7 +270,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.pos.barcode_reader.reset_action_callbacks();
|
||||
}
|
||||
this.pos_widget.action_bar.destroy_buttons();
|
||||
this.pos_widget.left_action_bar.destroy_buttons();
|
||||
},
|
||||
|
||||
// this methods hides the screen. It's not a good place to put your cleanup stuff as it is called on the
|
||||
|
@ -352,21 +313,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
});
|
||||
|
||||
module.HelpPopupWidget = module.PopUpWidget.extend({
|
||||
template:'HelpPopupWidget',
|
||||
show: function(){
|
||||
this._super();
|
||||
this.pos.proxy.help_needed();
|
||||
var self = this;
|
||||
|
||||
this.$el.find('.button').off('click').click(function(){
|
||||
self.pos_widget.screen_selector.close_popup();
|
||||
});
|
||||
},
|
||||
close:function(){
|
||||
this.pos.proxy.help_canceled();
|
||||
},
|
||||
});
|
||||
|
||||
module.ChooseReceiptPopupWidget = module.PopUpWidget.extend({
|
||||
template:'ChooseReceiptPopupWidget',
|
||||
|
@ -398,42 +344,64 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
module.ErrorPopupWidget = module.PopUpWidget.extend({
|
||||
template:'ErrorPopupWidget',
|
||||
show: function(){
|
||||
show: function(text){
|
||||
var self = this;
|
||||
this._super();
|
||||
this.pos.proxy.help_needed();
|
||||
this.pos.proxy.scan_item_error_unrecognized();
|
||||
|
||||
if( text && (text.message || text.comment) ){
|
||||
this.$('.message').text(text.message);
|
||||
this.$('.comment').text(text.comment);
|
||||
}
|
||||
|
||||
this.pos.barcode_reader.save_callbacks();
|
||||
this.pos.barcode_reader.reset_action_callbacks();
|
||||
this.pos.barcode_reader.set_action_callback({
|
||||
'cashier': function(code){
|
||||
clearInterval(this.intervalID);
|
||||
self.pos.proxy.cashier_mode_activated();
|
||||
self.pos_widget.screen_selector.set_user_mode('cashier');
|
||||
},
|
||||
});
|
||||
this.$('.footer .button').off('click').click(function(){
|
||||
self.pos_widget.screen_selector.close_popup();
|
||||
});
|
||||
},
|
||||
close:function(){
|
||||
this._super();
|
||||
this.pos.proxy.help_canceled();
|
||||
this.pos.barcode_reader.restore_callbacks();
|
||||
},
|
||||
});
|
||||
|
||||
module.ProductErrorPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ProductErrorPopupWidget',
|
||||
});
|
||||
|
||||
module.ErrorSessionPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ErrorSessionPopupWidget',
|
||||
});
|
||||
|
||||
module.ErrorNegativePricePopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ErrorNegativePricePopupWidget',
|
||||
module.ErrorBarcodePopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ErrorBarcodePopupWidget',
|
||||
show: function(barcode){
|
||||
this._super();
|
||||
this.$('.barcode').text(barcode);
|
||||
},
|
||||
});
|
||||
|
||||
module.ConfirmPopupWidget = module.PopUpWidget.extend({
|
||||
template: 'ConfirmPopupWidget',
|
||||
show: function(options){
|
||||
var self = this;
|
||||
this._super();
|
||||
|
||||
this.message = options.message || '';
|
||||
this.comment = options.comment || '';
|
||||
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.pos_widget.screen_selector.close_popup();
|
||||
if( options.confirm ){
|
||||
options.confirm.call(self);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
module.ErrorNoClientPopupWidget = module.ErrorPopupWidget.extend({
|
||||
|
@ -443,47 +411,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
module.ErrorInvoiceTransferPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template: 'ErrorInvoiceTransferPopupWidget',
|
||||
});
|
||||
|
||||
module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ScaleInviteScreenWidget',
|
||||
|
||||
next_screen:'scale',
|
||||
previous_screen:'products',
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
var queue = this.pos.proxy_queue;
|
||||
|
||||
queue.schedule(function(){
|
||||
return self.pos.proxy.weighting_start();
|
||||
},{ important: true });
|
||||
|
||||
queue.schedule(function(){
|
||||
return self.pos.proxy.weighting_read_kg().then(function(weight){
|
||||
if(weight > 0.001){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
}
|
||||
});
|
||||
},{duration: 100, repeat: true});
|
||||
|
||||
this.add_action_button({
|
||||
label: _t('Back'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
}
|
||||
});
|
||||
},
|
||||
close: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
this.pos.proxy_queue.clear();
|
||||
this.pos.proxy_queue.schedule(function(){
|
||||
return self.pos.proxy.weighting_end();
|
||||
},{ important: true });
|
||||
},
|
||||
});
|
||||
|
||||
module.ScaleScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ScaleScreenWidget',
|
||||
|
@ -491,6 +418,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
next_screen: 'products',
|
||||
previous_screen: 'products',
|
||||
|
||||
show_leftpane: false,
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
|
@ -510,23 +439,15 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
$('body').on('keyup',this.hotkey_handler);
|
||||
|
||||
this.add_action_button({
|
||||
label: _t('Back'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
}
|
||||
});
|
||||
this.$('.back').click(function(){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
});
|
||||
|
||||
this.$('.next,.buy-product').click(function(){
|
||||
self.order_product();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
});
|
||||
|
||||
this.validate_button = this.add_action_button({
|
||||
label: _t('Validate'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
||||
click: function(){
|
||||
self.order_product();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
},
|
||||
});
|
||||
|
||||
queue.schedule(function(){
|
||||
return self.pos.proxy.scale_read().then(function(weight){
|
||||
self.set_weight(weight.weight);
|
||||
|
@ -534,14 +455,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},{duration:50, repeat: true});
|
||||
|
||||
},
|
||||
renderElement: function(){
|
||||
var self = this;
|
||||
this._super();
|
||||
this.$('.product-picture').click(function(){
|
||||
self.order_product();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
});
|
||||
},
|
||||
get_product: function(){
|
||||
var ss = this.pos_widget.screen_selector;
|
||||
if(ss){
|
||||
|
@ -563,7 +476,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
set_weight: function(weight){
|
||||
this.weight = weight;
|
||||
this.$('.js-weight').text(this.get_product_weight_string());
|
||||
this.$('.weight').text(this.get_product_weight_string());
|
||||
this.$('.computed-price').text(this.get_computed_price_string());
|
||||
},
|
||||
get_product_weight_string: function(){
|
||||
var product = this.get_product();
|
||||
|
@ -581,13 +495,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
weightstr += ' Kg';
|
||||
return weightstr;
|
||||
},
|
||||
get_product_image_url: function(){
|
||||
var product = this.get_product();
|
||||
if(product){
|
||||
return window.location.origin + '/web/binary/image?model=product.product&field=image_medium&id='+product.id;
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
get_computed_price_string: function(){
|
||||
return this.format_currency(this.get_product_price() * this.weight);
|
||||
},
|
||||
close: function(){
|
||||
var self = this;
|
||||
|
@ -598,166 +507,9 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
});
|
||||
|
||||
|
||||
module.ClientPaymentScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ClientPaymentScreenWidget',
|
||||
|
||||
next_screen: 'welcome',
|
||||
previous_screen: 'products',
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
|
||||
this.queue = new module.JobQueue();
|
||||
this.canceled = false;
|
||||
this.paid = false;
|
||||
|
||||
// initiates the connection to the payment terminal and starts the update requests
|
||||
this.start = function(){
|
||||
var def = new $.Deferred();
|
||||
self.pos.proxy.payment_request(self.pos.get('selectedOrder').getDueLeft())
|
||||
.done(function(ack){
|
||||
if(ack === 'ok'){
|
||||
self.queue.schedule(self.update);
|
||||
}else if(ack.indexOf('error') === 0){
|
||||
console.error('cannot make payment. TODO');
|
||||
}else{
|
||||
console.error('unknown payment request return value:',ack);
|
||||
}
|
||||
def.resolve();
|
||||
});
|
||||
return def;
|
||||
};
|
||||
|
||||
// gets updated status from the payment terminal and performs the appropriate consequences
|
||||
this.update = function(){
|
||||
var def = new $.Deferred();
|
||||
if(self.canceled){
|
||||
return def.resolve();
|
||||
}
|
||||
self.pos.proxy.payment_status()
|
||||
.done(function(status){
|
||||
if(status.status === 'paid'){
|
||||
|
||||
var currentOrder = self.pos.get('selectedOrder');
|
||||
|
||||
//we get the first cashregister marked as self-checkout
|
||||
var selfCheckoutRegisters = [];
|
||||
for(var i = 0; i < self.pos.cashregisters.length; i++){
|
||||
var cashregister = self.pos.cashregisters[i];
|
||||
if(cashregister.self_checkout_payment_method){
|
||||
selfCheckoutRegisters.push(cashregister);
|
||||
}
|
||||
}
|
||||
|
||||
var cashregister = selfCheckoutRegisters[0] || self.pos.cashregisters[0];
|
||||
currentOrder.addPaymentline(cashregister);
|
||||
self.pos.push_order(currentOrder)
|
||||
currentOrder.destroy();
|
||||
self.pos.proxy.transaction_end();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
self.paid = true;
|
||||
}else if(status.status.indexOf('error') === 0){
|
||||
console.error('error in payment request. TODO');
|
||||
}else if(status.status === 'waiting'){
|
||||
self.queue.schedule(self.update,200);
|
||||
}else{
|
||||
console.error('unknown status value:',status.status);
|
||||
}
|
||||
def.resolve();
|
||||
});
|
||||
return def;
|
||||
}
|
||||
|
||||
// cancels a payment.
|
||||
this.cancel = function(){
|
||||
if(!self.paid && !self.canceled){
|
||||
self.canceled = true;
|
||||
self.pos.proxy.payment_cancel();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
self.queue.clear();
|
||||
}
|
||||
return (new $.Deferred()).resolve();
|
||||
}
|
||||
|
||||
if(this.pos.get('selectedOrder').getDueLeft() <= 0){
|
||||
this.pos_widget.screen_selector.show_popup('error-negative-price');
|
||||
}else{
|
||||
this.queue.schedule(this.start);
|
||||
}
|
||||
|
||||
this.add_action_button({
|
||||
label: _t('Back'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){
|
||||
self.queue.schedule(self.cancel);
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
}
|
||||
});
|
||||
},
|
||||
close: function(){
|
||||
if(this.queue){
|
||||
this.queue.schedule(this.cancel);
|
||||
}
|
||||
//TODO CANCEL
|
||||
this._super();
|
||||
},
|
||||
});
|
||||
|
||||
module.WelcomeScreenWidget = module.ScreenWidget.extend({
|
||||
template:'WelcomeScreenWidget',
|
||||
|
||||
next_screen: 'products',
|
||||
|
||||
show_numpad: false,
|
||||
show_leftpane: false,
|
||||
start: function(){
|
||||
this._super();
|
||||
$('.goodbye-message').click(function(){
|
||||
$(this).addClass('oe_hidden');
|
||||
});
|
||||
},
|
||||
|
||||
barcode_product_action: function(code){
|
||||
this.pos.proxy.transaction_start();
|
||||
this._super(code);
|
||||
},
|
||||
|
||||
barcode_client_action: function(code){
|
||||
this.pos.proxy.transaction_start();
|
||||
this._super(code);
|
||||
$('.goodbye-message').addClass('oe_hidden');
|
||||
this.pos_widget.screen_selector.show_popup('choose-receipt');
|
||||
},
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
|
||||
this.add_action_button({
|
||||
label: _t('Help'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
||||
click: function(){
|
||||
$('.goodbye-message').css({opacity:1}).addClass('oe_hidden');
|
||||
self.help_button_action();
|
||||
},
|
||||
});
|
||||
|
||||
$('.goodbye-message').css({opacity:1}).removeClass('oe_hidden');
|
||||
setTimeout(function(){
|
||||
$('.goodbye-message').animate({opacity:0},500,'swing',function(){$('.goodbye-message').addClass('oe_hidden');});
|
||||
},5000);
|
||||
},
|
||||
});
|
||||
|
||||
module.ProductScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ProductScreenWidget',
|
||||
|
||||
scale_screen: 'scale',
|
||||
client_scale_screen : 'scale_invite',
|
||||
client_next_screen: 'client_payment',
|
||||
|
||||
show_numpad: true,
|
||||
show_leftpane: true,
|
||||
|
||||
|
@ -767,7 +519,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.product_list_widget = new module.ProductListWidget(this,{
|
||||
click_product_action: function(product){
|
||||
if(product.to_weight && self.pos.config.iface_electronic_scale){
|
||||
self.pos_widget.screen_selector.set_current_screen( self.cashier_mode ? self.scale_screen : self.client_scale_screen, {product: product});
|
||||
self.pos_widget.screen_selector.set_current_screen('scale',{product: product});
|
||||
}else{
|
||||
self.pos.get('selectedOrder').addProduct(product);
|
||||
}
|
||||
|
@ -789,16 +541,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.product_categories_widget.reset_category();
|
||||
|
||||
this.pos_widget.order_widget.set_editable(true);
|
||||
|
||||
if(this.pos_widget.screen_selector.current_mode === 'client'){
|
||||
this.add_action_button({
|
||||
label: _t('Pay'),
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
||||
click: function(){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.client_next_screen);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
close: function(){
|
||||
|
@ -812,6 +554,180 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
});
|
||||
|
||||
module.ClientListScreenWidget = module.ScreenWidget.extend({
|
||||
template: 'ClientListScreenWidget',
|
||||
|
||||
show_leftpane: false,
|
||||
|
||||
auto_back: true,
|
||||
|
||||
show: function(){
|
||||
var self = this;
|
||||
this._super();
|
||||
|
||||
this.renderElement();
|
||||
this.details_visible = false;
|
||||
this.old_client = this.pos.get('selectedOrder').get('client');
|
||||
this.new_client = this.old_client;
|
||||
|
||||
this.$('.back').click(function(){
|
||||
self.pos_widget.screen_selector.back();
|
||||
});
|
||||
|
||||
this.$('.next').click(function(){
|
||||
self.save_changes();
|
||||
self.pos_widget.screen_selector.back();
|
||||
});
|
||||
|
||||
var partners = this.pos.db.get_partners_sorted();
|
||||
this.render_list(partners);
|
||||
|
||||
if( this.old_client ){
|
||||
this.display_client_details('show',this.old_client,0);
|
||||
}
|
||||
|
||||
this.$('.client-list-contents').delegate('.client-line','click',function(event){
|
||||
console.log('uh');
|
||||
self.line_select(event,$(this),parseInt($(this).data('id')));
|
||||
});
|
||||
|
||||
var search_timeout = null;
|
||||
this.$('.searchbox input').on('keyup',function(event){
|
||||
clearTimeout(search_timeout);
|
||||
|
||||
var query = this.value;
|
||||
|
||||
search_timeout = setTimeout(function(){
|
||||
self.perform_search(query,event.which === 13);
|
||||
},70);
|
||||
});
|
||||
|
||||
this.$('.searchbox .search-clear').click(function(){
|
||||
self.clear_search();
|
||||
});
|
||||
},
|
||||
perform_search: function(query, associate_result){
|
||||
if(query){
|
||||
var customers = this.pos.db.search_partner(query);
|
||||
this.display_client_details('hide');
|
||||
if ( associate_result && customers.length === 1){
|
||||
this.new_client = customers[0];
|
||||
this.save_changes();
|
||||
this.pos_widget.screen_selector.back();
|
||||
}
|
||||
this.render_list(customers);
|
||||
}else{
|
||||
var customers = this.pos.db.get_partners_sorted();
|
||||
this.render_list(customers);
|
||||
}
|
||||
},
|
||||
clear_search: function(){
|
||||
var customers = this.pos.db.get_partners_sorted();
|
||||
this.render_list(customers);
|
||||
this.$('.searchbox input')[0].value = '';
|
||||
this.$('.searchbox input').focus();
|
||||
},
|
||||
render_list: function(partners){
|
||||
var contents = this.$('.client-list-contents');
|
||||
contents.empty();
|
||||
for(var i = 0, len = partners.length; i < len; i++){
|
||||
var clientline = $(QWeb.render('ClientLine',{partner:partners[i]}));
|
||||
if( partners[i] === this.new_client ){
|
||||
clientline.addClass('highlight');
|
||||
}
|
||||
contents.append(clientline);
|
||||
}
|
||||
},
|
||||
save_changes: function(){
|
||||
if( this.has_client_changed() ){
|
||||
this.pos.get('selectedOrder').set_client(this.new_client);
|
||||
}
|
||||
},
|
||||
has_client_changed: function(){
|
||||
if( this.old_client && this.new_client ){
|
||||
return this.old_client.id !== this.new_client.id;
|
||||
}else{
|
||||
return !!this.old_client !== !!this.new_client;
|
||||
}
|
||||
},
|
||||
toggle_save_button: function(){
|
||||
var $button = this.$('.button.next');
|
||||
if( this.new_client ){
|
||||
if( !this.old_client){
|
||||
$button.text(_t('Set Customer'));
|
||||
}else{
|
||||
$button.text(_t('Change Customer'));
|
||||
}
|
||||
}else{
|
||||
$button.text(_t('Deselect Customer'));
|
||||
}
|
||||
$button.toggleClass('oe_hidden',!this.has_client_changed());
|
||||
},
|
||||
line_select: function(event,$line,id){
|
||||
var partner = this.pos.db.get_partner_by_id(id);
|
||||
this.$('.client-list .lowlight').removeClass('lowlight');
|
||||
if ( $line.hasClass('highlight') ){
|
||||
$line.removeClass('highlight');
|
||||
$line.addClass('lowlight');
|
||||
this.display_client_details('hide',partner);
|
||||
this.new_client = null;
|
||||
this.toggle_save_button();
|
||||
}else{
|
||||
this.$('.client-list .highlight').removeClass('highlight');
|
||||
$line.addClass('highlight');
|
||||
var y = event.pageY - $line.parent().offset().top
|
||||
this.display_client_details('show',partner,y);
|
||||
this.new_client = partner;
|
||||
this.toggle_save_button();
|
||||
}
|
||||
},
|
||||
partner_icon_url: function(id){
|
||||
return '/web/binary/image?model=res.partner&id='+id+'&field=image_small';
|
||||
},
|
||||
display_client_details: function(visibility,partner,clickpos){
|
||||
if(visibility === 'show'){
|
||||
var contents = this.$('.client-details-contents');
|
||||
var parent = this.$('.client-list').parent();
|
||||
var old_scroll = parent.scrollTop();
|
||||
var old_height = contents.height();
|
||||
contents.empty();
|
||||
contents.append($(QWeb.render('ClientDetails',{widget:this,partner:partner})));
|
||||
var new_height = contents.height();
|
||||
|
||||
if(!this.details_visible){
|
||||
if(clickpos < old_scroll + new_height + 20 ){
|
||||
parent.scrollTop( clickpos - 20 );
|
||||
}else{
|
||||
parent.scrollTop(parent.scrollTop() + new_height);
|
||||
}
|
||||
}else{
|
||||
parent.scrollTop(parent.scrollTop() - old_height + new_height);
|
||||
}
|
||||
|
||||
this.details_visible = true;
|
||||
}else if(visibility === 'hide'){
|
||||
var contents = this.$('.client-details-contents');
|
||||
var parent = this.$('.client-list').parent();
|
||||
var scroll = parent.scrollTop();
|
||||
var height = contents.height();
|
||||
contents.empty();
|
||||
if( height > scroll ){
|
||||
contents.css({height:height+'px'});
|
||||
contents.animate({height:0},400,function(){
|
||||
contents.css({height:''});
|
||||
});
|
||||
//parent.scrollTop(0);
|
||||
}else{
|
||||
parent.scrollTop( parent.scrollTop() - height);
|
||||
}
|
||||
this.details_visible = false;
|
||||
}
|
||||
},
|
||||
close: function(){
|
||||
this._super();
|
||||
},
|
||||
});
|
||||
|
||||
module.ReceiptScreenWidget = module.ScreenWidget.extend({
|
||||
template: 'ReceiptScreenWidget',
|
||||
|
||||
|
@ -879,6 +795,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
module.PaymentScreenWidget = module.ScreenWidget.extend({
|
||||
template: 'PaymentScreenWidget',
|
||||
back_screen: 'products',
|
||||
|
@ -913,7 +830,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
if(node){
|
||||
node.line.set_amount(this.value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.line_click_handler = function(event){
|
||||
|
@ -943,8 +859,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.focus_selected_line();
|
||||
|
||||
document.body.addEventListener('keyup', this.hotkey_handler);
|
||||
|
||||
|
||||
|
||||
this.add_action_button({
|
||||
label: _t('Back'),
|
||||
|
@ -1182,7 +1096,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
if(this.pos.config.iface_print_via_proxy){
|
||||
var receipt = currentOrder.export_for_printing();
|
||||
this.pos.proxy.print_receipt(QWeb.render('XmlReceipt',{
|
||||
receipt: receipt
|
||||
receipt: receipt, widget: self,
|
||||
}));
|
||||
this.pos.get('selectedOrder').destroy(); //finish order and go back to scan screen
|
||||
}else{
|
||||
|
|
|
@ -130,7 +130,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this._super(parent,options);
|
||||
this.editable = false;
|
||||
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
|
||||
this.bind_orderline_events();
|
||||
this.line_click_handler = function(event){
|
||||
if(!self.editable){
|
||||
return;
|
||||
|
@ -138,6 +137,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.pos.get('selectedOrder').selectLine(this.orderline);
|
||||
self.pos_widget.numpad.state.reset();
|
||||
};
|
||||
this.client_change_handler = function(event){
|
||||
self.update_summary();
|
||||
}
|
||||
this.bind_order_events();
|
||||
},
|
||||
enable_numpad: function(){
|
||||
this.disable_numpad(); //ensure we don't register the callbacks twice
|
||||
|
@ -177,11 +180,16 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
}
|
||||
},
|
||||
change_selected_order: function() {
|
||||
this.bind_orderline_events();
|
||||
this.bind_order_events();
|
||||
this.renderElement();
|
||||
},
|
||||
bind_orderline_events: function() {
|
||||
var lines = this.pos.get('selectedOrder').get('orderLines');
|
||||
bind_order_events: function() {
|
||||
|
||||
var order = this.pos.get('selectedOrder');
|
||||
order.unbind('change:client', this.client_change_handler);
|
||||
order.bind('change:client', this.client_change_handler);
|
||||
|
||||
var lines = order.get('orderLines');
|
||||
lines.unbind();
|
||||
lines.bind('add', function(){
|
||||
this.numpad_state.reset();
|
||||
|
@ -233,10 +241,12 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
var orderlines = order.get('orderLines').models;
|
||||
|
||||
var el_str = openerp.qweb.render('OrderWidget',{widget:this, order:order, orderlines:orderlines});
|
||||
|
||||
var el_node = document.createElement('div');
|
||||
el_node.innerHTML = _.str.trim(el_str);
|
||||
el_node = el_node.childNodes[0];
|
||||
|
||||
|
||||
var list_container = el_node.querySelector('.orderlines');
|
||||
for(var i = 0, len = orderlines.length; i < len; i++){
|
||||
var orderline = this.render_orderline(orderlines[i]);
|
||||
|
@ -260,6 +270,22 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
this.el.querySelector('.summary .total > .value').textContent = this.format_currency(total);
|
||||
this.el.querySelector('.summary .total .subentry .value').textContent = this.format_currency(taxes);
|
||||
|
||||
var $fidpoints = $(this.el).find('.summary .fidpoints');
|
||||
|
||||
if(this.pos.fidelity && order.get_client()){
|
||||
var points = order.getWonFidpoints();
|
||||
var total = order.get_client().fidpoints + points;
|
||||
if( points ){
|
||||
points = points > 0 ? '+'+points : +points;
|
||||
}
|
||||
$fidpoints.replaceWith($(QWeb.render('FidelityPoints',{ widget:this, totalpoints:total, wonpoints: points })));
|
||||
$fidpoints.removeClass('oe_hidden');
|
||||
}else{
|
||||
$fidpoints.empty();
|
||||
$fidpoints.addClass('oe_hidden');
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -275,12 +301,22 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.pos.bind('change:selectedOrder', this.renderElement,this );
|
||||
},
|
||||
renderElement:function(){
|
||||
this.selected = ( this.pos.get('selectedOrder') === this.order )
|
||||
this._super();
|
||||
var self = this;
|
||||
this.$el.click(function(){
|
||||
self.selectOrder();
|
||||
if( self.pos.get('selectedOrder') === self.order ){
|
||||
var ss = self.pos.pos_widget.screen_selector;
|
||||
if(ss.get_current_screen() === 'clientlist'){
|
||||
ss.back();
|
||||
}else{
|
||||
ss.set_current_screen('clientlist');
|
||||
}
|
||||
}else{
|
||||
self.selectOrder();
|
||||
}
|
||||
});
|
||||
if( this.order === this.pos.get('selectedOrder') ){
|
||||
if( this.selected){
|
||||
this.$el.addClass('selected');
|
||||
}
|
||||
},
|
||||
|
@ -687,14 +723,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
unknown_product: '9900000000004',
|
||||
},
|
||||
events:[
|
||||
'scan_item_success',
|
||||
'scan_item_error_unrecognized',
|
||||
'payment_request',
|
||||
'open_cashbox',
|
||||
'print_receipt',
|
||||
'print_pdf_invoice',
|
||||
'scale_read',
|
||||
'payment_status',
|
||||
],
|
||||
minimized: false,
|
||||
init: function(parent,options){
|
||||
|
@ -763,12 +794,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
}
|
||||
self.minimized = !self.minimized;
|
||||
});
|
||||
this.$('.button.accept_payment').click(function(){
|
||||
self.pos.proxy.debug_accept_payment();
|
||||
});
|
||||
this.$('.button.reject_payment').click(function(){
|
||||
self.pos.proxy.debug_reject_payment();
|
||||
});
|
||||
this.$('.button.set_weight').click(function(){
|
||||
var kg = Number(self.$('input.weight').val());
|
||||
if(!isNaN(kg)){
|
||||
|
@ -782,15 +807,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.$('.button.custom_ean').click(function(){
|
||||
var ean = self.pos.barcode_reader.sanitize_ean(self.$('input.ean').val() || '0');
|
||||
self.$('input.ean').val(ean);
|
||||
self.pos.barcode_reader.scan('ean13',ean);
|
||||
self.pos.barcode_reader.scan(ean);
|
||||
});
|
||||
this.$('.button.reference').click(function(){
|
||||
self.pos.barcode_reader.scan('reference',self.$('input.ean').val());
|
||||
self.pos.barcode_reader.scan(self.$('input.ean').val());
|
||||
});
|
||||
_.each(this.eans, function(ean, name){
|
||||
self.$('.button.'+name).click(function(){
|
||||
self.$('input.ean').val(ean);
|
||||
self.pos.barcode_reader.scan('ean13',ean);
|
||||
self.pos.barcode_reader.scan(ean);
|
||||
});
|
||||
});
|
||||
_.each(this.events, function(name){
|
||||
|
@ -799,18 +824,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.$('.event.'+name).animate({'background-color':'#1E1E1E'},2000);
|
||||
});
|
||||
});
|
||||
self.pos.proxy.add_notification('help_needed',function(){
|
||||
self.$('.status.help_needed').addClass('on');
|
||||
});
|
||||
self.pos.proxy.add_notification('help_canceled',function(){
|
||||
self.$('.status.help_needed').removeClass('on');
|
||||
});
|
||||
self.pos.proxy.add_notification('transaction_start',function(){
|
||||
self.$('.status.transaction').addClass('on');
|
||||
});
|
||||
self.pos.proxy.add_notification('transaction_end',function(){
|
||||
self.$('.status.transaction').removeClass('on');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -919,7 +932,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.pos_widget = this; //So that pos_widget's childs have pos_widget set automatically
|
||||
|
||||
this.numpad_visible = true;
|
||||
this.left_action_bar_visible = true;
|
||||
this.leftpane_visible = true;
|
||||
this.leftpane_width = '440px';
|
||||
this.cashier_controls_visible = true;
|
||||
|
@ -963,7 +975,17 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
});
|
||||
|
||||
self.$('.deleteorder-button').click(function(){
|
||||
self.pos.delete_current_order();
|
||||
if( !self.pos.get('selectedOrder').is_empty() ){
|
||||
self.screen_selector.show_popup('confirm',{
|
||||
message: _t('Destroy Current Order ?'),
|
||||
comment: _t('You will lose any data associated with the current order'),
|
||||
confirm: function(){
|
||||
self.pos.delete_current_order();
|
||||
},
|
||||
});
|
||||
}else{
|
||||
self.pos.delete_current_order();
|
||||
}
|
||||
});
|
||||
|
||||
//when a new order is created, add an order button widget
|
||||
|
@ -1048,28 +1070,20 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.payment_screen = new module.PaymentScreenWidget(this, {});
|
||||
this.payment_screen.appendTo(this.$('.screens'));
|
||||
|
||||
this.welcome_screen = new module.WelcomeScreenWidget(this,{});
|
||||
this.welcome_screen.appendTo(this.$('.screens'));
|
||||
|
||||
this.client_payment_screen = new module.ClientPaymentScreenWidget(this, {});
|
||||
this.client_payment_screen.appendTo(this.$('.screens'));
|
||||
|
||||
this.scale_invite_screen = new module.ScaleInviteScreenWidget(this, {});
|
||||
this.scale_invite_screen.appendTo(this.$('.screens'));
|
||||
this.clientlist_screen = new module.ClientListScreenWidget(this, {});
|
||||
this.clientlist_screen.appendTo(this.$('.screens'));
|
||||
|
||||
this.scale_screen = new module.ScaleScreenWidget(this,{});
|
||||
this.scale_screen.appendTo(this.$('.screens'));
|
||||
|
||||
// -------- Popups ---------
|
||||
|
||||
this.help_popup = new module.HelpPopupWidget(this, {});
|
||||
this.help_popup.appendTo(this.$el);
|
||||
// -------- Popups ---------
|
||||
|
||||
this.error_popup = new module.ErrorPopupWidget(this, {});
|
||||
this.error_popup.appendTo(this.$el);
|
||||
|
||||
this.error_product_popup = new module.ProductErrorPopupWidget(this, {});
|
||||
this.error_product_popup.appendTo(this.$el);
|
||||
this.error_barcode_popup = new module.ErrorBarcodePopupWidget(this, {});
|
||||
this.error_barcode_popup.appendTo(this.$el);
|
||||
|
||||
this.error_session_popup = new module.ErrorSessionPopupWidget(this, {});
|
||||
this.error_session_popup.appendTo(this.$el);
|
||||
|
@ -1077,15 +1091,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.choose_receipt_popup = new module.ChooseReceiptPopupWidget(this, {});
|
||||
this.choose_receipt_popup.appendTo(this.$el);
|
||||
|
||||
this.error_negative_price_popup = new module.ErrorNegativePricePopupWidget(this, {});
|
||||
this.error_negative_price_popup.appendTo(this.$el);
|
||||
|
||||
this.error_no_client_popup = new module.ErrorNoClientPopupWidget(this, {});
|
||||
this.error_no_client_popup.appendTo(this.$el);
|
||||
|
||||
this.error_invoice_transfer_popup = new module.ErrorInvoiceTransferPopupWidget(this, {});
|
||||
this.error_invoice_transfer_popup.appendTo(this.$el);
|
||||
|
||||
this.confirm_popup = new module.ConfirmPopupWidget(this,{});
|
||||
this.confirm_popup.appendTo(this.$el);
|
||||
|
||||
// -------- Misc ---------
|
||||
|
||||
this.close_button = new module.HeaderButtonWidget(this,{
|
||||
|
@ -1108,9 +1122,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.action_bar = new module.ActionBarWidget(this);
|
||||
this.action_bar.replace(this.$(".placeholder-RightActionBar"));
|
||||
|
||||
this.left_action_bar = new module.ActionBarWidget(this);
|
||||
this.left_action_bar.replace(this.$('.placeholder-LeftActionBar'));
|
||||
|
||||
this.paypad = new module.PaypadWidget(this, {});
|
||||
this.paypad.replace(this.$('.placeholder-PaypadWidget'));
|
||||
|
||||
|
@ -1125,13 +1136,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
});
|
||||
this.onscreen_keyboard.replace(this.$('.placeholder-OnscreenKeyboardWidget'));
|
||||
|
||||
this.client_button = new module.HeaderButtonWidget(this,{
|
||||
label: _t('Self-Checkout'),
|
||||
action: function(){ self.screen_selector.set_user_mode('client'); },
|
||||
});
|
||||
this.client_button.appendTo(this.$('.pos-rightheader'));
|
||||
|
||||
|
||||
// -------- Screen Selector ---------
|
||||
|
||||
this.screen_selector = new module.ScreenSelector({
|
||||
|
@ -1139,25 +1143,21 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
screen_set:{
|
||||
'products': this.product_screen,
|
||||
'payment' : this.payment_screen,
|
||||
'client_payment' : this.client_payment_screen,
|
||||
'scale_invite' : this.scale_invite_screen,
|
||||
'scale': this.scale_screen,
|
||||
'receipt' : this.receipt_screen,
|
||||
'welcome' : this.welcome_screen,
|
||||
'clientlist': this.clientlist_screen,
|
||||
},
|
||||
popup_set:{
|
||||
'help': this.help_popup,
|
||||
'error': this.error_popup,
|
||||
'error-product': this.error_product_popup,
|
||||
'error-barcode': this.error_barcode_popup,
|
||||
'error-session': this.error_session_popup,
|
||||
'error-negative-price': this.error_negative_price_popup,
|
||||
'choose-receipt': this.choose_receipt_popup,
|
||||
'error-no-client': this.error_no_client_popup,
|
||||
'error-invoice-transfer': this.error_invoice_transfer_popup,
|
||||
'confirm': this.confirm_popup,
|
||||
},
|
||||
default_client_screen: 'welcome',
|
||||
default_cashier_screen: 'products',
|
||||
default_mode: this.pos.config.iface_self_checkout ? 'client' : 'cashier',
|
||||
default_screen: 'products',
|
||||
default_mode: 'cashier',
|
||||
});
|
||||
|
||||
if(this.pos.debug){
|
||||
|
@ -1178,7 +1178,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
if(visible !== this.numpad_visible){
|
||||
this.numpad_visible = visible;
|
||||
if(visible){
|
||||
this.set_left_action_bar_visible(false);
|
||||
this.numpad.show();
|
||||
this.paypad.show();
|
||||
}else{
|
||||
|
@ -1187,39 +1186,16 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
}
|
||||
}
|
||||
},
|
||||
set_left_action_bar_visible: function(visible){
|
||||
if(visible !== this.left_action_bar_visible){
|
||||
this.left_action_bar_visible = visible;
|
||||
if(visible){
|
||||
this.set_numpad_visible(false);
|
||||
this.left_action_bar.show();
|
||||
}else{
|
||||
this.left_action_bar.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
//shows or hide the leftpane (contains the list of orderlines, the numpad, the paypad, etc.)
|
||||
set_leftpane_visible: function(visible){
|
||||
if(visible !== this.leftpane_visible){
|
||||
this.leftpane_visible = visible;
|
||||
if(visible){
|
||||
this.$('.pos-leftpane').removeClass('oe_hidden').animate({'width':this.leftpane_width},500,'swing');
|
||||
this.$('.pos-rightpane').animate({'left':this.leftpane_width},500,'swing');
|
||||
this.$('.pos-leftpane').removeClass('oe_hidden');
|
||||
this.$('.rightpane').css({'left':this.leftpane_width});
|
||||
}else{
|
||||
var leftpane = this.$('.pos-leftpane');
|
||||
leftpane.animate({'width':'0px'},500,'swing', function(){ leftpane.addClass('oe_hidden'); });
|
||||
this.$('.pos-rightpane').animate({'left':'0px'},500,'swing');
|
||||
}
|
||||
}
|
||||
},
|
||||
//shows or hide the controls in the PosWidget that are specific to the cashier ( Orders, close button, etc. )
|
||||
set_cashier_controls_visible: function(visible){
|
||||
if(visible !== this.cashier_controls_visible){
|
||||
this.cashier_controls_visible = visible;
|
||||
if(visible){
|
||||
this.$('.pos-rightheader').removeClass('oe_hidden');
|
||||
}else{
|
||||
this.$('.pos-rightheader').addClass('oe_hidden');
|
||||
this.$('.pos-leftpane').addClass('oe_hidden');
|
||||
this.$('.rightpane').css({'left':'0px'});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
</div>
|
||||
<div class="pos-rightheader">
|
||||
<div class="order-selector">
|
||||
<button class="order-button square neworder-button"><img src='/point_of_sale/static/src/img/plus.png' /></button>
|
||||
<button class="order-button square deleteorder-button"><img src='/point_of_sale/static/src/img/minus.png' /></button>
|
||||
<span class="orders"></span>
|
||||
<span class="order-button square neworder-button"><i class='fa fa-plus' /></span>
|
||||
<span class="order-button square deleteorder-button"><i class='fa fa-minus' /></span>
|
||||
</div>
|
||||
<!-- here goes header buttons -->
|
||||
</div>
|
||||
|
@ -35,6 +35,7 @@
|
|||
<div class='subwindow collapsed'>
|
||||
<div class='subwindow-container'>
|
||||
<div class='subwindow-container-fix pads'>
|
||||
<div class="control-buttons oe_hidden"></div>
|
||||
<div class="placeholder-PaypadWidget"></div>
|
||||
<div class="placeholder-NumpadWidget"></div>
|
||||
</div>
|
||||
|
@ -258,29 +259,142 @@
|
|||
|
||||
<t t-name="ScaleScreenWidget">
|
||||
<div class="scale-screen screen">
|
||||
<div class="display">
|
||||
<span class="weight">
|
||||
<p>
|
||||
<span class='js-weight'>
|
||||
<t t-esc="widget.get_product_weight_string()" />
|
||||
</span>
|
||||
</p>
|
||||
</span>
|
||||
<span class="product-name">
|
||||
<t t-esc="widget.get_product_name()" />
|
||||
</span>
|
||||
<div class="product-picture">
|
||||
<span class="product-price">
|
||||
<div class="screen-content">
|
||||
<div class="top-content">
|
||||
<span class='button back'>
|
||||
<i class='fa fa-angle-double-left'></i>
|
||||
Back
|
||||
</span>
|
||||
<h1 class='product-name'><t t-esc="widget.get_product_name()" /></h1>
|
||||
</div>
|
||||
<div class="centered-content">
|
||||
<div class='weight js-weight'>
|
||||
<t t-esc="widget.get_product_weight_string()" />
|
||||
</div>
|
||||
<div class='product-price'>
|
||||
<t t-esc="widget.format_currency(widget.get_product_price()) + '/Kg'" />
|
||||
</span>
|
||||
<t t-if="widget.get_product()">
|
||||
<img t-att-src="widget.get_product_image_url()" />
|
||||
</t>
|
||||
</div>
|
||||
<div class='computed-price'>
|
||||
123.14 €
|
||||
</div>
|
||||
<div class='buy-product'>
|
||||
Order
|
||||
<i class='fa fa-angle-double-right'></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ClientLine">
|
||||
<tr class='client-line' t-att-data-id='partner.id'>
|
||||
<td><t t-esc='partner.name' /></td>
|
||||
<td><t t-esc='partner.address' /></td>
|
||||
<td><t t-esc='partner.fidpoints.toFixed(0)' /></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
<t t-name="ClientDetails">
|
||||
<section class='client-details'>
|
||||
<div class='client-picture'>
|
||||
<img t-att-src='widget.partner_icon_url(partner.id)' />
|
||||
<!--<img src='http://static.fjcdn.com/gifs/Aku_c019d6_2548127.gif' />-->
|
||||
</div>
|
||||
<div class='client-name'><t t-esc='partner.name' /></div>
|
||||
<div class='client-details-box clearfix'>
|
||||
<div class='client-details-left'>
|
||||
<div class='client-detail'>
|
||||
<span class='label'>Address</span>
|
||||
<span class='detail client-address'><t t-esc='partner.address' /></span>
|
||||
</div>
|
||||
<div class='client-detail'>
|
||||
<span class='label'>email</span>
|
||||
<span class='detail client-email'><t t-esc='partner.email' /></span>
|
||||
</div>
|
||||
<div class='client-detail'>
|
||||
<span class='label'>phone</span>
|
||||
<t t-if='partner.phone'>
|
||||
<span class='detail client-phone'><t t-esc='partner.phone' /></span>
|
||||
</t>
|
||||
<t t-if='!partner.phone'>
|
||||
<span class='detail client-phone empty'>N/A</span>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<div class='client-details-right'>
|
||||
<div class='client-detail'>
|
||||
<span class='label'>Points</span>
|
||||
<span class='detail client-points'><t t-esc='partner.fidpoints.toFixed(0)' /></span>
|
||||
</div>
|
||||
<div class='client-detail'>
|
||||
<span class='label'>ID</span>
|
||||
<t t-if='partner.ean13'>
|
||||
<span class='detail client-id'><t t-esc='partner.ean13'/></span>
|
||||
</t>
|
||||
<t t-if='!partner.ean13'>
|
||||
<span class='detail client-id empty'>N/A</span>
|
||||
</t>
|
||||
</div>
|
||||
<div class='client-detail'>
|
||||
<span class='label'>Tax ID</span>
|
||||
<span class='detail client-vat'>123-45678-9101145</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</t>
|
||||
|
||||
<t t-name="ClientListScreenWidget">
|
||||
<div class="clientlist-screen screen">
|
||||
<div class="screen-content">
|
||||
<section class="top-content">
|
||||
<span class='button back'>
|
||||
<i class='fa fa-angle-double-left'></i>
|
||||
Cancel
|
||||
</span>
|
||||
<span class='searchbox'>
|
||||
<input placeholder='Search Customers' />
|
||||
<span class='search-clear'></span>
|
||||
</span>
|
||||
<span class='searchbox'></span>
|
||||
<span class='button next oe_hidden highlight'>
|
||||
Select Customer
|
||||
<i class='fa fa-angle-double-right'></i>
|
||||
</span>
|
||||
</section>
|
||||
<section class="full-content">
|
||||
<div class='window'>
|
||||
<section class='subwindow collapsed'>
|
||||
<div class='subwindow-container'>
|
||||
<div class='subwindow-container-fix client-details-contents'>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class='subwindow'>
|
||||
<div class='subwindow-container'>
|
||||
<div class='subwindow-container-fix touch-scrollable scrollable-y'>
|
||||
<table class='client-list'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Address</th>
|
||||
<th>Points</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class='client-list-contents'>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
|
||||
<t t-name="PaymentScreenWidget">
|
||||
<div class="payment-screen screen touch-scrollable">
|
||||
<div class="pos-payment-container">
|
||||
|
@ -330,6 +444,9 @@
|
|||
<br/>
|
||||
</t>
|
||||
<div font='b'>
|
||||
<t t-if='receipt.shop.name'>
|
||||
<div><t t-esc='receipt.shop.name' /></div>
|
||||
</t>
|
||||
<t t-if='receipt.company.contact_address'>
|
||||
<div><t t-esc='receipt.company.contact_address' /></div>
|
||||
</t>
|
||||
|
@ -373,7 +490,7 @@
|
|||
</t>
|
||||
<line indent='1'>
|
||||
<left>
|
||||
<value value-decimals='3' autoint='on'>
|
||||
<value value-decimals='3' value-autoint='on'>
|
||||
<t t-esc='line.quantity' />
|
||||
</value>
|
||||
<t t-if='line.unit_name !== "Unit(s)"'>
|
||||
|
@ -465,61 +582,9 @@
|
|||
</receipt>
|
||||
</t>
|
||||
|
||||
<t t-name="WelcomeScreenWidget">
|
||||
<div class="welcome-screen screen">
|
||||
<header class='rightpane-header'><h2>Welcome</h2></header>
|
||||
<div class="dialog">
|
||||
<img src="/point_of_sale/static/src/img/scan.png" />
|
||||
<p> Please scan an item or your member card </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goodbye-message">
|
||||
<p>Thank you for shopping with us.</p>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
<t t-name="ScanProductScreenWidget">
|
||||
<div class="scan-product-screen screen touch-scrollable">
|
||||
<header class='rightpane-header'><h2>Please scan an item</h2></header>
|
||||
<img src="/point_of_sale/static/src/img/scan.png" />
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ClientPaymentScreenWidget">
|
||||
<div class="scan-product-screen screen">
|
||||
<header class='rightpane-header'><h2>Payment</h2></header>
|
||||
<div class="dialog">
|
||||
<img src="/point_of_sale/static/src/img/bancontact.png" />
|
||||
<p>Please insert your card in the reader and follow the instructions to complete
|
||||
your purchase</p>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ScaleInviteScreenWidget">
|
||||
<div class="scale-invite-screen screen">
|
||||
<header class='rightpane-header'><h2>Please put your product on the scale</h2></header>
|
||||
<img src="/point_of_sale/static/src/img/scale.png" />
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="HelpPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<p class="message">Please be patient, help is on the way</p>
|
||||
<div class="footer">
|
||||
<div class="button">
|
||||
Cancel
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ChooseReceiptPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<div class="popup popup-receipt">
|
||||
<p class="message">Welcome <t t-esc="widget.get_client_name()" /><br /> Choose your type of receipt:</p>
|
||||
<div class = "button big-left receipt">
|
||||
Ticket
|
||||
|
@ -531,38 +596,17 @@
|
|||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ProductErrorPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<p class="message">The scanned product was not recognized<br /> Please wait, a cashier is on the way</p>
|
||||
<div class="footer">
|
||||
<div class="button">
|
||||
Ok
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ErrorSessionPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<div class="popup popup-nosession">
|
||||
<p class="message">Sorry, we could not create a session for this user.</p>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ErrorNegativePricePopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<p class="message">Your order has to be validated by a cashier.</p>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ErrorNoClientPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<div class="popup popup-noclient">
|
||||
<p class="message">An anonymous order cannot be invoiced</p>
|
||||
<div class="footer">
|
||||
<div class="button">
|
||||
|
@ -575,7 +619,7 @@
|
|||
|
||||
<t t-name="ErrorInvoiceTransferPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<div class="popup popup-invoice">
|
||||
<p class="message">The Order could not be sent to the server for invoicing. Invoices cannot be generated
|
||||
in offline mode. Please check your internet connection and try again.</p>
|
||||
<div class="footer">
|
||||
|
@ -589,9 +633,51 @@
|
|||
|
||||
<t t-name="ErrorPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<div class="popup popup-error">
|
||||
<p class="message"><t t-esc=" widget.message || 'Error' " /></p>
|
||||
<p class="comment"><t t-esc=" widget.comment || '' "/></p>
|
||||
<div class="footer">
|
||||
<div class="button">
|
||||
Ok
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ErrorBarcodePopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-barcode">
|
||||
<p class="message">Unknown Barcode
|
||||
<br />
|
||||
<span class='barcode'></span>
|
||||
</p>
|
||||
<p class="comment">
|
||||
The Point of Sale could not find any product, client, employee
|
||||
or action associated with the scanned barcode.
|
||||
</p>
|
||||
<div class="footer">
|
||||
<div class="button">
|
||||
Ok
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ConfirmPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-confirm">
|
||||
<p class="message"><t t-esc=" widget.message || 'Confirm ?' " /></p>
|
||||
<p class="comment"><t t-esc=" widget.comment || '' "/></p>
|
||||
<div class="footer">
|
||||
<div class="button confirm">
|
||||
Confirm
|
||||
</div>
|
||||
<div class="button cancel">
|
||||
Cancel
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
@ -617,84 +703,6 @@
|
|||
</span>
|
||||
</t>
|
||||
|
||||
<t t-name="OrderWidget">
|
||||
<div class="order-container">
|
||||
<div class="order-scroller touch-scrollable">
|
||||
<div class="order">
|
||||
<ul class="orderlines">
|
||||
<t t-if="orderlines.length === 0">
|
||||
<li class="orderline empty">
|
||||
Your shopping cart is empty
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
<div class="summary clearfix">
|
||||
<div t-attf-class="line #{orderlines.length === 0 ? 'empty' : ''}">
|
||||
<div class='entry total'>
|
||||
<span class="label">Total: </span> <span class="value">0.00 €</span>
|
||||
<div class='subentry'>Taxes: <span class="value">0.00€</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='clear'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="DebugWidget">
|
||||
<div class="debug-widget">
|
||||
<h1>Debug Window</h1>
|
||||
<div class="toggle">▾</div>
|
||||
<div class="content">
|
||||
<p class="category">Payment Terminal</p>
|
||||
|
||||
<ul>
|
||||
<li class="button accept_payment">Accept Payment</li>
|
||||
<li class="button reject_payment">Reject Payment</li>
|
||||
</ul>
|
||||
<p class="category">Electronic Scale</p>
|
||||
<ul>
|
||||
<li><input type="text" class="weight"></input></li>
|
||||
<li class="button set_weight">Set Weight</li>
|
||||
<li class="button reset_weight">Reset</li>
|
||||
</ul>
|
||||
|
||||
<p class="category">Barcode Scanner</p>
|
||||
<ul>
|
||||
<li><input type="text" class="ean"></input></li>
|
||||
<li class="button custom_ean">Custom Ean13</li>
|
||||
<li class="button admin_badge">Admin Badge</li>
|
||||
<li class="button client_badge">Client Badge</li>
|
||||
<li class="button soda_33cl">Soda 33cl</li>
|
||||
<li class="button oranges_kg">3.141Kg Oranges</li>
|
||||
<li class="button lemon_price">1.54€ Lemon</li>
|
||||
<li class="button unknown_product">Unknown Product</li>
|
||||
<li class="button invalid_ean">Invalid Ean</li>
|
||||
<li class="button reference">Reference</li>
|
||||
</ul>
|
||||
|
||||
<p class="category">Hardware Status</p>
|
||||
<ul>
|
||||
<li class="status help_needed">Help needed</li>
|
||||
<li class="status weighting">Weighting</li>
|
||||
<li class="status transaction">In Transaction</li>
|
||||
</ul>
|
||||
<p class="category">Hardware Events</p>
|
||||
<ul>
|
||||
<li class="event scan_item_success">Scan Item Success</li>
|
||||
<li class="event scan_item_error_unrecognized">Scan Item Unrecognized</li>
|
||||
<li class="event payment_request">Payment Request</li>
|
||||
<li class="event payment_status">Payment Status</li>
|
||||
<li class="event open_cashbox">Open Cashbox</li>
|
||||
<li class="event print_receipt">Print Receipt</li>
|
||||
<li class="event print_pdf_invoice">Print Invoice</li>
|
||||
<li class="event scale_read">Read Weighting Scale</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="Orderline">
|
||||
<li t-attf-class="orderline #{ line.selected ? 'selected' : '' }">
|
||||
<span class="product-name">
|
||||
|
@ -729,6 +737,85 @@
|
|||
</li>
|
||||
</t>
|
||||
|
||||
<t t-name="FidelityPoints">
|
||||
<div class='fidpoints'>
|
||||
<span class="won">
|
||||
<span class='value'><t t-esc='wonpoints'/></span> Points.
|
||||
</span>
|
||||
<span class='total'>
|
||||
Total: <span class='value'><t t-esc='totalpoints' /></span>
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="OrderWidget">
|
||||
<div class="order-container">
|
||||
<div class="order-scroller touch-scrollable">
|
||||
<div class="order">
|
||||
<ul class="orderlines">
|
||||
<t t-if="orderlines.length === 0">
|
||||
<li class="orderline empty">
|
||||
Your shopping cart is empty
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
<div class="summary clearfix">
|
||||
<div class='fidpoints oe_hidden'>.</div>
|
||||
<div t-attf-class="line #{orderlines.length === 0 ? 'empty' : ''}">
|
||||
<div class='entry total'>
|
||||
<span class="label">Total: </span> <span class="value">0.00 €</span>
|
||||
<div class='subentry'>Taxes: <span class="value">0.00€</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
|
||||
<t t-name="DebugWidget">
|
||||
<div class="debug-widget">
|
||||
<h1>Debug Window</h1>
|
||||
<div class="toggle">▾</div>
|
||||
<div class="content">
|
||||
<p class="category">Electronic Scale</p>
|
||||
<ul>
|
||||
<li><input type="text" class="weight"></input></li>
|
||||
<li class="button set_weight">Set Weight</li>
|
||||
<li class="button reset_weight">Reset</li>
|
||||
</ul>
|
||||
|
||||
<p class="category">Barcode Scanner</p>
|
||||
<ul>
|
||||
<li><input type="text" class="ean"></input></li>
|
||||
<li class="button custom_ean">Custom Ean13</li>
|
||||
<li class="button admin_badge">Admin Badge</li>
|
||||
<li class="button client_badge">Client Badge</li>
|
||||
<li class="button soda_33cl">Soda 33cl</li>
|
||||
<li class="button oranges_kg">3.141Kg Oranges</li>
|
||||
<li class="button lemon_price">1.54€ Lemon</li>
|
||||
<li class="button unknown_product">Unknown Product</li>
|
||||
<li class="button invalid_ean">Invalid Ean</li>
|
||||
<li class="button reference">Reference</li>
|
||||
</ul>
|
||||
|
||||
<p class="category">Hardware Status</p>
|
||||
<ul>
|
||||
<li class="status weighting">Weighting</li>
|
||||
</ul>
|
||||
<p class="category">Hardware Events</p>
|
||||
<ul>
|
||||
<li class="event open_cashbox">Open Cashbox</li>
|
||||
<li class="event print_receipt">Print Receipt</li>
|
||||
<li class="event scale_read">Read Weighting Scale</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
<t t-name="Paymentline">
|
||||
<div t-attf-class="paymentline #{line.selected ? 'selected' : ''}">
|
||||
<div class='paymentline-name'>
|
||||
|
@ -760,7 +847,22 @@
|
|||
</t>
|
||||
|
||||
<t t-name="OrderButtonWidget">
|
||||
<button class="order-button select-order"><t t-esc="(widget.order.get_client() ? widget.order.get_client_name()+' : ':'') + widget.order.get('creationDate').toString('t')"/></button>
|
||||
<span class="order-button select-order">
|
||||
<t t-if='widget.selected'>
|
||||
<span class='order-sequence'>
|
||||
<t t-esc='widget.order.sequence_number' />
|
||||
</span>
|
||||
<t t-if="widget.order.get_client()">
|
||||
<i class='fa fa-user'/>
|
||||
</t>
|
||||
<t t-esc="(widget.order.get_client() ? widget.order.get_client_name()+' : ':'Unknown Customer: ') + widget.order.get('creationDate').toString('t')"/>
|
||||
</t>
|
||||
<t t-if='!widget.selected'>
|
||||
<span class='order-sequence'>
|
||||
<t t-esc='widget.order.sequence_number' />
|
||||
</span>
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
<t t-name="UsernameWidget">
|
||||
|
@ -778,6 +880,7 @@
|
|||
<t t-esc="widget.pos.company.name"/><br />
|
||||
Phone: <t t-esc="widget.pos.company.phone || ''"/><br />
|
||||
User: <t t-esc="widget.pos.user.name"/><br />
|
||||
Shop: <t t-esc="widget.pos.shop.name"/><br />
|
||||
<br />
|
||||
<t t-if="widget.pos.config.receipt_header">
|
||||
<div style='text-align:center'>
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<template id="index" name="POS Index"><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenERP POS</title>
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||
<meta http-equiv="content-type" content="text/html, charset=utf-8" />
|
||||
|
||||
<meta name="viewport" content=" width=1024, user-scalable=no"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta name="mobile-web-app-capable" content="yes"/>
|
||||
|
||||
<link rel="shortcut icon" sizes="196x196" href="/point_of_sale/static/src/img/touch-icon-196.png"/>
|
||||
<link rel="shortcut icon" sizes="128x128" href="/point_of_sale/static/src/img/touch-icon-128.png"/>
|
||||
<link rel="apple-touch-icon" href="/point_of_sale/static/src/img/touch-icon-iphone.png"/>
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/point_of_sale/static/src/img/touch-icon-ipad.png"/>
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/point_of_sale/static/src/img/touch-icon-iphone-retina.png"/>
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/point_of_sale/static/src/img/touch-icon-ipad-retina.png"/>
|
||||
|
||||
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/fonts/lato/stylesheet.css" />
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/fonts/font-awesome-4.0.3/css/font-awesome.min.css" />
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/css/pos.css" id="pos-stylesheet"/>
|
||||
<link rel="stylesheet" href="/point_of_sale/static/src/css/keyboard.css" />
|
||||
|
||||
<t t-call-assets="web.assets_common"/>
|
||||
<t t-call-assets="web.assets_backend"/>
|
||||
|
||||
<script type="text/javascript" id="loading-script">
|
||||
$(function() {
|
||||
var s = new openerp.init(<t t-raw='modules' />);
|
||||
<t t-raw='init' />
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<!--[if lte IE 8]>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"></script>
|
||||
<script>CFInstall.check({mode: "overlay"});</script>
|
||||
<![endif]-->
|
||||
</body>
|
||||
</html>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -123,7 +123,7 @@ class pos_make_payment(osv.osv_memory):
|
|||
}
|
||||
_defaults = {
|
||||
'journal_id' : _default_journal,
|
||||
'payment_date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'payment_date': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'amount': _default_amount,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue