From c95acd624ef9753b2e2a7bd313b9fe15c6d8c2f3 Mon Sep 17 00:00:00 2001 From: Pierre Masereel Date: Thu, 29 Aug 2019 07:42:46 +0000 Subject: [PATCH] [IMP] point_of_sale: Send ticket by email. When you select a customer in the front end, you can send him an email with the receipt as an image. If you decided to send the mail and you'd like to print the receipt anyway, you have to click on the When you're offline, the order will be queued and the ticket printed. You'll receive an error message When invoicing, the invoice will be in attachment of the email. TASK-ID: 1922660 closes odoo/odoo#35812 Signed-off-by: pimodoo --- addons/point_of_sale/models/pos_order.py | 29 +++++++ addons/point_of_sale/static/src/js/models.js | 13 ++- addons/point_of_sale/static/src/js/screens.js | 80 +++++++++++++++++-- addons/point_of_sale/static/src/xml/pos.xml | 3 + 4 files changed, 118 insertions(+), 7 deletions(-) diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 6a6e84d2104..2c68e064f44 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -12,6 +12,7 @@ from odoo.tools import float_is_zero from odoo.exceptions import UserError from odoo.http import request from odoo.osv.expression import AND +import base64 _logger = logging.getLogger(__name__) @@ -607,6 +608,34 @@ class PosOrder(models.Model): 'target': 'current', } + @api.model + def action_receipt_to_customer(self, name, client, ticket, invoice_id=False): + template_obj = self.env['mail.mail'] + message = "

Dear %s,
Here is your electronic ticket from the %s.

" % (client['name'], name) + template_data = { + 'subject': 'Receipt %s' % name, + 'body_html': message + '' % ticket, + 'email_from': self.env.company.email, + 'email_to': client['email'] + } + + if invoice_id: + report = self.env.ref('point_of_sale.pos_invoice_report').render_qweb_pdf(invoice_id) + attachment = self.env['ir.attachment'].create({ + 'name': name, + 'type': 'binary', + 'datas': base64.b64encode(report[0]), + 'datas_fname': name + '.pdf', + 'store_fname': name, + 'res_model': 'account.move', + 'res_id': invoice_id, + 'mimetype': 'application/x-pdf' + }) + template_data['attachment_ids'] = attachment + + template_id = template_obj.create(template_data) + template_obj.send(template_id) + @api.model def remove_from_ui(self, server_ids): """ Remove orders from the frontend PoS application diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 3e008db4347..1bfe646ebee 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -890,7 +890,7 @@ exports.PosModel = Backbone.Model.extend({ // on success, get the order id generated by the server transfer.then(function(order_server_id){ // generate the pdf and download it - if (order_server_id.length) { + if (order_server_id.length && !order.is_to_email()) { self.chrome.do_action('point_of_sale.pos_invoice_report',{additional_context:{ active_ids:order_server_id, }}).then(function () { @@ -900,6 +900,9 @@ exports.PosModel = Backbone.Model.extend({ rejectInvoiced({code:401, message:'Backend Invoice', data:{order: order}}); rejectDone(); }); + } else if (order_server_id.length) { + resolveInvoiced(order_server_id[0]); + resolveDone(); } else { // The order has been pushed separately in batch when // the connection came back. @@ -2218,6 +2221,7 @@ exports.Order = Backbone.Model.extend({ this.temporary = options.temporary || false; this.creation_date = new Date(); this.to_invoice = false; + this.to_email = false; this.orderlines = new OrderlineCollection(); this.paymentlines = new PaymentlineCollection(); this.pos_session_id = this.pos.pos_session.id; @@ -2957,6 +2961,13 @@ exports.Order = Backbone.Model.extend({ is_to_invoice: function(){ return this.to_invoice; }, + /* ---- Email --- */ + set_to_email: function(to_email) { + this.to_email = to_email; + }, + is_to_email: function(){ + return this.to_email; + }, /* ---- Client / Customer --- */ // the client related to the current order. set_client: function(client){ diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index d22e9dd7f6a..c988db5cfdb 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -35,6 +35,7 @@ var rpc = require('web.rpc'); var utils = require('web.utils'); var field_utils = require('web.field_utils'); var BarcodeEvents = require('barcodes.BarcodeEvents').BarcodeEvents; +var Printer = require('point_of_sale.Printer').Printer; var QWeb = core.qweb; var _t = core._t; @@ -1629,7 +1630,7 @@ var ReceiptScreenWidget = ScreenWidget.extend({ this.handle_auto_print(); }, handle_auto_print: function() { - if (this.should_auto_print()) { + if (this.should_auto_print() && !this.pos.get_order().is_to_email()) { this.print(); if (this.should_close_immediately()){ this.click_next(); @@ -2119,6 +2120,11 @@ var PaymentScreenWidget = ScreenWidget.extend({ this.$('.js_invoice').removeClass('highlight'); } }, + click_email: function(){ + var order = this.pos.get_order(); + order.set_to_email(!order.is_to_email()); + this.$('.js_email').toggleClass('highlight', order.is_to_email()); + }, click_tip: function(){ var self = this; var order = this.pos.get_order(); @@ -2139,9 +2145,14 @@ var PaymentScreenWidget = ScreenWidget.extend({ } }); }, + toggle_email_button: function() { + var client = this.pos.get_client(); + this.$('.js_email').removeClass('oe_hidden', client); + }, customer_changed: function() { var client = this.pos.get_client(); - this.$('.js_customer_name').text( client ? client.name : _t('Customer') ); + this.$('.js_customer_name').text( client ? client.name : _t('Customer') ); + this.toggle_email_button(); }, click_set_customer: function(){ this.gui.show_screen('clientlist'); @@ -2179,7 +2190,9 @@ var PaymentScreenWidget = ScreenWidget.extend({ this.$('.js_invoice').click(function(){ self.click_invoice(); }); - + this.$('.js_email').click(function(){ + self.click_email(); + }); this.$('.js_cashdrawer').click(function(){ self.pos.proxy.printer.open_cashbox(); }); @@ -2269,6 +2282,17 @@ var PaymentScreenWidget = ScreenWidget.extend({ } } + if (order.get_client && order.is_to_email() && !order.get_client().email) { + this.gui.show_popup('confirm', { + 'title': _t('Please fill the Customer Email'), + 'body': _t('This customer does not have an email address, define one or do not send an email'), + confirm: function () { + this.gui.show_screen('clientlist'); + }, + }); + return false; + } + // if the change is too large, it's probably an input error, make the user confirm. if (!force_validation && order.get_total_with_tax() > 0 && (order.get_total_with_tax() * 1000 < order.get_total_paid())) { this.gui.show_popup('confirm',{ @@ -2310,13 +2334,32 @@ var PaymentScreenWidget = ScreenWidget.extend({ invoiced.catch(this._handleFailedPushForInvoice.bind(this, order, false)); - invoiced.then(function () { + invoiced.then(function (value) { self.invoicing = false; + self.send_receipt_to_customer(value || false); self.gui.show_screen('receipt'); }); } else { - this.pos.push_order(order); - this.gui.show_screen('receipt'); + if (order.is_to_email()){ + var ordered = this.pos.push_order(order); + ordered.then(function() { + self.send_receipt_to_customer(false); + self.gui.show_screen('receipt'); + }); + ordered.catch(function(value) { + order.set_to_email(false); + self.gui.show_screen('receipt'); + self.gui.show_popup('error',{ + 'title': "Error: no internet connection", + 'body': "There is no internet connection, impossible to send the email.", + }); + }); + } + else { + this.pos.push_order(order); + self.gui.show_screen('receipt'); + } + } }, @@ -2328,6 +2371,31 @@ var PaymentScreenWidget = ScreenWidget.extend({ this.finalize_validation(); } }, + + send_receipt_to_customer: function(invoice_server_id) { + var order = this.pos.get_order(); + if(order.is_to_email()){ + var data = { + widget: this, + pos: order.pos, + order: order, + receipt: order.export_for_printing(), + orderlines: order.get_orderlines(), + paymentlines: order.get_paymentlines(), + } + + var receipt = QWeb.render('OrderReceipt', data); + var printer = new Printer(); + + printer.htmlToImg(receipt).then(function(ticket) { + rpc.query({ + model: 'pos.order', + method: 'action_receipt_to_customer', + args: [order.get_name(), order.get_client(), ticket, invoice_server_id], + }); + }); + } + }, }); gui.define_screen({name:'payment', widget: PaymentScreenWidget}); diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 713aace77af..96529b384d5 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -824,6 +824,9 @@ +
+ Email +
Tip