Plugin Directory

Changeset 3436167


Ignore:
Timestamp:
01/09/2026 05:30:58 PM (3 weeks ago)
Author:
integracionandreani
Message:

Update to version 1.3.0 - Add minimum amount for free shipping and contract refresh functionality

Location:
andreani-shipping/trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • andreani-shipping/trunk/andreani.php

    r3434734 r3436167  
    44 * Plugin URI: https://wordpress.org/plugins/andreani-shipping
    55 * Description: Plugin oficial de Andreani. Simplifica la gestión de tus envíos con Andreani.
    6  * Version: 1.2.0
     6 * Version: 1.3.0
    77 * Author: Andreani
    88 * Author URI: https://www.andreani.com
  • andreani-shipping/trunk/includes/andreani-plugin.php

    r3434734 r3436167  
    8383        add_filter( 'woocommerce_shipping_methods', array( $this, 'add_andreani_shipping_method' ) );
    8484        add_action( 'woocommerce_shipping_init', array( $this, 'init_andreani_shipping_method' ) );
     85        add_action( 'wp_ajax_andreani_refresh_contratos', array( $this, 'ajax_refresh_contratos' ) );
    8586
    8687        Andreani_Checkout::get_instance();
     
    182183
    183184        return array_merge( $plugin_links, $links );
     185    }
     186
     187    /**
     188     * AJAX handler para refrescar contratos corporativos
     189     */
     190    public function ajax_refresh_contratos() {
     191        check_ajax_referer( 'andreani_refresh_contratos', 'nonce' );
     192
     193        if ( ! current_user_can( 'manage_woocommerce' ) ) {
     194            wp_send_json_error( array( 'message' => __( 'No tienes permisos para realizar esta acción.', 'andreani-shipping' ) ) );
     195        }
     196
     197        $settings = $this->get_shipping_settings();
     198        $hash_andreani = isset( $settings['hash_andreani'] ) ? $settings['hash_andreani'] : '';
     199        $tipo_cliente = isset( $settings['tipo_cliente'] ) ? $settings['tipo_cliente'] : '';
     200
     201        if ( empty( $hash_andreani ) || 'corporativo' !== $tipo_cliente ) {
     202            wp_send_json_error( array( 'message' => __( 'Configuración no válida para refrescar contratos.', 'andreani-shipping' ) ) );
     203        }
     204
     205        $corpo_api = Andreani_Corpo_Api::get_instance();
     206        $result = $corpo_api->validate_hash( $hash_andreani );
     207
     208        if ( ! $result ) {
     209            wp_send_json_error( array( 'message' => __( 'Error al conectar con Andreani. Verifica tu credencial.', 'andreani-shipping' ) ) );
     210        }
     211
     212        Andreani_Api_Manager::clear_settings_cache();
     213
     214        wp_send_json_success( array( 'message' => __( 'Contratos actualizados correctamente.', 'andreani-shipping' ) ) );
     215    }
     216
     217    /**
     218     * Obtener configuración del método de envío
     219     */
     220    private function get_shipping_settings() {
     221        global $wpdb;
     222
     223        $option_pattern = $wpdb->esc_like( 'woocommerce_' . ANDREANI_SHIPPING_METHOD_ID . '_' ) . '%' . $wpdb->esc_like( '_settings' );
     224
     225        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     226        $results = $wpdb->get_results(
     227            $wpdb->prepare(
     228                "SELECT option_value FROM {$wpdb->options} WHERE option_name LIKE %s LIMIT 1",
     229                $option_pattern
     230            ),
     231            ARRAY_A
     232        );
     233
     234        if ( ! empty( $results ) ) {
     235            return maybe_unserialize( $results[0]['option_value'] );
     236        }
     237
     238        return array();
    184239    }
    185240
  • andreani-shipping/trunk/includes/api/andreani-api-manager.php

    r3434734 r3436167  
    165165            'mostrar_sin_decimales' => isset($settings['mostrar_sin_decimales']) ? $settings['mostrar_sin_decimales'] === 'yes' : false,
    166166            'envio_gratis' => isset($settings['envio_gratis']) ? $settings['envio_gratis'] === 'yes' : false,
     167            'envio_gratis_monto_minimo' => isset($settings['envio_gratis_monto_minimo']) && $settings['envio_gratis_monto_minimo'] !== '' ? floatval($settings['envio_gratis_monto_minimo']) : 0,
    167168        );
    168169
  • andreani-shipping/trunk/includes/api/common/andreani-api-utils.php

    r3434734 r3436167  
    7575     * @param string $prefix Prefijo del método de envío
    7676     * @param bool $envio_gratis Si el envío es gratis para el cliente
     77     * @param float $monto_minimo Monto mínimo de compra para aplicar envío gratis (0 = sin mínimo)
     78     * @param float $cart_total Total del carrito
    7779     * @return array Tarifas de envío formateadas
    7880     */
    79     public static function create_shipping_rate_from_response($rates, $prefix, $envio_gratis = false) {
     81    public static function create_shipping_rate_from_response($rates, $prefix, $envio_gratis = false, $monto_minimo = 0, $cart_total = 0) {
    8082        $shipping_rates = array();
    8183        $codes_used = array();
     84
     85        // Determinar si aplica envío gratis
     86        $aplicar_envio_gratis = false;
     87        if ( $envio_gratis ) {
     88            // Si no hay monto mínimo configurado (0), siempre aplica envío gratis
     89            // Si hay monto mínimo, el carrito debe ser >= al monto mínimo
     90            $aplicar_envio_gratis = ( $monto_minimo <= 0 ) || ( $cart_total >= $monto_minimo );
     91        }
    8292
    8393        foreach ($rates as $rate) {
    8494            $code = $rate['code'];
    8595            if (!in_array($code, $codes_used)) {
    86                 $cost = $envio_gratis ? 0 : $rate['total'];
     96                $cost = $aplicar_envio_gratis ? 0 : $rate['total'];
     97                $label = "Andreani (" . sprintf("%s", $rate['code']) . ")";
     98
     99                if ( $aplicar_envio_gratis ) {
     100                    $label .= ' - ¡Envío gratis!';
     101                }
     102
    87103                $shipping_rates[] = array(
    88104                    'id' => $prefix . "$code",
    89                     'label' => "Andreani (" . sprintf("%s", $rate['code']) . ")",
     105                    'label' => $label,
    90106                    'cost' => $cost,
    91107                    'calc_tax' => 'per_item',
  • andreani-shipping/trunk/includes/api/corpo/andreani-corpo.php

    r3434734 r3436167  
    1818    private $mostrar_sin_decimales;
    1919    private $envio_gratis;
     20    private $envio_gratis_monto_minimo;
    2021    private $hash_andreani;
    2122    private $info_cliente;
     
    3839        $this->mostrar_sin_decimales = isset($settings['mostrar_sin_decimales']) ? $settings['mostrar_sin_decimales'] === 'yes' : false;
    3940        $this->envio_gratis = isset($settings['envio_gratis']) ? $settings['envio_gratis'] : false;
     41        $this->envio_gratis_monto_minimo = isset($settings['envio_gratis_monto_minimo']) ? floatval($settings['envio_gratis_monto_minimo']) : 0;
    4042        $this->info_cliente = $this->get_client_info();
    4143
     
    108110            $errors[] = $result->get_error_message();
    109111        } else {
    110             $rates = Andreani_Api_Utils::create_shipping_rate_from_response( $result, self::SHIPPING_METHOD_PREFIX, $this->envio_gratis );
     112            $cart_total = isset( $package['contents_cost'] ) ? floatval( $package['contents_cost'] ) : 0;
     113            $rates = Andreani_Api_Utils::create_shipping_rate_from_response( $result, self::SHIPPING_METHOD_PREFIX, $this->envio_gratis, $this->envio_gratis_monto_minimo, $cart_total );
    111114        }
    112115
  • andreani-shipping/trunk/includes/api/pyme/andreani-pyme.php

    r3434734 r3436167  
    1818    private $mostrar_sin_decimales;
    1919    private $envio_gratis;
     20    private $envio_gratis_monto_minimo;
    2021    private $hash_andreani;
    2122    private $info_cliente;
     
    3839        $this->mostrar_sin_decimales = isset($settings['mostrar_sin_decimales']) ? $settings['mostrar_sin_decimales'] === 'yes' : false;
    3940        $this->envio_gratis = isset($settings['envio_gratis']) ? $settings['envio_gratis'] : false;
     41        $this->envio_gratis_monto_minimo = isset($settings['envio_gratis_monto_minimo']) ? floatval($settings['envio_gratis_monto_minimo']) : 0;
    4042        $this->info_cliente = $this->get_client_info();
    4143
     
    257259            $errors[] = $result->get_error_message();
    258260        } else {
    259             $rates = Andreani_Api_Utils::create_shipping_rate_from_response( $result, self::SHIPPING_METHOD_PREFIX, $this->envio_gratis );
     261            $cart_total = isset( $package['contents_cost'] ) ? floatval( $package['contents_cost'] ) : 0;
     262            $rates = Andreani_Api_Utils::create_shipping_rate_from_response( $result, self::SHIPPING_METHOD_PREFIX, $this->envio_gratis, $this->envio_gratis_monto_minimo, $cart_total );
    260263        }
    261264
  • andreani-shipping/trunk/includes/assets/css/admin.css

    r3434734 r3436167  
    277277}
    278278
     279/* Contratos Card */
     280.andreani-settings-card--contratos {
     281  margin-top: 20px;
     282  transition: opacity 0.3s ease, transform 0.3s ease;
     283}
     284
     285.andreani-settings-card--hidden {
     286  opacity: 0;
     287  transform: translateY(-10px);
     288  pointer-events: none;
     289  height: 0;
     290  overflow: hidden;
     291  margin: 0;
     292  padding: 0;
     293}
     294
     295.andreani-badge--info {
     296  background: #f0f0f0;
     297  color: #50575e;
     298  font-size: 11px;
     299  padding: 4px 10px;
     300}
     301
     302.andreani-contratos-list {
     303  display: grid;
     304  gap: 12px;
     305}
     306
     307.andreani-contrato-item {
     308  background-color: #f8f9fa;
     309  border: 1px solid #e0e0e0;
     310  border-radius: 6px;
     311  padding: 12px 16px;
     312  display: grid;
     313  grid-template-columns: repeat(3, 1fr);
     314  gap: 8px;
     315}
     316
     317.andreani-contrato-item__row {
     318  display: flex;
     319  flex-direction: column;
     320  gap: 2px;
     321}
     322
     323.andreani-contrato-item__label {
     324  font-size: 11px;
     325  color: #667085;
     326  text-transform: uppercase;
     327  letter-spacing: 0.3px;
     328}
     329
     330.andreani-contrato-item__value {
     331  font-size: 14px;
     332  color: #1d2327;
     333  font-weight: 500;
     334}
     335
     336.andreani-contrato-item__value--code {
     337  font-family: monospace;
     338  background-color: #fff;
     339  padding: 2px 6px;
     340  border-radius: 4px;
     341  border: 1px solid #e0e0e0;
     342  display: inline-block;
     343}
     344
     345/* Refresh Contratos Button */
     346.andreani-refresh-contratos {
     347  display: inline-flex;
     348  align-items: center;
     349  gap: 6px;
     350  margin-left: auto;
     351  padding: 6px 12px;
     352  background-color: #fff;
     353  border: 1px solid #d0d5dd;
     354  border-radius: 6px;
     355  font-size: 13px;
     356  font-weight: 500;
     357  color: #667085;
     358  cursor: pointer;
     359  transition: all 0.2s ease;
     360}
     361
     362.andreani-refresh-contratos:hover {
     363  background-color: #f8f9fa;
     364  border-color: #e31e24;
     365  color: #e31e24;
     366}
     367
     368.andreani-refresh-contratos:disabled {
     369  opacity: 0.7;
     370  cursor: not-allowed;
     371}
     372
     373.andreani-refresh-contratos svg {
     374  width: 16px;
     375  height: 16px;
     376  fill: currentColor;
     377}
     378
     379.andreani-refresh-contratos--loading svg {
     380  animation: andreani-spin 1s linear infinite;
     381}
     382
     383@keyframes andreani-spin {
     384  from {
     385    transform: rotate(0deg);
     386  }
     387  to {
     388    transform: rotate(360deg);
     389  }
     390}
     391
    279392.andreani-admin-notice {
    280393  border-left-color: #e31e24 !important;
     
    327440    width: 100%;
    328441  }
    329 }
     442
     443  .andreani-contrato-item {
     444    grid-template-columns: 1fr;
     445  }
     446}
  • andreani-shipping/trunk/includes/assets/js/admin.js

    r3434734 r3436167  
    1313      this.addTooltipSpacing();
    1414      this.initCredentialEdit();
     15      this.initEnvioGratisToggle();
     16      this.initRefreshContratos();
    1517    },
    1618
     
    3840    },
    3941
     42    initRefreshContratos() {
     43      const $refreshBtn = $('.andreani-refresh-contratos');
     44      if ($refreshBtn.length === 0) return;
     45
     46      $refreshBtn.on('click', function(e) {
     47        e.preventDefault();
     48        const $btn = $(this);
     49        const nonce = $btn.data('nonce');
     50        const originalText = $btn.html();
     51
     52        $btn.prop('disabled', true).addClass('andreani-refresh-contratos--loading');
     53        $btn.html('<svg class="andreani-spinner" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg> Actualizando...');
     54
     55        $.ajax({
     56          url: ajaxurl,
     57          type: 'POST',
     58          data: {
     59            action: 'andreani_refresh_contratos',
     60            nonce: nonce
     61          },
     62          success: function(response) {
     63            if (response.success) {
     64              AndreaniAdmin.showNotice(response.data.message, 'success');
     65              setTimeout(() => location.reload(), 1000);
     66            } else {
     67              AndreaniAdmin.showNotice(response.data.message || 'Error al actualizar contratos.', 'error');
     68              $btn.prop('disabled', false).removeClass('andreani-refresh-contratos--loading');
     69              $btn.html(originalText);
     70            }
     71          },
     72          error: function() {
     73            AndreaniAdmin.showNotice('Error de conexión. Intenta nuevamente.', 'error');
     74            $btn.prop('disabled', false).removeClass('andreani-refresh-contratos--loading');
     75            $btn.html(originalText);
     76          }
     77        });
     78      });
     79    },
     80
     81    initEnvioGratisToggle() {
     82      const $envioGratisCheckbox = $('input[id*="envio_gratis"]').not('[id*="monto_minimo"]');
     83      const $montoMinimoInput = $('input[id*="envio_gratis_monto_minimo"]');
     84      const $montoMinimoRow = $montoMinimoInput.closest('tr');
     85
     86      if ($envioGratisCheckbox.length === 0 || $montoMinimoInput.length === 0) return;
     87
     88      // Ocultar la fila original
     89      $montoMinimoRow.hide();
     90
     91      // Crear el contenedor inline debajo del checkbox
     92      const $checkboxLabel = $envioGratisCheckbox.closest('label');
     93      const $fieldset = $checkboxLabel.closest('fieldset');
     94      const $container = $fieldset.length > 0 ? $fieldset : $checkboxLabel.parent();
     95
     96      const $inlineWrapper = $('<div class="andreani-monto-minimo-wrapper"></div>');
     97      $inlineWrapper.css({
     98        'margin-top': '10px',
     99        'padding-left': '24px',
     100        'display': 'flex',
     101        'align-items': 'center',
     102        'gap': '8px'
     103      });
     104
     105      const $label = $('<label></label>').css({
     106        'font-weight': 'normal',
     107        'color': '#50575e',
     108        'white-space': 'nowrap'
     109      }).text('Aplicar solo en compras mayores a $');
     110
     111      // Clonar el input y configurarlo
     112      const $newInput = $montoMinimoInput.clone();
     113      $newInput.css({
     114        'width': '120px',
     115        'margin': '0'
     116      });
     117
     118      // Sincronizar valores entre inputs
     119      $newInput.on('input', function() {
     120        $montoMinimoInput.val($(this).val());
     121      });
     122
     123      $inlineWrapper.append($label).append($newInput);
     124      $container.append($inlineWrapper);
     125
     126      // Estado inicial
     127      if (!$envioGratisCheckbox.is(':checked')) {
     128        $inlineWrapper.hide();
     129      }
     130
     131      // Escuchar cambios
     132      $envioGratisCheckbox.on('change', () => {
     133        if ($envioGratisCheckbox.is(':checked')) {
     134          $inlineWrapper.slideDown(200);
     135        } else {
     136          $inlineWrapper.slideUp(200);
     137        }
     138      });
     139    },
     140
    40141    bindEvents() {
    41142      $(document).on("submit", "form", function (e) {
     
    49150        $(".andreani-cancel-edit").toggle(hasChanged);
    50151        $(".andreani-badge").toggleClass("andreani-badge--hidden", hasChanged);
     152        $(".andreani-settings-card--contratos").toggleClass("andreani-settings-card--hidden", hasChanged);
    51153      });
    52154
     
    62164      $(".andreani-cancel-edit").hide();
    63165      $(".andreani-badge").removeClass("andreani-badge--hidden");
     166      $(".andreani-settings-card--contratos").removeClass("andreani-settings-card--hidden");
    64167      $credentialField.blur();
    65168    },
  • andreani-shipping/trunk/includes/shipping/andreani-form-fields-shipping-config.php

    r3434734 r3436167  
    3838    ),
    3939
     40    'envio_gratis_monto_minimo' => array(
     41        'title'       => __( 'Monto mínimo para envío gratis', 'andreani-shipping' ),
     42        'type'        => 'number',
     43        'default'     => '',
     44        'placeholder' => __( 'Sin mínimo', 'andreani-shipping' ),
     45        'description' => __( 'Monto mínimo de compra para aplicar envío gratis. Dejar vacío para que siempre sea gratis.', 'andreani-shipping' ),
     46        'desc_tip'    => true,
     47        'custom_attributes' => array(
     48            'min'  => '0',
     49            'step' => '1',
     50        ),
     51    ),
     52
    4053    'mostrar_sin_decimales' => array(
    4154        'title'       => __( 'Mostrar sin decimales', 'andreani-shipping' ),
  • andreani-shipping/trunk/includes/shipping/andreani-shipping.php

    r3434734 r3436167  
    101101                </div>
    102102            </div>
     103
     104            <?php
     105            if ( 'corporativo' === $tipo_cliente && ! empty( $hash_andreani ) ) :
     106                $info_corporativo = get_option( 'andreani_corporativo_info', array() );
     107                $contratos_raw = isset( $info_corporativo['contratos'] ) ? $info_corporativo['contratos'] : array();
     108
     109                $tipos_permitidos = array( 'paquetes', 'encomienda');
     110                $contratos = array_filter( $contratos_raw, function( $contrato ) use ( $tipos_permitidos ) {
     111                    $tipo = isset( $contrato['tipoDeEnvioNombre'] ) ? strtolower( $contrato['tipoDeEnvioNombre'] ) : '';
     112                    return in_array( $tipo, $tipos_permitidos, true );
     113                } );
     114
     115                if ( ! empty( $contratos ) ) :
     116            ?>
     117            <div class="andreani-settings-card andreani-settings-card--contratos">
     118                <div class="andreani-settings-card__header">
     119                    <div class="andreani-settings-card__icon">
     120                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></svg>
     121                    </div>
     122                    <h3 class="andreani-settings-card__title"><?php esc_html_e( 'Contratos Habilitados', 'andreani-shipping' ); ?></h3>
     123                    <span class="andreani-badge andreani-badge--info"><?php echo esc_html( count( $contratos ) ); ?></span>
     124                    <button type="button" class="andreani-refresh-contratos" data-nonce="<?php echo esc_attr( wp_create_nonce( 'andreani_refresh_contratos' ) ); ?>">
     125                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
     126                        <?php esc_html_e( 'Actualizar', 'andreani-shipping' ); ?>
     127                    </button>
     128                </div>
     129                <div class="andreani-settings-card__body">
     130                    <div class="andreani-contratos-list">
     131                        <?php foreach ( $contratos as $contrato ) : ?>
     132                            <div class="andreani-contrato-item">
     133                                <div class="andreani-contrato-item__row">
     134                                    <span class="andreani-contrato-item__label"><?php esc_html_e( 'Servicio:', 'andreani-shipping' ); ?></span>
     135                                    <span class="andreani-contrato-item__value"><?php echo esc_html( $contrato['tipoDeEnvioNombre'] ); ?></span>
     136                                </div>
     137                                <div class="andreani-contrato-item__row">
     138                                    <span class="andreani-contrato-item__label"><?php esc_html_e( 'Modo de entrega:', 'andreani-shipping' ); ?></span>
     139                                    <span class="andreani-contrato-item__value"><?php echo esc_html( ucfirst( $contrato['modoDeEntregaNombre'] ) ); ?></span>
     140                                </div>
     141                                <div class="andreani-contrato-item__row">
     142                                    <span class="andreani-contrato-item__label"><?php esc_html_e( 'Contrato:', 'andreani-shipping' ); ?></span>
     143                                    <span class="andreani-contrato-item__value andreani-contrato-item__value--code"><?php echo esc_html( $contrato['numeroDeContrato'] ); ?></span>
     144                                </div>
     145                            </div>
     146                        <?php endforeach; ?>
     147                    </div>
     148                </div>
     149            </div>
     150            <?php
     151                endif;
     152            endif;
     153            ?>
    103154
    104155            <div class="andreani-settings-footer">
  • andreani-shipping/trunk/includes/utils/andreani-utils.php

    r3434734 r3436167  
    3838        $endpoint_path = $endpoint_path ? basename( $endpoint_path ) : 'unknown';
    3939
     40        $body_log = '';
     41        if ( ! empty( $body ) && 'GET' !== $method ) {
     42            $body_json = wp_json_encode( $body );
     43            $body_log = ' | Body: ' . $body_json;
     44        }
     45
    4046        $attempt = 0;
    4147        $start_time = microtime( true );
     
    4854                $error_code = $response->get_error_code();
    4955                $error_msg = $response->get_error_message();
    50                 self::andreani_log( "[HTTP] {$method} /{$endpoint_path} - Error de conexión: [{$error_code}] {$error_msg} (intento " . ( $attempt + 1 ) . ", {$elapsed_ms}ms)", 'error' );
     56                self::andreani_log( "[HTTP] {$method} /{$endpoint_path} - Error de conexión: [{$error_code}] {$error_msg} (intento " . ( $attempt + 1 ) . ", {$elapsed_ms}ms){$body_log}", 'error' );
    5157                if ( ++$attempt > $retries ) return $response;
    5258                self::sleep_retry($attempt);
     
    5965                $response_body = wp_remote_retrieve_body( $response );
    6066                $error_detail = self::extract_api_error_message( $response_body );
    61                 self::andreani_log( "[HTTP] {$method} /{$endpoint_path} - Error {$response_code}: {$error_detail} (intento " . ( $attempt + 1 ) . ", {$elapsed_ms}ms)", 'error' );
     67                self::andreani_log( "[HTTP] {$method} /{$endpoint_path} - Error {$response_code}: {$error_detail} (intento " . ( $attempt + 1 ) . ", {$elapsed_ms}ms){$body_log}", 'error' );
    6268                if ( ++$attempt > $retries ) return new WP_Error( 'http_error', "Error HTTP {$response_code}: {$error_detail}" );
    6369                self::sleep_retry($attempt);
     
    6773
    6874            $response_body = wp_remote_retrieve_body( $response );
    69             self::andreani_log( "[HTTP] {$method} /{$endpoint_path} - OK {$response_code} ({$elapsed_ms}ms)", 'debug' );
     75            self::andreani_log( "[HTTP] {$method} /{$endpoint_path} - OK {$response_code} ({$elapsed_ms}ms){$body_log}", 'debug' );
    7076
    7177            return $response_body;
  • andreani-shipping/trunk/readme.txt

    r3434734 r3436167  
    55Requires at least: 5.0
    66Tested up to: 6.8
    7 Stable tag: 1.2.0
     7Stable tag: 1.3.0
    88Contributors: integracionandreani
    99Donate link:
     
    6767== Changelog ==
    6868
     69= 1.3.0 =
     70* Nueva funcionalidad: Configuración de monto mínimo personalizado para envío gratis por método de envío
     71* Nueva herramienta administrativa: Botón para refrescar contratos corporativos vía AJAX sin recargar la página
     72* Mejoras en la interfaz de administración con mejor feedback visual y estados de carga
     73* Optimización en el manejo de contratos Andreani con validación mejorada
     74
    6975= 1.2.0 =
    7076* Detección automática del tipo de cliente (Pyme/Corporativo) al validar credenciales
Note: See TracChangeset for help on using the changeset viewer.