403Webshell
Server IP : 85.158.181.41  /  Your IP : 216.73.217.12
Web Server : Apache
System : Linux cloud9-vm129 6.1.178+1-ph #ph SMP PREEMPT_DYNAMIC Wed Jul 29 09:00:54 UTC 2026 x86_64
User : moncbefd ( 1024)
PHP Version : 7.3.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/moncbefd/www.moneta.at/admin/javascript/engine/controllers/orders/overview/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/moncbefd/www.moneta.at/admin/javascript/engine/controllers/orders/overview/events.js
/* --------------------------------------------------------------
 events.js 2019-02-26
 Gambio GmbH
 http://www.gambio.de
 Copyright (c) 2018 Gambio GmbH
 Released under the GNU General Public License (Version 2)
 [http://www.gnu.org/licenses/gpl-2.0.html]
 --------------------------------------------------------------
 */

/**
 * Main Table Events
 *
 * Handles the events of the main orders table.
 */
gx.controllers.module(
    'events',

    [
        `${jse.source}/vendor/momentjs/moment.min.js`,
        'loading_spinner',
        'modal',
        'xhr'
    ],

    function (data) {

        'use strict';

        // ------------------------------------------------------------------------
        // VARIABLES
        // ------------------------------------------------------------------------

        /**
         * Module Selector
         *
         * @type {jQuery}
         */
        const $this = $(this);

        /**
         * Module Instance
         *
         * @type {Object}
         */
        const module = {};

        // ------------------------------------------------------------------------
        // FUNCTIONS
        // ------------------------------------------------------------------------

        /**
         * On Bulk Selection Change
         *
         * @param {jQuery.Event} event jQuery event object.
         * @param {Boolean} propagate Whether to affect the body elements. We do not need this on "draw.dt" event.
         */
        function _onBulkSelectionChange(event, propagate = true) {
            if (propagate === false) {
                return; // Do not propagate on draw event because the body checkboxes are unchecked by default.
            }

            $this.find('tbody input:checkbox').single_checkbox('checked', $(this).prop('checked')).trigger('change');
        }

        /**
         * On Table Row Click
         *
         * When a row is clicked then the row-checkbox must be toggled.
         *
         * @param {jQuery.Event} event
         */
        function _onTableRowClick(event) {
            if (!$(event.target).is('td')) {
                return;
            }

            $(this).find('input:checkbox')
                .prop('checked', !$(this).find('input:checkbox').prop('checked'))
                .trigger('change');
        }

        /**
         * On Table Row Checkbox Change
         *
         * Adjust the bulk actions state whenever there are changes in the table checkboxes.
         */
        function _onTableRowCheckboxChange() {
            if ($this.find('input:checkbox:checked').length > 0) {
                $this.parents('.orders').find('.bulk-action > button').removeClass('disabled');
            } else {
                $this.parents('.orders').find('.bulk-action > button').addClass('disabled');
            }
        }

        /**
         * On Cancel Order Click
         *
         * @param {jQuery.Event} event
         */
        function _onCancelOrderClick(event) {
            event.preventDefault();

            const selectedOrders = _getSelectedOrders($(this));

            // Show the order delete modal.
            $('.cancel.modal .selected-orders').text(selectedOrders.join(', '));
            $('.cancel.modal').modal('show');
        }

        /**
         * On Send Order Click.
         *
         * Sends the email order confirmations.
         *
         * @param {jQuery.Event} event jQuery event object.
         */
        function _onBulkEmailOrderClick(event) {
            const $modal = $('.bulk-email-order.modal');
            const $mailList = $modal.find('.email-list');

            const generateMailRowMarkup = data => {
                const $row = $('<div/>', {class: 'form-group email-list-item'});
                const $idColumn = $('<div/>', {class: 'col-sm-3'});
                const $emailColumn = $('<div/>', {class: 'col-sm-9'});

                const $idLabel = $('<label/>', {
                    class: 'control-label id-label force-text-color-black force-text-normal-weight',
                    text: data.id
                });

                const $emailInput = $('<input/>', {
                    class: 'form-control email-input',
                    type: 'text',
                    value: data.customerEmail
                });

                $idLabel.appendTo($idColumn);
                $emailInput.appendTo($emailColumn);

                $row.append([$idColumn, $emailColumn]);
                $row.data('order', data);

                return $row;
            };

            const selectedOrders = [];

            event.preventDefault();

            $this.find('tbody input:checkbox:checked').each(function () {
                const rowData = $(this).parents('tr').data();
                selectedOrders.push(rowData);
            });

            if (selectedOrders.length) {
                $mailList.empty();
                selectedOrders.forEach(order => $mailList.append(generateMailRowMarkup(order)));
                $modal.modal('show');
            }
        }

        /**
         * On Send Invoice Click.
         *
         * Sends the email invoice.
         *
         * @param {jQuery.Event} event Fired event.
         */
        function _onBulkEmailInvoiceClick(event) {
            const $modal = $('.bulk-email-invoice.modal');
            const $mailList = $modal.find('.email-list');

            const generateMailRowMarkup = data => {
                const $row = $('<div/>', {class: 'form-group email-list-item'});
                const $idColumn = $('<div/>', {class: 'col-sm-3'});
                const $invoiceColumn = $('<div/>', {class: 'col-sm-3'});
                const $emailColumn = $('<div/>', {class: 'col-sm-6'});

                const $latestInvoiceIdInput = $('<input/>', {
                    class: 'form-control latest-invoice-id',
                    type: 'hidden',
                    value: data.latestInvoiceId
                });

                const $idLabel = $('<label/>', {
                    class: 'control-label id-label force-text-color-black force-text-normal-weight',
                    text: data.id
                });

                const $invoiceLink = $('<label/>', {
                    class: 'control-label id-label force-text-color-black force-text-normal-weight',
                    html: data.latestInvoiceNumber ? `<a href="request_port.php?module=OrderAdmin&action=showPdf&type=invoice`
                        + `&invoice_number=${data.latestInvoiceNumber}&order_id=${data.id}" target="_blank">`
                        + `${data.latestInvoiceNumber}</a>` : `-`
                });

                const $emailInput = $('<input/>', {
                    class: 'form-control email-input',
                    type: 'text',
                    value: data.customerEmail
                });

                $idLabel.appendTo($idColumn);
                $invoiceLink.appendTo($invoiceColumn);
                $emailInput.appendTo($emailColumn);

                $row.append([$idColumn, $invoiceColumn, $emailColumn, $latestInvoiceIdInput]);
                $row.data('order', data);

                return $row;
            };

            const selectedInvoice = [];

            event.preventDefault();

            $this.find('tbody input:checkbox:checked').each(function () {
                const rowData = $(this).parents('tr').data();
                selectedInvoice.push(rowData);
            });

            if (selectedInvoice.length) {
                $mailList.empty();
                selectedInvoice.forEach(order => $mailList.append(generateMailRowMarkup(order)));
                $modal.modal('show');
            }
        }

        /**
         * Collects the IDs of the selected orders and returns them as an array.
         *
         * @param {jQuery} $target The triggering target
         *
         * @return {Number[]} array of order IDs
         */
        function _getSelectedOrders($target) {
            const selectedOrders = [];

            if ($target.parents('.bulk-action').length > 0) {
                // Fetch the selected order IDs.
                $this.find('tbody input:checkbox:checked').each(function () {
                    selectedOrders.push($(this).parents('tr').data('id'));
                });
            } else {
                const rowId = $target.parents('tr').data('id');

                if (!rowId) {
                    return; // No order ID was found.
                }

                selectedOrders.push(rowId);
            }

            return selectedOrders;
        }

        /**
         * On Email Invoice Click
         *
         * Display the email-invoice modal.
         */
        function _onEmailInvoiceClick() {
            const $modal = $('.email-invoice.modal');
            const rowData = $(this).parents('tr').data();
            const url = jse.core.config.get('appUrl') + '/admin/admin.php';
            const data = {
                id: rowData.id,
                do: 'OrdersModalsAjax/GetEmailInvoiceSubject',
                pageToken: jse.core.config.get('pageToken')
            };
            let invoiceNumbersHtml = '';

            $modal.find('.customer-info').text(`"${rowData.customerName}"`);
            $modal.find('.email-address').val(rowData.customerEmail);

            $modal
                .data('orderId', rowData.id)
                .modal('show');

            $.ajax({url, data, dataType: 'json'}).done((response) => {
                $modal.attr('data-gx-widget', 'single_checkbox');

                $modal.find('.subject').val(response.subject);
                if (response.invoiceIdExists) {
                    $modal.find('.invoice-num-info').addClass('hidden');
                    $modal.find('.no-invoice').removeClass('hidden');
                } else {
                    $modal.find('.invoice-num-info').removeClass('hidden');
                    $modal.find('.no-invoice').addClass('hidden');
                }

                if (Object.keys(response.invoiceNumbers).length <= 1) {
                    $modal.find('.invoice-numbers').addClass('hidden');
                } else {
                    $modal.find('.invoice-numbers').removeClass('hidden');
                }

                for (let invoiceId in response.invoiceNumbers) {
                    invoiceNumbersHtml +=
                        '<p><input type="checkbox" name="invoice_ids[]" value="' + invoiceId
                        + '" checked="checked" class="invoice-numbers-checkbox" /> '
                        + response.invoiceNumbers[invoiceId] + '</p>';
                }

                $modal.find('.invoice-numbers-checkboxes').html(invoiceNumbersHtml);

                $modal.find('.invoice-numbers-checkbox').on('change', _onChangeEmailInvoiceCheckbox);

                gx.widgets.init($modal);
            });
        }

        /**
         * On Email Invoice Checkbox Change
         *
         * Disable send button if all invoice number checkboxes are unchecked. Otherwise enable the send button again.
         */
        function _onChangeEmailInvoiceCheckbox() {
            const $modal = $('.email-invoice.modal');

            if ($modal.find('.invoice-numbers-checkbox').length > 0) {
                if ($modal.find('.invoice-numbers-checkbox:checked').length > 0) {
                    $modal.find('.send').prop('disabled', false);
                } else {
                    $modal.find('.send').prop('disabled', true);
                }
            } else {
                $modal.find('.send').prop('disabled', false);
            }
        }

        /**
         * On Email Order Click
         *
         * Display the email-order modal.
         *
         * @param {jQuery.Event} event
         */
        function _onEmailOrderClick(event) {
            const $modal = $('.email-order.modal');
            const rowData = $(this).parents('tr').data();
            const dateFormat = jse.core.config.get('languageCode') === 'de' ? 'DD.MM.YY' : 'MM/DD/YY';

            $modal.find('.customer-info').text(`"${rowData.customerName}"`);
            $modal.find('.subject').val(jse.core.lang.translate('ORDER_SUBJECT', 'gm_order_menu') + rowData.id
                + jse.core.lang.translate('ORDER_SUBJECT_FROM', 'gm_order_menu')
                + moment(rowData.purchaseDate.date).format(dateFormat));
            $modal.find('.email-address').val(rowData.customerEmail);

            $modal
                .data('orderId', rowData.id)
                .modal('show');
        }

        /**
         * On Change Order Status Click
         *
         * Display the change order status modal.
         *
         * @param {jQuery.Event} event
         */
        function _onChangeOrderStatusClick(event) {
            if ($(event.target).hasClass('order-status')) {
                event.stopPropagation();
            }

            const $modal = $('.status.modal');
            const rowData = $(this).parents('tr').data();
            const selectedOrders = _getSelectedOrders($(this));

            $modal.find('#status-dropdown').val((rowData) ? rowData.statusId : '');

            $modal.find('#comment').val('');
            $modal.find('#notify-customer, #send-parcel-tracking-code, #send-comment')
                .attr('checked', false)
                .parents('.single-checkbox')
                .removeClass('checked');

            // Show the order change status modal.
            $modal.find('.selected-orders').text(selectedOrders.join(', '));
            $modal.modal('show');
        }

        /**
         * On Add Tracking Number Click
         *
         * @param {jQuery.Event} event
         */
        function _onAddTrackingNumberClick(event) {
            const $modal = $('.add-tracking-number.modal');
            const rowData = $(event.target).parents('tr').data();

            $modal.data('orderId', rowData.id);
            $modal.modal('show');
        }

        /**
         * Opens the gm_pdf_order.php in a new tab with invoices as type $_GET argument.
         *
         * The order ids are passed as a serialized array to the oID $_GET argument.
         */
        function _onBulkDownloadInvoiceClick() {
            const orderIds = [];
            const maxAmountInvoicesBulkPdf = data.maxAmountInvoicesBulkPdf;

            $this.find('tbody input:checkbox:checked').each(function () {
                orderIds.push($(this).parents('tr').data('id'));
            });

            if (orderIds.length > maxAmountInvoicesBulkPdf) {
                const $modal = $('.bulk-error.modal');
                $modal.modal('show');

                const $invoiceMessageContainer = $modal.find('.invoices-message');
                $invoiceMessageContainer.removeClass('hidden');
                $modal.on('hide.bs.modal', () => $invoiceMessageContainer.addClass('hidden'));

                return;
            }

            _createBulkPdf(orderIds, 'invoice');
        }


        /**
         * Opens the gm_pdf_order.php in a new tab with packing slip as type $_GET argument.
         *
         * The order ids are passed as a serialized array to the oID $_GET argument.
         */
        function _onBulkDownloadPackingSlipClick() {
            const orderIds = [];
            const maxAmountPackingSlipsBulkPdf = data.maxAmountPackingSlipsBulkPdf;
            let $modal;
            let $packingSlipsMessageContainer;

            $this.find('tbody input:checkbox:checked').each(function () {
                orderIds.push($(this).parents('tr').data('id'));
            });

            if (orderIds.length > maxAmountPackingSlipsBulkPdf) {
                $modal = $('.bulk-error.modal');
                $modal.modal('show');
                $packingSlipsMessageContainer = $modal.find('.packing-slips-message');

                $packingSlipsMessageContainer.removeClass('hidden');

                $modal.on('hide.bs.modal', function () {
                    $packingSlipsMessageContainer.addClass('hidden');
                });

                return;
            }

            _createBulkPdf(orderIds, 'packingslip');
        }

        /**
         * Creates a bulk pdf with invoices or packing slips information.
         *
         * This method will check if all the selected orders have a document and open a concatenated PDF file. If there
         * are orders that do not have any document then a modal will be shown, prompting the user to create the missing
         * documents or continue without them.
         *
         * @param {Number[]} orderIds Provide the selected order IDs.
         * @param {String} type Provide the bulk PDF type "invoice" or "packingslip".
         */
        function _createBulkPdf(orderIds, type) {
            if (type !== 'invoice' && type !== 'packingslip') {
                throw new Error('Invalid type provided: ' + type);
            }

            const url = jse.core.config.get('appUrl') + '/admin/admin.php';
            const data = {
                do: 'OrdersOverviewAjax/GetOrdersWithoutDocuments',
                pageToken: jse.core.config.get('pageToken'),
                type,
                orderIds
            };

            $.getJSON(url, data)
                .done(orderIdsWithoutDocument => {
                    if (orderIdsWithoutDocument.exception) {
                        const title = jse.core.lang.translate('error', 'messages');
                        const message = jse.core.lang.translate('GET_ORDERS_WITHOUT_DOCUMENT_ERROR', 'admin_orders');
                        jse.libs.modal.showMessage(title, message);
                        return;
                    }

                    if (!orderIdsWithoutDocument.length) {
                        _openBulkPdfUrl(orderIds, type); // All the selected order have documents.
                        return;
                    }

                    // Some orders do not have documents, display the confirmation modal.
                    const $modal = $('.modal.create-missing-documents');
                    $modal.find('.order-ids-list').text(orderIdsWithoutDocument.join(', '));
                    $modal
                        .data({
                            orderIds,
                            orderIdsWithoutDocument,
                            type
                        })
                        .modal('show');
                })
                .fail((jqxhr, textStatus, errorThrown) => {
                    const title = jse.core.lang.translate('error', 'messages');
                    const message = jse.core.lang.translate('GET_ORDERS_WITHOUT_DOCUMENT_ERROR', 'admin_orders');
                    jse.libs.modal.showMessage(title, message);
                });
        }

        /**
         * Create Missing Documents Proceed Handler
         *
         * This handler will be executed whenever the user proceeds through the "create-missing-documents" modal. It will
         * be resolved even if the user does not select the checkbox "create-missing-documents".
         *
         * @param {jQuery.Event} event jQuery event object.
         * @param {Number[]} orderIds The selected orders to be included in the PDF.
         * @param {String} type Whether 'invoice' or 'packingslip'.
         * @param {Object} downloadPdfWindow Provide a window handle for bypassing browser's popup blocking.
         */
        function _onCreateMissingDocumentsProceed(event, orderIds, type, downloadPdfWindow) {
            _openBulkPdfUrl(orderIds, type, downloadPdfWindow);
        }

        /**
         * On Single Checkbox Ready
         *
         * This callback will use the event.data.orderIds to set the checked checkboxes after a table re-render.
         *
         * @param {jQuery.Event} event
         */
        function _onSingleCheckboxReady(event) {
            event.data.orderIds.forEach(id => {
                $this.find(`tr#${id} input:checkbox`).single_checkbox('checked', true).trigger('change');
            });

            // Bulk action button should't be disabled after a datatable reload.
            if ($('tr input:checkbox:checked').length) {
                $('.bulk-action').find('button').removeClass('disabled');
            }
        }

        /**
         * Opens the URL which provides the bulk PDF for download.
         *
         * @param {Number[]} orderIds The orders to be used for the concatenated document.
         * @param {String} type Whether 'invoice' or 'packingslip'.
         */
        function _openBulkPdfUrl(orderIds, type) {
            const parameters = {
                do: 'OrdersModalsAjax/BulkPdf' + (type === 'invoice' ? 'Invoices' : 'PackingSlips'),
                pageToken: jse.core.config.get('pageToken'),
                o: orderIds
            };

            const url = jse.core.config.get('appUrl') + '/admin/admin.php?' + $.param(parameters);

            window.open(url, '_parent');

            // Keep checkboxes checked after a datatable reload.
            $this.DataTable().ajax.reload(() => {
                $this
                    .off('single_checkbox:ready', _onSingleCheckboxReady)
                    .on('single_checkbox:ready', {orderIds}, _onSingleCheckboxReady);
            });
            $this.orders_overview_filter('reload');
        }

        /**
         * On Packing Slip Click
         */
        function _onShowPackingSlipClick() {
            // Message modal data.
            const title = jse.core.lang.translate('TITLE_SHOW_PACKINGSLIP', 'orders');
            const message = jse.core.lang.translate('NO_PACKINGSLIP_AVAILABLE', 'orders');

            // Request data.
            const rowData = $(this).parents('tr').data();
            const url = jse.core.config.get('appUrl') + '/admin/admin.php';

            // Request parameters.
            const data = {
                id: rowData.id,
                do: 'OrdersOverviewAjax/GetLatestPackingSlip',
                pageToken: jse.core.config.get('pageToken')
            };

            // Directly open a new tab (popup blocker workaround)
            const newTab = window.open('about:blank');

            $.ajax({dataType: 'json', url, data})
                .done(response => {
                    if (response.length) {
                        // Get the file name from the response.
                        const filename = response[0].file;

                        // Packing slip link parameters.
                        const parameters = {
                            module: 'OrderAdmin',
                            action: 'showPdf',
                            type: 'packingslip',
                            file: filename
                        };

                        // Open package slip.
                        newTab.location =
                            `${jse.core.config.get('appUrl')}/admin/request_port.php?${$.param(parameters)}`;
                    } else {
                        // No packing slip found
                        newTab.close();
                        jse.libs.modal.showMessage(title, message);
                    }
                });
        }

        /**
         * On Invoice Create Click
         */
        function _onCreateInvoiceClick() {
            const link = $(this).attr('href');
            const $loadingSpinner = jse.libs.loading_spinner.show($this);
            const pageToken = jse.core.config.get('pageToken');
            const orderId = $(this).parents('tr').data().id;
            const url = jse.core.config.get('appUrl')
                + `/admin/admin.php?do=OrdersModalsAjax/GetInvoiceCount&pageToken=${pageToken}&orderId=${orderId}`;

            // Directly open a new tab (popup blocker workaround)
            const newTab = window.open('about:blank');

            function createInvoice() {
                newTab.location = link;
                $this.DataTable().ajax.reload(null, false);
            }

            function addInvoice() {
                window.open(link, '_blank');
                $this.DataTable().ajax.reload(null, false);
            }

            function onRequestSuccess(response) {
                const modalTitle = jse.core.lang.translate('TITLE_CREATE_INVOICE', 'orders');
                const modalMessage = jse.core.lang.translate('TEXT_CREATE_INVOICE_CONFIRMATION', 'orders');
                const modalButtons = [
                    {
                        title: jse.core.lang.translate('yes', 'buttons'),
                        callback: event => {
                            closeModal(event);
                            addInvoice();
                        }
                    },
                    {
                        title: jse.core.lang.translate('no', 'buttons'),
                        callback: closeModal
                    }
                ];

                function closeModal(event) {
                    $(event.target).parents('.modal').modal('hide');
                }

                jse.libs.loading_spinner.hide($loadingSpinner);

                if (!response.count) {
                    createInvoice();
                } else {
                    newTab.close();
                    jse.libs.modal.showMessage(modalTitle, modalMessage, modalButtons)
                }
            }

            function onRequestFailure() {
                jse.libs.loading_spinner.hide($loadingSpinner);
                createInvoice();
            }

            jse.libs.xhr.get({url})
                .done(onRequestSuccess)
                .fail(onRequestFailure);
        }

        /**
         * On Invoice Link Click
         *
         * The script that generates the PDFs is changing the status of an order to "invoice-created". Thus the
         * table data need to be redrawn and the filter options to be updated.
         */
        function _onShowInvoiceClick() {
            // Message modal data.
            const title = jse.core.lang.translate('TITLE_SHOW_INVOICE', 'orders');
            const message = jse.core.lang.translate('NO_INVOICE_AVAILABLE', 'orders');

            // Request data.
            const rowData = $(this).parents('tr').data();
            const url = jse.core.config.get('appUrl') + '/admin/admin.php';

            // Request parameters.
            const data = {
                id: rowData.id,
                do: 'OrdersOverviewAjax/GetInvoices',
                pageToken: jse.core.config.get('pageToken')
            };

            // Directly open a new tab (popup blocker workaround)
            const newTab = window.open('about:blank');

            $.ajax({dataType: 'json', url, data})
                .done(response => {
                    if (response.length) {
                        // Get the file name from object with the highest ID within response array.
                        const {invoiceNumber, orderId} = response[0];

                        // Invoice link parameters.
                        const parameters = {
                            module: 'OrderAdmin',
                            action: 'showPdf',
                            type: 'invoice',
                            invoice_number: invoiceNumber,
                            order_id: orderId
                        };

                        // Open invoice
                        newTab.location =
                            `${jse.core.config.get('appUrl')}/admin/request_port.php?${$.param(parameters)}`;
                    } else {
                        // No invoice found
                        newTab.close();
                        jse.libs.modal.showMessage(title, message);
                    }
                });
        }

        // ------------------------------------------------------------------------
        // INITIALIZATION
        // ------------------------------------------------------------------------

        module.init = function (done) {
            // Bind table row actions.
            $this
                .on('click', 'tbody tr', _onTableRowClick)
                .on('change', '.bulk-selection', _onBulkSelectionChange)
                .on('change', 'input:checkbox', _onTableRowCheckboxChange)
                .on('click', '.show-invoice', _onShowInvoiceClick)
                .on('click', '.show-packing-slip', _onShowPackingSlipClick)
                .on('click', '.create-invoice', _onCreateInvoiceClick)
                .on('click', '.email-invoice', _onEmailInvoiceClick)
                .on('click', '.email-order', _onEmailOrderClick)
                .on('click', '.order-status.label', _onChangeOrderStatusClick)
                .on('click', '.add-tracking-number', _onAddTrackingNumberClick);

            // Bind table row and bulk actions.
            $this.parents('.orders')
                .on('click', '.btn-group .change-status', _onChangeOrderStatusClick)
                .on('click', '.btn-group .cancel', _onCancelOrderClick)
                .on('click', '.btn-group .bulk-email-order', _onBulkEmailOrderClick)
                .on('click', '.btn-group .bulk-email-invoice', _onBulkEmailInvoiceClick)
                .on('click', '.btn-group .bulk-download-invoice', _onBulkDownloadInvoiceClick)
                .on('click', '.btn-group .bulk-download-packing-slip', _onBulkDownloadPackingSlipClick);

            // Bind custom events.
            $(document).on('create_missing_documents:proceed', '.modal.create-missing-documents',
                _onCreateMissingDocumentsProceed);

            done();
        };

        return module;
    });

Youez - 2016 - github.com/yon3zu
LinuXploit