[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 <pimodoo@users.noreply.github.com>
This commit is contained in:
Pierre Masereel
2019-08-30 12:28:47 +00:00
parent 8fad800dd8
commit c95acd624e
4 changed files with 118 additions and 7 deletions
+29
View File
@@ -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 = "<p>Dear %s,<br/>Here is your electronic ticket from the %s. </p>" % (client['name'], name)
template_data = {
'subject': 'Receipt %s' % name,
'body_html': message + '<img src="data:image/jpeg;base64,%s"/>' % 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
+12 -1
View File
@@ -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){
+74 -6
View File
@@ -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});
@@ -824,6 +824,9 @@
</div>
</t>
</t>
<div t-attf-class='button js_email #{widget.pos.get_client() ? "" : "oe_hidden"}'>
<i class='fa fa-inbox' /> Email
</div>
<t t-if='widget.pos.config.tip_product_id'>
<div class='button js_tip'>
<i class='fa fa-heart' /> Tip