/****************************************************************************** * 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 . *****************************************************************************/ 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 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, }; });