|
@@ -0,0 +1,437 @@
|
|
|
+function pos_screens(instance, module){ //module is instance.point_of_sale
|
|
|
+ var QWeb = instance.web.qweb,
|
|
|
+ _t = instance.web._t;
|
|
|
+
|
|
|
+ var round_pr = instance.web.round_precision
|
|
|
+
|
|
|
+ module.ClientListScreenWidget = module.ScreenWidget.extend({
|
|
|
+ template: 'ClientListScreenWidget',
|
|
|
+
|
|
|
+ init: function(parent, options){
|
|
|
+ this._super(parent, options);
|
|
|
+ },
|
|
|
+
|
|
|
+ show_leftpane: false,
|
|
|
+
|
|
|
+ auto_back: true,
|
|
|
+
|
|
|
+ show: function(){
|
|
|
+ var self = this;
|
|
|
+ this._super();
|
|
|
+
|
|
|
+ this.renderElement();
|
|
|
+ this.details_visible = false;
|
|
|
+ this.old_client = this.pos.get('selectedOrder').get('client');
|
|
|
+ this.new_client = this.old_client;
|
|
|
+
|
|
|
+ this.$('.back').click(function(){
|
|
|
+ self.pos_widget.screen_selector.back();
|
|
|
+ });
|
|
|
+
|
|
|
+ this.$('.next').click(function(){
|
|
|
+ self.save_changes();
|
|
|
+ self.pos_widget.screen_selector.back();
|
|
|
+ });
|
|
|
+
|
|
|
+ this.$('.new-customer').click(function(){
|
|
|
+ self.display_client_details('edit',{
|
|
|
+ 'country_id': self.pos.company.country_id,
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ var partners = this.pos.db.get_partners_sorted(1000);
|
|
|
+ this.render_list(partners);
|
|
|
+
|
|
|
+ this.reload_partners();
|
|
|
+
|
|
|
+ if( this.old_client ){
|
|
|
+ this.display_client_details('show',this.old_client,0);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$('.client-list-contents').delegate('.client-line','click',function(event){
|
|
|
+ self.line_select(event,$(this),parseInt($(this).data('id')));
|
|
|
+ });
|
|
|
+
|
|
|
+ var search_timeout = null;
|
|
|
+
|
|
|
+ if(this.pos.config.iface_vkeyboard && this.pos_widget.onscreen_keyboard){
|
|
|
+ this.pos_widget.onscreen_keyboard.connect(this.$('.searchbox input'));
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$('.searchbox input').on('keyup',function(event){
|
|
|
+ clearTimeout(search_timeout);
|
|
|
+
|
|
|
+ var query = this.value;
|
|
|
+
|
|
|
+ search_timeout = setTimeout(function(){
|
|
|
+ self.perform_search(query,event.which === 13);
|
|
|
+ },70);
|
|
|
+ });
|
|
|
+
|
|
|
+ this.$('.searchbox .search-clear').click(function(){
|
|
|
+ self.clear_search();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ barcode_client_action: function(code){
|
|
|
+ if (this.editing_client) {
|
|
|
+ this.$('.detail.barcode').val(code.code);
|
|
|
+ } else if (this.pos.db.get_partner_by_ean13(code.code)) {
|
|
|
+ this.display_client_details('show',this.pos.db.get_partner_by_ean13(code.code));
|
|
|
+ }
|
|
|
+ },
|
|
|
+ perform_search: function(query, associate_result){
|
|
|
+ if(query){
|
|
|
+ var customers = this.pos.db.search_partner(query);
|
|
|
+ this.display_client_details('hide');
|
|
|
+ if ( associate_result && customers.length === 1){
|
|
|
+ this.new_client = customers[0];
|
|
|
+ this.save_changes();
|
|
|
+ this.pos_widget.screen_selector.back();
|
|
|
+ }
|
|
|
+ this.render_list(customers);
|
|
|
+ }else{
|
|
|
+ var customers = this.pos.db.get_partners_sorted();
|
|
|
+ this.render_list(customers);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ clear_search: function(){
|
|
|
+ var customers = this.pos.db.get_partners_sorted(1000);
|
|
|
+ this.render_list(customers);
|
|
|
+ this.$('.searchbox input')[0].value = '';
|
|
|
+ this.$('.searchbox input').focus();
|
|
|
+ },
|
|
|
+ render_list: function(partners){
|
|
|
+ var contents = this.$el[0].querySelector('.client-list-contents');
|
|
|
+ contents.innerHTML = "";
|
|
|
+ for(var i = 0, len = Math.min(partners.length,1000); i < len; i++){
|
|
|
+ var partner = partners[i];
|
|
|
+ var clientline_html = QWeb.render('ClientLine',{widget: this, partner:partners[i]});
|
|
|
+ var clientline = document.createElement('tbody');
|
|
|
+ clientline.innerHTML = clientline_html;
|
|
|
+ clientline = clientline.childNodes[1];
|
|
|
+
|
|
|
+ if( partners === this.new_client ){
|
|
|
+ clientline.classList.add('highlight');
|
|
|
+ }else{
|
|
|
+ clientline.classList.remove('highlight');
|
|
|
+ }
|
|
|
+
|
|
|
+ contents.appendChild(clientline);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ save_changes: function(){
|
|
|
+ if( this.has_client_changed() ){
|
|
|
+ this.pos.get('selectedOrder').set_client(this.new_client);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ has_client_changed: function(){
|
|
|
+ if( this.old_client && this.new_client ){
|
|
|
+ return this.old_client.id !== this.new_client.id;
|
|
|
+ }else{
|
|
|
+ return !!this.old_client !== !!this.new_client;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ toggle_save_button: function(){
|
|
|
+ var $button = this.$('.button.next');
|
|
|
+ if (this.editing_client) {
|
|
|
+ $button.addClass('oe_hidden');
|
|
|
+ return;
|
|
|
+ } else if( this.new_client ){
|
|
|
+ if( !this.old_client){
|
|
|
+ $button.text(_t('Set Customer'));
|
|
|
+ }else{
|
|
|
+ $button.text(_t('Change Customer'));
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ $button.text(_t('Deselect Customer'));
|
|
|
+ }
|
|
|
+ $button.toggleClass('oe_hidden',!this.has_client_changed());
|
|
|
+ },
|
|
|
+ line_select: function(event,$line,id){
|
|
|
+ var partner = this.pos.db.get_partner_by_id(id);
|
|
|
+ this.$('.client-list .lowlight').removeClass('lowlight');
|
|
|
+ if ( $line.hasClass('highlight') ){
|
|
|
+ $line.removeClass('highlight');
|
|
|
+ $line.addClass('lowlight');
|
|
|
+ this.display_client_details('hide',partner);
|
|
|
+ this.new_client = null;
|
|
|
+ this.toggle_save_button();
|
|
|
+ }else{
|
|
|
+ this.$('.client-list .highlight').removeClass('highlight');
|
|
|
+ $line.addClass('highlight');
|
|
|
+ var y = event.pageY - $line.parent().offset().top
|
|
|
+ this.display_client_details('show',partner,y);
|
|
|
+ this.new_client = partner;
|
|
|
+ this.toggle_save_button();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ partner_icon_url: function(id){
|
|
|
+ return '/web/binary/image?model=res.partner&id='+id+'&field=image_small';
|
|
|
+ },
|
|
|
+
|
|
|
+ // ui handle for the 'edit selected customer' action
|
|
|
+ edit_client_details: function(partner) {
|
|
|
+ this.display_client_details('edit',partner);
|
|
|
+ },
|
|
|
+
|
|
|
+ // ui handle for the 'cancel customer edit changes' action
|
|
|
+ undo_client_details: function(partner) {
|
|
|
+ if (!partner.id) {
|
|
|
+ this.display_client_details('hide');
|
|
|
+ } else {
|
|
|
+ this.display_client_details('show',partner);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // what happens when we save the changes on the client edit form -> we fetch the fields, sanitize them,
|
|
|
+ // send them to the backend for update, and call saved_client_details() when the server tells us the
|
|
|
+ // save was successfull.
|
|
|
+ save_client_details: function(partner) {
|
|
|
+ var self = this;
|
|
|
+
|
|
|
+ var fields = {}
|
|
|
+ this.$('.client-details-contents .detail').each(function(idx,el){
|
|
|
+ fields[el.name] = el.value;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!fields.name) {
|
|
|
+ this.pos_widget.screen_selector.show_popup('error',{
|
|
|
+ message: _t('A Customer Name Is Required'),
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.uploaded_picture) {
|
|
|
+ fields.image = this.uploaded_picture;
|
|
|
+ }
|
|
|
+
|
|
|
+ fields.id = partner.id || false;
|
|
|
+ fields.country_id = fields.country_id || false;
|
|
|
+ fields.ean13 = fields.ean13 ? this.pos.barcode_reader.sanitize_ean(fields.ean13) : false;
|
|
|
+
|
|
|
+ new instance.web.Model('res.partner').call('create_from_ui',[fields]).then(function(partner_id){
|
|
|
+ self.saved_client_details(partner_id, fields);
|
|
|
+ },function(err,event){
|
|
|
+ event.preventDefault();
|
|
|
+ self.pos_widget.screen_selector.show_popup('error',{
|
|
|
+ 'message':_t('Error: Could not Save Changes'),
|
|
|
+ 'comment':_t('Your Internet connection is probably down.'),
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // what happens when we've just pushed modifications for a partner of id partner_id
|
|
|
+ saved_client_details: function(partner_id, fields){
|
|
|
+ var self = this;
|
|
|
+ this.reload_partners().then(function(){
|
|
|
+ var partner = self.pos.db.get_partner_by_id(partner_id);
|
|
|
+ partner['ruc'] = fields.ruc;
|
|
|
+ if (partner) {
|
|
|
+ self.new_client = partner;
|
|
|
+ self.toggle_save_button();
|
|
|
+ self.display_client_details('show',partner);
|
|
|
+ } else {
|
|
|
+ // should never happen, because create_from_ui must return the id of the partner it
|
|
|
+ // has created, and reload_partner() must have loaded the newly created partner.
|
|
|
+ self.display_client_details('hide');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // resizes an image, keeping the aspect ratio intact,
|
|
|
+ // the resize is useful to avoid sending 12Mpixels jpegs
|
|
|
+ // over a wireless connection.
|
|
|
+ resize_image_to_dataurl: function(img, maxwidth, maxheight, callback){
|
|
|
+ img.onload = function(){
|
|
|
+ var png = new Image();
|
|
|
+ var canvas = document.createElement('canvas');
|
|
|
+ var ctx = canvas.getContext('2d');
|
|
|
+ var ratio = 1;
|
|
|
+
|
|
|
+ if (img.width > maxwidth) {
|
|
|
+ ratio = maxwidth / img.width;
|
|
|
+ }
|
|
|
+ if (img.height * ratio > maxheight) {
|
|
|
+ ratio = maxheight / img.height;
|
|
|
+ }
|
|
|
+ var width = Math.floor(img.width * ratio);
|
|
|
+ var height = Math.floor(img.height * ratio);
|
|
|
+
|
|
|
+ canvas.width = width;
|
|
|
+ canvas.height = height;
|
|
|
+ ctx.drawImage(img,0,0,width,height);
|
|
|
+
|
|
|
+ var dataurl = canvas.toDataURL();
|
|
|
+ callback(dataurl);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // Loads and resizes a File that contains an image.
|
|
|
+ // callback gets a dataurl in case of success.
|
|
|
+ load_image_file: function(file, callback){
|
|
|
+ var self = this;
|
|
|
+ if (!file.type.match(/image.*/)) {
|
|
|
+ this.pos_widget.screen_selector.show_popup('error',{
|
|
|
+ message:_t('Unsupported File Format'),
|
|
|
+ comment:_t('Only web-compatible Image formats such as .png or .jpeg are supported'),
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var reader = new FileReader();
|
|
|
+ reader.onload = function(event){
|
|
|
+ var dataurl = event.target.result;
|
|
|
+ var img = new Image();
|
|
|
+ img.src = dataurl;
|
|
|
+ self.resize_image_to_dataurl(img,800,600,callback);
|
|
|
+ }
|
|
|
+ reader.onerror = function(){
|
|
|
+ self.pos_widget.screen_selector.show_popup('error',{
|
|
|
+ message:_t('Could Not Read Image'),
|
|
|
+ comment:_t('The provided file could not be read due to an unknown error'),
|
|
|
+ });
|
|
|
+ };
|
|
|
+ reader.readAsDataURL(file);
|
|
|
+ },
|
|
|
+
|
|
|
+ // This fetches partner changes on the server, and in case of changes,
|
|
|
+ // rerenders the affected views
|
|
|
+ reload_partners: function(){
|
|
|
+ var self = this;
|
|
|
+ return this.pos.load_new_partners().then(function(){
|
|
|
+ self.render_list(self.pos.db.get_partners_sorted(1000));
|
|
|
+
|
|
|
+ // update the currently assigned client if it has been changed in db.
|
|
|
+ var curr_client = self.pos.get_order().get_client();
|
|
|
+ if (curr_client) {
|
|
|
+ self.pos.get_order().set_client(self.pos.db.get_partner_by_id(curr_client.id));
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // Shows,hides or edit the customer details box :
|
|
|
+ // visibility: 'show', 'hide' or 'edit'
|
|
|
+ // partner: the partner object to show or edit
|
|
|
+ // clickpos: the height of the click on the list (in pixel), used
|
|
|
+ // to maintain consistent scroll.
|
|
|
+ display_client_details: function(visibility,partner,clickpos){
|
|
|
+ var self = this;
|
|
|
+ var contents = this.$('.client-details-contents');
|
|
|
+ var parent = this.$('.client-list').parent();
|
|
|
+ var scroll = parent.scrollTop();
|
|
|
+ var height = contents.height();
|
|
|
+
|
|
|
+ contents.off('click','.button.edit');
|
|
|
+ contents.off('click','.button.save');
|
|
|
+ contents.off('click','.button.undo');
|
|
|
+ contents.on('click','.button.edit',function(){ self.edit_client_details(partner); });
|
|
|
+ contents.on('click','.button.save',function(){ self.save_client_details(partner); });
|
|
|
+ contents.on('click','.button.undo',function(){ self.undo_client_details(partner); });
|
|
|
+ this.editing_client = false;
|
|
|
+ this.uploaded_picture = null;
|
|
|
+
|
|
|
+ if(visibility === 'show'){
|
|
|
+ contents.empty();
|
|
|
+ contents.append($(QWeb.render('ClientDetails',{widget:this,partner:partner})));
|
|
|
+
|
|
|
+ var new_height = contents.height();
|
|
|
+
|
|
|
+ if(!this.details_visible){
|
|
|
+ if(clickpos < scroll + new_height + 20 ){
|
|
|
+ parent.scrollTop( clickpos - 20 );
|
|
|
+ }else{
|
|
|
+ parent.scrollTop(parent.scrollTop() + new_height);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ parent.scrollTop(parent.scrollTop() - height + new_height);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.details_visible = true;
|
|
|
+ this.toggle_save_button();
|
|
|
+ } else if (visibility === 'edit') {
|
|
|
+ this.editing_client = true;
|
|
|
+ contents.empty();
|
|
|
+ contents.append($(QWeb.render('ClientDetailsEdit',{widget:this,partner:partner})));
|
|
|
+ this.toggle_save_button();
|
|
|
+
|
|
|
+ contents.find('.image-uploader').on('change',function(event){
|
|
|
+ self.load_image_file(event.target.files[0],function(res){
|
|
|
+ if (res) {
|
|
|
+ contents.find('.client-picture img, .client-picture .fa').remove();
|
|
|
+ contents.find('.client-picture').append("<img src='"+res+"'>");
|
|
|
+ contents.find('.detail.picture').remove();
|
|
|
+ self.uploaded_picture = res;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } else if (visibility === 'hide') {
|
|
|
+ contents.empty();
|
|
|
+ if( height > scroll ){
|
|
|
+ contents.css({height:height+'px'});
|
|
|
+ contents.animate({height:0},400,function(){
|
|
|
+ contents.css({height:''});
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ parent.scrollTop( parent.scrollTop() - height);
|
|
|
+ }
|
|
|
+ this.details_visible = false;
|
|
|
+ this.toggle_save_button();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ close: function(){
|
|
|
+ this._super();
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ module.ReceiptScreenWidget = module.ScreenWidget.extend({
|
|
|
+ template: 'ReceiptScreenWidget',
|
|
|
+
|
|
|
+ show_numpad: false,
|
|
|
+ show_leftpane: false,
|
|
|
+
|
|
|
+ show: function(){
|
|
|
+ this._super();
|
|
|
+ var self = this;
|
|
|
+
|
|
|
+ var print_button = this.add_action_button({
|
|
|
+ label: _t('Print'),
|
|
|
+ icon: '/point_of_sale/static/src/img/icons/png48/printer.png',
|
|
|
+ click: function(){ self.print(); },
|
|
|
+ });
|
|
|
+
|
|
|
+ var finish_button = this.add_action_button({
|
|
|
+ label: _t('Next Order'),
|
|
|
+ icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
|
|
+ click: function() { self.finishOrder(); },
|
|
|
+ });
|
|
|
+
|
|
|
+ this.refresh();
|
|
|
+
|
|
|
+ finish_button.set_disabled(true);
|
|
|
+ setTimeout(function(){
|
|
|
+ finish_button.set_disabled(false);
|
|
|
+ }, 2000);
|
|
|
+ },
|
|
|
+ print: function() {
|
|
|
+ this.pos.get('selectedOrder')._printed = true;
|
|
|
+ window.print();
|
|
|
+ },
|
|
|
+ finishOrder: function() {
|
|
|
+ this.pos.get('selectedOrder').destroy();
|
|
|
+ },
|
|
|
+ refresh: function() {
|
|
|
+ var order = this.pos.get('selectedOrder');
|
|
|
+ $('.pos-receipt-container', this.$el).html(QWeb.render('PosTicket',{
|
|
|
+ widget:this,
|
|
|
+ order: order,
|
|
|
+ orderlines: order.get('orderLines').models,
|
|
|
+ paymentlines: order.get('paymentLines').models,
|
|
|
+ logo: order.pos.company_logo_base64
|
|
|
+ }));
|
|
|
+ },
|
|
|
+ close: function(){
|
|
|
+ this._super();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+}
|