CyberStore Documentation
BillingHistory_Grid Widget

A widget that produces a listing of open invoices on an account. Introduced in v2.20.0. 

 Remarks
The BillingHistory_Grid widget is designed to provide a front-end user interface that allows Shoppers to view their Customer Account information including open invoices. They may review account aging, view individual invoices (via the linked DocumentViewer_Popup widget, as well as make payments on their account (via the linked ProcessPayment_Popup widget).

By default the widget can be seen by navigating to /ecommerce/CustomerBilling.aspx as a logged in Shopper. 

       
Once the page has been accessed and the user logs in, they will see customer account information. The top section provides information about the current standing of their account including current balance, account status, available credit (if any), and aging information. Additionally, if the account balance is positive (i.e. not in a credit state) then the top section will also include a "Pay Account in Full" button. 

In the section below the account standing information, the invoice grid is displayed which will list any open invoices.
Users can view and print individual invoices by either clicking the invoice number, or clicking the view icon 

 

       
Shoppers may select individual invoices by bank account (ACH in the United States) or credit card by cliciking the checkboxes in each row and then click the "Pay Selected Invoices" button to pop up the payment options. If the shopper prefers to pay single invoices in full (or as a partial payment) they may click any individual Pay icon .
       

After payments are made, adjustments are displayed by reloading of the Billing History page. Changes will appear in both the account standing section and the invoice grid. Invoices paid in full will be removed from the list, or if partial payments are applied, the payment will be reflected in the Balance Due column.         
 Widget Option Usage

Widget options provide a way to customize widgets in various ways. Widget options are sent to the widget when loaded with the LoadWidgetControl.

 

 Widget Conventions
 Example

See an example of how to load and configure this widget in SitePages.config.

<Control src="LoadWidgetControl.ascx" 
    FileLocation="BillingHistory_Grid.html" 
    RequireLogin="true" 
/>
 Widget Source

The following is the source code for this widget.

Developer's Note:

To create a custom version of the widget, copy all of the code below into a file of the same name and place it into your Site's widgets folder (e.g., ../YourSiteFolder/Widgets). The CyberStore page engine will then override the default source with your customized version.

<style>
    /* override the font-size of the default widgets for readaiblity in the grid */
    .dx-widget {
        font-size: 16px !important;
    }
</style>
<div id="divLoadPanel"></div>
<h1>Billing History</h1>
<div id="divBillingHistoryWrapper" style="min-height:800px;">
    <div id="divSummary"
         style="display:none;background-color:#dedede; border:1px solid #ababab;padding:25px;vertical-align:middle;width:100%;">
        <h3 id="hCustomerName" style="margin-top:0px;"></h3>

        <div style="float:right;">
            <div id="btnMakePayment" class="btn btn-primary-theme"></div>
        </div>
        <div style="float:left;">
            <b>Account Balance:</b><br />
            <span id="spnBalance" style="font-size:36px;"></span><br />
            <span id="spnDunningMessage" style="font-size:small;"></span>
        </div>
        <div style="text-align:left;margin-left:150px;display:inline-block;font-size:smaller;">
            <div style="display:table;">
                <div style="display:table-row">
                    <div style="display:table-cell;padding-right:20px;">
                        <b>Current:</b>
                    </div>
                    <div style="display:table-cell;text-align:right;">
                        <span id="spnCurrent"></span><br />
                    </div>
                </div>
                <div style="display:table-row">
                    <div style="display:table-cell;">
                        <b>30 Days:</b>
                    </div>
                    <div style="display:table-cell;text-align:right;">
                        <span id="spn30Days"></span><br />
                    </div>
                </div>
                <div style="display:table-row">
                    <div style="display:table-cell;">
                        <b>60 Days:</b>
                    </div>
                    <div style="display:table-cell;text-align:right;">
                        <span id="spn60Days"></span><br />
                    </div>
                </div>
                <div style="display:table-row">
                    <div style="display:table-cell;">
                        <b>90+ Days:</b>
                    </div>
                    <div style="display:table-cell;text-align:right;">
                        <span id="spn90Days" class="format-currency"></span><br />
                    </div>

                </div>
            </div>
        </div>
    </div>
    <br />
    <div id="grdInvoices"></div>
</div>
<div id="popupContainer"></div>
<script type="text/javascript">
    /*'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' Widget:  BillingHistory_Grid.html
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' (c) 2021 by Dovetail Internet Technologies, LLC
      '              www.dovetailinternet.com
      '              info@dovetailinternet.com
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' All rights reserved. Not to be used without permission.
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' Development Date: May - September 2021
      ' Release Version:  2.20.0
      ' Revision:         2.0
      ' Last Modified:    09/7/2021
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' Purpose: display customer aging and open invoices with
      '          links for viewing and making payments
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' Usage:   Requires B2B login shopper context
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      ' Example SitePages usage:

          <Control src="LoadWidgetControl.ascx"
               FileLocation="BillingHistory_Grid.html"
               RequireLogin="true"
          />
      '
      '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  */

    // >>>>>>>>>>>>>>>>>>>>> Declare widget variables in GLOBAL space <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    var Invoices = [];
    var InvoicesToPay = [];
    var BillingLoadPanel = null
    var InvoiceGrid;
    var PayButton;
    var Aging = {};
    var PreferredPaymentType = '';
    var PaymentTypes = [];
    var SelectedPaymentType = '';



    ///-------------------------------------------------------------------------------------------------
    /// <summary>
    ///     The main widget function. Executes on page load.
    /// <returns>
    ///     .
    /// </returns>
    ///-------------------------------------------------------------------------------------------------
    $(function () {
        MakeAJAXCall("Billing.GetPaymentMethods", {}, function (DATA) {
            if (ValidAJAXResponse(DATA)) {
                var res = JSON.parse(DATA);
                PaymentTypes = res.Data.Methods
                for (var p = 0; p < PaymentTypes.length; p++) {
                    if (PaymentTypes[p].MethodType === 'BA' || PaymentTypes[p].MethodType === 'CC') {
                        PreferredPaymentType = PaymentTypes[p].MethodType;
                        break;
                    }
                }
                SelectedPaymentType = PreferredPaymentType;
            }

            BillingLoadPanel = $('#divLoadPanel').dxLoadPanel({
                shadingColor: 'rgba(0,0,0,0.7)',
                visible: true,
                showIndicator: true,
                showPane: true,
                closeOnOutsideClick: false,
                message: 'Loading account history ...',
            }).dxLoadPanel('instance');

            PayButton = $('#btnMakePayment').dxButton({
                text: "Pay Account in Full",
                type: 'danger',
            }).dxButton('instance');

            InvoiceGrid = $('#grdInvoices').dxDataGrid({
                visible: false,
            }).dxDataGrid('instance');


            function createInvoiceGrid() {
                InvoiceGrid.option({
                    columnHidingEnabled: true,
                    columns: [{
                        dataField: 'InvoiceDate',
                        caption: 'Date',
                        dataType: 'date',
                        sortIndex: 0,
                        sortOrder: 'desc',
                        hidingPriority: 2,
                    },
                    {
                        dataField: 'InvoiceNumber',
                        caption: 'Invoice Number',
                        dataType: 'string',
                        sortIndex: 1,
                        alignment: 'center',
                        cellTemplate: function (e, item) {
                            var num = item.data.InvoiceNumber;
                            if (num != '') {
                                return $("<div>").append(
                                    $("<a>")
                                        //.attr('onclick', 'GetInvoicePopup(\'' + num + '\');')
                                        .attr('onclick', 'showDocumentViewerPopUp("Invoice","' + num + '");')
                                        .text(num)
                                )

                            } else {
                                return num;
                            }
                        }
                    },
                    {
                        dataField: 'PONumber',
                        caption: 'P.O. Number',
                        dataType: 'string',
                        hidingPriority: 0,
                    },
                    {
                        dataField: 'DueDate',
                        dataType: 'date'
                    },
                    {
                        dataField: 'InvoiceTotal',
                        dataType: 'string',
                        hidingPriority: 1,

                    },
                    {
                        dataField: 'CurrentBalance',
                        caption: 'Balance Due',
                        dataType: 'string'
                    },
                    {
                        dataField: 'InvoiceTotalAmount',
                        dataType: 'decimal',
                        visible: false
                    },
                    {
                        dataField: 'CurrentBalanceAmount',
                        dataType: 'decimal',
                        visible: false
                    },
                    {
                        caption: 'View',
                        type: 'buttons',
                        alignment: 'center',
                        hidingPriority: 3,
                        buttons: [{
                            text: 'Open Invoice',
                            icon: 'fa fa-file-text-o',
                            onClick: function (e) {
                                // showDocumentViewerPopUp(doctype, doc id)
                                showDocumentViewerPopUp('Invoice', e.row.data.InvoiceNumber);
                            },
                            visible: function (e) {
                                return e.row.data.InvoiceNumber != '';
                            }
                        }]
                    },

                    {
                        caption: 'Pay',
                        type: 'buttons',
                        alignment: 'center',
                        visible: (PreferredPaymentType === 'BA' || PreferredPaymentType === 'CC'),
                        buttons: [{
                            text: 'Pay Invoice',
                            icon: 'fa fa-credit-card',
                            onClick: function (e) {
                                InvoicesToPay = [{
                                    Invoice: e.row.data.InvoiceNumber,
                                    AmountToPay: e.row.data.CurrentBalanceAmount
                                }];

                                ShowPaymentPopup(e.row.data.CurrentBalanceAmount, true);
                            },
                            visible: function (e) {
                                return e.row.data.CurrentBalanceAmount > 0 && e.row.data.InvoiceNumber != '';
                            }
                        }]
                    }
                    ],
                    hoverStateEnabled: true,
                    allowColumnReordering: true,
                    noDataText: 'No rows returned!',
                    showBorders: false,
                    showColumnHeaders: true,
                    showColumnLines: false,
                    rowAlternationEnabled: true,
                    paging: {
                        enabled: (widgetOptions.enablePaging != null) ?
                            widgetOptions.enablePaging :
                            true,
                        pageIndex: 0,
                        pageSize: widgetOptions.pageSize || 20,
                    },
                    pager: {
                        allowedPageSizes: "auto",
                        infoText: "Page {0} of {1} ({2} Total Invoices)",
                        showInfo: true,
                        showNavigationButtons: false,
                        showPageSizeSelector: true,
                        visible: "auto"
                    },
                    selection: {
                        allowSelectAll: true,
                        deferred: false,
                        mode: (PreferredPaymentType === 'BA' || PreferredPaymentType === 'CC')
                            ? 'multiple'
                            : 'none',
                        selectAllMode: 'allPages',
                        showCheckBoxesMode: 'always'
                    },
                    searchPanel: {
                        highlightCaseSensitive: false,
                        highlightSearchText: true,
                        placeholder: 'Filter by...',
                        searchVisibleColumnsOnly: true,
                        text: '',
                        visible: true,
                        width: 160
                    },
                    onToolbarPreparing: function (e) {
                        var dataGrid = e.component;

                        e.toolbarOptions.items.unshift({
                            location: 'before',
                            widget: 'dxButton',
                            options: {
                                text: 'Pay Selected Invoices',
                                visible: (PreferredPaymentType === 'BA' || PreferredPaymentType === 'CC'),

                                type: 'default',
                                onClick: function (e) {
                                    var selectedRows = dataGrid.getSelectedRowsData();
                                    // clear out the global InvoicesToPay value since we will reset it
                                    InvoicesToPay = [];

                                    if (selectedRows.length > 0) {
                                        var totalToPay = selectedRows.reduce((accum, item) => accum + item.CurrentBalanceAmount, 0);
                                        for (var r = 0; r < selectedRows.length; r++) {
                                            InvoicesToPay.push({
                                                Invoice: selectedRows[r].InvoiceNumber,
                                                AmountToPay: selectedRows[r].CurrentBalanceAmount
                                            });
                                        }
                                        ShowPaymentPopup(totalToPay, false);
                                    } else {
                                        ToastAlert('You must select at least one Invoice to pay.', false);
                                    }
                                }
                            }
                        });
                    },
                    // Customize what happens on these calls
                    onEditorPreparing: onEditorPreparing,
                    onSelectionChanged: onSelectionChanged
                });
            }

            MakeAJAXCall('Visitor.GetAccountProfile', {}, function (DATA) {
                var response = JSON.parse(DATA);
                if (response.Result.Success) {
                    var profile = response.Data;
                    $('#hCustomerName').text(profile.Name);
                    //
                    // setup the payment object valuess tied to the profile
                    if (typeof Payment !== 'undefined') {

                        Payment.Address1 = profile.BillingAddress.Address1;
                        Payment.Address2 = profile.BillingAddress.Address2;
                        Payment.City = profile.BillingAddress.City;
                        Payment.State = profile.BillingAddress.State;
                        Payment.ZipCode = profile.BillingAddress.Zip;
                        Payment.Country = profile.BillingAddress.Country;
                        Payment.FirstName = profile.FirstName;
                        Payment.LastName = profile.LastName;
                        Payment.BaNameOnAccount1 = profile.FirstName;
                        Payment.BaNameOnAccount2 = profile.LastName;
                        Payment.Email = profile.Email;
                        Payment.Telephone = profile.BillingAddress.Phone;
                    }
                } else {
                    $('#hCustomerName').css('display', 'none');
                }
            });


            var selectAllCheckBox;
            var checkBoxUpdating = false;



            // get aging and invoice details
            LoadAccountDetails(true);

            createInvoiceGrid();


            ///-------------------------------------------------------------------------------------------------
            /// <summary>
            ///     Is selectable.
            /// </summary>
            ///
            /// <param name="item">
            ///     The item.
            /// </param>
            ///
            /// <returns>
            ///     .
            /// </returns>
            ///-------------------------------------------------------------------------------------------------
            function isSelectable(item) {
                // Return true or false is the editor is selectable
                if (item.CurrentBalanceAmount < 0.01) {
                    return false;
                }
                if (item.InvoiceNumber == '') {
                    return false;
                }
                if (item.CurrentBalanceAmount > 0.00 && item.InvoiceNumber != '') {
                    return true;
                }
            }

            ///-------------------------------------------------------------------------------------------------
            /// <summary>
            ///     Is select all.
            /// </summary>
            ///
            /// <param name="dataGrid">
            ///     The data grid.
            /// </param>
            ///
            /// <returns>
            ///     .
            /// </returns>
            ///-------------------------------------------------------------------------------------------------
            function isSelectAll(dataGrid) {
                var items = [];
                items = Invoices;
                var selectableItems = items.filter(isSelectable);
                var selectedRowKeys = dataGrid.option("selectedRowKeys");

                if (!selectedRowKeys.length) {
                    return false;
                }
                return selectedRowKeys.length >= selectableItems.length ? true : undefined;
            }

            ///-------------------------------------------------------------------------------------------------
            /// <summary>
            ///     Executes the editor preparing action.
            /// </summary>
            ///
            /// <param name="e">
            ///     The editor.
            /// </param>
            ///
            /// <returns>
            ///     .
            /// </returns>
            ///-------------------------------------------------------------------------------------------------
            function onEditorPreparing(e) {
                var dataGrid = e.component;
                if (e.command === "select") {
                    if (e.parentType === "dataRow" && e.row) {
                        if (!isSelectable(e.row.data))
                            e.editorOptions.disabled = true;
                    } else if (e.parentType === "headerRow") {
                        e.editorOptions.onInitialized = function (e) {
                            selectAllCheckBox = e.component;
                        }
                        e.editorOptions.value = isSelectAll(dataGrid);
                        e.editorOptions.onValueChanged = function (e) {
                            if (!e.event) {
                                if (e.previousValue && !checkBoxUpdating) {
                                    e.component.option("value", e.previousValue);
                                }
                                return;
                            }
                            if (isSelectAll(dataGrid) === e.value) {
                                return;
                            }
                            e.value ? dataGrid.selectAll() : dataGrid.deselectAll();
                            e.event.preventDefault();
                        }
                    }
                }
            }

            ///-------------------------------------------------------------------------------------------------
            /// <summary>
            ///     Executes the selection changed action.
            /// </summary>
            ///
            /// <param name="e">
            ///     The editor.
            /// </param>
            ///
            /// <returns>
            ///     .
            /// </returns>
            ///-------------------------------------------------------------------------------------------------
            function onSelectionChanged(e) {
                var deselectRowKeys = [];
                e.selectedRowsData.forEach((item) => {
                    if (!isSelectable(item))
                        deselectRowKeys.push(e.component.keyOf(item));
                });
                if (deselectRowKeys.length) {
                    e.component.deselectRows(deselectRowKeys);
                }
                checkBoxUpdating = true;
                selectAllCheckBox.option("value", isSelectAll(e.component));
                checkBoxUpdating = false;

                //NOTE if InvoicesToPay ==[] then fill
                if (InvoicesToPay.length <= 0) {
                    e.selectedRowsData.forEach(j => {
                        InvoicesToPay.push({ Invoice: j.InvoiceNumber, AmountToPay: j.CurrentBalanceAmount });
                    });
                }
            }
        });
    });

    // >>>>>>>>>>>>>>>>>>>>> Widget Functions in GLOBAL space <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    ///-------------------------------------------------------------------------------------------------
    /// <summary>
    ///     Loads account details.
    /// </summary>
    ///
    /// <returns>
    ///     The account details.
    /// </returns>
    ///-------------------------------------------------------------------------------------------------
    function LoadAccountDetails(firstLoad) {
        // Get Aging
        MakeAJAXCall('Billing.GetCustomerAging', {}, function (DATA) {
            if (ValidAJAXResponse(DATA)) {
                var response = JSON.parse(DATA);
                if (response.Result.Success) {
                    var data = response.Data;
                    $('#spnBalance').text(data.CurrentBalance);
                    $('#spnCurrent').text(data.Current);
                    $('#spn30Days').text(data.Days30);
                    $('#spn60Days').text(data.Days60);

                    // we are only going to show up to 90 days of aging, so
                    // sum up the totals for 90, 120, 150 and 180 to come up
                    // with the 90 Days+ display number
                    var days90 = 0;
                    if (!isNaN(data.Days90Amount)) {
                        days90 = data.Days90Amount;
                    }
                    if (!isNaN(data.Days120Amount)) {
                        days90 += data.Days120Amount;
                    }
                    if (!isNaN(data.Days150Amount)) {
                        days90 += data.Days150Amount;
                    }
                    if (!isNaN(data.Days180Amount)) {
                        days90 += data.Days180Amount;
                    }

                    // load the sum into the text, it'll be formatted as currency because #spn90Days has class of .format-currency on it
                    $('#spn90Days').text(days90);

                    if (data.CustomerOnHold) {
                        $('#spnDunningMessage')
                            .text('Account On Hold')
                            .css('color', 'red');
                    }
                    if (data.CurrentBalanceAmount > 0 && data.CurrentBalanceAmount - data.CurrentAmount > 0) {
                        $('#spnDunningMessage')
                            .text('Account Past Due')
                            .css('color', 'red');
                    } else {
                        var availableCredit = data.CreditLimitAmount - data.CurrentBalanceAmount;
                        $('#spnDunningMessage')
                        // .html('Available Credit: <span class=\'format-currency\'>' + availableCredit + '</span>');
                        if (availableCredit < 0) {
                            $('#spnDunningMessage').css('color', 'red');
                        }
                    }

                    PayButton.option('onClick', function (e) {
                        InvoicesToPay = [];
                        InvoiceGrid.selectAll();
                        setTimeout(() => { ShowPaymentPopup(data.CurrentBalanceAmount, false) }, 40);

                    });

                    if (data.CurrentBalanceAmount <= 0 || !(PreferredPaymentType === 'BA' || PreferredPaymentType === 'CC')) {
                        PayButton.option('visible', false);
                    }

                    $('#divSummary').css('display', 'block');
                    InvoiceGrid.option('visible', true);

                    Aging = data;

                    PretifyNumbers();
                }
            }

            //
            // Get Open Invoices
            //
            MakeAJAXCall('Billing.GetCustomerInvoices', {}, function (DATA) {

                if (ValidAJAXResponse(DATA)) {
                    var response = JSON.parse(DATA);
                    if (response.Result.Success) {
                        Invoices = response.Data;
                        InvoiceGrid.option('dataSource', Invoices);
                        BillingLoadPanel.hide();
                        // get url and eveluate for direct link
                        if (firstLoad) {
                            var pagePath = window.location.pathname.toLowerCase();
                            if (pagePath.indexOf(String.Format('{0}/pay/', SITE_PATHS.application).toLowerCase()) > -1) {
                                var directPayInvoiceNumber = DOMPurify.sanitize(pagePath.substring(pagePath.lastIndexOf('/') + 1));
                                if (directPayInvoiceNumber !== null && directPayInvoiceNumber !== '') {
                                    var balDue = GetPropertyValueFromArrayByKeyValue(Invoices, 'InvoiceNumber', directPayInvoiceNumber, 'CurrentBalanceAmount');
                                    if (balDue !== '') {
                                        if (balDue <= 0) {
                                            var alertResult = DevExpress.ui.dialog.alert('Invoice number <b>' + directPayInvoiceNumber + '</b> does not have a balance due.<br><br>Please review the list of open invoices to make a payment.', 'Message');
                                            alertResult.done(function () {
                                                // nothing to do here
                                            });
                                        }
                                        else {
                                            InvoicesToPay = [{
                                                Invoice: directPayInvoiceNumber,
                                                AmountToPay: balDue
                                            }];
                                            ShowPaymentPopup(balDue, true);
                                        }
                                    }
                                    else {
                                        var alertResult = DevExpress.ui.dialog.alert('Sorry, invoice number <b>' + directPayInvoiceNumber + '</b> could not be found.<br><br>Please review the list of open invoices to make a payment.', 'Message');
                                        alertResult.done(function () {
                                            // nothing to do here
                                        });
                                    }
                                }
                            }
                        }

                    } else {
                        // handle if the call is not successful by alerting and redirecting to my account
                        var alertResult = DevExpress.ui.dialog.alert('Sorry, this feature is not currently available for your account.', 'Message');
                        alertResult.done(function () {
                            BillingLoadPanel.option('message', 'Redirecting...');
                            document.location.href = SITE_PATHS.application + '/CustomerMyAccount.aspx'
                        });
                    }
                }
            });
        });

    }


</script>

<style>
    .dx-datagrid-headers {
        color: #333;
        font-weight: 700;
    }
    span#spnBalance {
        line-height: 40px;
    }

    .dx-popup-title {
        background: #333;
        color: #fff;
    }

    .dx-popup-content {
        justify-content: space-around;
    }

    .dx-button-mode-contained .dx-icon,
    .dx-button-mode-text .dx-icon {
        color: #fff;
    }

    .dx-button-mode-contained.dx-button-default {
        background: #106e0b;
    }

        .dx-button-mode-contained.dx-button-default.dx-state-hover {
            background: #0f640a;
        }

    /*    .invoice-box {
        max-width: 800px;
        margin: auto;
        padding: 30px;
        border: 1px solid #eee;
        box-shadow: 0 0 10px rgba(0, 0, 0, .15);
        font-size: 16px;
        line-height: 24px;
        font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;
        color: #555;
    }*/

    .invoice-box table {
        width: 100;
        line-height: inherit;
        text-align: left;
    }

        .invoice-box table td {
            padding: 5px;
            vertical-align: top;
        }

        .invoice-box table tr td:nth-child(2) {
            text-align: right;
        }

        .invoice-box table tr.top table td {
            padding-bottom: 20px;
        }

            .invoice-box table tr.top table td.title {
                font-size: 45px;
                line-height: 45px;
                color: #333;
            }

        .invoice-box table tr.information table td {
            padding-bottom: 40px;
        }

        .invoice-box table tr.heading td {
            background: #eee;
            border-bottom: 1px solid #ddd;
            font-weight: bold;
        }

        .invoice-box table tr.details td {
            padding-bottom: 20px;
        }

        .invoice-box table tr.item td {
            border-bottom: 1px solid #eee;
        }

        .invoice-box table tr.item.last td {
            border-bottom: none;
        }

        .invoice-box table tr.total td:nth-child(2) {
            border-top: 2px solid #eee;
            font-weight: bold;
        }

    a.dx-link.dx-icon.fa.fa-file-text-o:focus {
        outline: 0px auto -webkit-focus-ring-color;
    }

    @media only screen and (max-width: 600px) {
        .invoice-box table tr.top table td {
            width;
            display: block;
            text-align: center;
        }

        .invoice-box table tr.information table td {
            width: 100;
            display: block;
            text-align: center;
        }
    }

    /** RTL **/
    .rtl {
        direction: rtl;
        font-family: 'Open Sans', Arial, sans-serif;
    }

        .rtl table {
            text-align: right;
        }

            .rtl table tr td:nth-child(2) {
                text-align: left;
            }

    .divTable {
        display: table;
        width;
    }

    .divTableRow {
        display: flex;
        /*table-row*/
        justify-content: space-between;
    }

        .divTableRow.headerRow {
            background-color: #106e0b;
            color: #fff;
        }

    .divTableHeading {
        background-color: #EEE;
        display: table-header-group;
    }

    .divTableCell.logo {
        background-image: url(/ecommerce/site/themes/images/logo.png);
        background-repeat: no-repeat;
        width: 250px;
        height: 100px;
        background-size: 100;
        margin: 0 0px;
        min-height: 10px;
        max-height: 180px;
    }

    .divTableCell {
        display: table-cell;
        padding: 5px 10px;
    }

    .divTableHead {
        display: table-cell;
        font-weight: bold;
        font-weight: bold;
    }

    .divTableRight {
        text-align: right;
    }

    .divTableBody {
        display: table-row-group;
    }

    .pseudocell {
        display: inline-block;
        width: 100px;
        text-align: left;
    }

    .divTableCell.StockCode,
    .divTableCell.divTableHead.divTableItem {
        min-width;
    }

    .divTableCell.StockDes,
    .divTableCell.divTableHead.divTableDesc {
        min-width: 35;
    }

    .divTableCell.Qty,
    .divTableCell.divTableHead.divTableQTY {
        min-width;
        text-align: center;
    }

    .divTableCell.Price,
    .divTableCell.divTableHead.divTableEA {
        min-width: 15;
        text-align: right;
    }

    .divTableCell.Gross,
    .divTableCell.divTableHead.divTablePrice {
        min-width;
        text-align: right;
    }

    .divTableCell.orderTotal {
        font-weight: 700;
    }
    .dx-toolbar-label > div {
        overflow: visible;
        width: fit-content;
    }
</style>
<link href="/ECommerce/site/Themes/css/widget.css" rel="stylesheet">