| Current Path : /var/www/homesaver/www/bitrix/admin/ |
| Current File : /var/www/homesaver/www/bitrix/admin/receipt_refund.php |
<?
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php');
/**
* Форма создания чека возврата по чеку прихода
*/
use Bitrix\Main\Page;
// $blogModulePermissions = $APPLICATION->GetGroupRight("blog");
// if ($blogModulePermissions < "R")
// $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED"));
IncludeModuleLangFile($_SERVER['DOCUMENT_ROOT'] . BX_ROOT . '/modules/main/options.php');
IncludeModuleLangFile(__FILE__);
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/ofdferma/prolog.php');
CJSCore::init('sidepanel');
CModule::includeModule('ofdferma');
$APPLICATION->SetTitle('Новый чек возврата');
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php');
$APPLICATION->SetAdditionalCSS('/bitrix/css/ofdferma/ofdferma_receipts.css');
// Page\Asset::getInstance()->addCss('/bitrix/css/ofdferma/ofdferma_receipts.css');
Page\Asset::getInstance()->addJs('/bitrix/js/ofdferma/ofdferma_receipts.js');
$receiptId = $_REQUEST['receiptId'];
$returnBtn = '<a href="' . $APPLICATION->GetCurPage() . '?receiptId=' . $receiptId . '&IFRAME=Y&IFRAME_TYPE=SIDE_SLIDER" class="adm-btn">Вернуться назад</a>';
$closeBtn = '<a href="javascript:window.BX.SidePanel.Instance.close()" class="adm-btn">Закрыть</a>';
if (empty($receiptId)) {
?>
<div class="adm-info-message-wrap adm-info-message-red">
<div class="adm-info-message">
<span>Не указан ID чека.</span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $closeBtn ?>
<?php
} else {
$receipt = COfdFermaReceipt::GetByReceiptID($receiptId);
if (empty($receipt)) {
?>
<div class="adm-info-message-wrap adm-info-message-red">
<div class="adm-info-message">
<span>Чек не найден.</span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $closeBtn ?>
<?php
} else {
$balance = 0;
$receipts = COfdFermaReceipt::GetList(['ID' => 'DESC'], ['ORDER_ID' => $receipt['ORDER_ID']]);
$linkedReceipts = [];
if ($receipts->SelectedRowsCount() > 0) {
while ($linkedReceipt = $receipts->GetNext()) {
$linkedReceipts[] = $linkedReceipt;
switch ($linkedReceipt['TYPE']) {
case 'Income':
case 'IncomePrepayment':
case 'ExpenseReturn':
$balance += $linkedReceipt['TOTAL_PRICE'];
break;
case 'IncomeReturn':
case 'IncomePrepaymentReturn':
case 'Expense':
$balance -= $linkedReceipt['TOTAL_PRICE'];
break;
}
}
}
try {
$fermaApiClient = CMainOfdFerma::getApiClient();
} catch (\RuntimeException $e) {
?>
<div class="adm-info-message-wrap adm-info-message-red">
<div class="adm-info-message">
<span>Не удалось создать клиент для api фермы.</span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $closeBtn ?>
<?php
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$items = [];
foreach ($_POST['items'] as $k => $item) {
$items[$k] = $item;
$items[$k]['Amount'] = (float)$items[$k]['Price'] * (int)$items[$k]['Quantity'];
}
$receiptData = $fermaApiClient->createElectronReceipt(
'IncomeReturn',
$_POST['email'], $_POST['phone'], (int)$_POST['payment-type'],
$receipt['ORDER_ID'], null, $items
);
try {
$response = $fermaApiClient->sendElectronReceipt($receiptData);
} catch (CFermaApiException $e) {
?>
<div class="adm-info-message-wrap adm-info-message-red">
<div class="adm-info-message">
<span>Ошибка при обращении к api фермы: <?= $e->getMessage() ?></span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $returnBtn ?>
<?= $closeBtn ?>
<?php
exit;
}
if ($response['Status'] === 'Failed') {
if (isset($response['Error']['Message'])) {
?>
<div class="adm-info-message-wrap adm-info-message-red">
<div class="adm-info-message">
<span>Отправка фискального чека не удалась: <?= $response['Error']['Message'] ?></span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $returnBtn ?>
<?= $closeBtn ?>
<?php
} else {
?>
<div class="adm-info-message-wrap adm-info-message-red">
<div class="adm-info-message">
<span>Отправка фискального чека не удалась по неизвестной причине.</span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $returnBtn ?>
<?= $closeBtn ?>
<?php
}
exit;
}
$data = $response['Data'];
$total = 0;
foreach ($receiptData['CustomerReceipt']['Items'] as $item) {
$total += $item['Amount'];
}
$id = COfdFermaReceipt::Add([
'SITE_ID' => SITE_ID,
'RECEIPT_ID' => $response['Data']['ReceiptId'],
'ORDER_ID' => $receipt['ORDER_ID'],
'CONTENT' => json_encode($receiptData),
'TYPE' => $receiptData['Type'],
'TOTAL_PRICE' => $total,
'=DATE_CREATE' => $DB->GetNowFunction(),
'=DATE_UPDATE' => $DB->GetNowFunction(),
]);
CMainOfdFerma::log('Отправка фискального чека возврата', 'Заказ №' . $order['ID'], 'Фискальный чек возврата успешно отправлен в ферму.', 'INFO');
CAgent::AddAgent(
'CMainOfdFerma::checkReceiptStatusAgent(' . json_encode($id) . ');',
CMainOfdFerma::$MODULE_ID,
'Y', 10
);
?>
<div class="adm-info-message-wrap adm-info-message-green">
<div class="adm-info-message">
<span>Чек возврата успешно передан в ОФД.</span>
<div class="adm-info-message-icon"></div>
</div>
</div>
<?= $closeBtn ?>
<?php
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php');
exit;
}
$receiptData = json_decode($receipt['CONTENT'], true);
ofdferma_receiptForm('receipt-form', $APPLICATION->GetCurPage() . '?receiptId=' . $receiptId . '&IFRAME=Y&IFRAME_TYPE=SIDE_SLIDER', [
'Email' => $receiptData['CustomerReceipt']['Email'],
'Phone' => $receiptData['CustomerReceipt']['Phone'],
]);
ofdferma_receiptTableItemTemplate();
if (!empty($linkedReceipts)) {
ofdferma_orderReceipts($receipt['ORDER_ID'], $balance, $linkedReceipts);
}
?>
<script>
BX.ready(function () {
var itemTemplate = document.querySelector('[data-role="receipt-item-template"]').innerHTML;
var items = <?=json_encode($receiptData['CustomerReceipt']['Items'])?>;
var nextIndex = items.length;
var nextNumber = nextIndex + 1;
finishLoader();
initItems();
initHandlers();
return void (0); // EOS
function initItems() {
for (var i = 0; i < items.length; i++) {
addItem({
Index: i,
Number: i + 1,
Label: items[i]['Label'],
Price: items[i]['Price'],
Quantity: items[i]['Quantity'],
VatNo: items[i]['Vat'] === 'VatNo',
Vat0: items[i]['Vat'] === 'Vat0',
Vat10: items[i]['Vat'] === 'Vat10',
Vat20: items[i]['Vat'] === 'Vat20',
CalculatedVat10110: items[i]['Vat'] === 'CalculatedVat10110',
CalculatedVat20120: items[i]['Vat'] === 'CalculatedVat20120'
});
}
}
function initHandlers() {
BX.bind(BX('cancel-btn'), 'click', function (e) {
e.preventDefault();
BX.SidePanel.Instance.close();
});
BX.bind(BX('receipt-form'), 'submit', function (e) {
if (!onSubmit()) {
e.preventDefault();
}
});
BX.bind(BX('add-item-btn'), 'click', function (e) {
e.preventDefault();
addItem({
Index: nextIndex++,
Number: nextNumber++,
Label: '',
Price: 1000,
Quantity: 1,
VatNo: true,
Vat0: false,
Vat10: false,
Vat20: false,
CalculatedVat10110: false,
CalculatedVat20120: false
});
});
multibind(BX('email-input'), ['keyup', 'blur'], function () {
var violations = validateEmail(this, BX('phone-input'));
highlightError(this, Object.keys(violations).length > 0);
});
multibind(BX('phone-input'), ['keyup', 'blur'], function () {
var violations = validatePhone(this, BX('email-input'));
highlightError(this, Object.keys(violations).length > 0);
});
var $items = BX('receipt-items');
BX.bindDelegate($items, 'click', { attrs: { 'data-role': 'remove-item-btn' } }, function (e) {
e.preventDefault();
removeItem(BX.findParent(this, {
attribute: { 'data-role': 'receipt-item' }
}));
});
multibindDelegate($items, ['keyup', 'blur'], { attrs: { 'data-role': 'name-input' } }, function () {
var violations = validateName(this);
highlightError(this, Object.keys(violations).length > 0);
});
multibindDelegate($items, ['keyup', 'blur'], { attrs: { 'data-role': 'price-input' } }, function () {
var violations = validatePrice(this);
highlightError(this, Object.keys(violations).length > 0);
recalculateTotalPrice();
});
multibindDelegate($items, ['keyup', 'blur'], { attrs: { 'data-role': 'quantity-input' } }, function () {
var violations = validateQuantity(this);
highlightError(this, Object.keys(violations).length > 0);
recalculateTotalPrice();
});
recalculateTotalPrice();
}
function multibind(node, events, selector, handler) {
for (var i in events) {
BX.bind(node, events[i], selector, handler);
}
}
function multibindDelegate(node, events, selector, handler) {
for (var i in events) {
BX.bindDelegate(node, events[i], selector, handler);
}
}
function onSubmit() {
var totalViolations = 0;
var violations;
violations = validateTotalPrice();
totalViolations += Object.keys(violations).length;
var emailInput = BX('email-input');
violations = validateEmail(emailInput, BX('phone-input'));
highlightError(emailInput, Object.keys(violations).length > 0);
totalViolations += Object.keys(violations).length;
var phoneInput = BX('phone-input');
violations = validatePhone(phoneInput, BX('email-input'));
highlightError(phoneInput, Object.keys(violations).length > 0);
totalViolations += Object.keys(violations).length;
if (emailInput.value.length === 0 && phoneInput.value.length === 0) {
highlightError(emailInput, true);
highlightError(phoneInput, true);
totalViolations++;
}
iterateItems(function (item) {
var nameInput = item.querySelector('[data-role="name-input"]');
violations = validateName(nameInput);
highlightError(nameInput, Object.keys(violations).length > 0);
totalViolations += Object.keys(violations).length;
var priceInput = item.querySelector('[data-role="price-input"]');
violations = validatePrice(priceInput);
highlightError(priceInput, Object.keys(violations).length > 0);
totalViolations += Object.keys(violations).length;
var quantityInput = item.querySelector('[data-role="quantity-input"]');
violations = validateQuantity(quantityInput);
highlightError(quantityInput, Object.keys(violations).length > 0);
totalViolations += Object.keys(violations).length;
});
return totalViolations === 0;
}
function addItem(data) {
var $items = BX('receipt-items');
var content = itemTemplate
.replace(/#INDEX#/ig, data.Index)
.replace(/#NUMBER#/ig, data.Number)
.replace(/#VALUE-Label#/ig, data.Label)
.replace(/#VALUE-Price#/ig, data.Price)
.replace(/#VALUE-Quantity#/ig, data.Quantity);
var vatCollection = <?=json_encode(CVatCollection::$collection)?>;
vatCollection.map(function(vat) {
content = content.replace(new RegExp('#VALUE-'+vat.code+'#', 'ig'), data[vat.code] ? ' selected' : '');
});
var div = BX.create('div', {
html: content
});
$items.appendChild(div);
recalculateTotalPrice();
}
function removeItem($item) {
BX.remove($item);
recalculateItemIndex();
recalculateTotalPrice();
}
/**
* @param {HTMLInputElement} input
* @param {boolean} state
*/
function highlightError(input, state) {
var $container = BX.findParent(input, {
attribute: { 'data-role': 'field-container' }
});
if (state === true) {
$container.classList.add('has-error');
} else {
$container.classList.remove('has-error');
}
}
/**
* @param {HTMLInputElement} input
* @param {HTMLInputElement} phoneInput
* @returns {Object}
*/
function validateEmail(input, phoneInput) {
var result = {};
var value = input.value;
var phoneValue = phoneInput.value;
var regexp = /^(([^<>()\[\].,;:\s@"]+(\.[^<>()\[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
if (value.length < input.minLength) {
// Ошибка происходит только если не заполнено поле телефона
if (value.length > 1 || phoneValue.length < phoneInput.minLength) {
result.min = true;
}
} else if (value.length > input.maxLength) {
result.max = true;
} else if (!regexp.test(value)) {
result.pattern = true;
}
return result;
}
/**
* @param {HTMLInputElement} input
* @param {HTMLInputElement} emailInput
* @returns {Object}
*/
function validatePhone(input, emailInput) {
var result = {};
var value = input.value;
var emailValue = emailInput.value;
value = value.replace(/[^0-9+]/g, '');
if (value.length < input.minLength) {
// Ошибка происходит только если не заполнено поле email
if (value.length > 1 || emailValue.length < emailInput.minLength) {
result.min = true;
}
} else if (value.length > input.maxLength) {
result.max = true;
}
return result;
}
/**
* @param {HTMLInputElement} input
* @returns {Object}
*/
function validateName(input) {
var result = {};
var value = input.value;
if (value.length < 1) {
result.required = true;
} else if (value.length < input.minLength) {
result.minlength = true;
} else if (value.length > input.maxLength) {
result.maxlength = true;
}
return result;
}
/**
* @param {HTMLInputElement} input
* @returns {Object}
*/
function validatePrice(input) {
var result = {};
var value = parseFloat(input.value);
if (isNaN(value)) {
result.nan = true;
} else if (value < parseFloat(input.min)) {
result.min = true;
} else if (value > parseFloat(input.max)) {
result.max = true;
}
return result;
}
/**
* @param {HTMLInputElement} input
* @returns {Object}
*/
function validateQuantity(input) {
var result = {};
var value = parseInt(input.value);
if (isNaN(value)) {
result.nan = true;
} else if (value < parseInt(input.min, 10)) {
result.min = true;
} else if (value > parseInt(input.max, 10)) {
result.max = true;
}
return result;
}
function getTotalPrice() {
var total = 0;
iterateItems(function (item) {
var price = parseFloat(item.querySelector('[data-role="price-input"]').value);
var quantity = parseFloat(item.querySelector('[data-role="quantity-input"]').value);
price = isNaN(price) ? 0 : price;
quantity = isNaN(quantity) ? 0 : quantity;
total += price * quantity;
});
return total;
}
function validateTotalPrice() {
var result = {};
var total = getTotalPrice();
if (total <= 0) {
result.min = true;
} else if (total > <?=json_encode($balance)?>) {
result.max = true;
}
if (result.min && !result.max) {
BX.show(BX('min-price-attention'));
} else {
BX.hide(BX('min-price-attention'));
}
if (result.max) {
BX.show(BX('max-price-attention'));
} else {
BX.hide(BX('max-price-attention'));
}
// закомментировать строку, чтобы запретить отправлять чеки возврата сверх суммы прихода
delete result.max;
return result;
}
function recalculateTotalPrice() {
var total = getTotalPrice();
validateTotalPrice();
BX('ofd-receipt-summ').innerHTML = total.toLocaleString('ru-RU', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}
function recalculateItemIndex() {
var index = 1;
iterateItems(function (item) {
item.querySelector('[data-role="number"]').innerText = index + '.';
index++;
});
nextNumber = index;
}
function iterateItems(handler) {
var items = document.querySelectorAll('#receipt-items [data-role="receipt-item"]');
for (var i = 0; i < items.length; i++) {
handler(items[i], i);
}
}
function startLoader() {
window.parent.BX.showWait();
}
function finishLoader() {
window.parent.BX.closeWait();
}
});
</script>
<?php
}
}
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php');