Plugin Directory

Changeset 3494405


Ignore:
Timestamp:
03/30/2026 09:58:31 AM (42 hours ago)
Author:
enituretechnology
Message:

1.3.13 - 2026-03-30

  • Update: Added bulk delete support for warehouse and drop ship locations.
  • Update: Added product-level offset days functionality.
  • Update: Added settings to include order metadata and control its visibility on the order details page.

Ticket# 23708293437, 40343186872

Location:
small-package-quotes-usps-edition
Files:
34 edited
1 copied

Legend:

Unmodified
Added
Removed
  • small-package-quotes-usps-edition/tags/1.3.13/admin/assets/en-usps-admin.css

    r3439225 r3494405  
    6464}
    6565
    66 #en_usps_quote_settings .en_usps_shipment_day,
    67 #en_usps_quote_settings .en_usps_all_shipment {
     66#en_usps_quote_settings .en_usps_shipment_day {
    6867    display: inline-block;
     68}
     69
     70#en_usps_quote_settings tr.en_usps_all_shipment {
     71    display: inline-flex;
     72    align-items: baseline;
    6973}
    7074
     
    140144.en_quote_settings_sub_options th {
    141145    padding: 0 0 10px 15px;
    142     margin-left: 10px !important;
    143146    font-weight: 400;
    144147}
     
    377380.woocommerce_variable_attributes.wc-metabox-content [class^="_nmfc_number"],
    378381.woocommerce_variable_attributes.wc-metabox-content [class^="_en_product_markup"],
     382.woocommerce_variable_attributes.wc-metabox-content [class^="_eniture_product_level_fulfillment_offset_days"],
    379383.woocommerce_variable_attributes.wc-metabox-content [class^="_nestedPercentage"],
    380384.woocommerce_variable_attributes.wc-metabox-content [class^="en_flat_rate_price"],
     
    400404.woocommerce_variable_attributes.wc-metabox-content [class^="en_flat_rate_price"],
    401405.woocommerce_variable_attributes.wc-metabox-content [class^="_en_product_markup"],
     406.woocommerce_variable_attributes.wc-metabox-content [class^="_eniture_product_level_fulfillment_offset_days"],
    402407.woocommerce_variable_attributes.wc-metabox-content [class^="_nestedPercentage"],
    403408.woocommerce_variable_attributes.wc-metabox-content [class^="_nestedDimension"],
     
    409414.woocommerce_variable_attributes.wc-metabox-content .data p[class*="en_flat_rate_price"] span.woocommerce-help-tip,
    410415.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_en_product_markup"] span.woocommerce-help-tip,
     416.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_eniture_product_level_fulfillment_offset_days"] span.woocommerce-help-tip,
    411417.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_nestedPercentage"] span.woocommerce-help-tip,
    412418.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_nestedDimension"] span.woocommerce-help-tip,
  • small-package-quotes-usps-edition/tags/1.3.13/admin/assets/en-usps-admin.js

    r3439225 r3494405  
    66    jQuery('#shipping_methods_do_not_sort_by_price').closest('table').attr('id', 'en_usps_quote_settings');
    77    jQuery("#order_shipping_line_items .shipping .display_meta").css('display', 'none');
     8    jQuery("#en_usps_fulfilment_offset_days").attr('maxlength', '2');
    89
    910    // Quote Settings Tab
     
    3031        // Delivery estimate options changed
    3132        jQuery("input[name=en_delivery_estimate_options_usps]").on('change load', function () {
    32             var en_delivery_estimate_val = jQuery('input[name=en_delivery_estimate_options_usps]:checked').val();
     33            const en_delivery_estimate_val = jQuery('input[name=en_delivery_estimate_options_usps]:checked').val();
    3334            if (en_delivery_estimate_val == 'dont_show_estimates') {
    3435                jQuery("#en_usps_cutt_off_time").prop('disabled', true);
    3536                jQuery("#en_usps_fulfilment_offset_days").prop('disabled', true);
     37                jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', true);
    3638            } else {
    3739                jQuery("#en_usps_cutt_off_time").prop('disabled', false);
    3840                jQuery("#en_usps_fulfilment_offset_days").prop('disabled', false);
    39             }
    40         });
     41                jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', false);
     42            }
     43        });
     44
     45        const en_delivery_estimate_val = jQuery('input[name=en_delivery_estimate_options_usps]:checked').val();
     46        if (en_delivery_estimate_val == 'dont_show_estimates') {
     47            jQuery("#en_usps_cutt_off_time").prop('disabled', true);
     48            jQuery("#en_usps_fulfilment_offset_days").prop('disabled', true);
     49            jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', true);
     50        } else {
     51            jQuery("#en_usps_cutt_off_time").prop('disabled', false);
     52            jQuery("#en_usps_fulfilment_offset_days").prop('disabled', false);
     53            jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', false);
     54        }
    4155
    4256        let en_usps_cutt_off_time = jQuery('#en_usps_cutt_off_time').length > 0 && jQuery('#en_usps_cutt_off_time').val().length > 0 ? jQuery('#en_usps_cutt_off_time').val() : '';
     
    111125            let en_validate_settings = {};
    112126            let en_data_error = true;
     127            jQuery(':checkbox:disabled').prop('disabled', false);
     128
    113129
    114130            en_validate_settings['#en_usps_handling_fee'] = {
     
    140156                'en_max_length': false,
    141157                'en_error_msg': 'Air hazardous material fee format should be 100.20 or 10%.',
    142             };
    143 
    144             en_validate_settings['#en_usps_fulfilment_offset_days'] = {
    145                 'en_data_type': 'isNumeric',
    146                 'en_decimal': false,
    147                 'en_after_decimal': 0,
    148                 'en_add_percentage': false,
    149                 'en_minus_sign': false,
    150                 'en_max_length': 1,
    151                 'en_error_msg': 'Entered Days are not valid.',
    152158            };
    153159
     
    232238            }
    233239
     240            // fulfillment offset days validation
     241            if (!en_usps_validate_fullfillment_offset_days()) return false;
    234242            // backup rates validation
    235243            if (!en_usps_small_backup_rates_validations()) return false;
     
    728736    }
    729737}
     738
     739if (typeof en_usps_validate_fullfillment_offset_days !== 'function') {
     740    function en_usps_validate_fullfillment_offset_days() {
     741        const offset_days = jQuery("#en_usps_fulfilment_offset_days").val();
     742        const number_regex = /^[0-9]+$/;
     743        let error_msg = '';
     744       
     745        if (offset_days != "" && offset_days < 1) error_msg = 'Fulfillment Offset Days must be greater than or equal to 1.';
     746        if (!error_msg && offset_days != "" && offset_days > 20) error_msg = 'Fulfillment Offset Days must be less than or equal to 20.';
     747        if (!error_msg && offset_days != "" && !number_regex.test(offset_days)) error_msg = 'Fulfillment Offset Days must be a number.';
     748
     749        if (error_msg) {
     750            jQuery('.en_settings_message').remove();
     751            jQuery('.usps_small_plan_notice').after('<div class="notice notice-error en_settings_message"><p><strong>Error! </strong>' + error_msg + '</p></div>');
     752            jQuery('#en_settings_message').delay(200).animate({scrollTop: 0}, 1000);
     753            jQuery('html, body').animate({scrollTop: 0}, 'slow');
     754            return false;
     755        }
     756
     757        return true;
     758    }
     759}
  • small-package-quotes-usps-edition/tags/1.3.13/admin/product/en-product-detail.php

    r3287624 r3494405  
    103103                    $custom_field = (isset($custom_field['id'])) ? $custom_field['id'] : '';
    104104                    $en_updated_product = (isset($_POST[$custom_field][$postId])) ? sanitize_text_field(wp_unslash($_POST[$custom_field][$postId])) : '';
    105                     $en_updated_product = $custom_field == '_dropship_location' ?
    106                         (maybe_serialize(is_array($en_updated_product) ? array_map('intval', $en_updated_product) : $en_updated_product)) : esc_attr($en_updated_product);
     105
     106                    if ($custom_field == '_dropship_location') {
     107                        $en_updated_product = maybe_serialize(is_array($en_updated_product) ? array_map('intval', $en_updated_product) : $en_updated_product);
     108                    } elseif ($custom_field == '_eniture_product_level_fulfillment_offset_days') {
     109                        $en_updated_product = $this->sanitize_fulfillment_offset_days($en_updated_product);
     110                    } else {
     111                        $en_updated_product = esc_attr($en_updated_product);
     112                    }
     113                   
    107114                    update_post_meta($postId, $custom_field, $en_updated_product);
    108115                }
    109116            }
     117        }
     118
     119        private function sanitize_fulfillment_offset_days($value)
     120        {
     121            $value = trim($value);
     122            if ($value === '' || $value === null) return '';
     123
     124            $value = preg_replace('/[^0-9.-]/', '', $value);
     125            if (!is_numeric($value)) return '';
     126
     127            $value = intval(floor(floatval($value)));
     128            return $value < 0 ? '' : strval($value);
    110129        }
    111130
     
    196215                ],
    197216                [
     217                    'type' => 'input_field',
     218                    'input_type' => 'number',
     219                    'id' => '_eniture_product_level_fulfillment_offset_days',
     220                    'class' => '_eniture_product_level_fulfillment_offset_days short',
     221                    'label' => __( 'Fulfillment Offset Days', 'woocommerce' ),
     222                    'placeholder' => 'Fulfillment offset days, e.g. 2',
     223                    'description' => "The number of days the ship date needs to be moved to allow for the processing of the order. If set, this will override the global Fulfillment Offset Days setting for this product.",
     224                    'custom_attributes' => [
     225                        'min' => '1',
     226                        'max' => '20',
     227                        'step' => '1',
     228                        'title' => 'Value must be greater than or equal to 1 and less than or equal to 20',
     229                        'oninvalid' => "this.setCustomValidity(this.validity.rangeUnderflow ? 'Value must be greater than or equal to 1' : this.validity.rangeOverflow ? 'Value must be less than or equal to 20' : '')",
     230                        'oninput' => "this.setCustomValidity('')"
     231                    ]
     232                ],
     233                [
    198234                    'type' => 'checkbox',
    199235                    'id' => '_en_insurance_fee',
     
    322358                'label' => $custom_field['label'],
    323359                'class' => $custom_field['class'],
    324                 'placeholder' => $custom_field['label'],
     360                'placeholder' => isset($custom_field['placeholder']) ? $custom_field['placeholder'] : $custom_field['label'],
    325361                'value' => get_post_meta($postId, $custom_field['id'], true)
    326362            ];
     
    329365                $custom_input_field['desc_tip'] = true;
    330366                $custom_input_field['description'] = $custom_field['description'];
     367            }
     368
     369            // Add input type if specified (e.g., 'number')
     370            if (isset($custom_field['input_type'])) {
     371                $custom_input_field['type'] = $custom_field['input_type'];
     372            }
     373
     374            // Add custom attributes if specified (e.g., min, max, step)
     375            if (isset($custom_field['custom_attributes'])) {
     376                $custom_input_field['custom_attributes'] = $custom_field['custom_attributes'];
    331377            }
    332378
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/location/assets/css/en-usps-location.css

    r3439225 r3494405  
    3333}
    3434
     35.en_usps_location_btn_container {
     36    clear: both;
     37    margin: 10px !important;
     38    display: flex;
     39    justify-content: flex-end;
     40}
     41
    3542.en_usps_location_btn {
    36     clear: both;
    37     float: right;
    38     margin: 10px !important;
     43    margin-right: 10px !important;
    3944}
    4045
     
    124129    color: #ff0000;
    125130    font-size: 11px;
    126     margin: 0 0 0 40.2%;
    127     width: 100%;
     131    width: 58.7%;
    128132    display: block;
    129 }
    130 
    131 .en_location_error_message {
     133    float: right;
     134}
     135
     136.en_location_error_message,
     137.en_usps_small_warehouse_error_message, .en_usps_small_dropship_error_message {
    132138    background: #f1f1f1 none repeat scroll 0 0;
    133139    border-left: 4px solid #dc3232;
     
    139145}
    140146
    141 .en_location_success_message {
     147.en_location_success_message,
     148.en_usps_wh_location_success_message, .en_usps_ds_location_success_message,
     149.en_usps_small_warehouse_success_message, .en_usps_small_dropship_success_message {
    142150    background: #fff none repeat scroll 0 0;
    143151    border-left: 4px solid #46b450;
     
    149157}
    150158
     159.en_usps_small_warehouse_success_message, .en_usps_small_dropship_success_message {
     160    margin: auto;
     161}
     162
    151163.spinner_disable {
    152164    color: #000000;
     
    175187.en_location_table td,
    176188.en_location_table th {
    177     color: #555;
    178189    padding: 12px 35px;
    179190    border-collapse: collapse;
    180191    text-align: center;
     192}
     193
     194.en_location_table td {
     195    color: #555;
    181196}
    182197
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/location/assets/js/en-usps-location.js

    r3347910 r3494405  
    164164        } else if (en_is_var_exist('severity', data) && data['severity'] == 'error') {
    165165            jQuery('.en_popup_location_form').delay(200).animate({scrollTop: 0}, 300);
    166             jQuery('.en_location_error_message span').text(data['message']);
    167             en_show_errors('.en_location_error_message');
     166            const location_type = data['location'] == 'warehouse' ? 'wh' : 'ds';
     167            jQuery(`.en_usps_${location_type}_location_error_message span`).text(data['message']);
     168            en_show_errors(`.en_usps_${location_type}_location_error_message`);
    168169        }
    169170
     
    367368    function en_usps_location_delete(e, data, en_location_type, en_location_id) {
    368369        e.preventDefault();
     370
     371        // If warehouse location then directly delete
     372        if (en_location_type) {
     373            en_usps_location_confirm_delete(data, en_location_type, en_location_id);
     374            return;
     375        }
     376
    369377        en_popup_confirmation_location_delete_show();
    370378
     
    408416        if (data['message'].length > 0) {
    409417            jQuery('.en_popup_location_form').delay(200).animate({scrollTop: 0}, 300);
    410             jQuery('.en_location_success_message span').text(data['message']);
    411             en_show_errors('.en_location_success_message');
     418            const location_type = data['location'] == 'warehouse' ? 'wh' : 'ds';
     419            jQuery(`.en_usps_${location_type}_location_success_message span`).text(data['message']);
     420            en_show_errors(`.en_usps_${location_type}_location_success_message`);
    412421        }
    413422    }
     
    449458    }
    450459}
     460
     461if (typeof en_usps_small_select_bulk_locations != 'function') {
     462    function en_usps_small_select_bulk_locations(location_class, e) {
     463        const checked = jQuery(e).is(':checked');
     464        jQuery(`.${location_class}`).prop('checked', checked);
     465    }
     466}
     467
     468if (typeof en_usps_small_toggle_select_all_locations != 'function') {
     469    function en_usps_small_toggle_select_all_locations(location_class, select_all_locations) {
     470        const allChecked = jQuery(`.${location_class}:checked`).length === jQuery(`.${location_class}`).length;
     471        jQuery(`#${select_all_locations}`).prop('checked', allChecked);
     472    }
     473}
     474
     475if (typeof en_usps_small_delete_bulk_locations != 'function') {
     476    function en_usps_small_delete_bulk_locations(e, location_class, location_type) {
     477        e.preventDefault();
     478        const location_ids = jQuery(`.${location_class}:checked`).map(function () {
     479            return this.value;
     480        }).get();
     481
     482        // Show error message if no locations are selected
     483        if (location_ids.length === 0) {
     484            const loc_error_class = `en_usps_small_${location_type}_error_message`;
     485            jQuery(`.${loc_error_class}`).show('slow').delay(3000).hide('slow');
     486            return;
     487        }
     488
     489        const postForm = {
     490            'action': 'en_usps_location_bulk_delete',
     491            'location_ids': location_ids,
     492            'location_type': location_type,
     493            'wp_nonce': en_usps_location_script.nonce
     494        }
     495        const delete_locs_btn = `.en_usps_small_bulk_delete_${location_type}`,
     496        loc_success_class = `.en_usps_small_${location_type}_success_message`,
     497        loc_error_class = `.en_usps_small_${location_type}_error_message`;
     498       
     499        jQuery.ajax({
     500            type: 'POST',
     501            url: ajaxurl,
     502            data: postForm,
     503            dataType: 'json',
     504            beforeSend: function () {
     505                jQuery(delete_locs_btn).addClass('spinner_disable');
     506            },
     507            success: function (data) {
     508                if (data.error && data.message) {
     509                    jQuery(delete_locs_btn).removeClass('spinner_disable');
     510                    jQuery(loc_error_class).show('slow').delay(3000).hide('slow');
     511                } else {
     512                    jQuery(delete_locs_btn).removeClass('spinner_disable');
     513                    jQuery(data.target_location).replaceWith(data.html);
     514                    jQuery(loc_success_class).show('slow').delay(3000).hide('slow');
     515                    jQuery('.warehouse_updated, .warehouse_created, .warehouse_deleted, .dropship_deleted, .dropship_updated, .dropship_created').css('display', 'none');
     516                }
     517            },
     518            error: function (error) {
     519                jQuery(delete_locs_btn).removeClass('spinner_disable');
     520                console.log(error);
     521            }
     522        });
     523    }
     524}
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/location/dropship/en-dropship.php

    r3347910 r3494405  
    4545
    4646            <h1><?php esc_attr_e('Drop ships', 'small-package-quotes-usps-edition'); ?></h1>
    47             <button onclick="en_show_popup_location(false, event)" type="button"
    48                     class="button-primary"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?></button>
     47            <div style="display: flex; gap: 3px; margin-top: 10px;">
     48                <button title="Add Drop Ship" onclick="en_show_popup_location(false, event)" type="button"
     49                        class="button-primary"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?></button>
     50                <button title="Delete Drop Ships" type="button" class="en_usps_small_bulk_delete_dropship en_wd_add_dropship_btn button-primary" title="Delete Drop Ships" onclick="return en_usps_small_delete_bulk_locations(event, 'en_usps_small_delete_dropship_item', 'dropship');"><?php _e('Delete', 'eniture-technology'); ?></button>
     51            </div>
    4952            <p><?php esc_attr_e("Locations that inventory specific items that are drop shipped to the destination. Use the product's settings
    5053                    page to identify it as a drop shipped item and its associated drop ship location. Orders that include drop
     
    5255                    cheapest option of each shipment required to fulfill the order.", 'small-package-quotes-usps-edition'); ?></p>
    5356
     57            <!-- Success/Error messages -->
     58            <div class="en_usps_ds_location_success_message"><strong>Success! </strong><span></span></div>
     59            <div class="en_usps_small_dropship_success_message"><strong>Success!</strong> <span>Selected drop ships deleted successfully.</span></div>
     60            <div class="en_usps_small_dropship_error_message"><strong>Error!</strong> Please select at least one drop ship to delete.</div>
     61
    5462            <table class="en_location_table en_location_dropship_table">
    5563            <thead>
    5664            <tr>
     65                <th class="en_wd_dropship_list_heading en_usps_small_bulk_delete_col">
     66                    <!-- Bulk delete -->
     67                    <input type="checkbox" name="en_usps_small_bulk_delete_dropships" id="en_usps_small_bulk_delete_dropships" onclick="return en_usps_small_select_bulk_locations('en_usps_small_delete_dropship_item', this);" />
     68                </th>
    5769                <?php echo wp_kses_post(\EnLocation::en_arrange_table_data('th', $en_heading)); ?>
    5870                <th><?php esc_attr_e('Action', 'small-package-quotes-usps-edition'); ?></th>
     
    7587        {
    7688            return array(
    77                 'div' => array('class' => []), 'button' => array('class' => [], 'onclick' => []), 'strong' => [], 'span' => [], 'table' => array('class' => []), 'thead' => [], 'tr' => array('class' => [], 'id' => []), 'th' => [], 'tbody' => [], 'td' => array('class' => [], 'id' => [], 'data-available_id' => [], 'onclick' => []), 'img' => array('src' => [], 'title' => []), 'a' => array('href' => [], 'onclick' => []), 'p' => [], 'h1' => [], 'br' => [],
     89                'div' => array('class' => [], 'style' => []), 'button' => array('class' => [], 'onclick' => [], 'type' => [], 'title' => []), 'strong' => [], 'span' => [], 'table' => array('class' => []), 'thead' => [], 'tr' => array('class' => [], 'id' => []), 'th' => ['input' => ['type' => [], 'name' => [], 'id' => [], 'onclick' => []]], 'tbody' => [], 'td' => array('class' => [], 'id' => [], 'data-available_id' => [], 'onclick' => []),
     90                'input' => ['type' => [], 'name' => [], 'id' => [], 'onclick' => [], 'value' => [], 'class' => [], 'checked' => []],
     91                'img' => array('src' => [], 'title' => []), 'a' => array('href' => [], 'onclick' => []), 'p' => [], 'h1' => [], 'br' => [],
    7892                'a' => ['href' => [], 'onclick' => [], 'title' => [], 'class' => [], 'id' => [], 'data-action'=> []],
    7993            );
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/location/en-location.php

    r3246136 r3494405  
    252252
    253253                echo '<tr class="' . esc_attr($append_class) . '" id="en_location_row_id_' . esc_attr($en_location_id). '">';
     254
     255                $loc_type = isset($location['location']) && $location['location'] == 'warehouse' ? 'wh' : 'ds';
     256                $_type = ($loc_type === 'wh') ? 'warehouse' : 'dropship';
     257                echo '<td class="en_wd_' . esc_attr($_type) . '_list_data en_usps_small_bulk_delete_col">
     258                    <input
     259                        type="checkbox"
     260                        class="en_usps_small_delete_' . esc_attr($_type) . '_item"
     261                        value="' . esc_attr($en_location_id) . '"
     262                        onclick="return en_usps_small_toggle_select_all_locations(
     263                            \'en_usps_small_delete_' . esc_attr($_type) . '_item\',
     264                            \'en_usps_small_bulk_delete_' . esc_attr($_type) . 's\'
     265                        );"
     266                    >
     267                </td>';
     268
    254269                echo wp_kses_post(self::en_arrange_table_data('td', $en_sorted_location));
    255270
     
    284299                        <?php esc_attr_e('Warning!', 'small-package-quotes-usps-edition'); ?>
    285300                    </h2>
     301                    <hr>
    286302                    <p class="en_confirmation_message">
    287                         <?php esc_attr_e('If you delete this location, then location settings will be disabled against products
    288                         (if any).', 'small-package-quotes-usps-edition'); ?>
     303                        Warning! If you delete this location, Drop ship location settings will be disabled against products if any.
    289304                    </p>
     305                    <hr>
    290306                    <div class="en_confirmation_buttons">
    291307                        <a href="#"
     
    342358            }
    343359
    344             echo '<input type="submit" value="Save" class="en_usps_location_btn button-primary">';
     360            echo '<div class="en_usps_location_btn_container"><input type="submit" value="Save" class="en_usps_location_btn button-primary"></div>';
    345361            echo '</form>';
    346362            echo '</div>';
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/location/includes/en-location-ajax.php

    r3347910 r3494405  
    2020            add_action('wp_ajax_en_usps_get_location', [$this, 'en_usps_get_location']);
    2121            add_action('wp_ajax_en_usps_location_delete_row', [$this, 'en_usps_location_delete_row']);
     22            add_action('wp_ajax_en_usps_location_bulk_delete', array($this, 'en_usps_bulk_delete_locations_ajax'));
    2223        }
    2324
     
    195196
    196197                if ($location === 'warehouse') {
    197                     $location_step = 'Warehouse';
     198                    $location_step = 'New warehouse';
    198199                    $en_location_template_obj = new EnUspsWarehouseTemplate();
    199200                    $en_target_location = '.en_location_warehouse_main_div';
    200201                    $validate = ['zip', 'city', 'state', 'country', 'location'];
    201202                } else {
    202                     $location_step = 'Dropship';
     203                    $location_step = 'New drop ship';
    203204                    $en_location_template_obj = new EnUspsDropshipTemplate();
    204205                    $en_target_location = '.en_location_dropship_main_div';
     
    218219                        (!empty($en_location_data) &&
    219220                        reset($en_location_data)['id'] === $location_id))) {
     221                    $location_step = $location === 'warehouse' ? 'Warehouse' : 'Drop ship';
    220222                    $message = $location_step . ' updated successfully.';
    221223                    $action = 'update';
     
    260262        }
    261263
     264        public function en_usps_bulk_delete_locations_ajax()
     265        {
     266            if (!(current_user_can('manage_options') || current_user_can('manage_woocommerce')) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['wp_nonce'])), 'en_usps_location_nonce')) {
     267                echo wp_json_encode(array('error' => true, 'message' => 'Unauthorized Access.'));
     268                exit;
     269            }
     270
     271            $location_ids = isset($_POST['location_ids']) ? $_POST['location_ids'] : array();
     272            $loc_type = isset($_POST['location_type']) ? $_POST['location_type'] : '';
     273            if (empty($location_ids)) {
     274                echo wp_json_encode(['error' => true, 'message' => "Please select at least one {$loc_type} to delete."]);
     275                exit;
     276            }
     277
     278            global $wpdb;
     279            foreach ($location_ids as $location_id) {
     280                if ($loc_type == 'dropship') {
     281                    $get_dropship_id = '';
     282                    $dropship_id = intval($location_id);
     283                    $get_dropship_array = array($dropship_id);
     284                    $ser = maybe_serialize($get_dropship_id);
     285                    $get_dropship_val = array_map('intval', $get_dropship_array);
     286                    $get_post_id = $wpdb->get_results("SELECT group_concat(post_id) as post_ids_list FROM `" . $wpdb->prefix . "postmeta` WHERE `meta_key` = '_dropship_location' AND (`meta_value` LIKE '%" . $ser . "%' OR `meta_value` = '" . $dropship_id . "')");
     287                    $post_id = reset($get_post_id)->post_ids_list;
     288
     289                    if (isset($post_id)) {
     290                        $wpdb->query("UPDATE `" . $wpdb->prefix . "postmeta` SET `meta_value` = '' WHERE `meta_key` IN('_enable_dropship','_dropship_location')  AND `post_id` IN ($post_id)");
     291                    }
     292                }
     293
     294                $wpdb->delete($wpdb->prefix . "warehouse", array('id' => intval($location_id), 'location' => $loc_type));
     295            }
     296
     297            if ($loc_type === 'warehouse') {
     298                $en_location_template_obj = new EnUspsWarehouseTemplate();
     299                $en_target_location = '.en_location_warehouse_main_div';
     300            } else {
     301                $en_location_template_obj = new EnUspsDropshipTemplate();
     302                $en_target_location = '.en_location_dropship_main_div';
     303            }
     304
     305            $html = $en_location_template_obj::en_load();
     306
     307            echo wp_json_encode(['error' => false, 'message' => 'Locations deleted successfully.', 'target_location' => $en_target_location, 'html' => $html]);
     308            exit;
     309        }
    262310    }
    263311
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/location/warehouse/en-warehouse.php

    r3347910 r3494405  
    3838            <div class="en_location_warehouse_main_div">
    3939
    40                 <div class="en_location_success_message">
    41                     <strong><?php esc_attr_e('Success!', 'small-package-quotes-usps-edition'); ?> </strong><span></span></div>
     40                <h1><?php esc_attr_e('Warehouses', 'small-package-quotes-usps-edition'); ?></h1>
     41                <div style="display: flex; gap: 3px; margin-top: 10px;">
     42                    <button title="Add Warehouse" onclick="en_show_popup_location(true, event)" type="button"
     43                            class="button-primary <?php echo esc_attr(self::$disabled_plan); ?>"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?>
     44                    </button>
     45                    <button title="Delete Warehouses" type="button" class="en_usps_small_bulk_delete_warehouse en_wd_add_warehouse_btn button-primary" title="Delete Warehouses" onclick="return en_usps_small_delete_bulk_locations(event, 'en_usps_small_delete_warehouse_item', 'warehouse');"><?php _e('Delete', 'eniture-technology'); ?>
     46                    </button>
    4247
    43                 <h1><?php esc_attr_e('Warehouses', 'small-package-quotes-usps-edition'); ?></h1>
    44                 <button onclick="en_show_popup_location(true, event)" type="button"
    45                         class="button-primary <?php echo esc_attr(self::$disabled_plan); ?>"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?>
    46                 </button>
    47                 <?php echo wp_kses_post(self::$plan_required); ?>
     48                    <?php echo wp_kses_post(self::$plan_required); ?>
     49                </div>
    4850
    4951                <p><?php esc_attr_e('Warehouses that inventory all products not otherwise identified as drop shipped items. The warehouse with the
    5052            lowest shipping cost to the destination is used for quoting purposes.', 'small-package-quotes-usps-edition'); ?></p>
    5153
     54                <div class="en_usps_wh_location_success_message"><strong>Success! </strong><span></span></div>
     55                <div class="en_usps_small_warehouse_success_message"><strong>Success! </strong> <span>Selected warehouses deleted successfully.</span></div>
     56                <div class="en_usps_small_warehouse_error_message"><strong>Error!</strong> <span>Please select at least one warehouse to delete.</span></div>
     57
    5258                <table class="en_location_table en_location_warehouse_table">
    5359                    <thead>
    5460                        <tr>
     61                            <th class="en_wd_warehouse_list_heading en_usps_small_bulk_delete_col">
     62                                <!-- Bulk delete -->
     63                                <input type="checkbox" name="en_usps_small_bulk_delete_warehouses" id="en_usps_small_bulk_delete_warehouses" onclick="return en_usps_small_select_bulk_locations('en_usps_small_delete_warehouse_item', this);" />
     64                            </th>
    5565                            <?php echo wp_kses_post(\EnLocation::en_arrange_table_data('th', $en_heading)); ?>
    5666                            <th><?php esc_attr_e('Action', 'small-package-quotes-usps-edition'); ?></th>
  • small-package-quotes-usps-edition/tags/1.3.13/admin/tab/quote-settings/en-quote-settings.php

    r3439225 r3494405  
    154154            ];
    155155
     156            $services['usps_quote_information_preference'] = [
     157                'name' => __('Quote Information Preference', 'small-package-quotes-usps-edition'),
     158                'type' => 'radio',
     159                'default' => 'yes',
     160                'id' => 'usps_quote_information_preference',
     161                'options' => array(
     162                    'yes' => __('Record it in the Additional Order Details widget. (Default)', 'small-package-quotes-usps-edition'),
     163                    'no' => __('Don\'t record it in the Additional Order Details widget.', 'small-package-quotes-usps-edition'),
     164                ),
     165            ];
     166
     167            $services = array_merge($services, self::delivery_estimate_option(), self::cutt_off_time());
    156168
    157169            /**
     
    222234         */
    223235        static public function delivery_estimate_option() {
    224             $option = $message = '';
    225             if (isset($_REQUEST['tab'])) {
    226                 $feature_option = apply_filters("usps_plans_suscription_and_features", 'delivery_estimate_option');
    227                 if (is_array($feature_option)) {
    228                     $option = 'en_usps_disabled';
    229                     $message = apply_filters("usps_plans_notification_link", $feature_option);
    230                 }
    231             }
    232 
    233236            return [
    234237                'delivery_estimate_options' => [
     
    236239                    'type' => 'text',
    237240                    'class' => 'hidden',
    238                     'desc' => $message,
    239241                    'id' => 'delivery_estimate_options'
    240242                ],
     
    242244                    'name' => '',
    243245                    'type' => 'radio',
    244                     'class' => $option,
    245246                    'default' => "dont_show_estimates",
    246247                    'options' => [
     
    326327                ],
    327328                'en_usps_fulfilment_offset_days' => [
    328                     'name' => __('Fulfilment Offset Days', 'small-package-quotes-usps-edition'),
    329                     'type' => 'text',
    330                     'class' => $option,
    331                     'desc' => 'The number of days the ship date needs to be moved to allow the processing of the order.',
     329                    'name' => __('Fulfillment Offset Days', 'small-package-quotes-usps-edition'),
     330                    'type' => 'text',
     331                    'class' => $option,
     332                    'desc' => 'The number of days the ship date needs to be moved to allow for the processing of the order.',
     333                    'placeholder' => 'Fulfillment offset days, e.g. 2',
    332334                    'id' => 'en_usps_fulfilment_offset_days'
    333335                ],
  • small-package-quotes-usps-edition/tags/1.3.13/en-install.php

    r3439225 r3494405  
    4242        ]);
    4343
    44         wp_enqueue_script('EnUspsAdminJs', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.js', [], '1.0.7');
     44        wp_enqueue_script('EnUspsAdminJs', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.js', [], '1.0.8');
    4545        wp_localize_script('EnUspsAdminJs', 'en_usps_admin_script', [
    4646            'pluginsUrl' => EN_USPS_PLUGIN_URL,
     
    6262        wp_enqueue_style('EnWickedPickerCss');
    6363
    64         wp_enqueue_script('EnUspsLocationScript', EN_USPS_DIR_FILE . '/admin/tab/location/assets/js/en-usps-location.js', [], '1.0.2');
     64        wp_enqueue_script('EnUspsLocationScript', EN_USPS_DIR_FILE . '/admin/tab/location/assets/js/en-usps-location.js', [], '1.0.3');
    6565        wp_localize_script('EnUspsLocationScript', 'en_usps_location_script', array(
    6666            'pluginsUrl' => EN_USPS_PLUGIN_URL,
     
    6868        ));
    6969
    70         wp_register_style('EnUspsLocationStyle', EN_USPS_DIR_FILE . '/admin/tab/location/assets/css/en-usps-location.css', false, '1.0.2');
     70        wp_register_style('EnUspsLocationStyle', EN_USPS_DIR_FILE . '/admin/tab/location/assets/css/en-usps-location.css', false, '1.0.3');
    7171        wp_enqueue_style('EnUspsLocationStyle');
    7272
    73         wp_register_style('EnUspsAdminCss', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.css', false, '1.0.5');
     73        wp_register_style('EnUspsAdminCss', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.css', false, '1.0.6');
    7474        wp_enqueue_style('EnUspsAdminCss');
    7575
     
    247247            }else{
    248248                $plan_required = '0';
    249                 $feature_status = EN_USPS_NAME . ': Enabled.';
     249                $feature_status = 'WooCommerce USPS Small Package Quotes: Enabled.';
    250250            }
    251251
  • small-package-quotes-usps-edition/tags/1.3.13/http/en-curl.php

    r3439225 r3494405  
    123123        {
    124124            $cachable_keys = [
    125                 'serverName', 'licenseKey', 'includeDeclaredValue', 'shipment_type', 'shipment_weight', 'commdityDetails', 'productDetails', 'originAddress', 'product_quantities', 'product_prices', 'receiverZip', 'receiverState', 'receiverCountryCode', 'receiverCity', 'instorPickupLocalDelEnable', 'activeServices', 'rateTier', 'sbsMode'
     125                'serverName', 'licenseKey', 'includeDeclaredValue', 'shipment_type', 'shipment_weight', 'commdityDetails', 'productDetails', 'originAddress', 'product_quantities', 'product_prices', 'receiverZip', 'receiverState', 'receiverCountryCode', 'receiverCity', 'instorPickupLocalDelEnable', 'activeServices', 'rateTier', 'sbsMode', 'modifyShipmentDateTime', 'OrderCutoffTime', 'shipmentOffsetDays', 'shipmentWeekDays'
    126126            ];
    127127            $cachable_data = [];
     
    137137                $cachable_data['addressLine2'] = (isset($request_data['addressLine2'])) ? $request_data['addressLine2'] : '';
    138138                $cachable_data['defaultRADAddressType'] = $request_data['defaultRADAddressType'];
     139                $cachable_data['defaultRADWithoutStreetAddress'] = isset($request_data['defaultRADWithoutStreetAddress']) ? $request_data['defaultRADWithoutStreetAddress'] : '';
    139140                $cachable_data['poboxAddressValidation'] = $request_data['poboxAddressValidation'];
    140141            }
    141142
    142             if (isset($request_data['standardPackaging']) && $request_data['standardPackaging'] == 1) {
    143                 $cachable_data['standardPackaging'] = $request_data['standardPackaging'];
    144                 $cachable_data['pallet'] = $request_data['pallet'];
     143            if (isset($request_data['binPackaging']) && $request_data['binPackaging'] == 1) {
     144                $cachable_data['binPackaging'] = $request_data['binPackaging'];
     145                $cachable_data['bins'] = $request_data['bins'];
    145146            }
    146147
  • small-package-quotes-usps-edition/tags/1.3.13/readme.txt

    r3439225 r3494405  
    44Requires at least: 6.4
    55Tested up to: 6.9
    6 Stable tag: 1.3.12
     6Stable tag: 1.3.13
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    132132== Changelog ==
    133133
     134= 1.3.13 - 2026-03-30 =
     135* Update: Added bulk delete support for warehouse and drop ship locations.
     136* Update: Added product-level offset days functionality.
     137* Update: Added settings to include order metadata and control its visibility on the order details page.
     138
    134139= 1.3.12 - 2026-01-14 =
    135140* Update: Added data sanitization in the quotes request to ensure cleaner and more reliable API communication.
  • small-package-quotes-usps-edition/tags/1.3.13/server/api/en-response.php

    r3439225 r3494405  
    384384                    // Cut Off Time & Ship Date Offset
    385385                    $transitDays = self::en_sanitize_rate('transitDays', '');
    386                     $calender_date = self::en_sanitize_rate('calenderDate', '');
    387                     $calender_days_in_transit = self::en_sanitize_rate('CalenderDaysInTransit', '');
     386                    $calender_date = self::en_sanitize_rate('transitDate', '');
     387                    $calender_days_in_transit = self::en_sanitize_rate('totalTransitTimeInDays', '');
    388388
    389389                    if ($delivery_estimate_option == "delivery_date" && strlen($calender_date) > 0) {
    390                         $label .= ' ( Expected delivery by ' . gmdate('Y-m-d', strtotime($calender_date)) . ')';
     390                        $label .= ' (Expected delivery by ' . gmdate('m-d-Y', strtotime($calender_date)) . ')';
    391391                    } elseif ($delivery_estimate_option == "delivery_days" && strlen($calender_days_in_transit) > 0) {
    392                         $correct_word = $calender_days_in_transit == 1 ? 'is' : 'are';
    393                         $label .= ' ( Estimated number of days until delivery ' . $correct_word . ' ' . $calender_days_in_transit . ' )';
     392                        $label .= ' (Intransit days: ' . $calender_days_in_transit . ')';
    394393                    }
    395394
  • small-package-quotes-usps-edition/tags/1.3.13/server/en-shipping-rates.php

    r3439225 r3494405  
    223223                    // Images for FDO
    224224                    $image_urls = apply_filters('en_fdo_image_urls_merge', []);
     225                    $save_order_meta_data = get_option('usps_quote_information_preference');
     226                    $save_packaging_data = get_option('box_sizing_packaging_solution_preference');
    225227
    226228                    foreach ($en_rates as $accessorial => $rate) {
     
    245247                            // Images for FDO
    246248                            $rate['meta_data']['en_fdo_image_urls'] = wp_json_encode($image_urls);
     249
     250                            // Remove meta data and packaging data if not required
     251                            if ($save_order_meta_data == 'no') unset($rate['meta_data']['en_fdo_meta_data']);
     252                            if ($save_packaging_data == 'no') unset($rate['meta_data']['bin_packaging']);
    247253                        }
    248254
  • small-package-quotes-usps-edition/tags/1.3.13/server/package/en-package.php

    r3439225 r3494405  
    105105                    // Get product level markup value
    106106                    $product_level_markup = self::en_get_product_level_markup($product_data, $product['variation_id'], $product['product_id'], $product['quantity']);
     107                    $product_level_fulfillment_offset = self::en_get_product_level_fulfillment_offset_days($product_data, $product['variation_id'], $product['product_id']);
    107108
    108109                    self::$post_id = (isset($product['variation_id']) && $product['variation_id'] > 0) ?
     
    147148                        'isInsuranceActive' => $isInsuranceIctive,
    148149                        'lineItemSlug' => $product_tag,
    149                         'markup' => $product_level_markup
     150                        'markup' => $product_level_markup,
     151                        'fulfillment_offset_days' => $product_level_fulfillment_offset,
    150152                    ];
    151153
     
    302304                            self::$en_request['product_prices'][$origin_zip_code] = floatval($product_data->get_price() * floatval($product['quantity']));
    303305                        }
     306
     307                        // Track maximum fulfillment offset days
     308                        if (is_numeric($product_level_fulfillment_offset) && $product_level_fulfillment_offset > 0) {
     309                            if (!isset(self::$en_request['max_fulfillment_offset_days']) || $product_level_fulfillment_offset > self::$en_request['max_fulfillment_offset_days']) {
     310                                self::$en_request['max_fulfillment_offset_days'] = $product_level_fulfillment_offset;
     311                            }
     312                        }
    304313                    }
    305314                }
     
    502511            $en_settings = json_decode(EN_USPS_SET_QUOTE_SETTINGS, true);
    503512            extract($en_settings);
     513
     514            // Use product-level fulfillment offset days if available, otherwise use global setting
     515            if (isset(self::$en_request['max_fulfillment_offset_days']) && is_numeric(self::$en_request['max_fulfillment_offset_days']) && self::$en_request['max_fulfillment_offset_days'] > 0) {
     516                $fulfilment_offset_days = self::$en_request['max_fulfillment_offset_days'];
     517            }
     518
    504519            if (!is_array($feature_option) && ($delivery_estimate_option == 'delivery_days' || $delivery_estimate_option == 'delivery_date')) {
    505520                $settings = [
    506                     'modifyShipmentDateTime' => strlen($cutt_off_time) > 0 && strlen($fulfilment_offset_days) > 0 && !empty($shipment_days) ? true : false,
     521                    'modifyShipmentDateTime' => strlen($cutt_off_time) > 0 || strlen($fulfilment_offset_days) > 0 || !empty($shipment_days) ? true : false,
    507522                    'OrderCutoffTime' => $cutt_off_time,
    508523                    'shipmentOffsetDays' => $fulfilment_offset_days,
     
    870885            return $is_filter_applied;
    871886        }
     887
     888        public static function en_get_product_level_fulfillment_offset_days($_product, $variation_id, $product_id)
     889        {
     890            $fulfillment_offset_days = '';
     891            $field_name = '_eniture_product_level_fulfillment_offset_days';
     892
     893            if ($_product->get_type() == 'variation' && $variation_id > 0) {
     894                $fulfillment_offset_days = get_post_meta($variation_id, $field_name, true);
     895
     896                if (empty($fulfillment_offset_days) || !is_numeric($fulfillment_offset_days)) {
     897                    $parent_id = $_product->get_parent_id();
     898                    if ($parent_id > 0) {
     899                        $fulfillment_offset_days = get_post_meta($parent_id, $field_name, true);
     900                    }
     901                }
     902            } else {
     903                $fulfillment_offset_days = get_post_meta($_product->get_id(), $field_name, true);
     904            }
     905
     906            if (empty($fulfillment_offset_days) || !is_numeric($fulfillment_offset_days)) {
     907                $fulfillment_offset_days = get_post_meta($product_id, $field_name, true);
     908            }
     909
     910            // Validate and sanitize the value before returning
     911            if (is_numeric($fulfillment_offset_days)) {
     912                $value = intval($fulfillment_offset_days);
     913                return $value;
     914            }
     915
     916            // Return empty string if invalid
     917            return '';
     918        }
    872919    }
    873920
  • small-package-quotes-usps-edition/tags/1.3.13/small-package-quotes-usps-edition.php

    r3439225 r3494405  
    44 * Plugin URI: https://eniture.com/products/
    55 * Description: Dynamically retrieves your negotiated shipping rates from Usps Express and displays the results in the WooCommerce shopping cart.
    6  * Version: 1.3.12
     6 * Version: 1.3.13
    77 * Author: Eniture Technology
    88 * Author URI: http://eniture.com/
     
    2525});
    2626
    27 if (empty(\EnUspsGuard\EnUspsGuard::en_check_prerequisites('USPS', '5.6', '4.0', '2.3'))) {
    28     require_once 'en-install.php';
    29 }
     27add_action( 'init', function () {
     28    if (!is_textdomain_loaded('small-package-quotes-usps-edition')) {
     29        load_plugin_textdomain('small-package-quotes-usps-edition', false, dirname(plugin_basename(__FILE__)) . '/languages/');
     30    }
     31   
     32    if (empty(\EnUspsGuard\EnUspsGuard::en_check_prerequisites('USPS', '5.6', '4.0', '2.3'))) {
     33        require_once 'en-install.php';
     34    }
     35});
  • small-package-quotes-usps-edition/trunk/admin/assets/en-usps-admin.css

    r3439225 r3494405  
    6464}
    6565
    66 #en_usps_quote_settings .en_usps_shipment_day,
    67 #en_usps_quote_settings .en_usps_all_shipment {
     66#en_usps_quote_settings .en_usps_shipment_day {
    6867    display: inline-block;
     68}
     69
     70#en_usps_quote_settings tr.en_usps_all_shipment {
     71    display: inline-flex;
     72    align-items: baseline;
    6973}
    7074
     
    140144.en_quote_settings_sub_options th {
    141145    padding: 0 0 10px 15px;
    142     margin-left: 10px !important;
    143146    font-weight: 400;
    144147}
     
    377380.woocommerce_variable_attributes.wc-metabox-content [class^="_nmfc_number"],
    378381.woocommerce_variable_attributes.wc-metabox-content [class^="_en_product_markup"],
     382.woocommerce_variable_attributes.wc-metabox-content [class^="_eniture_product_level_fulfillment_offset_days"],
    379383.woocommerce_variable_attributes.wc-metabox-content [class^="_nestedPercentage"],
    380384.woocommerce_variable_attributes.wc-metabox-content [class^="en_flat_rate_price"],
     
    400404.woocommerce_variable_attributes.wc-metabox-content [class^="en_flat_rate_price"],
    401405.woocommerce_variable_attributes.wc-metabox-content [class^="_en_product_markup"],
     406.woocommerce_variable_attributes.wc-metabox-content [class^="_eniture_product_level_fulfillment_offset_days"],
    402407.woocommerce_variable_attributes.wc-metabox-content [class^="_nestedPercentage"],
    403408.woocommerce_variable_attributes.wc-metabox-content [class^="_nestedDimension"],
     
    409414.woocommerce_variable_attributes.wc-metabox-content .data p[class*="en_flat_rate_price"] span.woocommerce-help-tip,
    410415.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_en_product_markup"] span.woocommerce-help-tip,
     416.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_eniture_product_level_fulfillment_offset_days"] span.woocommerce-help-tip,
    411417.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_nestedPercentage"] span.woocommerce-help-tip,
    412418.woocommerce_variable_attributes.wc-metabox-content .data p[class*="_nestedDimension"] span.woocommerce-help-tip,
  • small-package-quotes-usps-edition/trunk/admin/assets/en-usps-admin.js

    r3439225 r3494405  
    66    jQuery('#shipping_methods_do_not_sort_by_price').closest('table').attr('id', 'en_usps_quote_settings');
    77    jQuery("#order_shipping_line_items .shipping .display_meta").css('display', 'none');
     8    jQuery("#en_usps_fulfilment_offset_days").attr('maxlength', '2');
    89
    910    // Quote Settings Tab
     
    3031        // Delivery estimate options changed
    3132        jQuery("input[name=en_delivery_estimate_options_usps]").on('change load', function () {
    32             var en_delivery_estimate_val = jQuery('input[name=en_delivery_estimate_options_usps]:checked').val();
     33            const en_delivery_estimate_val = jQuery('input[name=en_delivery_estimate_options_usps]:checked').val();
    3334            if (en_delivery_estimate_val == 'dont_show_estimates') {
    3435                jQuery("#en_usps_cutt_off_time").prop('disabled', true);
    3536                jQuery("#en_usps_fulfilment_offset_days").prop('disabled', true);
     37                jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', true);
    3638            } else {
    3739                jQuery("#en_usps_cutt_off_time").prop('disabled', false);
    3840                jQuery("#en_usps_fulfilment_offset_days").prop('disabled', false);
    39             }
    40         });
     41                jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', false);
     42            }
     43        });
     44
     45        const en_delivery_estimate_val = jQuery('input[name=en_delivery_estimate_options_usps]:checked').val();
     46        if (en_delivery_estimate_val == 'dont_show_estimates') {
     47            jQuery("#en_usps_cutt_off_time").prop('disabled', true);
     48            jQuery("#en_usps_fulfilment_offset_days").prop('disabled', true);
     49            jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', true);
     50        } else {
     51            jQuery("#en_usps_cutt_off_time").prop('disabled', false);
     52            jQuery("#en_usps_fulfilment_offset_days").prop('disabled', false);
     53            jQuery(".en_usps_all_shipment, .en_usps_shipment_day").prop('disabled', false);
     54        }
    4155
    4256        let en_usps_cutt_off_time = jQuery('#en_usps_cutt_off_time').length > 0 && jQuery('#en_usps_cutt_off_time').val().length > 0 ? jQuery('#en_usps_cutt_off_time').val() : '';
     
    111125            let en_validate_settings = {};
    112126            let en_data_error = true;
     127            jQuery(':checkbox:disabled').prop('disabled', false);
     128
    113129
    114130            en_validate_settings['#en_usps_handling_fee'] = {
     
    140156                'en_max_length': false,
    141157                'en_error_msg': 'Air hazardous material fee format should be 100.20 or 10%.',
    142             };
    143 
    144             en_validate_settings['#en_usps_fulfilment_offset_days'] = {
    145                 'en_data_type': 'isNumeric',
    146                 'en_decimal': false,
    147                 'en_after_decimal': 0,
    148                 'en_add_percentage': false,
    149                 'en_minus_sign': false,
    150                 'en_max_length': 1,
    151                 'en_error_msg': 'Entered Days are not valid.',
    152158            };
    153159
     
    232238            }
    233239
     240            // fulfillment offset days validation
     241            if (!en_usps_validate_fullfillment_offset_days()) return false;
    234242            // backup rates validation
    235243            if (!en_usps_small_backup_rates_validations()) return false;
     
    728736    }
    729737}
     738
     739if (typeof en_usps_validate_fullfillment_offset_days !== 'function') {
     740    function en_usps_validate_fullfillment_offset_days() {
     741        const offset_days = jQuery("#en_usps_fulfilment_offset_days").val();
     742        const number_regex = /^[0-9]+$/;
     743        let error_msg = '';
     744       
     745        if (offset_days != "" && offset_days < 1) error_msg = 'Fulfillment Offset Days must be greater than or equal to 1.';
     746        if (!error_msg && offset_days != "" && offset_days > 20) error_msg = 'Fulfillment Offset Days must be less than or equal to 20.';
     747        if (!error_msg && offset_days != "" && !number_regex.test(offset_days)) error_msg = 'Fulfillment Offset Days must be a number.';
     748
     749        if (error_msg) {
     750            jQuery('.en_settings_message').remove();
     751            jQuery('.usps_small_plan_notice').after('<div class="notice notice-error en_settings_message"><p><strong>Error! </strong>' + error_msg + '</p></div>');
     752            jQuery('#en_settings_message').delay(200).animate({scrollTop: 0}, 1000);
     753            jQuery('html, body').animate({scrollTop: 0}, 'slow');
     754            return false;
     755        }
     756
     757        return true;
     758    }
     759}
  • small-package-quotes-usps-edition/trunk/admin/product/en-product-detail.php

    r3287624 r3494405  
    103103                    $custom_field = (isset($custom_field['id'])) ? $custom_field['id'] : '';
    104104                    $en_updated_product = (isset($_POST[$custom_field][$postId])) ? sanitize_text_field(wp_unslash($_POST[$custom_field][$postId])) : '';
    105                     $en_updated_product = $custom_field == '_dropship_location' ?
    106                         (maybe_serialize(is_array($en_updated_product) ? array_map('intval', $en_updated_product) : $en_updated_product)) : esc_attr($en_updated_product);
     105
     106                    if ($custom_field == '_dropship_location') {
     107                        $en_updated_product = maybe_serialize(is_array($en_updated_product) ? array_map('intval', $en_updated_product) : $en_updated_product);
     108                    } elseif ($custom_field == '_eniture_product_level_fulfillment_offset_days') {
     109                        $en_updated_product = $this->sanitize_fulfillment_offset_days($en_updated_product);
     110                    } else {
     111                        $en_updated_product = esc_attr($en_updated_product);
     112                    }
     113                   
    107114                    update_post_meta($postId, $custom_field, $en_updated_product);
    108115                }
    109116            }
     117        }
     118
     119        private function sanitize_fulfillment_offset_days($value)
     120        {
     121            $value = trim($value);
     122            if ($value === '' || $value === null) return '';
     123
     124            $value = preg_replace('/[^0-9.-]/', '', $value);
     125            if (!is_numeric($value)) return '';
     126
     127            $value = intval(floor(floatval($value)));
     128            return $value < 0 ? '' : strval($value);
    110129        }
    111130
     
    196215                ],
    197216                [
     217                    'type' => 'input_field',
     218                    'input_type' => 'number',
     219                    'id' => '_eniture_product_level_fulfillment_offset_days',
     220                    'class' => '_eniture_product_level_fulfillment_offset_days short',
     221                    'label' => __( 'Fulfillment Offset Days', 'woocommerce' ),
     222                    'placeholder' => 'Fulfillment offset days, e.g. 2',
     223                    'description' => "The number of days the ship date needs to be moved to allow for the processing of the order. If set, this will override the global Fulfillment Offset Days setting for this product.",
     224                    'custom_attributes' => [
     225                        'min' => '1',
     226                        'max' => '20',
     227                        'step' => '1',
     228                        'title' => 'Value must be greater than or equal to 1 and less than or equal to 20',
     229                        'oninvalid' => "this.setCustomValidity(this.validity.rangeUnderflow ? 'Value must be greater than or equal to 1' : this.validity.rangeOverflow ? 'Value must be less than or equal to 20' : '')",
     230                        'oninput' => "this.setCustomValidity('')"
     231                    ]
     232                ],
     233                [
    198234                    'type' => 'checkbox',
    199235                    'id' => '_en_insurance_fee',
     
    322358                'label' => $custom_field['label'],
    323359                'class' => $custom_field['class'],
    324                 'placeholder' => $custom_field['label'],
     360                'placeholder' => isset($custom_field['placeholder']) ? $custom_field['placeholder'] : $custom_field['label'],
    325361                'value' => get_post_meta($postId, $custom_field['id'], true)
    326362            ];
     
    329365                $custom_input_field['desc_tip'] = true;
    330366                $custom_input_field['description'] = $custom_field['description'];
     367            }
     368
     369            // Add input type if specified (e.g., 'number')
     370            if (isset($custom_field['input_type'])) {
     371                $custom_input_field['type'] = $custom_field['input_type'];
     372            }
     373
     374            // Add custom attributes if specified (e.g., min, max, step)
     375            if (isset($custom_field['custom_attributes'])) {
     376                $custom_input_field['custom_attributes'] = $custom_field['custom_attributes'];
    331377            }
    332378
  • small-package-quotes-usps-edition/trunk/admin/tab/location/assets/css/en-usps-location.css

    r3439225 r3494405  
    3333}
    3434
     35.en_usps_location_btn_container {
     36    clear: both;
     37    margin: 10px !important;
     38    display: flex;
     39    justify-content: flex-end;
     40}
     41
    3542.en_usps_location_btn {
    36     clear: both;
    37     float: right;
    38     margin: 10px !important;
     43    margin-right: 10px !important;
    3944}
    4045
     
    124129    color: #ff0000;
    125130    font-size: 11px;
    126     margin: 0 0 0 40.2%;
    127     width: 100%;
     131    width: 58.7%;
    128132    display: block;
    129 }
    130 
    131 .en_location_error_message {
     133    float: right;
     134}
     135
     136.en_location_error_message,
     137.en_usps_small_warehouse_error_message, .en_usps_small_dropship_error_message {
    132138    background: #f1f1f1 none repeat scroll 0 0;
    133139    border-left: 4px solid #dc3232;
     
    139145}
    140146
    141 .en_location_success_message {
     147.en_location_success_message,
     148.en_usps_wh_location_success_message, .en_usps_ds_location_success_message,
     149.en_usps_small_warehouse_success_message, .en_usps_small_dropship_success_message {
    142150    background: #fff none repeat scroll 0 0;
    143151    border-left: 4px solid #46b450;
     
    149157}
    150158
     159.en_usps_small_warehouse_success_message, .en_usps_small_dropship_success_message {
     160    margin: auto;
     161}
     162
    151163.spinner_disable {
    152164    color: #000000;
     
    175187.en_location_table td,
    176188.en_location_table th {
    177     color: #555;
    178189    padding: 12px 35px;
    179190    border-collapse: collapse;
    180191    text-align: center;
     192}
     193
     194.en_location_table td {
     195    color: #555;
    181196}
    182197
  • small-package-quotes-usps-edition/trunk/admin/tab/location/assets/js/en-usps-location.js

    r3347910 r3494405  
    164164        } else if (en_is_var_exist('severity', data) && data['severity'] == 'error') {
    165165            jQuery('.en_popup_location_form').delay(200).animate({scrollTop: 0}, 300);
    166             jQuery('.en_location_error_message span').text(data['message']);
    167             en_show_errors('.en_location_error_message');
     166            const location_type = data['location'] == 'warehouse' ? 'wh' : 'ds';
     167            jQuery(`.en_usps_${location_type}_location_error_message span`).text(data['message']);
     168            en_show_errors(`.en_usps_${location_type}_location_error_message`);
    168169        }
    169170
     
    367368    function en_usps_location_delete(e, data, en_location_type, en_location_id) {
    368369        e.preventDefault();
     370
     371        // If warehouse location then directly delete
     372        if (en_location_type) {
     373            en_usps_location_confirm_delete(data, en_location_type, en_location_id);
     374            return;
     375        }
     376
    369377        en_popup_confirmation_location_delete_show();
    370378
     
    408416        if (data['message'].length > 0) {
    409417            jQuery('.en_popup_location_form').delay(200).animate({scrollTop: 0}, 300);
    410             jQuery('.en_location_success_message span').text(data['message']);
    411             en_show_errors('.en_location_success_message');
     418            const location_type = data['location'] == 'warehouse' ? 'wh' : 'ds';
     419            jQuery(`.en_usps_${location_type}_location_success_message span`).text(data['message']);
     420            en_show_errors(`.en_usps_${location_type}_location_success_message`);
    412421        }
    413422    }
     
    449458    }
    450459}
     460
     461if (typeof en_usps_small_select_bulk_locations != 'function') {
     462    function en_usps_small_select_bulk_locations(location_class, e) {
     463        const checked = jQuery(e).is(':checked');
     464        jQuery(`.${location_class}`).prop('checked', checked);
     465    }
     466}
     467
     468if (typeof en_usps_small_toggle_select_all_locations != 'function') {
     469    function en_usps_small_toggle_select_all_locations(location_class, select_all_locations) {
     470        const allChecked = jQuery(`.${location_class}:checked`).length === jQuery(`.${location_class}`).length;
     471        jQuery(`#${select_all_locations}`).prop('checked', allChecked);
     472    }
     473}
     474
     475if (typeof en_usps_small_delete_bulk_locations != 'function') {
     476    function en_usps_small_delete_bulk_locations(e, location_class, location_type) {
     477        e.preventDefault();
     478        const location_ids = jQuery(`.${location_class}:checked`).map(function () {
     479            return this.value;
     480        }).get();
     481
     482        // Show error message if no locations are selected
     483        if (location_ids.length === 0) {
     484            const loc_error_class = `en_usps_small_${location_type}_error_message`;
     485            jQuery(`.${loc_error_class}`).show('slow').delay(3000).hide('slow');
     486            return;
     487        }
     488
     489        const postForm = {
     490            'action': 'en_usps_location_bulk_delete',
     491            'location_ids': location_ids,
     492            'location_type': location_type,
     493            'wp_nonce': en_usps_location_script.nonce
     494        }
     495        const delete_locs_btn = `.en_usps_small_bulk_delete_${location_type}`,
     496        loc_success_class = `.en_usps_small_${location_type}_success_message`,
     497        loc_error_class = `.en_usps_small_${location_type}_error_message`;
     498       
     499        jQuery.ajax({
     500            type: 'POST',
     501            url: ajaxurl,
     502            data: postForm,
     503            dataType: 'json',
     504            beforeSend: function () {
     505                jQuery(delete_locs_btn).addClass('spinner_disable');
     506            },
     507            success: function (data) {
     508                if (data.error && data.message) {
     509                    jQuery(delete_locs_btn).removeClass('spinner_disable');
     510                    jQuery(loc_error_class).show('slow').delay(3000).hide('slow');
     511                } else {
     512                    jQuery(delete_locs_btn).removeClass('spinner_disable');
     513                    jQuery(data.target_location).replaceWith(data.html);
     514                    jQuery(loc_success_class).show('slow').delay(3000).hide('slow');
     515                    jQuery('.warehouse_updated, .warehouse_created, .warehouse_deleted, .dropship_deleted, .dropship_updated, .dropship_created').css('display', 'none');
     516                }
     517            },
     518            error: function (error) {
     519                jQuery(delete_locs_btn).removeClass('spinner_disable');
     520                console.log(error);
     521            }
     522        });
     523    }
     524}
  • small-package-quotes-usps-edition/trunk/admin/tab/location/dropship/en-dropship.php

    r3347910 r3494405  
    4545
    4646            <h1><?php esc_attr_e('Drop ships', 'small-package-quotes-usps-edition'); ?></h1>
    47             <button onclick="en_show_popup_location(false, event)" type="button"
    48                     class="button-primary"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?></button>
     47            <div style="display: flex; gap: 3px; margin-top: 10px;">
     48                <button title="Add Drop Ship" onclick="en_show_popup_location(false, event)" type="button"
     49                        class="button-primary"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?></button>
     50                <button title="Delete Drop Ships" type="button" class="en_usps_small_bulk_delete_dropship en_wd_add_dropship_btn button-primary" title="Delete Drop Ships" onclick="return en_usps_small_delete_bulk_locations(event, 'en_usps_small_delete_dropship_item', 'dropship');"><?php _e('Delete', 'eniture-technology'); ?></button>
     51            </div>
    4952            <p><?php esc_attr_e("Locations that inventory specific items that are drop shipped to the destination. Use the product's settings
    5053                    page to identify it as a drop shipped item and its associated drop ship location. Orders that include drop
     
    5255                    cheapest option of each shipment required to fulfill the order.", 'small-package-quotes-usps-edition'); ?></p>
    5356
     57            <!-- Success/Error messages -->
     58            <div class="en_usps_ds_location_success_message"><strong>Success! </strong><span></span></div>
     59            <div class="en_usps_small_dropship_success_message"><strong>Success!</strong> <span>Selected drop ships deleted successfully.</span></div>
     60            <div class="en_usps_small_dropship_error_message"><strong>Error!</strong> Please select at least one drop ship to delete.</div>
     61
    5462            <table class="en_location_table en_location_dropship_table">
    5563            <thead>
    5664            <tr>
     65                <th class="en_wd_dropship_list_heading en_usps_small_bulk_delete_col">
     66                    <!-- Bulk delete -->
     67                    <input type="checkbox" name="en_usps_small_bulk_delete_dropships" id="en_usps_small_bulk_delete_dropships" onclick="return en_usps_small_select_bulk_locations('en_usps_small_delete_dropship_item', this);" />
     68                </th>
    5769                <?php echo wp_kses_post(\EnLocation::en_arrange_table_data('th', $en_heading)); ?>
    5870                <th><?php esc_attr_e('Action', 'small-package-quotes-usps-edition'); ?></th>
     
    7587        {
    7688            return array(
    77                 'div' => array('class' => []), 'button' => array('class' => [], 'onclick' => []), 'strong' => [], 'span' => [], 'table' => array('class' => []), 'thead' => [], 'tr' => array('class' => [], 'id' => []), 'th' => [], 'tbody' => [], 'td' => array('class' => [], 'id' => [], 'data-available_id' => [], 'onclick' => []), 'img' => array('src' => [], 'title' => []), 'a' => array('href' => [], 'onclick' => []), 'p' => [], 'h1' => [], 'br' => [],
     89                'div' => array('class' => [], 'style' => []), 'button' => array('class' => [], 'onclick' => [], 'type' => [], 'title' => []), 'strong' => [], 'span' => [], 'table' => array('class' => []), 'thead' => [], 'tr' => array('class' => [], 'id' => []), 'th' => ['input' => ['type' => [], 'name' => [], 'id' => [], 'onclick' => []]], 'tbody' => [], 'td' => array('class' => [], 'id' => [], 'data-available_id' => [], 'onclick' => []),
     90                'input' => ['type' => [], 'name' => [], 'id' => [], 'onclick' => [], 'value' => [], 'class' => [], 'checked' => []],
     91                'img' => array('src' => [], 'title' => []), 'a' => array('href' => [], 'onclick' => []), 'p' => [], 'h1' => [], 'br' => [],
    7892                'a' => ['href' => [], 'onclick' => [], 'title' => [], 'class' => [], 'id' => [], 'data-action'=> []],
    7993            );
  • small-package-quotes-usps-edition/trunk/admin/tab/location/en-location.php

    r3246136 r3494405  
    252252
    253253                echo '<tr class="' . esc_attr($append_class) . '" id="en_location_row_id_' . esc_attr($en_location_id). '">';
     254
     255                $loc_type = isset($location['location']) && $location['location'] == 'warehouse' ? 'wh' : 'ds';
     256                $_type = ($loc_type === 'wh') ? 'warehouse' : 'dropship';
     257                echo '<td class="en_wd_' . esc_attr($_type) . '_list_data en_usps_small_bulk_delete_col">
     258                    <input
     259                        type="checkbox"
     260                        class="en_usps_small_delete_' . esc_attr($_type) . '_item"
     261                        value="' . esc_attr($en_location_id) . '"
     262                        onclick="return en_usps_small_toggle_select_all_locations(
     263                            \'en_usps_small_delete_' . esc_attr($_type) . '_item\',
     264                            \'en_usps_small_bulk_delete_' . esc_attr($_type) . 's\'
     265                        );"
     266                    >
     267                </td>';
     268
    254269                echo wp_kses_post(self::en_arrange_table_data('td', $en_sorted_location));
    255270
     
    284299                        <?php esc_attr_e('Warning!', 'small-package-quotes-usps-edition'); ?>
    285300                    </h2>
     301                    <hr>
    286302                    <p class="en_confirmation_message">
    287                         <?php esc_attr_e('If you delete this location, then location settings will be disabled against products
    288                         (if any).', 'small-package-quotes-usps-edition'); ?>
     303                        Warning! If you delete this location, Drop ship location settings will be disabled against products if any.
    289304                    </p>
     305                    <hr>
    290306                    <div class="en_confirmation_buttons">
    291307                        <a href="#"
     
    342358            }
    343359
    344             echo '<input type="submit" value="Save" class="en_usps_location_btn button-primary">';
     360            echo '<div class="en_usps_location_btn_container"><input type="submit" value="Save" class="en_usps_location_btn button-primary"></div>';
    345361            echo '</form>';
    346362            echo '</div>';
  • small-package-quotes-usps-edition/trunk/admin/tab/location/includes/en-location-ajax.php

    r3347910 r3494405  
    2020            add_action('wp_ajax_en_usps_get_location', [$this, 'en_usps_get_location']);
    2121            add_action('wp_ajax_en_usps_location_delete_row', [$this, 'en_usps_location_delete_row']);
     22            add_action('wp_ajax_en_usps_location_bulk_delete', array($this, 'en_usps_bulk_delete_locations_ajax'));
    2223        }
    2324
     
    195196
    196197                if ($location === 'warehouse') {
    197                     $location_step = 'Warehouse';
     198                    $location_step = 'New warehouse';
    198199                    $en_location_template_obj = new EnUspsWarehouseTemplate();
    199200                    $en_target_location = '.en_location_warehouse_main_div';
    200201                    $validate = ['zip', 'city', 'state', 'country', 'location'];
    201202                } else {
    202                     $location_step = 'Dropship';
     203                    $location_step = 'New drop ship';
    203204                    $en_location_template_obj = new EnUspsDropshipTemplate();
    204205                    $en_target_location = '.en_location_dropship_main_div';
     
    218219                        (!empty($en_location_data) &&
    219220                        reset($en_location_data)['id'] === $location_id))) {
     221                    $location_step = $location === 'warehouse' ? 'Warehouse' : 'Drop ship';
    220222                    $message = $location_step . ' updated successfully.';
    221223                    $action = 'update';
     
    260262        }
    261263
     264        public function en_usps_bulk_delete_locations_ajax()
     265        {
     266            if (!(current_user_can('manage_options') || current_user_can('manage_woocommerce')) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['wp_nonce'])), 'en_usps_location_nonce')) {
     267                echo wp_json_encode(array('error' => true, 'message' => 'Unauthorized Access.'));
     268                exit;
     269            }
     270
     271            $location_ids = isset($_POST['location_ids']) ? $_POST['location_ids'] : array();
     272            $loc_type = isset($_POST['location_type']) ? $_POST['location_type'] : '';
     273            if (empty($location_ids)) {
     274                echo wp_json_encode(['error' => true, 'message' => "Please select at least one {$loc_type} to delete."]);
     275                exit;
     276            }
     277
     278            global $wpdb;
     279            foreach ($location_ids as $location_id) {
     280                if ($loc_type == 'dropship') {
     281                    $get_dropship_id = '';
     282                    $dropship_id = intval($location_id);
     283                    $get_dropship_array = array($dropship_id);
     284                    $ser = maybe_serialize($get_dropship_id);
     285                    $get_dropship_val = array_map('intval', $get_dropship_array);
     286                    $get_post_id = $wpdb->get_results("SELECT group_concat(post_id) as post_ids_list FROM `" . $wpdb->prefix . "postmeta` WHERE `meta_key` = '_dropship_location' AND (`meta_value` LIKE '%" . $ser . "%' OR `meta_value` = '" . $dropship_id . "')");
     287                    $post_id = reset($get_post_id)->post_ids_list;
     288
     289                    if (isset($post_id)) {
     290                        $wpdb->query("UPDATE `" . $wpdb->prefix . "postmeta` SET `meta_value` = '' WHERE `meta_key` IN('_enable_dropship','_dropship_location')  AND `post_id` IN ($post_id)");
     291                    }
     292                }
     293
     294                $wpdb->delete($wpdb->prefix . "warehouse", array('id' => intval($location_id), 'location' => $loc_type));
     295            }
     296
     297            if ($loc_type === 'warehouse') {
     298                $en_location_template_obj = new EnUspsWarehouseTemplate();
     299                $en_target_location = '.en_location_warehouse_main_div';
     300            } else {
     301                $en_location_template_obj = new EnUspsDropshipTemplate();
     302                $en_target_location = '.en_location_dropship_main_div';
     303            }
     304
     305            $html = $en_location_template_obj::en_load();
     306
     307            echo wp_json_encode(['error' => false, 'message' => 'Locations deleted successfully.', 'target_location' => $en_target_location, 'html' => $html]);
     308            exit;
     309        }
    262310    }
    263311
  • small-package-quotes-usps-edition/trunk/admin/tab/location/warehouse/en-warehouse.php

    r3347910 r3494405  
    3838            <div class="en_location_warehouse_main_div">
    3939
    40                 <div class="en_location_success_message">
    41                     <strong><?php esc_attr_e('Success!', 'small-package-quotes-usps-edition'); ?> </strong><span></span></div>
     40                <h1><?php esc_attr_e('Warehouses', 'small-package-quotes-usps-edition'); ?></h1>
     41                <div style="display: flex; gap: 3px; margin-top: 10px;">
     42                    <button title="Add Warehouse" onclick="en_show_popup_location(true, event)" type="button"
     43                            class="button-primary <?php echo esc_attr(self::$disabled_plan); ?>"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?>
     44                    </button>
     45                    <button title="Delete Warehouses" type="button" class="en_usps_small_bulk_delete_warehouse en_wd_add_warehouse_btn button-primary" title="Delete Warehouses" onclick="return en_usps_small_delete_bulk_locations(event, 'en_usps_small_delete_warehouse_item', 'warehouse');"><?php _e('Delete', 'eniture-technology'); ?>
     46                    </button>
    4247
    43                 <h1><?php esc_attr_e('Warehouses', 'small-package-quotes-usps-edition'); ?></h1>
    44                 <button onclick="en_show_popup_location(true, event)" type="button"
    45                         class="button-primary <?php echo esc_attr(self::$disabled_plan); ?>"><?php esc_attr_e('Add', 'small-package-quotes-usps-edition'); ?>
    46                 </button>
    47                 <?php echo wp_kses_post(self::$plan_required); ?>
     48                    <?php echo wp_kses_post(self::$plan_required); ?>
     49                </div>
    4850
    4951                <p><?php esc_attr_e('Warehouses that inventory all products not otherwise identified as drop shipped items. The warehouse with the
    5052            lowest shipping cost to the destination is used for quoting purposes.', 'small-package-quotes-usps-edition'); ?></p>
    5153
     54                <div class="en_usps_wh_location_success_message"><strong>Success! </strong><span></span></div>
     55                <div class="en_usps_small_warehouse_success_message"><strong>Success! </strong> <span>Selected warehouses deleted successfully.</span></div>
     56                <div class="en_usps_small_warehouse_error_message"><strong>Error!</strong> <span>Please select at least one warehouse to delete.</span></div>
     57
    5258                <table class="en_location_table en_location_warehouse_table">
    5359                    <thead>
    5460                        <tr>
     61                            <th class="en_wd_warehouse_list_heading en_usps_small_bulk_delete_col">
     62                                <!-- Bulk delete -->
     63                                <input type="checkbox" name="en_usps_small_bulk_delete_warehouses" id="en_usps_small_bulk_delete_warehouses" onclick="return en_usps_small_select_bulk_locations('en_usps_small_delete_warehouse_item', this);" />
     64                            </th>
    5565                            <?php echo wp_kses_post(\EnLocation::en_arrange_table_data('th', $en_heading)); ?>
    5666                            <th><?php esc_attr_e('Action', 'small-package-quotes-usps-edition'); ?></th>
  • small-package-quotes-usps-edition/trunk/admin/tab/quote-settings/en-quote-settings.php

    r3439225 r3494405  
    154154            ];
    155155
     156            $services['usps_quote_information_preference'] = [
     157                'name' => __('Quote Information Preference', 'small-package-quotes-usps-edition'),
     158                'type' => 'radio',
     159                'default' => 'yes',
     160                'id' => 'usps_quote_information_preference',
     161                'options' => array(
     162                    'yes' => __('Record it in the Additional Order Details widget. (Default)', 'small-package-quotes-usps-edition'),
     163                    'no' => __('Don\'t record it in the Additional Order Details widget.', 'small-package-quotes-usps-edition'),
     164                ),
     165            ];
     166
     167            $services = array_merge($services, self::delivery_estimate_option(), self::cutt_off_time());
    156168
    157169            /**
     
    222234         */
    223235        static public function delivery_estimate_option() {
    224             $option = $message = '';
    225             if (isset($_REQUEST['tab'])) {
    226                 $feature_option = apply_filters("usps_plans_suscription_and_features", 'delivery_estimate_option');
    227                 if (is_array($feature_option)) {
    228                     $option = 'en_usps_disabled';
    229                     $message = apply_filters("usps_plans_notification_link", $feature_option);
    230                 }
    231             }
    232 
    233236            return [
    234237                'delivery_estimate_options' => [
     
    236239                    'type' => 'text',
    237240                    'class' => 'hidden',
    238                     'desc' => $message,
    239241                    'id' => 'delivery_estimate_options'
    240242                ],
     
    242244                    'name' => '',
    243245                    'type' => 'radio',
    244                     'class' => $option,
    245246                    'default' => "dont_show_estimates",
    246247                    'options' => [
     
    326327                ],
    327328                'en_usps_fulfilment_offset_days' => [
    328                     'name' => __('Fulfilment Offset Days', 'small-package-quotes-usps-edition'),
    329                     'type' => 'text',
    330                     'class' => $option,
    331                     'desc' => 'The number of days the ship date needs to be moved to allow the processing of the order.',
     329                    'name' => __('Fulfillment Offset Days', 'small-package-quotes-usps-edition'),
     330                    'type' => 'text',
     331                    'class' => $option,
     332                    'desc' => 'The number of days the ship date needs to be moved to allow for the processing of the order.',
     333                    'placeholder' => 'Fulfillment offset days, e.g. 2',
    332334                    'id' => 'en_usps_fulfilment_offset_days'
    333335                ],
  • small-package-quotes-usps-edition/trunk/en-install.php

    r3439225 r3494405  
    4242        ]);
    4343
    44         wp_enqueue_script('EnUspsAdminJs', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.js', [], '1.0.7');
     44        wp_enqueue_script('EnUspsAdminJs', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.js', [], '1.0.8');
    4545        wp_localize_script('EnUspsAdminJs', 'en_usps_admin_script', [
    4646            'pluginsUrl' => EN_USPS_PLUGIN_URL,
     
    6262        wp_enqueue_style('EnWickedPickerCss');
    6363
    64         wp_enqueue_script('EnUspsLocationScript', EN_USPS_DIR_FILE . '/admin/tab/location/assets/js/en-usps-location.js', [], '1.0.2');
     64        wp_enqueue_script('EnUspsLocationScript', EN_USPS_DIR_FILE . '/admin/tab/location/assets/js/en-usps-location.js', [], '1.0.3');
    6565        wp_localize_script('EnUspsLocationScript', 'en_usps_location_script', array(
    6666            'pluginsUrl' => EN_USPS_PLUGIN_URL,
     
    6868        ));
    6969
    70         wp_register_style('EnUspsLocationStyle', EN_USPS_DIR_FILE . '/admin/tab/location/assets/css/en-usps-location.css', false, '1.0.2');
     70        wp_register_style('EnUspsLocationStyle', EN_USPS_DIR_FILE . '/admin/tab/location/assets/css/en-usps-location.css', false, '1.0.3');
    7171        wp_enqueue_style('EnUspsLocationStyle');
    7272
    73         wp_register_style('EnUspsAdminCss', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.css', false, '1.0.5');
     73        wp_register_style('EnUspsAdminCss', EN_USPS_DIR_FILE . '/admin/assets/en-usps-admin.css', false, '1.0.6');
    7474        wp_enqueue_style('EnUspsAdminCss');
    7575
     
    247247            }else{
    248248                $plan_required = '0';
    249                 $feature_status = EN_USPS_NAME . ': Enabled.';
     249                $feature_status = 'WooCommerce USPS Small Package Quotes: Enabled.';
    250250            }
    251251
  • small-package-quotes-usps-edition/trunk/http/en-curl.php

    r3439225 r3494405  
    123123        {
    124124            $cachable_keys = [
    125                 'serverName', 'licenseKey', 'includeDeclaredValue', 'shipment_type', 'shipment_weight', 'commdityDetails', 'productDetails', 'originAddress', 'product_quantities', 'product_prices', 'receiverZip', 'receiverState', 'receiverCountryCode', 'receiverCity', 'instorPickupLocalDelEnable', 'activeServices', 'rateTier', 'sbsMode'
     125                'serverName', 'licenseKey', 'includeDeclaredValue', 'shipment_type', 'shipment_weight', 'commdityDetails', 'productDetails', 'originAddress', 'product_quantities', 'product_prices', 'receiverZip', 'receiverState', 'receiverCountryCode', 'receiverCity', 'instorPickupLocalDelEnable', 'activeServices', 'rateTier', 'sbsMode', 'modifyShipmentDateTime', 'OrderCutoffTime', 'shipmentOffsetDays', 'shipmentWeekDays'
    126126            ];
    127127            $cachable_data = [];
     
    137137                $cachable_data['addressLine2'] = (isset($request_data['addressLine2'])) ? $request_data['addressLine2'] : '';
    138138                $cachable_data['defaultRADAddressType'] = $request_data['defaultRADAddressType'];
     139                $cachable_data['defaultRADWithoutStreetAddress'] = isset($request_data['defaultRADWithoutStreetAddress']) ? $request_data['defaultRADWithoutStreetAddress'] : '';
    139140                $cachable_data['poboxAddressValidation'] = $request_data['poboxAddressValidation'];
    140141            }
    141142
    142             if (isset($request_data['standardPackaging']) && $request_data['standardPackaging'] == 1) {
    143                 $cachable_data['standardPackaging'] = $request_data['standardPackaging'];
    144                 $cachable_data['pallet'] = $request_data['pallet'];
     143            if (isset($request_data['binPackaging']) && $request_data['binPackaging'] == 1) {
     144                $cachable_data['binPackaging'] = $request_data['binPackaging'];
     145                $cachable_data['bins'] = $request_data['bins'];
    145146            }
    146147
  • small-package-quotes-usps-edition/trunk/readme.txt

    r3439225 r3494405  
    44Requires at least: 6.4
    55Tested up to: 6.9
    6 Stable tag: 1.3.12
     6Stable tag: 1.3.13
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    132132== Changelog ==
    133133
     134= 1.3.13 - 2026-03-30 =
     135* Update: Added bulk delete support for warehouse and drop ship locations.
     136* Update: Added product-level offset days functionality.
     137* Update: Added settings to include order metadata and control its visibility on the order details page.
     138
    134139= 1.3.12 - 2026-01-14 =
    135140* Update: Added data sanitization in the quotes request to ensure cleaner and more reliable API communication.
  • small-package-quotes-usps-edition/trunk/server/api/en-response.php

    r3439225 r3494405  
    384384                    // Cut Off Time & Ship Date Offset
    385385                    $transitDays = self::en_sanitize_rate('transitDays', '');
    386                     $calender_date = self::en_sanitize_rate('calenderDate', '');
    387                     $calender_days_in_transit = self::en_sanitize_rate('CalenderDaysInTransit', '');
     386                    $calender_date = self::en_sanitize_rate('transitDate', '');
     387                    $calender_days_in_transit = self::en_sanitize_rate('totalTransitTimeInDays', '');
    388388
    389389                    if ($delivery_estimate_option == "delivery_date" && strlen($calender_date) > 0) {
    390                         $label .= ' ( Expected delivery by ' . gmdate('Y-m-d', strtotime($calender_date)) . ')';
     390                        $label .= ' (Expected delivery by ' . gmdate('m-d-Y', strtotime($calender_date)) . ')';
    391391                    } elseif ($delivery_estimate_option == "delivery_days" && strlen($calender_days_in_transit) > 0) {
    392                         $correct_word = $calender_days_in_transit == 1 ? 'is' : 'are';
    393                         $label .= ' ( Estimated number of days until delivery ' . $correct_word . ' ' . $calender_days_in_transit . ' )';
     392                        $label .= ' (Intransit days: ' . $calender_days_in_transit . ')';
    394393                    }
    395394
  • small-package-quotes-usps-edition/trunk/server/en-shipping-rates.php

    r3439225 r3494405  
    223223                    // Images for FDO
    224224                    $image_urls = apply_filters('en_fdo_image_urls_merge', []);
     225                    $save_order_meta_data = get_option('usps_quote_information_preference');
     226                    $save_packaging_data = get_option('box_sizing_packaging_solution_preference');
    225227
    226228                    foreach ($en_rates as $accessorial => $rate) {
     
    245247                            // Images for FDO
    246248                            $rate['meta_data']['en_fdo_image_urls'] = wp_json_encode($image_urls);
     249
     250                            // Remove meta data and packaging data if not required
     251                            if ($save_order_meta_data == 'no') unset($rate['meta_data']['en_fdo_meta_data']);
     252                            if ($save_packaging_data == 'no') unset($rate['meta_data']['bin_packaging']);
    247253                        }
    248254
  • small-package-quotes-usps-edition/trunk/server/package/en-package.php

    r3439225 r3494405  
    105105                    // Get product level markup value
    106106                    $product_level_markup = self::en_get_product_level_markup($product_data, $product['variation_id'], $product['product_id'], $product['quantity']);
     107                    $product_level_fulfillment_offset = self::en_get_product_level_fulfillment_offset_days($product_data, $product['variation_id'], $product['product_id']);
    107108
    108109                    self::$post_id = (isset($product['variation_id']) && $product['variation_id'] > 0) ?
     
    147148                        'isInsuranceActive' => $isInsuranceIctive,
    148149                        'lineItemSlug' => $product_tag,
    149                         'markup' => $product_level_markup
     150                        'markup' => $product_level_markup,
     151                        'fulfillment_offset_days' => $product_level_fulfillment_offset,
    150152                    ];
    151153
     
    302304                            self::$en_request['product_prices'][$origin_zip_code] = floatval($product_data->get_price() * floatval($product['quantity']));
    303305                        }
     306
     307                        // Track maximum fulfillment offset days
     308                        if (is_numeric($product_level_fulfillment_offset) && $product_level_fulfillment_offset > 0) {
     309                            if (!isset(self::$en_request['max_fulfillment_offset_days']) || $product_level_fulfillment_offset > self::$en_request['max_fulfillment_offset_days']) {
     310                                self::$en_request['max_fulfillment_offset_days'] = $product_level_fulfillment_offset;
     311                            }
     312                        }
    304313                    }
    305314                }
     
    502511            $en_settings = json_decode(EN_USPS_SET_QUOTE_SETTINGS, true);
    503512            extract($en_settings);
     513
     514            // Use product-level fulfillment offset days if available, otherwise use global setting
     515            if (isset(self::$en_request['max_fulfillment_offset_days']) && is_numeric(self::$en_request['max_fulfillment_offset_days']) && self::$en_request['max_fulfillment_offset_days'] > 0) {
     516                $fulfilment_offset_days = self::$en_request['max_fulfillment_offset_days'];
     517            }
     518
    504519            if (!is_array($feature_option) && ($delivery_estimate_option == 'delivery_days' || $delivery_estimate_option == 'delivery_date')) {
    505520                $settings = [
    506                     'modifyShipmentDateTime' => strlen($cutt_off_time) > 0 && strlen($fulfilment_offset_days) > 0 && !empty($shipment_days) ? true : false,
     521                    'modifyShipmentDateTime' => strlen($cutt_off_time) > 0 || strlen($fulfilment_offset_days) > 0 || !empty($shipment_days) ? true : false,
    507522                    'OrderCutoffTime' => $cutt_off_time,
    508523                    'shipmentOffsetDays' => $fulfilment_offset_days,
     
    870885            return $is_filter_applied;
    871886        }
     887
     888        public static function en_get_product_level_fulfillment_offset_days($_product, $variation_id, $product_id)
     889        {
     890            $fulfillment_offset_days = '';
     891            $field_name = '_eniture_product_level_fulfillment_offset_days';
     892
     893            if ($_product->get_type() == 'variation' && $variation_id > 0) {
     894                $fulfillment_offset_days = get_post_meta($variation_id, $field_name, true);
     895
     896                if (empty($fulfillment_offset_days) || !is_numeric($fulfillment_offset_days)) {
     897                    $parent_id = $_product->get_parent_id();
     898                    if ($parent_id > 0) {
     899                        $fulfillment_offset_days = get_post_meta($parent_id, $field_name, true);
     900                    }
     901                }
     902            } else {
     903                $fulfillment_offset_days = get_post_meta($_product->get_id(), $field_name, true);
     904            }
     905
     906            if (empty($fulfillment_offset_days) || !is_numeric($fulfillment_offset_days)) {
     907                $fulfillment_offset_days = get_post_meta($product_id, $field_name, true);
     908            }
     909
     910            // Validate and sanitize the value before returning
     911            if (is_numeric($fulfillment_offset_days)) {
     912                $value = intval($fulfillment_offset_days);
     913                return $value;
     914            }
     915
     916            // Return empty string if invalid
     917            return '';
     918        }
    872919    }
    873920
  • small-package-quotes-usps-edition/trunk/small-package-quotes-usps-edition.php

    r3439225 r3494405  
    44 * Plugin URI: https://eniture.com/products/
    55 * Description: Dynamically retrieves your negotiated shipping rates from Usps Express and displays the results in the WooCommerce shopping cart.
    6  * Version: 1.3.12
     6 * Version: 1.3.13
    77 * Author: Eniture Technology
    88 * Author URI: http://eniture.com/
     
    2525});
    2626
    27 if (empty(\EnUspsGuard\EnUspsGuard::en_check_prerequisites('USPS', '5.6', '4.0', '2.3'))) {
    28     require_once 'en-install.php';
    29 }
     27add_action( 'init', function () {
     28    if (!is_textdomain_loaded('small-package-quotes-usps-edition')) {
     29        load_plugin_textdomain('small-package-quotes-usps-edition', false, dirname(plugin_basename(__FILE__)) . '/languages/');
     30    }
     31   
     32    if (empty(\EnUspsGuard\EnUspsGuard::en_check_prerequisites('USPS', '5.6', '4.0', '2.3'))) {
     33        require_once 'en-install.php';
     34    }
     35});
Note: See TracChangeset for help on using the changeset viewer.