[MERGE] point_of_sale: new css design
bzr revid: fva@openerp.com-20121001131752-jq8rs2u90vc4tgo4
This commit is contained in:
@@ -119,21 +119,21 @@ class PointOfSaleController(openerpweb.Controller):
|
||||
return
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def payment_request(self, request, price, method, info):
|
||||
def payment_request(self, request, price):
|
||||
"""
|
||||
The PoS will activate the method payment
|
||||
"""
|
||||
print "payment_request: price:"+str(price)+" method:"+str(method)+" info:"+str(info)
|
||||
return
|
||||
print "payment_request: price:"+str(price)
|
||||
return 'ok'
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def is_payment_accepted(self, request):
|
||||
print "is_payment_accepted"
|
||||
return 'waiting_for_payment'
|
||||
def payment_status(self, request):
|
||||
print "payment_status"
|
||||
return { 'status':'waiting' }
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def payment_canceled(self, request):
|
||||
print "payment_canceled"
|
||||
def payment_cancel(self, request):
|
||||
print "payment_cancel"
|
||||
return
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
|
||||
@@ -111,12 +111,10 @@
|
||||
left:0;
|
||||
top:0;
|
||||
width: 100%;
|
||||
height: 33px;
|
||||
height: 34px;
|
||||
margin:0;
|
||||
padding:0;
|
||||
color: gray;
|
||||
border-top: solid 1px #d3d3d3;
|
||||
border-bottom: solid 1px black;
|
||||
background: #393939;
|
||||
background: -moz-linear-gradient(#7b7979, #393939);
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#7b7979), to(#393939));
|
||||
@@ -253,7 +251,7 @@
|
||||
.point-of-sale #content {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
top: 34px;
|
||||
bottom: 0;
|
||||
background: #F0EEEE;
|
||||
}
|
||||
@@ -292,22 +290,29 @@
|
||||
vertical-align: top;
|
||||
}
|
||||
.point-of-sale #paypad button {
|
||||
height: 54px;
|
||||
height: 50px;
|
||||
width: 208px;
|
||||
margin: 0 -3px;
|
||||
margin: 0px -6px 4px -2px;
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
color: #555555;
|
||||
border-top: 1px solid #efefef;
|
||||
font-size: 14px;
|
||||
}
|
||||
.point-of-sale #paypad button:hover {
|
||||
.point-of-sale #paypad button:hover, .point-of-sale #numpad button:hover, .point-of-sale #numpad .selected-mode, .point-of-sale .popup button:hover {
|
||||
border: none;
|
||||
color: white;
|
||||
background: #7f82ac;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#9d9fc5), to(#7f82ac));
|
||||
background: -moz-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: -ms-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: linear-gradient(#9d9fc5, #7f82ac);
|
||||
text-shadow: 0px 0px 5px rgba(255,255,255,0.21);
|
||||
-webkit-box-shadow: 0px 0px 2px rgba(0,0,0,0.3) inset, 0px 1px 2px rgba(0,0,0,0.1);
|
||||
-moz-box-shadow: 0px 0px 2px rgba(0,0,0,0.3) inset, 0px 1px 2px rgba(0,0,0,0.1);
|
||||
-ms-box-shadow: 0px 0px 2px rgba(0,0,0,0.3) inset, 0px 1px 2px rgba(0,0,0,0.1);
|
||||
-o-box-shadow: 0px 0px 2px rgba(0,0,0,0.3) inset, 0px 1px 2px rgba(0,0,0,0.1);
|
||||
box-shadow: 0px 0px 2px rgba(0,0,0,0.3) inset, 0px 1px 2px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* ********* The Numpad ********* */
|
||||
@@ -318,30 +323,14 @@
|
||||
text-align: center;
|
||||
}
|
||||
.point-of-sale #numpad button {
|
||||
height: 54px;
|
||||
width: 54px;
|
||||
margin: 0 -3px;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
margin: 0px 0px 4px 0px;
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
color: #555555;
|
||||
border-top: 1px solid #efefef;
|
||||
}
|
||||
.point-of-sale #numpad button:hover {
|
||||
color: white;
|
||||
background: #7f82ac;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#9d9fc5), to(#7f82ac));
|
||||
background: -moz-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: -ms-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: linear-gradient(#9d9fc5, #7f82ac);
|
||||
}
|
||||
.point-of-sale #numpad .selected-mode {
|
||||
color: white;
|
||||
background: #7f82ac;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#9d9fc5), to(#7f82ac));
|
||||
background: -moz-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: -ms-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: linear-gradient(#9d9fc5, #7f82ac);
|
||||
}
|
||||
.point-of-sale .input-button {
|
||||
font-size: 24px;
|
||||
}
|
||||
@@ -364,7 +353,7 @@
|
||||
.point-of-sale #rightpane header {
|
||||
padding: 0;
|
||||
height: 32px;
|
||||
border-bottom: 1px solid #cecbcb;
|
||||
border-bottom: 1px solid #c7c7c7;
|
||||
background: #d3d3d3;
|
||||
background: -moz-linear-gradient(white, #d3d3d3);
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(white), to(#d3d3d3));
|
||||
@@ -391,7 +380,6 @@
|
||||
bottom:0px;
|
||||
left:0px;
|
||||
right:0px;
|
||||
background: #eeedff;
|
||||
}
|
||||
|
||||
/* a) the product list navigation bar */
|
||||
@@ -451,7 +439,7 @@
|
||||
/*background:#f0f0f0;*/
|
||||
position: relative;
|
||||
background-image: url('../img/bg.png');
|
||||
border-bottom: 1px solid #cecbcb;
|
||||
border-bottom: 2px solid #e0e0e0;
|
||||
}
|
||||
.point-of-sale #categories .white-gradient{
|
||||
position: absolute;
|
||||
@@ -485,9 +473,9 @@
|
||||
background:#fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
-webkit-box-shadow: 0px 2px 0px #E9E9E9, 0px 3px 8px rgba(0, 0, 0, 0.34);
|
||||
-moz-box-shadow: 0px 2px 0px #E9E9E9, 0px 3px 8px rgba(0, 0, 0, 0.34);
|
||||
box-shadow: 0px 2px 0px #E9E9E9, 0px 3px 8px rgba(0, 0, 0, 0.34);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -546,16 +534,18 @@
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
top:auto;
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
background: #8a89ba; /*-webkit-linear-gradient(-90deg,rgba(138,137,186,0),rgba(138,137,186,1), rgba(138,137,186,1));*/
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
line-height: 14px;
|
||||
width: 100%;
|
||||
background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1));
|
||||
background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1));
|
||||
background: -ms-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1));
|
||||
background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1));
|
||||
/*background:#FFF;*/
|
||||
padding: 3px;
|
||||
/*color:#8a89ba;*/
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
padding-top: 15px;
|
||||
color: #7C7BAD;
|
||||
}
|
||||
|
||||
/* e) the product */
|
||||
@@ -572,9 +562,9 @@
|
||||
background:#fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: 0px 1px 8px rgba(127,130,172,0.4);
|
||||
-moz-box-shadow: 0px 1px 8px rgba(127,130,172,0.4);
|
||||
box-shadow: 0px 1px 8px rgba(127,130,172,0.4);
|
||||
-webkit-box-shadow: 0px 2px 0px #dad8e4, 0px 1px 8px #636480;
|
||||
-moz-box-shadow: 0px 2px 0px #dad8e4, 0px 1px 8px #636480;
|
||||
box-shadow: 0px 2px 0px #dad8e4, 0px 1px 8px #636480;
|
||||
}
|
||||
|
||||
.point-of-sale .product .product-img {
|
||||
@@ -596,10 +586,11 @@
|
||||
right: 2px;
|
||||
vertical-align: top;
|
||||
color: white;
|
||||
line-height: 14px;
|
||||
line-height: 13px;
|
||||
background: #7f82ac;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 1px 0px #9A9CC5, 0px 3px 0px #7E86AC, 0px 3px 3px rgba(12, 14, 68, 0.67);
|
||||
}
|
||||
|
||||
.point-of-sale .product .product-name {
|
||||
@@ -630,6 +621,8 @@
|
||||
top:0px;
|
||||
bottom:0px;
|
||||
width:100%;
|
||||
background-image: -webkit-radial-gradient(rgba(255, 255, 255, 0),rgba(51, 17, 124, 0.25)), url('../img/grid.png');
|
||||
box-shadow: 0px 36px 24px rgba(0, 0, 0, 0.14) inset;
|
||||
}
|
||||
.point-of-sale .screen header h2 {
|
||||
margin-top: 0px;
|
||||
@@ -638,6 +631,22 @@
|
||||
.point-of-sale .screen p{
|
||||
font-size: 18px;
|
||||
}
|
||||
.point-of-sale .dialog{
|
||||
width: 500px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 50px;
|
||||
padding: 40px;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
box-shadow: 0px 1px 0px white,0px -1px 0px white, 0px 4px 0px #DFDFDF, 0px 10px 30px rgba(0, 0, 0, 0.21);
|
||||
}
|
||||
.point-of-sale .dialog p{
|
||||
font-size: 25px;
|
||||
margin-top: 10px;
|
||||
color: #5a5a5a;
|
||||
}
|
||||
|
||||
/* a) Layout for the Product Screen */
|
||||
|
||||
@@ -681,11 +690,32 @@
|
||||
}
|
||||
.point-of-sale .pos-step-container input{
|
||||
font-size: 1em;
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 0px 8px;
|
||||
padding-top: 8px;
|
||||
margin-left: 16px;
|
||||
border-radius: 5px;
|
||||
background: white;
|
||||
box-shadow: 0px -1px 0px #E2E2E2 inset,0px 1px 0px white inset, 0px 4px 0px #DDD inset, 0px 4px 8px rgba(0, 0, 0, 0.55) inset;
|
||||
color: #4c4c4c;
|
||||
-webkit-animation: all 250ms linear;
|
||||
}
|
||||
|
||||
.point-of-sale .pos-step-container input:focus{
|
||||
box-shadow: 0px -1px 0px #C9CFFD inset,0px 1px 0px #B8C8FC inset, 0px 4px 0px #9FD5FF inset, 0px 4px 9px rgba(0, 31, 255, 0.55) inset;
|
||||
color: #5d7ad6;
|
||||
-webkit-animation: all 250ms linear;
|
||||
}
|
||||
|
||||
.point-of-sale .pos-payment-container {
|
||||
text-align: left;
|
||||
min-width: 500px;
|
||||
margin-top: 50px;
|
||||
padding: 40px;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 1px 0px white,0px -1px 0px white, 0px 4px 0px #DFDFDF, 0px 10px 30px rgba(0, 0, 0, 0.21);
|
||||
}
|
||||
.point-of-sale .pos-payment-container .left-block{
|
||||
display: inline-block;
|
||||
@@ -695,7 +725,7 @@
|
||||
text-align:left;
|
||||
}
|
||||
.point-of-sale .pos-payment-container .header{
|
||||
margin-top: 50px;
|
||||
margin-top: 0px;
|
||||
margin-bottom:20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -738,9 +768,8 @@
|
||||
padding-bottom:30px;
|
||||
display: inline-block;
|
||||
font-family: "Inconsolata";
|
||||
-webkit-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
-moz-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 1px 0px white, 0px 3px 0px #C1B9D6, 0px 8px 16px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.point-of-sale .pos-sale-ticket .emph{
|
||||
font-size: 20px;
|
||||
@@ -774,6 +803,9 @@
|
||||
.pos-sale-ticket {
|
||||
margin: 0;
|
||||
}
|
||||
.debug-widget{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* d) The Scale screen */
|
||||
@@ -785,9 +817,14 @@
|
||||
margin-top: 100px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 40px;
|
||||
background: #f1f1f1;
|
||||
box-shadow: 0px 1px 0px white, 0px -1px 0px white, 0px 4px 0px #dfdfdf, 0px 10px 30px rgba(0,0,0,0.21);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.point-of-sale .scale-screen .product-picture {
|
||||
position: relative;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
@@ -803,9 +840,7 @@
|
||||
background:#fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 2px 0px #e9e9e9, 0px 2px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.point-of-sale .scale-screen .product-picture img{
|
||||
@@ -832,30 +867,40 @@
|
||||
.point-of-sale .scale-screen .product-name {
|
||||
position: absolute;
|
||||
left:0;
|
||||
top:20px;
|
||||
top:50px;
|
||||
height:50px;
|
||||
font-size:40px;
|
||||
line-height:50px;
|
||||
text-align:right;
|
||||
right:225px;
|
||||
right:275px;
|
||||
color: #8d8d8d;
|
||||
}
|
||||
.point-of-sale .scale-screen .weight{
|
||||
position: absolute;
|
||||
left:0;
|
||||
height:90px;
|
||||
bottom:15px;
|
||||
right:220px;
|
||||
padding:5px;
|
||||
left: 40px;
|
||||
height: 90px;
|
||||
bottom: 55px;
|
||||
right: 260px;
|
||||
padding: 6px;
|
||||
padding-right: 33px;
|
||||
padding-top: 11px;
|
||||
background: white;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px -1px #E2E2E2 inset,0px 1px white inset, 0px 4px #E6E4E4 inset, 0px 4px 8px rgba(0, 0, 0, 0.4) inset;
|
||||
|
||||
}
|
||||
.point-of-sale .scale-screen .weight p{
|
||||
display: inline-block;
|
||||
text-align:right;
|
||||
line-height: 90px;
|
||||
font-size: 80px;
|
||||
width:100%;
|
||||
height:100%;
|
||||
margin:0;
|
||||
font-size: 70px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
margin-right: 18px
|
||||
font-family: "Inconsolata";
|
||||
color: #6c6c6c;
|
||||
text-shadow: 0px 3px 3px rgba(0,0,0, 0.2);
|
||||
}
|
||||
|
||||
/* e) The Welcome Screen */
|
||||
@@ -909,9 +954,10 @@
|
||||
margin-top:16px;
|
||||
margin-bottom:16px;
|
||||
font-size:16px;
|
||||
-webkit-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
-moz-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
border-radius: 2px;
|
||||
-webkit-box-shadow: 0px 1px 0px white, 0px 3px 0px #DFDFDF, 0px 7px 16px rgba(0, 0, 0, 0.20);
|
||||
-moz-box-shadow: 0px 1px 0px white, 0px 3px 0px #DFDFDF, 0px 7px 16px rgba(0, 0, 0, 0.20);
|
||||
box-shadow: 0px 1px 0px white, 0px 3px 0px #DFDFDF, 0px 7px 16px rgba(0, 0, 0, 0.20);
|
||||
|
||||
}
|
||||
|
||||
@@ -1201,10 +1247,8 @@
|
||||
font-size:20px;
|
||||
font-weight:bold;
|
||||
background-color: #F0EEEE;
|
||||
border: 1px solid #E0DDDD;
|
||||
-webkit-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
|
||||
-moz-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
|
||||
-ms-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px -1px white, 0px 1px white, 0px 4px #949494, 0px 10px 20px rgba(0, 0, 0, 0.3);
|
||||
z-index:1200;
|
||||
}
|
||||
.point-of-sale .popup .footer{
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
@@ -14,7 +14,14 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
this.weighting = false;
|
||||
|
||||
this.paying = false;
|
||||
this.payment_status = 'waiting_for_payment';
|
||||
this.default_payment_status = {
|
||||
status: 'waiting',
|
||||
message: '',
|
||||
payment_method: undefined,
|
||||
receipt_client: undefined,
|
||||
receipt_shop: undefined,
|
||||
};
|
||||
this.custom_payment_status = this.default_payment_status;
|
||||
|
||||
this.connection = new instance.web.JsonRPC();
|
||||
this.connection.setup(url);
|
||||
@@ -23,16 +30,21 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
this.notifications = {};
|
||||
|
||||
},
|
||||
message : function(name,params,success_callback, error_callback){
|
||||
success_callback = success_callback || function(){};
|
||||
error_callback = error_callback || function(){};
|
||||
|
||||
message : function(name,params){
|
||||
var ret = new $.Deferred();
|
||||
var callbacks = this.notifications[name] || [];
|
||||
for(var i = 0; i < callbacks.length; i++){
|
||||
callbacks[i](params);
|
||||
}
|
||||
|
||||
this.connection.rpc('/pos/'+name, params || {}, success_callback, error_callback);
|
||||
this.connection.rpc('/pos/'+name, params || {},
|
||||
function(result){
|
||||
ret.resolve(result);
|
||||
},
|
||||
function(error){
|
||||
ret.reject(error);
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
// this allows the client to be notified when a proxy call is made. The notification
|
||||
@@ -47,23 +59,23 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
//a product has been scanned and recognized with success
|
||||
// ean is a parsed ean object
|
||||
scan_item_success: function(ean){
|
||||
this.message('scan_item_success',{ean: 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){
|
||||
this.message('scan_item_error_unrecognized',{ean: ean});
|
||||
return this.message('scan_item_error_unrecognized',{ean: ean});
|
||||
},
|
||||
|
||||
//the client is asking for help
|
||||
help_needed: function(){
|
||||
this.message('help_needed');
|
||||
return this.message('help_needed');
|
||||
},
|
||||
|
||||
//the client does not need help anymore
|
||||
help_canceled: function(){
|
||||
this.message('help_canceled');
|
||||
return this.message('help_canceled');
|
||||
},
|
||||
|
||||
//the client is starting to weight
|
||||
@@ -72,7 +84,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
this.weight = 0;
|
||||
this.weighting = true;
|
||||
this.bypass_proxy = false;
|
||||
this.message('weighting_start');
|
||||
return this.message('weighting_start');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -84,11 +96,12 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
if(this.bypass_proxy){
|
||||
return this.weight;
|
||||
}else{
|
||||
this.message('weighting_read_kg',{},function(weight){
|
||||
if(self.weighting && !self.bypass_proxy){
|
||||
self.weight = weight;
|
||||
}
|
||||
});
|
||||
this.message('weighting_read_kg',{})
|
||||
.then(function(weight){
|
||||
if(self.weighting && !self.bypass_proxy){
|
||||
self.weight = weight;
|
||||
}
|
||||
});
|
||||
return this.weight;
|
||||
}
|
||||
},
|
||||
@@ -104,77 +117,76 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
this.weight = 0;
|
||||
this.weighting = false;
|
||||
this.bypass_proxy = false;
|
||||
this.message('weighting_end');
|
||||
return this.message('weighting_end');
|
||||
},
|
||||
|
||||
// the pos asks the client to pay 'price' units
|
||||
// method: 'mastercard' | 'cash' | ... ? TBD
|
||||
// info: 'extra information to display on the payment terminal' ... ? TBD
|
||||
payment_request: function(price, method, info){
|
||||
payment_request: function(price){
|
||||
var ret = new $.Deferred();
|
||||
this.paying = true;
|
||||
this.payment_status = 'waiting_for_payment';
|
||||
this.message('payment_request',{'price':price,'method':method,'info':info});
|
||||
this.custom_payment_status = this.default_payment_status;
|
||||
return this.message('payment_request',{'price':price});
|
||||
},
|
||||
|
||||
// is called at regular interval after a payment request to see if the client
|
||||
// has paid the required money
|
||||
// returns 'waiting_for_payment' | 'payment_accepted' | 'payment_rejected'
|
||||
is_payment_accepted: function(){
|
||||
var self = this;
|
||||
payment_status: function(){
|
||||
if(this.bypass_proxy){
|
||||
this.bypass_proxy = false;
|
||||
return this.payment_status;
|
||||
return (new $.Deferred()).resolve(this.custom_payment_status);
|
||||
}else{
|
||||
this.message('is_payment_accepted', {}, function(payment_status){
|
||||
if(self.paying){
|
||||
self.payment_status = payment_status;
|
||||
}
|
||||
});
|
||||
return this.payment_status;
|
||||
return this.message('payment_status');
|
||||
}
|
||||
},
|
||||
|
||||
// override what the proxy says and accept the payment
|
||||
debug_accept_payment: function(){
|
||||
this.bypass_proxy = true;
|
||||
this.payment_status = 'payment_accepted';
|
||||
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.payment_status = 'payment_rejected';
|
||||
this.custom_payment_status = {
|
||||
status: 'error-rejected',
|
||||
message: 'Sorry you don\'t have enough money :(',
|
||||
};
|
||||
},
|
||||
// the client cancels his payment
|
||||
payment_canceled: function(){
|
||||
payment_cancel: function(){
|
||||
this.paying = false;
|
||||
this.payment_status = 'waiting_for_payment';
|
||||
this.message('payment_canceled');
|
||||
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(){
|
||||
this.message('transaction_start');
|
||||
return this.message('transaction_start');
|
||||
},
|
||||
|
||||
// called when the clients has finished his interaction with the machine
|
||||
transaction_end: function(){
|
||||
this.message('transaction_end');
|
||||
return this.message('transaction_end');
|
||||
},
|
||||
|
||||
// called when the POS turns to cashier mode
|
||||
cashier_mode_activated: function(){
|
||||
this.message('cashier_mode_activated');
|
||||
return this.message('cashier_mode_activated');
|
||||
},
|
||||
|
||||
// called when the POS turns to client mode
|
||||
cashier_mode_deactivated: function(){
|
||||
this.message('cashier_mode_deactivated');
|
||||
return this.message('cashier_mode_deactivated');
|
||||
},
|
||||
|
||||
// ask for the cashbox (the physical box where you store the cash) to be opened
|
||||
open_cashbox: function(){
|
||||
this.message('open_cashbox');
|
||||
return this.message('open_cashbox');
|
||||
},
|
||||
|
||||
/* ask the printer to print a receipt
|
||||
@@ -216,12 +228,12 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
* }
|
||||
*/
|
||||
print_receipt: function(receipt){
|
||||
this.message('print_receipt',{receipt: receipt});
|
||||
return this.message('print_receipt',{receipt: receipt});
|
||||
},
|
||||
|
||||
// asks the proxy to print an invoice in pdf form ( used to print invoices generated by the server )
|
||||
print_pdf_invoice: function(pdfinvoice){
|
||||
this.message('print_pdf_invoice',{pdfinvoice: pdfinvoice});
|
||||
return this.message('print_pdf_invoice',{pdfinvoice: pdfinvoice});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ 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', //if defined, this popup will be loaded when there's an error in the popup
|
||||
barcode_product_error_popup: 'error-product', //if defined, this popup will be loaded when there's an error in the popup
|
||||
|
||||
// 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
|
||||
@@ -411,6 +411,9 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
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();
|
||||
@@ -419,12 +422,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
},
|
||||
});
|
||||
|
||||
module.ErrorProductNotRecognizedPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ErrorProductNotRecognizedPopupWidget',
|
||||
module.ProductErrorPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ProductErrorPopupWidget',
|
||||
});
|
||||
|
||||
module.ErrorNoSessionPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ErrorNoSessionPopupWidget',
|
||||
module.ErrorSessionPopupWidget = module.ErrorPopupWidget.extend({
|
||||
template:'ErrorSessionPopupWidget',
|
||||
});
|
||||
|
||||
module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
|
||||
@@ -539,6 +542,60 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
},
|
||||
});
|
||||
|
||||
// the JobQueue schedules a sequence of 'jobs'. each job is
|
||||
// a function returning a deferred. the queue waits for each job to finish
|
||||
// before launching the next. Each job can also be scheduled with a delay.
|
||||
// the queue jobqueue is used to prevent parallel requests to the payment terminal.
|
||||
|
||||
module.JobQueue = function(){
|
||||
var queue = [];
|
||||
var running = false;
|
||||
var run = function(){
|
||||
if(queue.length > 0){
|
||||
running = true;
|
||||
var job = queue.shift();
|
||||
setTimeout(function(){
|
||||
var def = job.fun();
|
||||
if(def){
|
||||
def.then(run);
|
||||
}else{
|
||||
run();
|
||||
}
|
||||
},job.delay || 0);
|
||||
}else{
|
||||
running = false;
|
||||
}
|
||||
};
|
||||
|
||||
// adds a job to the schedule.
|
||||
this.schedule = function(fun, delay){
|
||||
queue.push({fun:fun, delay:delay});
|
||||
if(!running){
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
// remove all jobs from the schedule
|
||||
this.clear = function(){
|
||||
queue = [];
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
module.BasicPaymentScreen = module.ScreenWidget.extend({
|
||||
queue: new JobQueue(),
|
||||
start_payment_transaction: function(){
|
||||
},
|
||||
update_payment_transaction: function(){
|
||||
},
|
||||
cancel_payment_transaction: function(){
|
||||
},
|
||||
show: function(){
|
||||
this._super();
|
||||
},
|
||||
});
|
||||
*/
|
||||
|
||||
module.ClientPaymentScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ClientPaymentScreenWidget',
|
||||
|
||||
@@ -548,50 +605,102 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
|
||||
this.queue = new module.JobQueue();
|
||||
this.canceled = false;
|
||||
this.paid = false;
|
||||
|
||||
this.pos.proxy.payment_request(this.pos.get('selectedOrder').getDueLeft(),'card','info'); //TODO TOTAL
|
||||
|
||||
this.intervalID = setInterval(function(){
|
||||
var payment = self.pos.proxy.is_payment_accepted();
|
||||
if(payment === 'payment_accepted'){
|
||||
clearInterval(this.intervalID);
|
||||
|
||||
var currentOrder = self.pos.get('selectedOrder');
|
||||
|
||||
//we get the first cashregister marked as self-checkout
|
||||
var selfCheckoutRegisters = [];
|
||||
for(var i = 0; i < self.pos.get('cashRegisters').models.length; i++){
|
||||
var cashregister = self.pos.get('cashRegisters').models[i];
|
||||
if(cashregister.self_checkout_payment_method){
|
||||
selfCheckoutRegisters.push(cashregister);
|
||||
// initiates the connection to the payment terminal and starts the update requests
|
||||
this.start = function(){
|
||||
var def = new $.Deferred();
|
||||
console.log("START");
|
||||
self.pos.proxy.payment_request(self.pos.get('selectedOrder').getDueLeft())
|
||||
.then(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);
|
||||
}
|
||||
}
|
||||
|
||||
var cashregister = selfCheckoutRegisters[0] || self.pos.get('cashRegisters').models[0];
|
||||
currentOrder.addPaymentLine(cashregister);
|
||||
self.pos.push_order(currentOrder.exportAsJSON())
|
||||
currentOrder.destroy();
|
||||
self.pos.proxy.transaction_end();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
}else if(payment === 'payment_rejected'){
|
||||
clearInterval(self.intervalID);
|
||||
//TODO show a tryagain thingie ?
|
||||
console.log("START_END");
|
||||
def.resolve();
|
||||
});
|
||||
return def;
|
||||
};
|
||||
|
||||
// gets updated status from the payment terminal and performs the appropriate consequences
|
||||
this.update = function(){
|
||||
console.log("UPDATE");
|
||||
var def = new $.Deferred();
|
||||
if(self.canceled){
|
||||
console.log("UPDATE_END");
|
||||
return def.resolve();
|
||||
}
|
||||
},500);
|
||||
self.pos.proxy.payment_status()
|
||||
.then(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.get('cashRegisters').models.length; i++){
|
||||
var cashregister = self.pos.get('cashRegisters').models[i];
|
||||
if(cashregister.self_checkout_payment_method){
|
||||
selfCheckoutRegisters.push(cashregister);
|
||||
}
|
||||
}
|
||||
|
||||
var cashregister = selfCheckoutRegisters[0] || self.pos.get('cashRegisters').models[0];
|
||||
currentOrder.addPaymentLine(cashregister);
|
||||
self.pos.push_order(currentOrder.exportAsJSON())
|
||||
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);
|
||||
}
|
||||
console.log("UPDATE_END");
|
||||
def.resolve();
|
||||
});
|
||||
return def;
|
||||
}
|
||||
|
||||
// cancels a payment.
|
||||
this.cancel = function(){
|
||||
console.log("CANCEL");
|
||||
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();
|
||||
}
|
||||
console.log("CANCEL_END");
|
||||
return (new $.Deferred()).resolve();
|
||||
}
|
||||
|
||||
this.queue.schedule(this.start);
|
||||
|
||||
this.add_action_button({
|
||||
label: 'back',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){
|
||||
clearInterval(this.intervalID);
|
||||
self.pos.proxy.payment_canceled();
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
self.queue.schedule(self.cancel);
|
||||
}
|
||||
});
|
||||
},
|
||||
close: function(){
|
||||
if(this.queue){
|
||||
this.queue.schedule(this.cancel);
|
||||
}
|
||||
//TODO CANCEL
|
||||
this._super();
|
||||
clearInterval(this.intervalID);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -687,7 +687,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
'print_receipt',
|
||||
'print_pdf_invoice',
|
||||
'weighting_read_kg',
|
||||
'is_payment_accepted',
|
||||
'payment_status',
|
||||
],
|
||||
minimized: false,
|
||||
start: function(){
|
||||
@@ -898,10 +898,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
this.error_popup = new module.ErrorPopupWidget(this, {});
|
||||
this.error_popup.appendTo($('.point-of-sale'));
|
||||
|
||||
this.error_product_popup = new module.ErrorProductNotRecognizedPopupWidget(this, {});
|
||||
this.error_product_popup = new module.ProductErrorPopupWidget(this, {});
|
||||
this.error_product_popup.appendTo($('.point-of-sale'));
|
||||
|
||||
this.error_session_popup = new module.ErrorNoSessionPopupWidget(this, {});
|
||||
this.error_session_popup = new module.ErrorSessionPopupWidget(this, {});
|
||||
this.error_session_popup.appendTo($('.point-of-sale'));
|
||||
|
||||
this.choose_receipt_popup = new module.ChooseReceiptPopupWidget(this, {});
|
||||
|
||||
@@ -261,8 +261,10 @@
|
||||
<t t-name="WelcomeScreenWidget">
|
||||
<div class="welcome-screen screen">
|
||||
<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>
|
||||
@@ -280,9 +282,11 @@
|
||||
<t t-name="ClientPaymentScreenWidget">
|
||||
<div class="scan-product-screen screen">
|
||||
<header><h2>Payment</h2></header>
|
||||
<img src="/point_of_sale/static/src/img/bancontact.png" />
|
||||
<p>Please insert your card in the reader and follow the instructions to complete
|
||||
<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>
|
||||
|
||||
@@ -327,15 +331,20 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ErrorProductNotRecognizedPopupWidget">
|
||||
<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>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="button">
|
||||
Ok
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="ErrorNoSessionPopupWidget">
|
||||
<t t-name="ErrorSessionPopupWidget">
|
||||
<div class="modal-dialog">
|
||||
<div class="popup popup-help">
|
||||
<p class="message">Sorry, we could not create a session for this user.</p>
|
||||
@@ -455,11 +464,11 @@
|
||||
<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 weighting_read_kg">Read Weighting Scale</li>
|
||||
<li class="event is_payment_accepted">Check Payment</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user