Extending Order handling with PDF RMA Form

4 个月 前
Hi
I'm trying to extend the Order List with new features, by adding new buttons on the top of the Order List page. (in the admin_order_list_buttons widget zone).
Until now, parts of it, is working as expected and I'm able to Select a series of Orders and call a action to Mark all selected orders as Shipped. When I try to call a action that will create a Pdf RMA Form, the Pdf file is not downloaded as expected.

I have implemented the Pdf download logic the same way as the PDF Invoice feature in the Order List, and the main difference here is that the calling the action to generate the Pdf, is activated from the Widget, embedded in the admin_order_list_buttons widget zone.

This is how it’s currently implemented where the action is called as expected and the RMA Pdf logic is called and a get back the Pdf file, but it’s not downloaded in the Order List view:

@{
    Layout = "";
}
<div class="btn-group">
    <button type="button" id="ship-selected" class="btn bg-olive">
        <i class="fa fa-file-code-o"></i>
        @T("OrderManagerAdmin.Ship.Selected")
    </button>
</div>

<div class="btn-group">
    <button type="button" id="rmaform-selected" class="btn bg-olive">
        <i class="fa fa-file-code-o"></i>
        @T("OrderManagerAdmin.RmaForm.Selected")
    </button>
</div>

<script>
    $(document).ready(function () {

        //"ship selected" button
        $('#ship-selected').click(function(e) {
            e.preventDefault();

            var ids = selectedIds.join(",");
            if (!ids) {
                $('#orderManagementSelected-info').text("@T("Admin.Orders.NoOrders")");
                $("#orderManagementSelected").click();
            }
            else {
                var postData = {
                    selectedIds: selectedIds
                };
                addAntiForgeryToken(postData);

                $.ajax({
                    cache: false,
                    type: "POST",
                    url: "@(Url.Action("ShipSelectedOrders", "OrderManagement"))",
                    data: postData,
                    complete: function (data) {
                        //reload grid
                        updateTable('#orders-grid');
                    },
                    error: function (xhr, ajaxOptions, thrownError) {
                        $('#orderManagementSelected-info').text(errorThrown);
                        $("#orderManagementSelected").click();
                    },
                    traditional: true
                });
            }
            return false;
        });

        //"Rma Form selected" button
        $('#rmaform-selected').click(function(e) {
            e.preventDefault();

            var ids = selectedIds.join(",");
            if (!ids) {
                $('#rmaExtensionSelected-info').text("@T("Admin.Orders.NoOrders")");
                $("#rmaExtensionSelected").click();
            }
            else {
                var postData = {
                    selectedIds: selectedIds
                };
                addAntiForgeryToken(postData);

                $.ajax({
                    cache: false,
                    type: "POST",
                    url: "@(Url.Action("OrdersPdfRmaFormsSelected", "OrderManagement"))",
                    data: postData,
                    complete: function (data) {
                        //reload grid
                        updateTable('#orders-grid');
                    },
                    error: function (xhr, ajaxOptions, thrownError) {
                        $('#rmaExtensionSelected-info').text(errorThrown);
                        $("#rmaExtensionSelected").click();
                    },
                    traditional: true
                });
            }
            return false;
        });
    });
</script>

<nop-alert asp-alert-id="rmaExtensionSelected" />
<nop-alert asp-alert-id="orderManagementSelected" />

This is the action called to generate the Pdf file
        [HttpPost]
        public virtual async Task<IActionResult> OrdersPdfRmaFormsSelected(string selectedIds)
        {
            if (!await _permissionService.AuthorizeAsync(StandardPermissionProvider.ManageOrders))
                return AccessDeniedView();

            var orders = new List<Order>();

            if (selectedIds != null)
            {
                var ids = selectedIds
                .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => Convert.ToInt32(x))
                .ToArray();

                orders.AddRange((await _orderService.GetOrdersByIdsAsync(ids)));
            }

            try
            {
                byte[] bytes;
                await using (var stream = new MemoryStream())
                {
                    await _rmaPdfService.PrintOrderRmaToPdfAsync(stream, orders, _orderSettings.GeneratePdfInvoiceInCustomerLanguage ? 0 : (await _workContext.GetWorkingLanguageAsync()).Id);
                    bytes = stream.ToArray();
                }

                return File(bytes, MimeTypes.ApplicationPdf, "rma-forms.pdf");
            }
            catch (Exception exc)
            {
                await _notificationService.ErrorNotificationAsync(exc);
                return NoContent();
            }
        }

I also tried this, to mimic the logic used in the List.cshtml (Core Order List View), but then the action is not called:

@{
    Layout = "";
}

<div class="btn-group">
    <button type="button" id="rmaform-selected" class="btn bg-olive">
        <i class="fa fa-file-code-o"></i>
        @T("RmaExtensionAdmin.RmaForm.Selected")
    </button>
</div>

<form asp-controller="RmaExtension" asp-action="OrderManagement" method="post" id="pdf-rmaform-selected-form">
    <input type="hidden" id="selectedIds" name="selectedIds" value="" />
</form>

<script>
    $(document).ready(function () {

        $('#rmaform-selected').click(function (e) {
            e.preventDefault();
            var ids = selectedIds.join(",");
            if (!ids) {
                $('#rmaExtensionSelected-info').text("@T("Admin.Orders.NoOrders")");
                $("#rmaExtensionSelected").click();
            }
            else {
                $('#pdf-rmaform-selected-form #selectedIds').val(ids);
                $('#pdf-rmaform-selected-form').submit();
                updateTable('#orders-grid');
            }
            return false;
        });
    });
</script>

<nop-alert asp-alert-id="rmaExtensionSelected" />

Finally, I have tried to add a form to the end of the List.cshtml (Core Order List View) as shown below, then the Pfd file is download correctly:

@*Print packaging slips selected (XML). We don't use GET approach because it's limited to 2K-4K chars and won't work for large number of entities*@
<form asp-controller="Order" asp-action="PdfInvoiceSelected" method="post" id="pdf-invoice-selected-form">
    <input type="hidden" id="selectedIds" name="selectedIds" value="" />
</form>

<script>
    $(document).ready(function () {
        $('#pdf-invoice-selected').click(function (e) {
            e.preventDefault();
            var ids = selectedIds.join(",");
           if (!ids) {
                $('#pdfInvoiceSelected-info').text("@T("Admin.Orders.NoOrders")");
                $("#pdfInvoiceSelected").click();
            }
            else {
                $('#pdf-invoice-selected-form #selectedIds').val(ids);
                $('#pdf-invoice-selected-form').submit();
                updateTable('#orders-grid');
            }
            return false;
        });
    });
</script>

//Print RMA Form added as a plugin
<form asp-controller="RmaExtension" asp-action="OrdersPdfRmaFormsSelected" method="post" id="pdf-rmaform-selected-form">
    <input type="hidden" id="selectedIds" name="selectedIds" value="" />
</form>

I believe that the main problem is the Pdf generated in the action cannot be returned from the Ajax call, but when You add the form, it’s possible, but only if the form is on the List.cshtml and not in the ViewComponent (Widget). Also calling an action form the Widget works fine as long as it does not return anything, like the “Mark all selected orders as Shipped” I have implemented.

Does anyone have a suggestion for an alternative solution for this problem?

Best Regards
Objecta Data
Klaus E. Frederiksen
4 个月 前
Just trying  to give alternative suggestion:
You can call a js function when clicking top download button and inside that function you can trigger click event to all selected grid order list download button one by one. Thanks