Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/admin/
Upload File :
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 . '&amp;IFRAME=Y&amp;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 . '&amp;IFRAME=Y&amp;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');