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.
320 lines
12 KiB
320 lines
12 KiB
/** ***************************************************************************
|
|
Copyright (C) 2017 - Today: GRAP (http://www.grap.coop)
|
|
@author: Sylvain LE GAL (https://twitter.com/legalsylvain)
|
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
******************************************************************************/
|
|
|
|
odoo.define('pos_picking_load.widget', function (require) {
|
|
"use strict";
|
|
|
|
var core = require('web.core');
|
|
var framework = require('web.framework');
|
|
var rpc = require('web.rpc');
|
|
|
|
var gui = require('point_of_sale.gui');
|
|
var screens = require('point_of_sale.screens');
|
|
|
|
var QWeb = core.qweb;
|
|
var _t = core._t;
|
|
|
|
|
|
/** **********************************************************************
|
|
New ScreenWidget LoadPickingScreenWidget:
|
|
* On show, display all pickings;
|
|
* on click on a picking, display the content;
|
|
* on click on 'validate', allow to use this picking;
|
|
* on click on 'cancel', display the preview screen;
|
|
*/
|
|
var LoadPickingScreenWidget = screens.ScreenWidget.extend({
|
|
template: 'LoadPickingScreenWidget',
|
|
auto_back: true,
|
|
|
|
current_picking_id: false,
|
|
current_picking_name: false,
|
|
|
|
show: function () {
|
|
var self = this;
|
|
this._super();
|
|
|
|
this.renderElement();
|
|
|
|
// Bind functions
|
|
this.$('.back').click(_.bind(this.clickBackButton, this));
|
|
this.$('.validate').click(_.bind(this.clickValidateButton, this));
|
|
|
|
// Initialize display
|
|
this.$('.validate').hide();
|
|
|
|
this.search_pickings();
|
|
|
|
this.$('.picking-list-contents').delegate(
|
|
'.picking-line', 'click', function (event) {
|
|
self.select_picking(event);
|
|
});
|
|
|
|
// Handle search
|
|
var search_timeout = null;
|
|
this.$('.searchbox input').on('keyup', function () {
|
|
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();
|
|
});
|
|
|
|
},
|
|
|
|
select_picking: function (event) {
|
|
var origin_picking_id = parseInt(
|
|
event.target.parentNode.dataset.pickingId, 10);
|
|
var self = this;
|
|
this.current_picking_data = false;
|
|
this.$('span.button.validate').hide();
|
|
this.$('.picking-list .highlight').removeClass('highlight');
|
|
|
|
framework.blockUI();
|
|
var params = {
|
|
model: 'stock.picking',
|
|
method: 'load_picking_for_pos',
|
|
args: [origin_picking_id],
|
|
};
|
|
rpc.query(params)
|
|
.then(function (picking_data) {
|
|
framework.unblockUI();
|
|
if (self.check_picking(picking_data)) {
|
|
self.current_picking_data = picking_data;
|
|
$(event.target.parentNode).addClass('highlight');
|
|
self.$('span.button.validate').show();
|
|
}
|
|
}).fail(function (error, fail_event) {
|
|
framework.unblockUI();
|
|
self.handle_errors(error, fail_event);
|
|
});
|
|
},
|
|
|
|
check_picking: function (picking_data) {
|
|
var self = this;
|
|
|
|
var picking_selectable = true;
|
|
|
|
// Forbid POS Order loading if some products are unknown
|
|
var unknown_products = [];
|
|
|
|
picking_data.line_ids.forEach(function (picking_line_data) {
|
|
var line_name = picking_line_data.name.replace('\n', ' ');
|
|
var product = self.pos.db.get_product_by_id(
|
|
picking_line_data.product_id);
|
|
if (_.isUndefined(product)) {
|
|
unknown_products.push(line_name);
|
|
}
|
|
});
|
|
if (unknown_products.length > 0) {
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
'title': _t('Unknown Products'),
|
|
'body': _t(
|
|
"Unable to load some picking lines because the" +
|
|
" products are not available in the POS" +
|
|
" cache.\n\n" +
|
|
"Please check that lines :\n\n * ") +
|
|
unknown_products.join("; \n *"),
|
|
});
|
|
picking_selectable = false;
|
|
}
|
|
|
|
// Check if the partner is unknown
|
|
var partner = self.pos.db.get_partner_by_id(
|
|
picking_data.partner_id);
|
|
|
|
if (_.isUndefined(partner)) {
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
'title': _t('Unknown Partner'),
|
|
'body': _t(
|
|
"Unable to load this picking because the partner" +
|
|
" is not known in the Point Of Sale" +
|
|
" as a customer"),
|
|
});
|
|
picking_selectable = false;
|
|
}
|
|
|
|
// Check if the picking is still loaded in another PoS tab
|
|
self.pos.db.get_unpaid_orders().forEach(function (order) {
|
|
if (order.origin_picking_id === picking_data.id) {
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
'title': _t('Picking Still Loaded'),
|
|
'body': _t(
|
|
"Unable to load this picking because it has" +
|
|
" been loaded in another draft" +
|
|
" PoS Order :\n\n") +
|
|
order.name,
|
|
});
|
|
picking_selectable = false;
|
|
}
|
|
});
|
|
|
|
// Check if the picking has still been handled in another PoS Order
|
|
self.pos.db.get_orders().forEach(function (order) {
|
|
if (order.origin_picking_id === picking_data.id) {
|
|
self.gui.show_popup(
|
|
'error-traceback', {
|
|
'title': _t('Picking Still Loaded'),
|
|
'body': _t(
|
|
"Unable to load this picking because it has" +
|
|
" been loaded in another confirmed" +
|
|
" PoS Order :\n\n") +
|
|
order.name,
|
|
});
|
|
picking_selectable = false;
|
|
}
|
|
});
|
|
return picking_selectable;
|
|
},
|
|
|
|
perform_search: function (query) {
|
|
this.search_pickings(query);
|
|
},
|
|
|
|
clear_search: function () {
|
|
this.search_pickings();
|
|
this.$('.searchbox input')[0].value = '';
|
|
this.$('.searchbox input').focus();
|
|
},
|
|
|
|
search_pickings: function (query) {
|
|
var self = this;
|
|
var params = {
|
|
model: 'stock.picking',
|
|
method: 'search_pickings_for_pos',
|
|
args: [query || '', this.pos.pos_session.id],
|
|
};
|
|
rpc.query(params)
|
|
.then(function (result) {
|
|
self.render_list(result);
|
|
}).fail(function (error, event) {
|
|
self.handle_errors(error, event);
|
|
});
|
|
},
|
|
|
|
render_list: function (pickings) {
|
|
var contents = this.$el[0].querySelector('.picking-list-contents');
|
|
contents.innerHTML = "";
|
|
var line_list = document.createDocumentFragment();
|
|
_.each(pickings, function (picking) {
|
|
var picking_line_html = QWeb.render(
|
|
'LoadPickingLine', {widget: this, picking:picking});
|
|
var picking_line = document.createElement('tbody');
|
|
picking_line.innerHTML = picking_line_html;
|
|
picking_line = picking_line.childNodes[1];
|
|
line_list.appendChild(picking_line);
|
|
});
|
|
contents.appendChild(line_list);
|
|
},
|
|
|
|
// User Event
|
|
clickBackButton: function () {
|
|
this.gui.back();
|
|
},
|
|
|
|
clickValidateButton: function () {
|
|
var order = this.pos.get_order();
|
|
order.load_from_picking_data(this.current_picking_data);
|
|
this.gui.show_screen('products');
|
|
},
|
|
|
|
handle_errors: function (error, event) {
|
|
var self = this;
|
|
if (parseInt(error.code, 10) === 200) {
|
|
// Business Logic Error, not a connection problem
|
|
self.gui.show_popup('error-traceback', {
|
|
'title': error.data.message || _t("Server Error"),
|
|
'body': error.data.debug || _t(
|
|
"The server encountered an error while" +
|
|
" receiving your order."),
|
|
});
|
|
} else {
|
|
self.gui.show_popup('error', {
|
|
'title': _t('Connection error'),
|
|
'body': _t(
|
|
"Can not execute this action because the POS" +
|
|
" is currently offline"),
|
|
});
|
|
}
|
|
event.preventDefault();
|
|
},
|
|
});
|
|
|
|
gui.define_screen({
|
|
'name': 'load_picking',
|
|
'widget': LoadPickingScreenWidget,
|
|
'condition': function () {
|
|
return this.pos.config.iface_load_picking;
|
|
},
|
|
});
|
|
|
|
|
|
/** **********************************************************************
|
|
New Widget LoadPickingButtonWidget:
|
|
* On click, display a new screen to select a picking;
|
|
*/
|
|
var LoadPickingButtonWidget = screens.ActionButtonWidget.extend({
|
|
template: 'LoadPickingButtonWidget',
|
|
|
|
button_click: function () {
|
|
if (_.isUndefined(this.pos.get_order().get('origin_picking_id'))) {
|
|
this.gui.show_screen('load_picking');
|
|
} else {
|
|
this.gui.show_popup('error', {
|
|
'title': _t('Pending Picking'),
|
|
'body': _t(
|
|
"A picking is still loaded. You can not load" +
|
|
" another picking. Please create a new order."),
|
|
});
|
|
}
|
|
},
|
|
|
|
button_text: function () {
|
|
if (! this.pos.get_order() ||
|
|
_.isUndefined(
|
|
this.pos.get_order().get('origin_picking_id'))) {
|
|
return _t("Load Picking");
|
|
}
|
|
return this.pos.get_order().get('origin_picking_name');
|
|
},
|
|
|
|
is_visible: function () {
|
|
if (this.pos.get_order()) {
|
|
return (
|
|
this.pos.get_order().get_orderlines().length === 0 ||
|
|
! _.isUndefined(
|
|
this.pos.get_order().get('origin_picking_id')));
|
|
}
|
|
return false;
|
|
},
|
|
|
|
});
|
|
|
|
screens.define_action_button({
|
|
'name': 'load_picking',
|
|
'widget': LoadPickingButtonWidget,
|
|
'condition': function () {
|
|
return this.pos.config.iface_load_picking;
|
|
},
|
|
});
|
|
|
|
screens.OrderWidget.include({
|
|
update_summary: function () {
|
|
this._super();
|
|
if (this.getParent().action_buttons &&
|
|
this.getParent().action_buttons.load_picking) {
|
|
this.getParent().action_buttons.load_picking.renderElement();
|
|
}
|
|
},
|
|
});
|
|
|
|
});
|