[merge] improvements to pos

bzr revid: nicolas.vanhoren@openerp.com-20111219132705-loei0ppbvxns3z39
This commit is contained in:
niv-openerp 2011-12-19 14:27:05 +01:00
commit 49823622de
3 changed files with 267 additions and 197 deletions

View File

@ -16,7 +16,7 @@
border-spacing: 0;
border-collapse: collapse;
}
.point-of-sale td {
.point-of-sale td {
border: 1px solid #e9eaec;
}
.point-of-sale input {
@ -472,9 +472,6 @@
.point-of-sale .pos-sale-ticket table td {
border: 0;
}
.point-of-sale .pos-sale-ticket table td.receiptline-amount {
text-align: right;
}
.point-of-sale .pos-receipt-container {
font-size: 0.75em;
}
@ -487,6 +484,10 @@
background-color: #D92A2A;
}
.receipt-buttons {
white-space: nowrap;
}
@media print {
#oe_header, #oe_menu, .point-of-sale #topheader, .point-of-sale #leftpane {
display: none;

View File

@ -70,20 +70,28 @@ openerp.point_of_sale = function(db) {
this.flush_mutex = new $.Mutex();
this.build_tree = _.bind(this.build_tree, this);
this.session = session;
this.set({'pending_operations': this.store.get('pending_operations', [])});
this.bind('change:pending_operations', _.bind(function(unused, val) {
this.store.set('pending_operations', val);
}, this));
this.set({'currency': this.store.get('currency', {symbol: '$', position: 'after'})});
this.bind('change:currency', _.bind(function(unused, val) {
this.store.set('currency', val);
var attributes = {
'pending_operations': [],
'currency': {symbol: '$', position: 'after'},
'shop': {},
'company': {},
'user': {},
};
_.each(attributes, _.bind(function(def, attr) {
var to_set = {};
to_set[attr] = this.store.get(attr, def);
this.set(to_set);
this.bind('change:' + attr, _.bind(function(unused, val) {
this.store.set(attr, val);
}, this));
}, this));
$.when(this.fetch('pos.category', ['name', 'parent_id', 'child_id']),
this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'img'], [['pos_categ_id', '!=', 'false']]),
this.fetch('account.bank.statement', ['account_id', 'currency', 'journal_id', 'state', 'name'], [['state', '=', 'open']]),
this.fetch('account.bank.statement', ['account_id', 'currency', 'journal_id', 'state', 'name'],
[['state', '=', 'open'], ['user_id', '=', this.session.uid]]),
this.fetch('account.journal', ['auto_cash', 'check_dtls', 'currency', 'name', 'type']),
this.get_currency())
.then(this.build_tree);
this.get_app_data())
.pipe(_.bind(this.build_tree, this));
},
fetch: function(osvModel, fields, domain) {
var dataSetSearch;
@ -93,19 +101,23 @@ openerp.point_of_sale = function(db) {
return self.store.set(osvModel, result);
});
},
get_currency: function() {
return new db.web.Model("sale.shop").get_func("search_read")([]).pipe(function(result) {
get_app_data: function() {
var self = this;
return $.when(new db.web.Model("sale.shop").get_func("search_read")([]).pipe(function(result) {
self.set({'shop': result[0]});
var company_id = result[0]['company_id'][0];
return new db.web.Model("res.company").get_func("read")(company_id, ['currency_id']).pipe(function(result) {
return new db.web.Model("res.company").get_func("read")(company_id, ['currency_id', 'name', 'phone']).pipe(function(result) {
self.set({'company': result});
var currency_id = result['currency_id'][0]
return new db.web.Model("res.currency").get_func("read")([currency_id],
['symbol', 'position']).pipe(function(result) {
return result[0];
self.set({'currency': result[0]});
});
});
}).then(_.bind(function(currency) {
this.set({'currency': currency});
}, this));
}), new db.web.Model("res.users").get_func("read")(this.session.uid, ['name']).pipe(function(result) {
self.set({'user': result});
}));
},
push: function(osvModel, record) {
var ops = _.clone(this.get('pending_operations'));
@ -490,21 +502,12 @@ openerp.point_of_sale = function(db) {
The numpad handles both the choice of the property currently being modified
(quantity, price or discount) and the edition of the corresponding numeric value.
*/
var NumpadState = (function() {
__extends(NumpadState, Backbone.Model);
function NumpadState() {
NumpadState.__super__.constructor.apply(this, arguments);
}
NumpadState.prototype.defaults = {
var NumpadState = Backbone.Model.extend({
defaults: {
buffer: "0",
mode: "quantity"
};
NumpadState.prototype.initialize = function(options) {
this.shop = options.shop;
return this.shop.bind('change:selectedOrder', this.reset, this);
};
NumpadState.prototype.appendNewChar = function(newChar) {
},
appendNewChar: function(newChar) {
var oldBuffer;
oldBuffer = this.get('buffer');
if (oldBuffer === '0') {
@ -520,9 +523,9 @@ openerp.point_of_sale = function(db) {
buffer: (this.get('buffer')) + newChar
});
}
return this.updateTarget();
};
NumpadState.prototype.deleteLastChar = function() {
this.updateTarget();
},
deleteLastChar: function() {
var tempNewBuffer;
tempNewBuffer = (this.get('buffer')).slice(0, -1) || "0";
if (isNaN(tempNewBuffer)) {
@ -531,38 +534,36 @@ openerp.point_of_sale = function(db) {
this.set({
buffer: tempNewBuffer
});
return this.updateTarget();
};
NumpadState.prototype.switchSign = function() {
this.updateTarget();
},
switchSign: function() {
var oldBuffer;
oldBuffer = this.get('buffer');
this.set({
buffer: oldBuffer[0] === '-' ? oldBuffer.substr(1) : "-" + oldBuffer
});
return this.updateTarget();
};
NumpadState.prototype.changeMode = function(newMode) {
return this.set({
this.updateTarget();
},
changeMode: function(newMode) {
this.set({
buffer: "0",
mode: newMode
});
};
NumpadState.prototype.reset = function() {
return this.set({
buffer: "0"
},
reset: function() {
this.set({
buffer: "0",
mode: "quantity"
});
};
NumpadState.prototype.updateTarget = function() {
},
updateTarget: function() {
var bufferContent, params;
bufferContent = this.get('buffer');
if (bufferContent && !isNaN(bufferContent)) {
params = {};
params[this.get('mode')] = parseFloat(bufferContent);
return (this.shop.get('selectedOrder')).selected.set(params);
this.trigger('setValue', parseFloat(bufferContent));
}
};
return NumpadState;
})();
},
});
/*
---
Views
@ -571,9 +572,11 @@ openerp.point_of_sale = function(db) {
var NumpadWidget = db.web.Widget.extend({
init: function(parent, options) {
this._super(parent);
this.state = options.state;
this.state = new NumpadState();
},
start: function() {
this.state.bind('change:mode', this.changedMode, this);
this.changedMode();
this.$element.find('button#numpad-backspace').click(_.bind(this.clickDeleteLastChar, this));
this.$element.find('button#numpad-minus').click(_.bind(this.clickSwitchSign, this));
this.$element.find('button.number-char').click(_.bind(this.clickAppendNewChar, this));
@ -591,12 +594,14 @@ openerp.point_of_sale = function(db) {
return this.state.appendNewChar(newChar);
},
clickChangeMode: function(event) {
var newMode;
$('.selected-mode').removeClass('selected-mode');
$(event.currentTarget).addClass('selected-mode');
newMode = event.currentTarget.attributes['data-mode'].nodeValue;
var newMode = event.currentTarget.attributes['data-mode'].nodeValue;
return this.state.changeMode(newMode);
}
},
changedMode: function() {
var mode = this.state.get('mode');
$('.selected-mode').removeClass('selected-mode');
$(_.str.sprintf('.mode-button[data-mode="%s"]', mode), this.$element).addClass('selected-mode');
},
});
/*
Gives access to the payment methods (aka. 'cash registers')
@ -688,14 +693,12 @@ openerp.point_of_sale = function(db) {
return this.$element.remove();
}, this));
this.order = options.order;
this.numpadState = options.numpadState;
},
start: function() {
this.$element.click(_.bind(this.clickHandler, this));
},
clickHandler: function() {
this.numpadState.reset();
return this.select();
this.select();
},
render_element: function() {
this.select();
@ -706,17 +709,34 @@ openerp.point_of_sale = function(db) {
select: function() {
$('tr.selected').removeClass('selected');
this.$element.addClass('selected');
return this.order.selected = this.model;
this.order.selected = this.model;
this.on_selected();
},
on_selected: function() {},
});
var OrderWidget = db.web.Widget.extend({
init: function(parent, options) {
this._super(parent);
this.shop = options.shop;
this.numpadState = options.numpadState;
this.setNumpadState(options.numpadState);
this.shop.bind('change:selectedOrder', this.changeSelectedOrder, this);
this.bindOrderLineEvents();
},
setNumpadState: function(numpadState) {
if (this.numpadState) {
this.numpadState.unbind('setValue', this.setValue);
}
this.numpadState = numpadState;
if (this.numpadState) {
this.numpadState.bind('setValue', this.setValue, this);
this.numpadState.reset();
}
},
setValue: function(val) {
var param = {};
param[this.numpadState.get('mode')] = val;
this.shop.get('selectedOrder').selected.set(param);
},
changeSelectedOrder: function() {
this.currentOrderLines.unbind();
this.bindOrderLineEvents();
@ -730,20 +750,30 @@ openerp.point_of_sale = function(db) {
addLine: function(newLine) {
var line = new OrderlineWidget(null, {
model: newLine,
order: this.shop.get('selectedOrder'),
numpadState: this.numpadState
order: this.shop.get('selectedOrder')
});
line.on_selected.add(_.bind(this.selectedLine, this));
this.selectedLine();
line.appendTo(this.$element);
this.updateSummary();
},
selectedLine: function() {
var reset = false;
if (this.currentSelected !== this.shop.get('selectedOrder').selected) {
reset = true;
}
this.currentSelected = this.shop.get('selectedOrder').selected;
if (reset && this.numpadState)
this.numpadState.reset();
},
render_element: function() {
this.$element.empty();
this.currentOrderLines.each(_.bind( function(orderLine) {
var line = new OrderlineWidget(null, {
model: orderLine,
order: this.shop.get('selectedOrder'),
numpadState: this.numpadState
order: this.shop.get('selectedOrder')
});
line.on_selected.add(_.bind(this.selectedLine, this));
line.appendTo(this.$element);
}, this));
this.updateSummary();
@ -847,27 +877,32 @@ openerp.point_of_sale = function(db) {
init: function(parent, options) {
this._super(parent);
this.model = options.model;
this.model.bind('change', this.render_element, this);
},
start: function () {
this.$element.addClass('paymentline');
$('input', this.$element).keyup(_.bind(this.changeAmount, this));
this.model.bind('change', this.changedAmount, this);
},
on_delete: function() {},
changeAmount: function(event) {
var newAmount;
newAmount = event.currentTarget.value;
if (newAmount && !isNaN(newAmount)) {
return this.model.set({
amount: parseFloat(newAmount)
this.amount = parseFloat(newAmount);
this.model.set({
amount: this.amount,
});
}
},
changedAmount: function() {
if (this.amount !== this.model.get('amount'))
this.render_element();
},
render_element: function() {
this.amount = this.model.get('amount');
this.$element.html(this.template_fct({
name: (this.model.get('journal_id'))[1],
amount: this.model.get('amount')
amount: this.amount,
}));
return this;
this.$element.addClass('paymentline');
$('input', this.$element).keyup(_.bind(this.changeAmount, this));
$('.delete-payment-line', this.$element).click(this.on_delete);
},
});
var PaymentWidget = db.web.Widget.extend({
@ -899,6 +934,7 @@ openerp.point_of_sale = function(db) {
bindPaymentLineEvents: function() {
this.currentPaymentLines = (this.shop.get('selectedOrder')).get('paymentLines');
this.currentPaymentLines.bind('add', this.addPaymentLine, this);
this.currentPaymentLines.bind('remove', this.render_element, this);
this.currentPaymentLines.bind('all', this.updatePaymentSummary, this);
},
bindOrderLineEvents: function() {
@ -916,18 +952,19 @@ openerp.point_of_sale = function(db) {
var x = new PaymentlineWidget(null, {
model: newPaymentLine
});
x.on_delete.add(_.bind(this.deleteLine, this, x));
x.appendTo(this.paymentLineList());
},
render_element: function() {
this.paymentLineList().empty();
this.currentPaymentLines.each(_.bind( function(paymentLine) {
var x = new PaymentlineWidget(null, {
model: paymentLine
});
this.paymentLineList().append(x);
this.addPaymentLine(paymentLine);
}, this));
this.updatePaymentSummary();
},
deleteLine: function(lineWidget) {
this.currentPaymentLines.remove([lineWidget.model]);
},
updatePaymentSummary: function() {
var currentOrder, dueTotal, paidTotal, remaining, remainingAmount;
currentOrder = this.shop.get('selectedOrder');
@ -939,21 +976,24 @@ openerp.point_of_sale = function(db) {
remaining = remainingAmount > 0 ? 0 : (-remainingAmount).toFixed(2);
$('#payment-remaining').html(remaining);
},
});
/*
"Receipt" step.
*/
var ReceiptLineWidget = db.web.Widget.extend({
tag_name: 'tr',
template_fct: qweb_template('pos-receiptline-template'),
init: function(parent, options) {
this._super(parent);
this.model = options.model;
this.model.bind('change', this.render_element, this);
setNumpadState: function(numpadState) {
if (this.numpadState) {
this.numpadState.unbind('setValue', this.setValue);
this.numpadState.unbind('change:mode', this.setNumpadMode);
}
this.numpadState = numpadState;
if (this.numpadState) {
this.numpadState.bind('setValue', this.setValue, this);
this.numpadState.bind('change:mode', this.setNumpadMode, this);
this.numpadState.reset();
this.setNumpadMode();
}
},
render_element: function() {
this.$element.addClass('receiptline');
this.$element.html(this.template_fct(this.model.toJSON()));
setNumpadMode: function() {
this.numpadState.set({mode: 'payment'});
},
setValue: function(val) {
this.currentPaymentLines.last().set({amount: val});
},
});
var ReceiptWidget = db.web.Widget.extend({
@ -961,60 +1001,38 @@ openerp.point_of_sale = function(db) {
this._super(parent);
this.model = options.model;
this.shop = options.shop;
this.user = pos.get('user');
this.company = pos.get('company');
this.shop_obj = pos.get('shop');
},
start: function() {
this.shop.bind('change:selectedOrder', this.changeSelectedOrder, this);
this.bindOrderLineEvents();
this.bindPaymentLineEvents();
},
finishOrder: function() {
this.shop.get('selectedOrder').destroy();
},
receiptLineList: function() {
return this.$element.find('#receiptlines');
},
bindOrderLineEvents: function() {
this.currentOrderLines = (this.shop.get('selectedOrder')).get('orderLines');
this.currentOrderLines.bind('add', this.addReceiptLine, this);
this.currentOrderLines.bind('change', this.render_element, this);
this.currentOrderLines.bind('remove', this.render_element, this);
},
bindPaymentLineEvents: function() {
this.currentPaymentLines = (this.shop.get('selectedOrder')).get('paymentLines');
this.currentPaymentLines.bind('all', this.updateReceiptSummary, this);
},
changeSelectedOrder: function() {
this.currentOrderLines.unbind();
this.bindOrderLineEvents();
this.currentPaymentLines.unbind();
this.bindPaymentLineEvents();
this.render_element();
},
addReceiptLine: function(newOrderItem) {
var x = new ReceiptLineWidget(null, {
model: newOrderItem
});
x.appendTo(this.receiptLineList());
this.updateReceiptSummary();
this.changeSelectedOrder();
},
render_element: function() {
this.$element.html(qweb_template('pos-receipt-view'));
$('button#pos-finish-order', this.$element).click(_.bind(this.finishOrder, this));
this.currentOrderLines.each(_.bind( function(orderItem) {
var x = new ReceiptLineWidget(null, {
model: orderItem
});
x.appendTo(this.receiptLineList());
}, this));
this.updateReceiptSummary();
$('button#print-the-ticket', this.$element).click(function(){window.print();});
},
updateReceiptSummary: function() {
var change, currentOrder, tax, total;
currentOrder = this.shop.get('selectedOrder');
total = currentOrder.getTotal();
tax = currentOrder.getTax();
change = currentOrder.getPaidTotal() - total;
$('#receipt-summary-tax').html(tax.toFixed(2));
$('#receipt-summary-total').html(total.toFixed(2));
$('#receipt-summary-change').html(change.toFixed(2));
finishOrder: function() {
this.shop.get('selectedOrder').destroy();
},
changeSelectedOrder: function() {
if (this.currentOrderLines)
this.currentOrderLines.unbind();
this.currentOrderLines = (this.shop.get('selectedOrder')).get('orderLines');
this.currentOrderLines.bind('add', this.refresh, this);
this.currentOrderLines.bind('change', this.refresh, this);
this.currentOrderLines.bind('remove', this.refresh, this);
if (this.currentPaymentLines)
this.currentPaymentLines.unbind();
this.currentPaymentLines = (this.shop.get('selectedOrder')).get('paymentLines');
this.currentPaymentLines.bind('all', this.refresh, this);
this.refresh();
},
refresh: function() {
this.currentOrder = this.shop.get('selectedOrder');
$('.pos-receipt-container', this.$element).html(qweb_template('pos-ticket')({widget:this}));
},
});
var OrderButtonWidget = db.web.Widget.extend({
@ -1066,9 +1084,6 @@ openerp.point_of_sale = function(db) {
(this.shop.get('orders')).bind('add', this.orderAdded, this);
(this.shop.get('orders')).add(new Order);
this.numpadState = new NumpadState({
shop: this.shop
});
this.productListView = new ProductListWidget(null, {
shop: this.shop
});
@ -1081,9 +1096,11 @@ openerp.point_of_sale = function(db) {
this.paypadView.$element = $('#paypad');
this.paypadView.render_element();
this.paypadView.start();
this.numpadView = new NumpadWidget(null);
this.numpadView.$element = $('#numpad');
this.numpadView.start();
this.orderView = new OrderWidget(null, {
shop: this.shop,
numpadState: this.numpadState
});
this.orderView.$element = $('#current-order-content');
this.orderView.start();
@ -1097,14 +1114,11 @@ openerp.point_of_sale = function(db) {
shop: this.shop,
});
this.receiptView.replace($('#receipt-screen'));
this.numpadView = new NumpadWidget(null, {
state: this.numpadState
});
this.numpadView.$element = $('#numpad');
this.numpadView.start();
this.stepsView = new StepsWidget(null, {shop: this.shop});
this.stepsView.$element = $('#steps');
this.stepsView.start();
this.shop.bind('change:selectedOrder', this.changedSelectedOrder, this);
this.changedSelectedOrder();
},
createNewOrder: function() {
var newOrder;
@ -1123,6 +1137,24 @@ openerp.point_of_sale = function(db) {
newOrderButton.appendTo($('#orders'));
newOrderButton.selectOrder();
},
changedSelectedOrder: function() {
if (this.currentOrder) {
this.currentOrder.unbind('change:step', this.changedStep);
}
this.currentOrder = this.shop.get('selectedOrder');
this.currentOrder.bind('change:step', this.changedStep, this);
this.changedStep();
},
changedStep: function() {
var step = this.currentOrder.get('step');
this.orderView.setNumpadState(null);
this.paymentView.setNumpadState(null);
if (step === 'products') {
this.orderView.setNumpadState(this.numpadView.state);
} else if (step === 'payment') {
this.paymentView.setNumpadState(this.numpadView.state);
}
},
});
var App = (function() {
function App($element) {

View File

@ -66,7 +66,7 @@
<button class="input-button number-char">1</button>
<button class="input-button number-char">2</button>
<button class="input-button number-char">3</button>
<button class="mode-button selected-mode" data-mode='quantity'>Qty</button>
<button class="mode-button" data-mode='quantity'>Qty</button>
<br />
<button class="input-button number-char">4</button>
<button class="input-button number-char">5</button>
@ -97,17 +97,35 @@
<header><h2>Payment</h2></header>
<div class="pos-step-container">
<div class="pos-payment-container">
<span id="payment-due-total" class="payment-due pos-rigth-align"></span>
<br />
<table>
<tr>
<td class="paymentline-type">Total:</td>
<td class="paymentline-amount pos-rigth-align">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<span id="payment-due-total"></span>
<t t-if="currency.position == 'after'" t-esc="currency.symbol"/>
</td>
</tr>
</table>
<table id="paymentlines">
</table>
<table>
<tr>
<td class="paymentline-type">Paid:</td>
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/> <td class="paymentline-amount pos-rigth-align"><span id="payment-paid-total"></span> <t t-if="currency.position == 'after'" t-esc="currency.symbol"/></td>
<td class="paymentline-amount pos-rigth-align">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<span id="payment-paid-total"></span>
<t t-if="currency.position == 'after'" t-esc="currency.symbol"/>
</td>
</tr>
<tr>
<td class="paymentline-type">Change:</td>
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/> <td class="paymentline-amount pos-rigth-align"><span id="payment-remaining"></span> <t t-if="currency.position == 'after'" t-esc="currency.symbol"/></td>
<td class="paymentline-amount pos-rigth-align">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<span id="payment-remaining"></span>
<t t-if="currency.position == 'after'" t-esc="currency.symbol"/>
</td>
</tr>
</table>
</div>
@ -204,17 +222,7 @@
</td>
<td class="paymentline-amount pos-rigth-align">
<input type="text" t-att-value="amount.toFixed(2)" />
</td>
</t>
<t t-name="pos-receiptline-template">
<td class="receiptline-quantity pos-rigth-align">
<t t-esc="quantity.toFixed(0)"/>
</td>
<td class="receiptline-name">
<t t-esc="name"/>
</td>
<td class="receiptline-amount">
<t t-esc="format_amount((list_price * (1 - discount/100) * quantity).toFixed(2))"/>
<a href='javascript:void(0)' class='delete-payment-line'><img src="/point_of_sale/static/src/img/search_reset.gif" /></a>
</td>
</t>
<t t-name="pos-payment-button-template">
@ -232,35 +240,64 @@
<header><h2>Receipt</h2></header>
<div class="pos-step-container">
<div class="pos-receipt-container">
<div class="pos-sale-ticket">
OpenERP Point of Sale<br />
<br />
<div class="pos-rigth-align"><t t-esc="new Date().toString(Date.CultureInfo.formatPatterns.shortDate + ' ' +
Date.CultureInfo.formatPatterns.longTime)"/></div>
<br />
<table id="receiptlines"></table>
<br />
<table>
<tr><td>Total:</td><td class="pos-rigth-align">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<span id="receipt-summary-total"></span>
<t t-if="currency.position == 'after'" t-esc="currency.symbol"/>
</td></tr>
<tr><td>Tax:</td><td class="pos-rigth-align">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<span id="receipt-summary-tax"></span>
<t t-if="currency.position == 'after'" t-esc="currency.symbol"/>
</td></tr>
<tr><td>Change:</td><td class="pos-rigth-align">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<span id="receipt-summary-change"></span>
<t t-if="currency.position == 'after'" t-esc="currency.symbol"/>
</td></tr>
</table>
</div>
</div>
<button id="pos-finish-order">Next Order</button>
<div class='receipt-buttons'>
<button id="print-the-ticket">
Print</button>
<button id="pos-finish-order">Next Order</button>
</div>
</div>
</div>
</t>
<t t-name="pos-ticket">
<div class="pos-sale-ticket">
<div class="pos-rigth-align"><t t-esc="new Date().toString(Date.CultureInfo.formatPatterns.shortDate + ' ' +
Date.CultureInfo.formatPatterns.longTime)"/></div>
<br />
<t t-esc="widget.company.name"/><br />
Phone: <t t-esc="widget.company.phone || ''"/><br />
User: <t t-esc="widget.user.name"/><br />
Shop: <t t-esc="widget.shop_obj.name"/><br />
<br />
<table>
<tr t-foreach="widget.currentOrderLines.toArray()" t-as="order">
<td>
<t t-esc="order.get('name')"/>
</td>
<td class="pos-rigth-align">
<t t-esc="order.get('quantity').toFixed(0)"/>
</td>
<td class="pos-rigth-align">
<t t-esc="format_amount((order.get('list_price') * (1 - order.get('discount')/100) * order.get('quantity')).toFixed(2))"/>
</td>
</tr>
</table>
<br />
<table>
<tr><td>Tax:</td><td class="pos-rigth-align">
<t t-esc="format_amount(widget.currentOrder.getTax().toFixed(2))"/>
</td></tr>
<tr><td>Total:</td><td class="pos-rigth-align">
<t t-esc="format_amount(widget.currentOrder.getTotal().toFixed(2))"/>
</td></tr>
</table>
<br />
<table>
<tr t-foreach="widget.currentPaymentLines.toArray()" t-as="pline">
<td>
<t t-esc="pline.get('journal_id')[1]"/>
</td>
<td class="pos-rigth-align">
<t t-esc="format_amount((pline.getAmount()).toFixed(2))"/>
</td>
</tr>
</table>
<br />
<table>
<tr><td>Change:</td><td class="pos-rigth-align">
<t t-esc="format_amount((widget.currentOrder.getPaidTotal() - widget.currentOrder.getTotal()).toFixed(2))"/>
</td></tr>
</table>
</div>
</t>
</templates>