You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
14 KiB
385 lines
14 KiB
/******************************************************************************
|
|
* Point Of Sale - Product Template module for Odoo
|
|
* Copyright (C) 2014-Today Akretion (http://www.akretion.com)
|
|
* @author Sylvain Calador (sylvain.calador@akretion.com)
|
|
* @author Sylvain Le Gal (https://twitter.com/legalsylvain)
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*****************************************************************************/
|
|
|
|
odoo.define('pos_order_load', function (require) {
|
|
"use strict";
|
|
|
|
var PosBaseWidget = require('point_of_sale.BaseWidget');
|
|
var chrome = require('point_of_sale.chrome');
|
|
var gui = require('point_of_sale.gui');
|
|
var models = require('point_of_sale.models');
|
|
var screens = require('point_of_sale.screens');
|
|
var rpc = require('web.rpc');
|
|
|
|
var utils = require('web.utils');
|
|
var round_pr = utils.round_precision;
|
|
|
|
var core = require('web.core');
|
|
var QWeb = core.qweb;
|
|
var _t = core._t;
|
|
|
|
|
|
/*************************************************************************
|
|
Extend Model Order:
|
|
* Add getter and setter function for field 'order_id';
|
|
*/
|
|
|
|
var _super_order = models.Order.prototype;
|
|
models.Order = models.Order.extend({
|
|
|
|
|
|
set_order_id: function(id) {
|
|
this.set({
|
|
order_id: id,
|
|
});
|
|
},
|
|
|
|
get_order_id: function() {
|
|
return this.get('order_id');
|
|
},
|
|
|
|
});
|
|
|
|
/*************************************************************************
|
|
New Widget LoadButtonWidget:
|
|
* On click, display a new screen to select draft orders;
|
|
*/
|
|
var LoadButtonWidget = PosBaseWidget.extend({
|
|
template: 'LoadButtonWidget',
|
|
|
|
renderElement: function() {
|
|
var self = this;
|
|
this._super();
|
|
this.$el.click(function(){
|
|
self.gui.show_screen('orderlist');
|
|
});
|
|
},
|
|
});
|
|
|
|
/*************************************************************************
|
|
New Widget SaveButtonWidget:
|
|
* On click, save the current draft order;
|
|
*/
|
|
var SaveButtonWidget = PosBaseWidget.extend({
|
|
template: 'SaveButtonWidget',
|
|
|
|
renderElement: function() {
|
|
var self = this;
|
|
this._super();
|
|
this.$el.click(function(){
|
|
self.gui.show_popup('confirm',{
|
|
'title': _t('Save The current Order ?'),
|
|
'body': _t('This operation will save the current order in a draft state. You\'ll have to mark it as paid after.'),
|
|
confirm: function(){
|
|
var currentOrder = this.pos.get('selectedOrder');
|
|
this.pos.push_order(currentOrder);
|
|
self.pos.get('selectedOrder').destroy();
|
|
},
|
|
});
|
|
});
|
|
},
|
|
});
|
|
|
|
|
|
/*************************************************************************
|
|
Extend PosWidget:
|
|
* Create new screen;
|
|
* Add load and save button;
|
|
*/
|
|
chrome.Chrome.include({
|
|
build_widgets: function() {
|
|
this._super();
|
|
|
|
this.load_button = new LoadButtonWidget(this, {});
|
|
this.load_button.appendTo(this.$('div.order-empty'));
|
|
|
|
this.save_button = new SaveButtonWidget(this, {});
|
|
|
|
},
|
|
});
|
|
|
|
|
|
/*************************************************************************
|
|
* Extend OrderWidget:
|
|
*/
|
|
screens.OrderWidget.include({
|
|
renderElement: function(scrollbottom){
|
|
this._super(scrollbottom);
|
|
if (this.chrome.load_button) {
|
|
this.chrome.load_button.appendTo(
|
|
this.chrome.$('div.order-empty')
|
|
);
|
|
}
|
|
if (this.pos.get_order()) {
|
|
if (this.chrome.save_button && (this.pos.get_order().get_orderlines().length > 0)) {
|
|
this.chrome.save_button.appendTo(
|
|
this.chrome.$('div.summary')
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
/*************************************************************************
|
|
* New ScreenWidget OrderListScreenWidget:
|
|
* On show, display all draft orders;
|
|
* on click on an order, display the content;
|
|
* on click on 'validate', allow to use this POS Order;
|
|
* on click on 'cancel', display the preview screen;
|
|
*/
|
|
//
|
|
var OrderListScreenWidget = screens.ScreenWidget.extend({
|
|
template: 'OrderListScreenWidget',
|
|
show_leftpane: true,
|
|
model: 'pos.order',
|
|
current_order_id: 0,
|
|
|
|
init: function(parent, options){
|
|
this._super(parent, options);
|
|
},
|
|
|
|
reset_order: function(order) {
|
|
order.set_client(undefined);
|
|
order.set_order_id(undefined);
|
|
order.orderlines.reset();
|
|
return order;
|
|
},
|
|
|
|
start: function() {
|
|
var self = this;
|
|
this._super();
|
|
this.$el.find('span.button.back').click(function(){
|
|
var order = self.pos.get('selectedOrder');
|
|
self.reset_order(order);
|
|
self.chrome.screens.products.order_widget.change_selected_order();
|
|
self.gui.show_screen('products');
|
|
});
|
|
this.$el.find('span.button.validate').click(function(){
|
|
var orderModel = rpc.query({
|
|
model: 'pos.order',
|
|
method: 'unlink',
|
|
args: [self.current_order_id],
|
|
});
|
|
return orderModel.then(function (result) {
|
|
self.gui.show_screen('products');
|
|
}).fail(function (error, event){
|
|
if (parseInt(error.code) === 200) {
|
|
// Business Logic Error, not a connection problem
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
message: error.data.message,
|
|
comment: error.data.debug
|
|
});
|
|
}
|
|
else{
|
|
self.gui.show_popup('error',{
|
|
message: _t('Connection error'),
|
|
comment: _t('Can not load the Selected Order because the POS is currently offline'),
|
|
});
|
|
}
|
|
event.preventDefault();
|
|
});
|
|
});
|
|
|
|
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);
|
|
},70);
|
|
|
|
});
|
|
|
|
this.$('.searchbox .search-clear').click(function(){
|
|
self.clear_search();
|
|
});
|
|
|
|
},
|
|
|
|
// to override if necessary
|
|
add_product_attribute: function(product, key, orderline){
|
|
return product;
|
|
},
|
|
|
|
load_order_fields: function(order, fields) {
|
|
order.set_order_id(fields.id);
|
|
var partner = this.pos.db.get_partner_by_id(
|
|
fields.partner_id);
|
|
order.set_client(partner || undefined);
|
|
return order;
|
|
},
|
|
|
|
prepare_orderline_options: function(orderline) {
|
|
return {
|
|
quantity: orderline.qty,
|
|
price: orderline.price_unit,
|
|
discount: orderline.discount,
|
|
};
|
|
},
|
|
|
|
load_order: function(order_id) {
|
|
var self = this;
|
|
var orderModel = rpc.query({
|
|
model: this.model,
|
|
method: 'load_order',
|
|
args: [order_id],
|
|
});
|
|
return orderModel.then(function (result) {
|
|
var order = self.pos.get('selectedOrder');
|
|
order = self.load_order_fields(order, result);
|
|
order.orderlines.reset();
|
|
var orderlines = result.orderlines || [];
|
|
var unknown_products = [];
|
|
for (var i=0, len=orderlines.length; i<len; i++) {
|
|
var orderline = orderlines[i];
|
|
var product_id = orderline.product_id[0];
|
|
var product_name = orderline.product_id[1];
|
|
var product = self.pos.db.get_product_by_id(product_id);
|
|
if (_.isUndefined(product)) {
|
|
unknown_products.push(product_name);
|
|
continue;
|
|
}
|
|
|
|
for (var key in orderline) {
|
|
if (!key.indexOf('product__')) {
|
|
product = self.add_product_attribute(
|
|
product, key, orderline
|
|
);
|
|
}
|
|
}
|
|
|
|
order.add_product(product,
|
|
self.prepare_orderline_options(orderline)
|
|
);
|
|
var last_orderline = order.get_last_orderline();
|
|
last_orderline = jQuery.extend(last_orderline, orderline);
|
|
}
|
|
// Forbid POS Order loading if some products are unknown
|
|
if (unknown_products.length > 0){
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
message: _t('Unknown Products'),
|
|
comment: _t('Unable to load some order lines because the ' +
|
|
'products are not available in the POS cache.\n\n' +
|
|
'Please check that lines :\n\n * ') + unknown_products.join("; \n *")
|
|
});
|
|
self.$el.find('span.button.validate').hide();
|
|
}
|
|
else{
|
|
self.$el.find('span.button.validate').show();
|
|
}
|
|
|
|
}).fail(function (error, event){
|
|
if (parseInt(error.code) === 200) {
|
|
// Business Logic Error, not a connection problem
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
message: error.data.message,
|
|
comment: error.data.debug
|
|
});
|
|
}
|
|
else{
|
|
self.gui.show_popup('error',{
|
|
message: _t('Connection error'),
|
|
comment: _t('Can not execute this action because the POS is currently offline'),
|
|
});
|
|
}
|
|
event.preventDefault();
|
|
});
|
|
},
|
|
|
|
load_orders: function(query) {
|
|
var self = this;
|
|
var orderModel = rpc.query({
|
|
model: this.model,
|
|
method: 'search_read_orders',
|
|
args: [query || ''],
|
|
})
|
|
return orderModel.then(function (result) {
|
|
self.render_list(result);
|
|
}).fail(function (error, event){
|
|
if (parseInt(error.code) === 200) {
|
|
// Business Logic Error, not a connection problem
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
message: error.data.message,
|
|
comment: error.data.debug
|
|
}
|
|
);
|
|
}
|
|
else{
|
|
self.gui.show_popup('error',{
|
|
message: _t('Connection error'),
|
|
comment: _t('Can not execute this action because the POS is currently offline'),
|
|
});
|
|
}
|
|
event.preventDefault();
|
|
});
|
|
},
|
|
|
|
show: function() {
|
|
this._super();
|
|
if (this.gui.get_current_screen() == 'orderlist') {
|
|
this.load_orders();
|
|
}
|
|
},
|
|
|
|
on_click_draft_order: function(event){
|
|
this.$('.order-list .highlight').removeClass('highlight');
|
|
this.current_order_id = parseInt(event.target.parentNode.dataset.orderId);
|
|
this.load_order(this.current_order_id);
|
|
$(event.target.parentNode).addClass('highlight');
|
|
},
|
|
|
|
render_list: function(orders){
|
|
var self = this;
|
|
var contents = this.$el[0].querySelector('.order-list-contents');
|
|
contents.innerHTML = "";
|
|
for (var i = 0, len = orders.length; i < len; i++){
|
|
var order = orders[i];
|
|
var orderline_html = QWeb.render('LoadOrderLine',
|
|
{widget: this, order:orders[i]});
|
|
var orderline = document.createElement('tbody');
|
|
orderline.innerHTML = orderline_html;
|
|
orderline = orderline.childNodes[1];
|
|
orderline.addEventListener('click', this.on_click_draft_order);
|
|
contents.appendChild(orderline);
|
|
}
|
|
},
|
|
|
|
perform_search: function(query){
|
|
this.load_orders(query);
|
|
},
|
|
|
|
clear_search: function(){
|
|
this.load_orders();
|
|
this.$('.searchbox input')[0].value = '';
|
|
this.$('.searchbox input').focus();
|
|
},
|
|
|
|
});
|
|
gui.define_screen({'name': 'orderlist', 'widget': OrderListScreenWidget});
|
|
return {
|
|
LoadButtonButton: LoadButtonWidget,
|
|
SaveButtonButton: SaveButtonWidget,
|
|
OrderListScreenWidget: OrderListScreenWidget,
|
|
};
|
|
});
|