[WIP] point_of_sale: in progress of solving ]bugs in taxes and order editing
bzr revid: fva@openerp.com-20130122131801-46dyysig5e2owifa
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
function openerp_pos_models(instance, module){ //module is instance.point_of_sale
|
||||
var QWeb = instance.web.qweb;
|
||||
|
||||
function round(value,decimals){
|
||||
var mult = Math.pow(10,decimals || 0);
|
||||
return Math.round(value*mult)/mult;
|
||||
}
|
||||
|
||||
|
||||
// The PosModel contains the Point Of Sale's representation of the backend.
|
||||
// Since the PoS must work in standalone ( Without connection to the server )
|
||||
@@ -24,8 +29,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy
|
||||
this.db = new module.PosLS(); // a database used to store the products and categories
|
||||
this.db.clear('products','categories');
|
||||
this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode
|
||||
|
||||
this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode
|
||||
|
||||
// default attributes values. If null, it will be loaded below.
|
||||
this.set({
|
||||
@@ -338,20 +342,38 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
this.order = options.order;
|
||||
this.product = options.product;
|
||||
this.price = options.product.get('price');
|
||||
this.priceStr = '' + this.price;
|
||||
this.quantity = 1;
|
||||
this.quantityStr = '1';
|
||||
this.discount = 0;
|
||||
this.discountStr = '0';
|
||||
this.type = 'unit';
|
||||
this.selected = false;
|
||||
},
|
||||
// sets a discount [0,100]%
|
||||
set_discount: function(discount){
|
||||
this.discount = Math.max(0,Math.min(100,discount));
|
||||
var disc = parseFloat(discount);
|
||||
if(_.isNaN(disc)){
|
||||
return;
|
||||
}else if(disc < 0){
|
||||
this.discount = 0;
|
||||
this.discountStr = '0';
|
||||
}else if(disc > 100){
|
||||
this.discount = 100;
|
||||
this.discountStr = '100';
|
||||
}else{
|
||||
this.discount = disc;
|
||||
this.discountStr = discount;
|
||||
}
|
||||
this.trigger('change');
|
||||
},
|
||||
// returns the discount [0,100]%
|
||||
get_discount: function(){
|
||||
return this.discount;
|
||||
},
|
||||
get_discount_str: function(){
|
||||
return this.discountStr;
|
||||
},
|
||||
get_product_type: function(){
|
||||
return this.type;
|
||||
},
|
||||
@@ -359,13 +381,23 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
// product's unity of measure properties. Quantities greater than zero will not get
|
||||
// rounded to zero
|
||||
set_quantity: function(quantity){
|
||||
if(_.isNaN(quantity)){
|
||||
this.order.removeOrderline(this);
|
||||
}else if(quantity !== undefined){
|
||||
this.quantity = Math.max(0,quantity);
|
||||
var quant = parseFloat(quantity);
|
||||
if(_.isNaN(quant)){
|
||||
if(quantity === 'remove'){
|
||||
this.order.removeOrderline(this);
|
||||
}
|
||||
return;
|
||||
}else{
|
||||
if(quant < 0){
|
||||
quant = 0;
|
||||
}
|
||||
var unit = this.get_unit();
|
||||
if(unit && this.quantity > 0 ){
|
||||
this.quantity = Math.max(unit.rounding, Math.round(quantity / unit.rounding) * unit.rounding);
|
||||
if(unit){
|
||||
this.quantity = Math.max(unit.rounding, Math.round(quant / unit.rounding) * unit.rounding);
|
||||
this.quantityStr = this.quantity.toFixed(Math.ceil(Math.log(1.0 / unit.rounding) / Math.log(10)));
|
||||
}else{
|
||||
this.quantity = quant;
|
||||
this.quantityStr = '' + this.quantity;
|
||||
}
|
||||
}
|
||||
this.trigger('change');
|
||||
@@ -374,6 +406,17 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
get_quantity: function(){
|
||||
return this.quantity;
|
||||
},
|
||||
get_quantity_str: function(){
|
||||
return this.quantityStr;
|
||||
},
|
||||
get_quantity_str_with_unit: function(){
|
||||
var unit = this.get_unit();
|
||||
if(unit && unit.name !== 'Unit(s)'){
|
||||
return this.quantityStr + ' ' + unit.name;
|
||||
}else{
|
||||
return this.quantityStr;
|
||||
}
|
||||
},
|
||||
// return the unit of measure of the product
|
||||
get_unit: function(){
|
||||
var unit_id = (this.product.get('uos_id') || this.product.get('uom_id'));
|
||||
@@ -390,15 +433,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
get_product: function(){
|
||||
return this.product;
|
||||
},
|
||||
// return the base price of this product (for this orderline)
|
||||
get_price: function(){
|
||||
return this.price;
|
||||
},
|
||||
// changes the base price of the product for this orderline
|
||||
set_price: function(price){
|
||||
this.price = price;
|
||||
this.trigger('change');
|
||||
},
|
||||
// selects or deselects this orderline
|
||||
set_selected: function(selected){
|
||||
this.selected = selected;
|
||||
@@ -429,7 +463,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
export_as_JSON: function() {
|
||||
return {
|
||||
qty: this.get_quantity(),
|
||||
price_unit: this.get_price(),
|
||||
price_unit: this.get_unit_price(),
|
||||
discount: this.get_discount(),
|
||||
product_id: this.get_product().get('id'),
|
||||
};
|
||||
@@ -439,9 +473,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
return {
|
||||
quantity: this.get_quantity(),
|
||||
unit_name: this.get_unit().name,
|
||||
price: this.get_price(),
|
||||
price: this.get_unit_price(),
|
||||
discount: this.get_discount(),
|
||||
product_name: this.get_product().get('name'),
|
||||
price_display : this.get_display_price(),
|
||||
price_with_tax : this.get_price_with_tax(),
|
||||
price_without_tax: this.get_price_without_tax(),
|
||||
tax: this.get_tax(),
|
||||
@@ -449,6 +484,21 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
product_description_sale: this.get_product().get('description_sale'),
|
||||
};
|
||||
},
|
||||
// changes the base price of the product for this orderline
|
||||
set_unit_price: function(price){
|
||||
var pr = parseFloat(price);
|
||||
if(_.isNaN(pr)){
|
||||
return;
|
||||
}
|
||||
this.price = round(pr,2);
|
||||
this.trigger('change');
|
||||
},
|
||||
get_unit_price: function(){
|
||||
return this.price;
|
||||
},
|
||||
get_display_price: function(){
|
||||
return round(round(this.price * this.get_quantity(),2) * (1- this.get_discount()/100.0),2);
|
||||
},
|
||||
get_price_without_tax: function(){
|
||||
return this.get_all_prices().priceWithoutTax;
|
||||
},
|
||||
@@ -460,7 +510,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
},
|
||||
get_all_prices: function() {
|
||||
var self = this;
|
||||
var base = this.get_quantity() * this.price * (1 - (this.get_discount() / 100));
|
||||
var base = round(this.get_quantity() * this.price * (1 - (this.get_discount() / 100)),2); //FIXME en fonction de la currency
|
||||
var totalTax = base;
|
||||
var totalNoTax = base;
|
||||
|
||||
@@ -474,12 +524,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
if (tax.price_include) {
|
||||
var tmp;
|
||||
if (tax.type === "percent") {
|
||||
tmp = base - (base / (1 + tax.amount));
|
||||
tmp = base - round(base / (1 + tax.amount),2); //FIXME en fonction de la currency
|
||||
} else if (tax.type === "fixed") {
|
||||
tmp = tax.amount * self.get_quantity();
|
||||
tmp = round(tax.amount * self.get_quantity(),2);
|
||||
} else {
|
||||
throw "This type of tax is not supported by the point of sale: " + tax.type;
|
||||
}
|
||||
tmp = round(tmp,2);
|
||||
taxtotal += tmp;
|
||||
totalNoTax -= tmp;
|
||||
} else {
|
||||
@@ -491,6 +542,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
} else {
|
||||
throw "This type of tax is not supported by the point of sale: " + tax.type;
|
||||
}
|
||||
tmp = round(tmp,2);
|
||||
taxtotal += tmp;
|
||||
totalTax += tmp;
|
||||
}
|
||||
@@ -515,8 +567,16 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
},
|
||||
//sets the amount of money on this payment line
|
||||
set_amount: function(value){
|
||||
this.amount = value;
|
||||
this.trigger('change');
|
||||
if(typeof value === 'string'){
|
||||
var val = parseFloat(value);
|
||||
if(!isNaN(val)){
|
||||
this.amount = val;
|
||||
this.trigger('change');
|
||||
}
|
||||
}else{
|
||||
this.amount = value;
|
||||
this.trigger('change');
|
||||
}
|
||||
},
|
||||
// returns the amount of money on this paymentline
|
||||
get_amount: function(){
|
||||
@@ -584,7 +644,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
line.set_quantity(options.quantity);
|
||||
}
|
||||
if(options.price !== undefined){
|
||||
line.set_price(options.price);
|
||||
line.set_unit_price(options.price);
|
||||
}
|
||||
|
||||
var last_orderline = this.getLastOrderline();
|
||||
@@ -613,14 +673,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
getName: function() {
|
||||
return this.get('name');
|
||||
},
|
||||
getTotal: function() {
|
||||
getSubtotal : function(){
|
||||
return (this.get('orderLines')).reduce((function(sum, orderLine){
|
||||
return sum + orderLine.get_display_price();
|
||||
}), 0);
|
||||
},
|
||||
getTotalTaxIncluded: function() {
|
||||
return (this.get('orderLines')).reduce((function(sum, orderLine) {
|
||||
return sum + orderLine.get_price_with_tax();
|
||||
}), 0);
|
||||
},
|
||||
getDiscountTotal: function() {
|
||||
return (this.get('orderLines')).reduce((function(sum, orderLine) {
|
||||
return sum + (orderLine.get_price() * (orderLine.get_discount()/100) * orderLine.get_quantity());
|
||||
return sum + (orderLine.get_unit_price() * (orderLine.get_discount()/100) * orderLine.get_quantity());
|
||||
}), 0);
|
||||
},
|
||||
getTotalTaxExcluded: function() {
|
||||
@@ -807,7 +872,11 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
|
||||
if(!tempNewBuffer){
|
||||
this.set({ buffer: "0" });
|
||||
this.killTarget();
|
||||
if(this.get('mode') === 'quantity'){
|
||||
this.killTarget();
|
||||
}else{
|
||||
this.updateTarget();
|
||||
}
|
||||
}else{
|
||||
if (isNaN(tempNewBuffer)) {
|
||||
tempNewBuffer = "0";
|
||||
@@ -836,15 +905,20 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
mode: "quantity"
|
||||
});
|
||||
},
|
||||
resetValue: function(){
|
||||
this.set({buffer:'0'});
|
||||
},
|
||||
updateTarget: function() {
|
||||
var bufferContent, params;
|
||||
bufferContent = this.get('buffer');
|
||||
if (bufferContent && !isNaN(bufferContent)) {
|
||||
this.trigger('set_value', parseFloat(bufferContent));
|
||||
console.log('set_value ',bufferContent);
|
||||
this.trigger('set_value',bufferContent);
|
||||
}
|
||||
},
|
||||
killTarget: function(){
|
||||
this.trigger('set_value',Number.NaN);
|
||||
console.log('set_value ','remove');
|
||||
this.trigger('set_value','remove');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -942,6 +942,9 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
l.appendTo(this.$('#paymentlines'));
|
||||
this.paymentlinewidgets.push(l);
|
||||
this.$('.paymentline-amount input:last').focus();
|
||||
if(this.numpadState){
|
||||
this.numpadState.resetValue();
|
||||
}
|
||||
},
|
||||
renderElement: function() {
|
||||
this._super();
|
||||
@@ -962,7 +965,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
updatePaymentSummary: function() {
|
||||
var currentOrder = this.pos.get('selectedOrder');
|
||||
var paidTotal = currentOrder.getPaidTotal();
|
||||
var dueTotal = currentOrder.getTotal();
|
||||
var dueTotal = currentOrder.getTotalTaxIncluded();
|
||||
var remaining = dueTotal > paidTotal ? dueTotal - paidTotal : 0;
|
||||
var change = paidTotal > dueTotal ? paidTotal - dueTotal : 0;
|
||||
|
||||
@@ -998,5 +1001,4 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
this.currentPaymentLines.last().set_amount(val);
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -26,10 +26,14 @@ function openerp_pos_basewidget(instance, module){ //module is instance.point_of
|
||||
}
|
||||
|
||||
this.format_currency = function(amount){
|
||||
if(typeof amount === 'number'){
|
||||
amount = Math.round(amount*100)/100;
|
||||
amount = amount.toFixed(2);
|
||||
}
|
||||
if(this.currency.position === 'after'){
|
||||
return Math.round(amount*100)/100 + ' ' + this.currency.symbol;
|
||||
return amount + ' ' + this.currency.symbol;
|
||||
}else{
|
||||
return this.currency.symbol + ' ' + Math.round(amount*100)/100;
|
||||
return this.currency.symbol + ' ' + amount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
}else if( mode === 'discount'){
|
||||
order.getSelectedLine().set_discount(val);
|
||||
}else if( mode === 'price'){
|
||||
order.getSelectedLine().set_price(val);
|
||||
order.getSelectedLine().set_unit_price(val);
|
||||
}
|
||||
} else {
|
||||
this.pos.get('selectedOrder').destroy();
|
||||
@@ -269,7 +269,11 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
},
|
||||
update_summary: function(){
|
||||
var order = this.pos.get('selectedOrder');
|
||||
var total = order ? order.getTotal() : 0;
|
||||
var subtotal = order ? order.getSubtotal() : 0;
|
||||
var total = order ? order.getTotalTaxIncluded() : 0;
|
||||
var taxes = order ? total - order.getTotalTaxExcluded() : 0;
|
||||
this.$('.summary .value.subtotal').html(this.format_currency(subtotal));
|
||||
this.$('.summary .value.taxes').html(this.format_currency(taxes));
|
||||
this.$('.summary .value.total').html(this.format_currency(total));
|
||||
},
|
||||
set_display_mode: function(mode){
|
||||
@@ -311,14 +315,23 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
},
|
||||
changeAmount: function(event) {
|
||||
var newAmount = event.currentTarget.value;
|
||||
if (newAmount && !isNaN(newAmount)) {
|
||||
this.amount = parseFloat(newAmount);
|
||||
this.payment_line.set_amount(this.amount);
|
||||
console.log(event);
|
||||
console.log('changeAmount:',newAmount);
|
||||
if( typeof newAmmount === 'string'){
|
||||
var amount = parseFloat(newAmount);
|
||||
if(!isNaN(amount)){
|
||||
this.amount = amount;
|
||||
this.payment_line.set_amount(amount);
|
||||
}
|
||||
}else if(!isNaN(newAmount)){
|
||||
this.amount = newAmount;
|
||||
this.payment_line.set_amount(newAmount);
|
||||
}
|
||||
},
|
||||
changedAmount: function() {
|
||||
if (this.amount !== this.payment_line.get_amount())
|
||||
if (this.amount !== this.payment_line.get_amount()){
|
||||
this.renderElement();
|
||||
}
|
||||
},
|
||||
renderElement: function() {
|
||||
var self = this;
|
||||
|
||||
@@ -438,7 +438,15 @@
|
||||
</ul>
|
||||
<div class="summary">
|
||||
<span t-attf-class="line #{widget.pos.get('selectedOrder').get('orderLines').length === 0 ? 'empty' : ''}">
|
||||
<span class="label total">Total:</span> <span class="value total">0.00 €</span>
|
||||
<span class='entry subtotal'>
|
||||
<span class="label subtotal">Subtotal:</span> <span class="value subtotal">0.00 €</span>
|
||||
</span>
|
||||
<span class='entry taxes'>
|
||||
<span class="label taxes">Taxes:</span> <span class="value taxes">0.00€</span>
|
||||
</span>
|
||||
<span class='entry total'>
|
||||
<span class="label total">Total:</span> <span class="value total">0.00 €</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -506,26 +514,26 @@
|
||||
<t t-esc="widget.model.get_product().get('name')"/>
|
||||
</span>
|
||||
<span class="price">
|
||||
<t t-esc="widget.format_currency(widget.model.get_price_with_tax())"/>
|
||||
<t t-esc="widget.format_currency(widget.model.get_display_price())"/>
|
||||
</span>
|
||||
<ul class="info-list">
|
||||
<t t-if="widget.model.get_quantity() !== 1.0">
|
||||
<t t-if="widget.model.get_quantity_str() !== '1'">
|
||||
<li class="info">
|
||||
<em>
|
||||
<t t-esc="widget.model.get_quantity()" />
|
||||
<t t-esc="widget.model.get_quantity_str()" />
|
||||
</em>
|
||||
<t t-esc="widget.model.get_unit().name" />
|
||||
at
|
||||
<t t-esc="widget.format_currency(widget.model.get_price())" />
|
||||
<t t-esc="widget.format_currency(widget.model.get_unit_price())" />
|
||||
/
|
||||
<t t-esc="widget.model.get_unit().name" />
|
||||
</li>
|
||||
</t>
|
||||
<t t-if="widget.model.get_discount() > 0">
|
||||
<t t-if="widget.model.get_discount_str() !== '0'">
|
||||
<li class="info">
|
||||
With a
|
||||
<em>
|
||||
<t t-esc="widget.model.get_discount()" />%
|
||||
<t t-esc="widget.model.get_discount_str()" />%
|
||||
</em>
|
||||
discount
|
||||
</li>
|
||||
@@ -577,33 +585,33 @@
|
||||
Shop: <t t-esc="widget.shop_obj.name"/><br />
|
||||
<br />
|
||||
<table>
|
||||
<tr t-foreach="widget.currentOrderLines.toArray()" t-as="order">
|
||||
<tr t-foreach="widget.currentOrderLines.toArray()" t-as="orderline">
|
||||
<td>
|
||||
<t t-esc="order.get_product().get('name')"/>
|
||||
<t t-if="order.get_discount() > 0">
|
||||
<t t-esc="orderline.get_product().get('name')"/>
|
||||
<t t-if="orderline.get_discount() > 0">
|
||||
<div class="pos-disc-font">
|
||||
With a <t t-esc="order.get_discount()"/>% discount
|
||||
With a <t t-esc="orderline.get_discount()"/>% discount
|
||||
</div>
|
||||
</t>
|
||||
</td>
|
||||
<td class="pos-right-align">
|
||||
<t t-esc="order.get_quantity().toFixed(0)"/>
|
||||
<t t-esc="orderline.get_quantity_str_with_unit()"/>
|
||||
</td>
|
||||
<td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency(order.get_price() * (1 - order.get_discount()/100) * order.get_quantity().toFixed(2))"/>
|
||||
<t t-esc="widget.format_currency(orderline.get_display_price())"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<table>
|
||||
<tr><td>Tax:</td><td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getTax().toFixed(2))"/>
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getTax())"/>
|
||||
</td></tr>
|
||||
<tr><td>Discount:</td><td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getDiscountTotal().toFixed(2))"/>
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getDiscountTotal())"/>
|
||||
</td></tr>
|
||||
<tr class="emph"><td>Total:</td><td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getTotal().toFixed(2))"/>
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getTotalTaxIncluded())"/>
|
||||
</td></tr>
|
||||
</table>
|
||||
<br />
|
||||
@@ -613,14 +621,14 @@
|
||||
<t t-esc="pline.get_cashregister().get('journal_id')[1]"/>
|
||||
</td>
|
||||
<td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency((pline.get_amount()).toFixed(2))"/>
|
||||
<t t-esc="widget.format_currency(pline.get_amount())"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
<table>
|
||||
<tr><td>Change:</td><td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency((widget.currentOrder.getPaidTotal() - widget.currentOrder.getTotal()).toFixed(2))"/>
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getPaidTotal() - widget.currentOrder.getTotalTaxIncluded())"/>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user