Files
suite/pos_pax/static/src/js/pos_pax.js
2020-11-20 14:36:00 -08:00

350 lines
11 KiB
JavaScript

odoo.define('pos_pax.pos_pax', function (require) {
"use strict";
// Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
var core = require('web.core');
var screens = require('point_of_sale.screens');
var gui = require('point_of_sale.gui');
var pos_model = require('point_of_sale.models');
var _t = core._t;
var PopupWidget = require('point_of_sale.popups');
var PaymentScreenWidget = screens.PaymentScreenWidget;
var PAX = require('pos_pax.pax_device');
PAX.mDestinationIP = '';
pos_model.load_fields("account.journal", "pos_use_pax");
pos_model.PosModel = pos_model.PosModel.extend({
getPAXOnlinePaymentJournals: function () {
var self = this;
var online_payment_journals = [];
$.each(this.journals, function (i, val) {
if (val.pos_use_pax) {
online_payment_journals.push({label:self.getCashRegisterByJournalID(val.id).journal_id[1], item:val.id});
}
});
return online_payment_journals;
},
getCashRegisterByJournalID: function (journal_id) {
var cashregister_return = false;
$.each(this.cashregisters, function (index, cashregister) {
if (cashregister.journal_id[0] === journal_id) {
cashregister_return = cashregister;
}
});
return cashregister_return;
},
decodePAXResponse: function (data) {
console.log(data);
if (data[5] == 'ABORTED') {
console.log('aborted');
return {fail: 'Transaction Aborted'};
} else if (data[5] == 'OK') {
return {
success: true,
approval: data[6][2],
txn_id: data[10][0],
card_num: '***' + data[9][0],
}
}
return {fail: 'Unknown Response. ' + data};
}
});
var _paylineproto = pos_model.Paymentline.prototype;
pos_model.Paymentline = pos_model.Paymentline.extend({
init_from_JSON: function (json) {
_paylineproto.init_from_JSON.apply(this, arguments);
this.paid = true;
this.pax_txn_pending = json.pax_txn_pending;
this.pax_card_number = json.pax_card_number;
this.pax_approval = json.pax_approval;
this.pax_txn_id = json.pax_txn_id;
this.set_credit_card_name();
},
export_as_JSON: function () {
return _.extend(_paylineproto.export_as_JSON.apply(this, arguments), {
paid: this.paid,
pax_txn_pending: this.pax_txn_pending,
pax_card_number: this.pax_card_number,
pax_approval: this.pax_approval,
pax_txn_id: this.pax_txn_id,
});
},
set_credit_card_name: function () {
if (this.pax_card_number) {
this.name = this.pax_card_number;
}
}
});
// Popup to show all transaction state for the payment.
var PAXPaymentTransactionPopupWidget = PopupWidget.extend({
template: 'PAXPaymentTransactionPopupWidget',
show: function (options) {
var self = this;
this._super(options);
options.transaction.then(function (data) {
if (data.auto_close) {
setTimeout(function () {
self.gui.close_popup();
}, 2000);
} else {
self.close();
self.$el.find('.popup').append('<div class="footer"><div class="button cancel">Ok</div></div>');
}
self.$el.find('p.body').html(data.message);
}).progress(function (data) {
self.$el.find('p.body').html(data.message);
});
}
});
gui.define_popup({name:'pax-payment-transaction', widget: PAXPaymentTransactionPopupWidget});
PaymentScreenWidget.include({
_get_pax_txn_pending_line: function () {
var i = 0;
var lines = this.pos.get_order().get_paymentlines();
for (i = 0; i < lines.length; i++) {
if (lines[i].pax_txn_pending) {
return lines[i];
}
}
return 0;
},
// Handler to manage the card reader string
pax_credit_transaction: function (old_deferred, retry_nr) {
var order = this.pos.get_order();
if(this.pos.getPAXOnlinePaymentJournals().length === 0) {
return;
}
var self = this;
var transaction = {};
var pending_line = self._get_pax_txn_pending_line();
if ( ! pending_line ) {
console.log('no pending line found!');
return;
}
var purchase_amount = pending_line.get_amount();
var transactionType = '01'; // SALE
if (purchase_amount < 0.0) {
purchase_amount = -purchase_amount;
transactionType = '02'; // RETURN
}
transaction = {
command: 'T00',
version: '1.28',
transactionType: transactionType,
amountInformation: {
TransactionAmount: (purchase_amount * 100) | 0, // cast to integer
},
cashierInformation: {
ClerkID: this.pos.user.name,
},
traceInformation: {
ReferenceNumber: self.pos.get_order().uid,
// InvoiceNumber: self.pos.get_order().uid,
},
}
var def = old_deferred || new $.Deferred();
retry_nr = retry_nr || 0;
// show the transaction popup.
// the transaction deferred is used to update transaction status
// if we have a previous deferred it indicates that this is a retry
if (! old_deferred) {
self.gui.show_popup('pax-payment-transaction', {
transaction: def
});
def.notify({
message: _t('Handling transaction...'),
});
}
PAX.mDestinationIP = this.pos.config.pax_endpoint;
PAX.DoCredit(transaction, function (response) {
console.log(response);
var parsed_response = self.pos.decodePAXResponse(response);
if (parsed_response.fail) {
def.resolve({message: parsed_response.fail})
return;
}
if (parsed_response.success) {
pending_line.paid = true;
pending_line.pax_card_number = parsed_response.card_num;
pending_line.pax_txn_id = parsed_response.txn_id;
pending_line.pax_approval = parsed_response.approval;
pending_line.pax_txn_pending = false;
pending_line.set_credit_card_name();
self.order_changes();
self.reset_input();
self.render_paymentlines();
order.trigger('change', order);
def.resolve({message: 'Approval ' + parsed_response.approval, auto_close: true})
}
def.resolve({message: _t('Unknown response.')})
}, function (fail){
def.resolve({message: _t('Communication Failure: ') + fail});
});
},
remove_paymentline_by_ref: function (line) {
this.pos.get_order().remove_paymentline(line);
this.reset_input();
this.render_paymentlines();
},
pax_do_reversal: function (line) {
var def = new $.Deferred();
var self = this;
var transaction = {};
// show the transaction popup.
// the transaction deferred is used to update transaction status
this.gui.show_popup('pax-payment-transaction', {
transaction: def
});
def.notify({
message: 'Sending reversal...',
});
transaction = {
command: 'T00',
version: '1.28',
transactionType: (line.get_amount() > 0) ? '17' : '18', // V/SALE, V/RETURN
cashierInformation: {
ClerkID: this.pos.user.name,
},
traceInformation: {
ReferenceNumber: self.pos.get_order().uid,
InvoiceNumber: '',
AuthCode: line.pax_approval,
TransactionNumber: line.pax_txn_id,
},
}
PAX.mDestinationIP = this.pos.config.pax_endpoint;
PAX.DoCredit(transaction, function (response) {
var parsed_response = self.pos.decodePAXResponse(response);
if (parsed_response.fail) {
def.resolve({message: parsed_response.fail})
return;
}
if (parsed_response.success) {
def.resolve({
message: _t('Reversal succeeded.'),
auto_close: true,
});
self.remove_paymentline_by_ref(line);
return;
}
def.resolve({message: _t('Unknown response.')})
}, function (fail){
def.resolve({message: _t('Communication Failure: ') + fail});
});
},
click_delete_paymentline: function (cid) {
var lines = this.pos.get_order().get_paymentlines();
for (var i = 0; i < lines.length; i++) {
if (lines[i].cid === cid && lines[i].pax_txn_id) {
this.pax_do_reversal(lines[i]);
return;
}
}
this._super(cid);
},
// make sure there is only one paymentline waiting for a swipe
click_paymentmethods: function (id) {
var order = this.pos.get_order();
var cashregister = null;
for (var i = 0; i < this.pos.cashregisters.length; i++) {
if (this.pos.cashregisters[i].journal_id[0] === id){
cashregister = this.pos.cashregisters[i];
break;
}
}
if (cashregister.journal.pos_use_pax) {
var pending_line = this._get_pax_txn_pending_line();
if (pending_line) {
this.gui.show_popup('error',{
'title': _t('Error'),
'body': _t('One credit card txn already pending.'),
});
} else {
this._super(id);
order.selected_paymentline.pax_txn_pending = true;
this.render_paymentlines();
order.trigger('change', order); // needed so that export_to_JSON gets triggered
}
} else {
this._super(id);
}
},
click_pax_send_transaction: function (id) {
var pending_txn_line = this._get_pax_txn_pending_line();
if (!pending_txn_line) {
this.gui.show_popup('error',{
'title': _t('Error'),
'body': _t('No pending payment line to send.'),
});
return;
}
this.pax_credit_transaction();
},
render_paymentlines: function() {
this._super();
var self = this;
self.$('.paymentlines-container').on('click', '.pax_send_transaction', function(){
self.click_pax_send_transaction();
});
},
// before validating, get rid of any paymentlines that are pending
validate_order: function(force_validation) {
if (this.pos.get_order().is_paid() && ! this.invoicing) {
var lines = this.pos.get_order().get_paymentlines();
for (var i = 0; i < lines.length; i++) {
if (lines[i].pax_txn_pending) {
this.pos.get_order().remove_paymentline(lines[i]);
this.render_paymentlines();
}
}
}
this._super(force_validation);
},
});
});