[FIX] l10n_fr_pos_cert: display hash on receipt

When an order is sent to the server from the point of sale, a unique
hash is generated by the server. This hash must be printed on the
receipt to allow the comparison between the receipt and the data on the
server and guarantee the unalterability of the data on the server.

TASK-ID: 47990
This commit is contained in:
Pierre Masereel
2019-10-01 10:02:49 +00:00
parent b213c9ee3c
commit 9e5ea29e34
7 changed files with 170 additions and 39 deletions
+2
View File
@@ -28,6 +28,8 @@ The module adds following features:
'data': [
'views/pos_inalterability_menuitem.xml',
'views/account_views.xml',
'views/l10n_fr_pos_cert_templates.xml',
],
'qweb': ['static/src/xml/pos.xml'],
'post_init_hook': '_setup_inalterability',
}
@@ -0,0 +1,73 @@
odoo.define('l10n_fr_pos_cert.pos', function (require) {
"use strict";
var models = require('point_of_sale.models');
var screens = require('point_of_sale.screens');
var rpc = require('web.rpc');
var session = require('web.session');
models.PosModel = models.PosModel.extend({
is_french_country: function(){
var french_countries = ['FR', 'MF', 'MQ', 'NC', 'PF', 'RE', 'GF', 'GP', 'TF'];
return _.contains(french_countries, this.company.country.code);
}
});
var _super_order = models.Order.prototype;
models.Order = models.Order.extend({
initialize: function() {
_super_order.initialize.apply(this,arguments);
this.l10n_fr_hash = this.l10n_fr_hash || false;
this.save_to_db();
},
export_for_printing: function() {
var result = _super_order.export_for_printing.apply(this,arguments);
result.l10n_fr_hash = this.get_l10n_fr_hash();
return result;
},
set_l10n_fr_hash: function (l10n_fr_hash){
this.l10n_fr_hash = l10n_fr_hash;
},
get_l10n_fr_hash: function() {
return this.l10n_fr_hash;
},
wait_for_push_order: function() {
var result = _super_order.wait_for_push_order.apply(this,arguments);
result = Boolean(result || this.pos.is_french_country());
return result;
}
});
screens.PaymentScreenWidget.include({
post_push_order_resolve: function (order, server_ids) {
if (this.pos.is_french_country()) {
var _super = this._super;
var args = arguments;
var self = this;
var get_hash_prom = new Promise (function (resolve, reject) {
rpc.query({
model: 'pos.order',
method: 'search_read',
domain: [['id', 'in', server_ids]],
fields: ['l10n_fr_hash'],
context: session.user_context,
}).then(function (result) {
order.set_l10n_fr_hash(result[0].l10n_fr_hash || false);
}).finally(function () {
_super.apply(self, args).then(function () {
resolve();
}).catch(function (error) {
reject(error);
});
});
});
return get_hash_prom;
}
else {
return this._super(arguments);
}
},
});
});
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-extend="OrderReceipt">
<t t-jquery=".pos-receipt-order-data" t-operation="append">
<t t-if="receipt.l10n_fr_hash !== false">
<div style="word-wrap:break-word;"><t t-esc="receipt.l10n_fr_hash"/></div>
</t>
</t>
</t>
</templates>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets" inherit_id="point_of_sale.assets">
<xpath expr="." position="inside">
<script type="text/javascript" src="/l10n_fr_pos_cert/static/src/js/pos.js"></script>
</xpath>
</template>
</odoo>
+4 -4
View File
@@ -615,7 +615,7 @@ class PosOrder(models.Model):
}
@api.model
def action_receipt_to_customer(self, name, client, ticket, invoice_id=False):
def action_receipt_to_customer(self, name, client, ticket, order_ids=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 = {
@@ -625,8 +625,8 @@ class PosOrder(models.Model):
'email_to': client['email']
}
if invoice_id:
report = self.env.ref('point_of_sale.pos_invoice_report').render_qweb_pdf(invoice_id)
if order_ids and self.env['pos.order'].browse(order_ids[0]).account_move:
report = self.env.ref('point_of_sale.pos_invoice_report').render_qweb_pdf(order_ids[0])
attachment = self.env['ir.attachment'].create({
'name': name,
'type': 'binary',
@@ -634,7 +634,7 @@ class PosOrder(models.Model):
'datas_fname': name + '.pdf',
'store_fname': name,
'res_model': 'account.move',
'res_id': invoice_id,
'res_id': order_ids[0],
'mimetype': 'application/x-pdf'
})
template_data['attachment_ids'] = attachment
+6 -3
View File
@@ -214,7 +214,7 @@ exports.PosModel = Backbone.Model.extend({
},
},{
model: 'res.country',
fields: ['name', 'vat_label'],
fields: ['name', 'vat_label', 'code'],
loaded: function(self,countries){
self.countries = countries;
self.company.country = null;
@@ -909,14 +909,14 @@ exports.PosModel = Backbone.Model.extend({
self.chrome.do_action('point_of_sale.pos_invoice_report',{additional_context:{
active_ids:order_server_id,
}}).then(function () {
resolveInvoiced();
resolveInvoiced(order_server_id);
resolveDone();
}).guardedCatch(function (error) {
rejectInvoiced({code:401, message:'Backend Invoice', data:{order: order}});
rejectDone();
});
} else if (order_server_id.length) {
resolveInvoiced(order_server_id[0]);
resolveInvoiced(order_server_id);
resolveDone();
} else {
// The order has been pushed separately in batch when
@@ -3013,6 +3013,9 @@ exports.Order = Backbone.Model.extend({
get_screen_data: function(key){
return this.screen_data[key];
},
wait_for_push_order: function () {
return this.is_to_email();
},
});
var OrderCollection = Backbone.Collection.extend({
+63 -32
View File
@@ -2374,35 +2374,61 @@ var PaymentScreenWidget = ScreenWidget.extend({
invoiced.catch(this._handleFailedPushForInvoice.bind(this, order, false));
invoiced.then(function (value) {
invoiced.then(function (server_ids) {
self.invoicing = false;
self.send_receipt_to_customer(value || false);
self.gui.show_screen('receipt');
var post_push_promise = [];
post_push_promise = self.post_push_order_resolve(order, server_ids);
post_push_promise.then(function () {
self.gui.show_screen('receipt');
}).catch(function (error) {
self.gui.show_screen('receipt');
if (error) {
self.gui.show_popup('error',{
'title': "Error: no internet connection",
'body': error,
});
}
});
});
} else {
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.",
});
});
var ordered = this.pos.push_order(order);
if (order.wait_for_push_order()){
var server_ids = [];
ordered.then(function (ids) {
server_ids = ids;
}).finally(function() {
var post_push_promise = [];
post_push_promise = self.post_push_order_resolve(order, server_ids);
post_push_promise.then(function () {
self.gui.show_screen('receipt');
}).catch(function (error) {
self.gui.show_screen('receipt');
if (error) {
self.gui.show_popup('error',{
'title': "Error: no internet connection",
'body': error,
});
}
});
});
}
else {
this.pos.push_order(order);
self.gui.show_screen('receipt');
}
}
},
post_push_order_resolve: function(order, server_ids){
var self = this;
if (order.is_to_email()) {
var email_promise = self.send_receipt_to_customer(server_ids);
return email_promise;
}
else {
return Promise.resolve();
}
},
// Check if the order is paid, then sends it to the backend,
// and complete the sale process
@@ -2412,29 +2438,34 @@ var PaymentScreenWidget = ScreenWidget.extend({
}
},
send_receipt_to_customer: function(invoice_server_id) {
send_receipt_to_customer: function(order_server_ids) {
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 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();
var receipt = QWeb.render('OrderReceipt', data);
var printer = new Printer();
return new Promise(function (resolve, reject) {
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],
args: [order.get_name(), order.get_client(), ticket, order_server_ids],
}).then(function() {
resolve();
}).catch(function () {
order.set_to_email(false);
reject("There is no internet connection, impossible to send the email.");
});
});
}
});
},
});
gui.define_screen({name:'payment', widget: PaymentScreenWidget});