(function ($) { "use strict"; var portkkm = function () { var o = this; }; var p = portkkm.prototype; p.printer_name = "FPG-1000"; p.btn_repeat_sale = 'Повторить продажу'; p.btn_repeat_refund = 'Повторить возврат'; p.btn_close_check = 'Отменить'; p.btn_cancel_check = 'Отменить'; p.btn_close_shift = 'Закрыть смену'; p.webroot = '/'+window.location.pathname.split('/')[1]+'/'; p.next_action = null;//метод внешней системы p.next_action_args = null;//аргументы метода внешней системы p.control_mixed_payment = null;//элемент управления признаком смешанной оплаты внешней системы p.control_card_payment = null;//элемент управления признаком оплаты картой внешней системы p.control_amount = null;//элемент управления суммой от покупателя внешней системы p.control_noncash = null;//элемент управления суммой безналичного расчета от покупателя внешней системы p.control_total = null;//элемент управления итоговой суммой чека внешней системы p.control_confirm = null;//элемент управления confirm внешней системы p.rest_api_url = 'http://127.0.0.1:55555';//адрес API сервиса p.type = 0; //тип подключения к терминалу p.ip = ''; //адрес терминала p.port = ''; //порт терминала p.com = ''; //номер последовательного порта терминала p.fiscal_sign = ''; p.doc_number = ''; p.type_operation = null;//Тип операции Внесение/Изятие p.first_operation = false; p.salling = false; //инициализация p.init = async function(data) { if (data) { for (var key in data) { switch (key) { case "ip": p.ip = data[key].split(':')[0]; p.port = data[key].split(':')[1]; break; case "load_finish": p.set_load_finish(data[key]); break; default: p[key] = data[key]; break; } } } p.update_printer_name(); } //регистрация или обновление связи с терминалом в настройках внешней системы p.check_connect = function(data) { p.load('start'); $.post(p.rest_api_url, JSON.stringify({ FnName: "Connect", Port: data, Baudrate :"115200" }), function(data){ console.log(data); if (data.ErrorCode==0) { ajax_msg('main_portkkm', 'success', 'Соединение установлено. Не забудьте нажать кнопку Сохранить', 2); p.update_session({type: 1, com: data}); } else { ajax_msg('main_portkkm', 'danger', 'Соединение не установлено.', 2); } p.load('finish'); }); }; //регистрация кассы внешней системы в терминале p.check_connect_socket = function(ip) { p.load('start'); $.post(p.rest_api_url, JSON.stringify({ FnName: "ConnectToSocket", Host: ip.split(':')[0], Port: ip.split(':')[1] }), function(data){ console.log(data); if (data.ErrorCode==0) { ajax_msg('main_portkkm', 'success', 'Соединение установлено успешно. Не забудьте нажать кнопку Сохранить', 2); p.update_session({type: 0, ip: ip}); } else { ajax_msg('main_portkkm', 'danger', 'Соединение не установлено.', 2); } p.load('finish'); }); }; p.sale = function(add_params) { if (!p.salling) { add_params = add_params || {}; p.prepare_sale(); p.get_cashbox_list(function(positions){//получаем позиции с кассы p.salling = true; p.connect( function() { p.is_first_operation(function(){ p.open_sale(function() {//открытие продажи с сопутствующими операциями p.registration_loop(positions, 1, function() {//регистация позиций чека p.close_sale(); }); }, add_params); }); }); }); } } p.prepare_sale = function() { var paid_mode = $(p.control_mixed_payment).prop('checked') ? 2 : Number($(p.control_card_payment).prop('checked')); var amount = $(p.control_mixed_payment).prop('checked') ? $(p.control_noncash).val() : ($(p.control_card_payment).prop('checked') ? $(p.control_amount).val() : 0); amount = amount > 0 ? amount : parseInt($(p.control_total).html()); var cash = 0; var noncash = 0; if (paid_mode == 2) { cash = $(p.control_amount).val(); noncash = $(p.control_noncash).val(); } else { if (paid_mode == 0) cash = amount; if (paid_mode == 1) noncash = amount; } p.store.set('cash', cash); p.store.set('noncash', noncash); p.store.set('paid_mode', paid_mode); } p.refund = function(args) { var confirm_text = 'ПОРТ ККМ: Провести операцию \"Возврат\" для выбранного товара?'; p.control_confirm(confirm_text, function(){ p.next_action_args = args; var guid = args[0], full_check = args[2]; //console.log(args); p.get_check_list(guid, full_check, function(positions){//получаем позиции чека p.connect( function() { p.is_first_operation(function(){ p.open_refund(function() {//открытие возврата с сопутствующими операциями p.registration_loop(positions, 1, function() {//регистация позиций чека p.close_refund(); }); }); }); }); }); }); } p.get_cashbox_list = function(success) { $.post(p.webroot + 'Portkkm_api/portkkm/get_cashbox_list', {}, function(response) { //console.log(response); if (p.is_json(response)) { var obj = JSON.parse(response); //console.log(obj); if (!p.objectEmpty(obj)) { success(obj); } else { ajax_msg('main', 'danger', 'Отсутствуют позиции в чеке', 1); } } else { ajax_msg('main', 'danger', 'Произошла ошибка при получении позиций чека для ПОРТ ККМ', 1); p.load('finish'); } }) .fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); } p.get_check_list = function(guid, full_check, success) { $.post(p.webroot + 'Portkkm_api/portkkm/get_check_list', { guid: guid, full_check: full_check }, function(response) { //console.log(response); if (p.is_json(response)) { var obj = JSON.parse(response); console.log(obj); if (obj['status']=='ok') { p.store.set('paid_mode', obj['check']['pay_type']); if (obj['check']['pay_type'] == '0') p.store.set('cash', obj['check']['summ']); if (obj['check']['pay_type'] == '1') p.store.set('noncash', obj['check']['summ']); if (obj['check']['pay_type'] == '2') { // p.store.set('paid_mode', '0'); // p.store.set('cash', Number(obj['check']['cash']) + Number(obj['check']['noncash'])); p.store.set('cash', obj['check']['cash']); p.store.set('noncash', obj['check']['noncash']); } success(obj['check']['items']); } else { ajax_msg('main', 'danger', 'Отсутствуют позиции в чеке', 1); } } else { ajax_msg('main', 'danger', 'Произошла ошибка при получении позиций чека для ПОРТ ККМ', 1); p.load('finish'); } }) .fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); } p.open_sale = function(success, add_params) { p.reset_prev_check( function() { p.open_new_check("0", function() { if (p.objectEmpty(add_params)) { success(); } else { p.set_additional_parameters(add_params, success); } }) }); } p.open_refund = function(success) { p.reset_prev_check( function() { p.open_new_check("1", function() { success(); }) }) ; } p.connect = function(success) { var param = {}; console.log(p.type); if (p.type==0) { param = { FnName: "ConnectToSocket", Host: p.ip, Port: p.port } } else if (p.type==1) { param = { FnName: "Connect", Port: p.com, Baudrate :"115200" } } $.post(p.rest_api_url, JSON.stringify(param), function(response){ if (response.ErrorCode==0) { console.log('portkkm: connected'); success(); } else { ajax_msg('main', 'danger', 'ПОРТ: ККМ не доступен', 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); } p.reset_prev_check = function(success) { $.post(p.rest_api_url, JSON.stringify({ FnName: "SetFiscalInvParam", Type: "2", Data: "" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: previous check has been reset'); success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при обнулении параметров предыдущего чека перед открытием нового чека', 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); }; p.open_new_check = function(receipt_type, success) { var btn_repeat = receipt_type==0 ? p.btn_repeat_sale : p.btn_repeat_refund; $.post(p.rest_api_url, JSON.stringify({ FnName: "OpenFiscalInv", OpCode: "30", OpPwd :"30", TillNmb: "1", ReceiptType: receipt_type //,ShiftNumber: "2" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: new check has been open'); success(); } else { if (data.ErrorCode==111024) { ajax_msg('main', 'danger', 'ПОРТ: Продолжительность смены превышает 24 часа. Произведите закрытие смены. ' + p.btn_close_shift, 1); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при открытии нового чека. ' + btn_repeat + ' | ' + p.btn_close_check, 1); } p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); }; p.set_additional_parameters = function(add_params, success) { add_params.FnName = "SetFiscalInvParam"; $.post(p.rest_api_url, JSON.stringify(add_params), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: installs additional parameters'); success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при установки дополнительных параметров чека', 1); p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); } p.register_position = function(position, success) { console.log(position); var json = JSON.stringify({ FnName: "RegisterSale", PluName: position['name'], TaxCd: "1", Price: position['price'], Quantity: position['count'], DiscountType: "4", DiscountValue: position['discount'], Department: "1", MarkStamp: position['mark'], RoundPrice: position['summ'], UnitCode: "796", ProductID: "", BarCode: "" }).replace(/\\u001d/g, ""); console.log(json); $.post(p.rest_api_url, json, function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: position is registered'); success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при регистрации позиции нового чека: ' + data.ErrorMessage, 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); } p.registration_loop = function(positions, i, finished) { i = i || 1; p.register_position(positions[i], function() { i++; if (positions[i]) { p.registration_loop(positions, i, finished); } else { finished(); } }); } p.repeat_sale = function() { $('.alert').hide(); p.close_sale(); } p.repeat_refund = function() { $('.alert').hide(); p.close_refund(); } p.close_sale = function() { p.total( function(){ p.close_check( function() { p.next_action(); }) }); } p.close_refund = function() { p.total( function(){ p.close_check( function() { p.next_action(p.next_action_args[0], p.next_action_args[1], p.next_action_args[2]); }) }); } p.total = function(success) { var paid_mode = p.store.get('paid_mode').toString(); var amount = 0; if (paid_mode == '0') amount = p.store.get('cash').toString(); if (paid_mode == '1') amount = p.store.get('noncash').toString(); if (paid_mode == '2') { paid_mode = '0'; amount = p.store.get('cash').toString(); } console.log({ FnName: "Total", PaidMode: paid_mode, Amount: amount }); $.post(p.rest_api_url, JSON.stringify({ FnName: "Total", PaidMode: paid_mode, Amount: amount }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: сheck paid'); if (p.store.get('paid_mode').toString()=='2') { p.second_total(success); } else { p.store.clear(); success(); } } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при оплате чека. ' + data.ErrorMessage + ' ' + p.btn_cancel_check, 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); } p.second_total = function(success) {//вторая оплата при смешаном типе оплаты var paid_mode = '1'; var amount = p.store.get('noncash').toString(); console.log({ FnName: "Total", PaidMode: paid_mode, Amount: amount }); $.post(p.rest_api_url, JSON.stringify({ FnName: "Total", PaidMode: paid_mode, Amount: amount }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: second сheck paid'); p.store.clear(); success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при оплате чека. ' + data.ErrorMessage + ' ' + p.btn_cancel_check, 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); } p.close_check = function(success) { $.post(p.rest_api_url, JSON.stringify({ FnName: "CloseFiscalInv" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: check closed'); p.fiscal_sign = data.FiscalSign; p.doc_number = data.DocNumber; if (p.first_operation) { p.set_type_operation('2'); p.save_reports(); p.first_operation = false; } success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при закрытии чека. ' + p.btn_cancel_check, 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); }; p.cancel_check = function() { $.post(p.rest_api_url, JSON.stringify({ FnName: "CancelFiscalInv" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: the check was canceled'); $('.alert').hide(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при отмене чека.', 1); p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); } p.open_shift = function() { $.post(p.rest_api_url, JSON.stringify({ FnName: "OpenFiscalInv", OpCode: "30", OpPwd :"30", TillNmb: "1", ReceiptType: "4" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: shift open'); //success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при открытии смены', 1); p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); }; p.close_shift = function() { p.connect( function() { $.post(p.rest_api_url, JSON.stringify({ FnName: "PrintReport", Type: "Z" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: shift closed'); $('.alert').hide(); p.set_type_operation('3'); p.save_reports(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при закрытии смены', 1); } p.load('finish'); }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); }); }; // p.zreport = function () { // p.connect( function() { // p.close_shift(); // }); // } p.xreport = function () { p.connect( function() { $.post(p.rest_api_url, JSON.stringify({ FnName: "PrintReport", Type: "X" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: X report received'); $('.alert').hide(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при получении X отчета', 1); p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); }); } p.creport = function () { p.connect( function() { $.post(p.rest_api_url, JSON.stringify({ FnName: "PrintReport", Type: "C" }), function(data){ console.log(data); // if (data.ErrorCode==0) { // console.log('portkkm: X report received'); // $('.alert').hide(); // } else { // ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при получении X отчета', 1); // p.load('finish'); // } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); }); } p.get_sum_at_cashbox = function() { p.connect( function() { $.post(p.rest_api_url, JSON.stringify({ FnName: "ParishOrConsumption", Type: "0", Amount: "0" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: get_sum_at_cashbox'); $('#portkkm_cash').val(data.CashSum); $('#modal_portkkm_transaction').show(); $('#formPortkkmTransaction').modal('show') } else { ajax_msg('portkkm_transaction_modal_msg', 'danger', 'ПОРТ: Произошла ошибка при получении данных с кассы', 1); p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('portkkm_transaction_modal_msg', 'danger', p.error_message(xhr), 1); p.load('finish'); }); }); } p.parish_or_consumption = function(success) { var amount = $('#portkkm_operation_sum').val(); $.post(p.rest_api_url, JSON.stringify({ FnName: "ParishOrConsumption", Type: p.type_operation, Amount: amount }), function(data){ console.log(data); if (data.ErrorCode==0) { if (p.type_operation == '0') { console.log('portkkm: parish ' + amount); ajax_msg('portkkm_transaction_modal_msg', 'success', 'ПОРТ: Внесена сумма ' + amount, 1); success(); } else { console.log('portkkm: consumption ' + amount); ajax_msg('portkkm_transaction_modal_msg', 'success', 'ПОРТ: Изъята сумма ' + amount, 1); success(); } } else { if (data.ErrorCode==111024) { ajax_msg('portkkm_transaction_modal_msg', 'danger', 'ПОРТ: Продолжительность смены превышает 24 часа. Произведите закрытие смены. ' + p.btn_close_shift, 1); } else { ajax_msg('portkkm_transaction_modal_msg', 'danger', 'ПОРТ: Произошла ошибка при выполнении операции', 1); } p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('portkkm_transaction_modal_msg', 'danger', p.error_message(xhr), 1); p.load('finish'); }); } p.save_reports = function() { var rubus_operations = { '0': 'deposit_cash', '1': 'remove_cash', '2': 'shift_open', '3': 'shift_close' }; var data_operation = {}; if (p.type_operation <= 1) { data_operation = { sum: $('#portkkm_operation_sum').val(), comment: $('#portkkm_operation_comment').val() }; } $.post(p.webroot + 'Portkkm_api/portkkm/save_reports/'+rubus_operations[p.type_operation], data_operation, function(response){ console.log('report saved'); }); } p.is_first_operation = function(success) { $.post(p.rest_api_url, JSON.stringify({ FnName: "Programming", Name: "DFR_needed" }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: DFR_needed ' + data.Value); console.log(!+data.Value); p.first_operation = !+data.Value; success(); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при получении служебной переменной DFR_needed. Проверьте подключение к терминалу.', 1); p.load('finish'); p.reset_flag_salling(); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); p.reset_flag_salling(); }); } //реализует возможность получения и установки системных переменных. Выполнять после connect p.programming = function(name, index, value) { if((p.printer_name=="DP-25" || p.printer_name=="DPG-25" || p.printer_name=="DPG-35" || p.printer_name=="DPG-150") && name=="NetInterfaceToUse") { name = 'GprsInterface'; } $.post(p.rest_api_url, JSON.stringify({ FnName: "Programming", Name: name, Index: index, Value: value }), function(data){ console.log(data); if (data.ErrorCode==0) { console.log('portkkm: ' + name + ' = ' + data.Value); } else { ajax_msg('main', 'danger', 'ПОРТ: Произошла ошибка при выполнении комманды Programming', 1); p.load('finish'); } }).fail(function(xhr, status, error) { //console.log(xhr);console.log(status);console.log(data); ajax_msg('main', 'danger', p.error_message(xhr), 1); p.load('finish'); }); } p.clear_fiscal_data = function() { p.fiscal_sign = ''; p.doc_number = ''; } p.set_type_operation = function(value) { p.type_operation = value; } p.update_printer_name = function () { $.post(p.rest_api_url, JSON.stringify({ FnName: "DiagnosticInfo" }), function(data){ //console.log(data); if (data.ErrorCode==0) { p.printer_name = data.Name; } }).fail(function(xhr, status, error) { console.log(xhr);console.log(status);console.log(data); }); } //обновляем сессионные переменные kaspi на сервере внешней системы p.update_session = function(data){ $.post(p.webroot + 'Portkkm_api/portkkm/update_session', data, function(response){ console.log('session updated'); }); } p.objectEmpty = function(obj){ if (Object.keys(obj).length == 0) return true; return false; } //обновляем сессионные переменные kaspi на сервере внешней системы // p.reset_session = function(){ // $.post(p.webroot + 'Kaspi_api/kaspi/reset_session',{}, // function(response){ // console.log('session reset'); // }); // } p.reset_flag_salling = function() { if (p.salling) p.salling = false; } //показываем/скрываем процесс загрузки p.load = function(comand){ if (comand == 'start') { $('.kaspi_load').addClass('spin'); } else { if (p.load_finish) p.load_finish(); $('.kaspi_load').removeClass('spin'); } } p.set_load_finish = function(func) { if (func) p.load_finish = func; else p.load_finish = function() {}; } //обработка ошибок p.error_message = function(xhr, repeat) { if (xhr.responseJSON) return xhr.responseJSON.message; return 'ПОРТ ККМ недоступен или вышло время ожидания.';//+repeat_btn; } p.is_json = function(str) { try { JSON.parse(str); } catch (e) { return false; } return true; } p.isEmpty = function(str) { return (!str || str.length === 0 ); } p.repeat_func = p.refund; p.store = { set: function(label, value) { localStorage.setItem('portkkm_' + label, value); }, get: function(label) { return localStorage.getItem('portkkm_' + label); }, clear: function() { localStorage.removeItem('portkkm_amount'); localStorage.removeItem('portkkm_paid_mode'); } }; p.test_method = function() { //p.port = 101010; console.log(p.port); } window.Portkkm = new portkkm; }(jQuery));