Plugin Directory

Changeset 3439783


Ignore:
Timestamp:
01/14/2026 06:39:09 PM (8 weeks ago)
Author:
perseosoftware
Message:

Sincronizar incativos

Location:
perseo-software/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • perseo-software/trunk/PluginPerseo.php

    r3270560 r3439783  
    44Plugin URI: https://perseo.ec/
    55Description: Este Plugins integra el Sistema Contable Perseo Web y PC con la tienda Woocommerce
    6 Version: 32.0
     6Version: 33.0
    77Author: Perseo Soft S.A. - Ecuador
    88Author URI: https://perseo.ec
     
    1313*/
    1414
    15 $version_Plugin = '32.0';
     15$version_Plugin = '33.0';
    1616define('PERSEO_DIR_PATH', plugin_dir_path(__FILE__));
    17 define('PERSEOCONFIGBASE', get_option('pluginperseo_configuracion'));
    18 define('PERSEOCONFIGPARAMETROS', get_option('pluginperseo_parametros'));
     17
     18$perseo_config_temp = get_option('pluginperseo_configuracion');
     19$perseo_parametros_temp = get_option('pluginperseo_parametros');
     20
     21define('PERSEOCONFIGBASE', is_array($perseo_config_temp) ? $perseo_config_temp : []);
     22define('PERSEOCONFIGPARAMETROS', is_array($perseo_parametros_temp) ? $perseo_parametros_temp : []);
     23
     24function fperseo_get_config() {
     25    $config = get_option('pluginperseo_configuracion', []);
     26    return is_array($config) ? $config : [];
     27}
     28
     29function fperseo_get_parametros() {
     30    $parametros = get_option('pluginperseo_parametros', []);
     31    return is_array($parametros) ? $parametros : [];
     32}
    1933
    2034function pluginperseo_install()
     
    5670    // Opcional: Forzar la eliminación de caché de transients
    5771    wp_cache_flush();
     72}
     73
     74// Función para limpiar transients de bloqueo de Perseo
     75function fperseo_limpiar_transients()
     76{
     77    global $wpdb;
     78
     79    // Verificar permisos y nonce
     80    if (!current_user_can('manage_options')) {
     81        return false;
     82    }
     83
     84    if (!isset($_POST['perseo_limpiar_nonce']) || !wp_verify_nonce($_POST['perseo_limpiar_nonce'], 'perseo_limpiar_transients')) {
     85        return false;
     86    }
     87
     88    // Eliminar transients de bloqueo de Perseo (usar $wpdb->options directamente)
     89    $eliminados_transients = $wpdb->query(
     90        "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_perseo_cron_bloqueo_%'"
     91    );
     92    $eliminados_timeouts = $wpdb->query(
     93        "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_perseo_cron_bloqueo_%'"
     94    );
     95
     96    // Limpiar caché
     97    wp_cache_flush();
     98
     99    return $eliminados_transients + $eliminados_timeouts;
     100}
     101add_action('admin_post_perseo_limpiar_transients', 'fperseo_limpiar_transients');
     102
     103// Función para obtener transients activos de Perseo
     104function fperseo_obtener_transients_activos()
     105{
     106    global $wpdb;
     107
     108    $transients = $wpdb->get_results(
     109        "SELECT option_name, option_value
     110         FROM {$wpdb->options}
     111         WHERE option_name LIKE '_transient_perseo_cron_bloqueo_%'
     112         AND option_name NOT LIKE '_transient_timeout_%'"
     113    );
     114
     115    return $transients;
    58116}
    59117
     
    123181            settings_errors('eperseo_verificacion');
    124182            ///////////////////////////////////////////////////////////////////////
    125             //llamamos a la pag de secciones 
     183            //llamamos a la pag de secciones
    126184            //validamos el formulario y enviamos valores para redirigir a la pag perseo
    127185            echo "<form action='options.php' method='post'> ";
     
    129187            do_settings_sections('pluginperseo_menu');
    130188            submit_button('Guardar Cambios');
    131             //submit_button('Guardar Cambios','primary','submit', true, array('id'=>'perseoconexion', 'onclick'=>'perseotestconec()')); 
     189            //submit_button('Guardar Cambios','primary','submit', true, array('id'=>'perseoconexion', 'onclick'=>'perseotestconec()'));
    132190            echo "</form>";
    133191            ///////////////////////////////////////////////////////////////////////
    134             //TEST de conexion 
    135             //echo "<p id='perseovalidarconexion'></p>"; 
     192            //TEST de conexion
     193            //echo "<p id='perseovalidarconexion'></p>";
    136194        }
    137195    }
     
    157215            settings_errors('eperseo_verificacion');
    158216            ///////////////////////////////////////////////////////////////////////
    159             //llamamos a la pag de secciones 
     217            //llamamos a la pag de secciones
    160218            //validamos el formulario y enviamos valores para redirigir a la pag perseo
    161219            echo "<form action='options.php' method='post'   > ";
     
    175233//////////////////////////////////////////////////////////////////////
    176234/// Api settings
    177 /// permiso para guardar configuraciones 
     235/// permiso para guardar configuraciones
    178236function fperseo_plugininicio()
    179237{
     
    420478function sperseo_seccionencabezado()
    421479{
     480    global $wpdb;
     481
     482    // 🔹 Procesar limpieza ANTES de todo (usando GET en lugar de POST)
     483    $mensaje_limpieza = '';
     484    if (isset($_GET['perseo_limpiar']) && $_GET['perseo_limpiar'] == '1') {
     485        if (isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'perseo_limpiar_transients') && current_user_can('manage_options')) {
     486
     487            $eliminados_transients = $wpdb->query(
     488                "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_perseo_cron_bloqueo_%'"
     489            );
     490            $eliminados_timeouts = $wpdb->query(
     491                "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_perseo_cron_bloqueo_%'"
     492            );
     493
     494            wp_cache_flush();
     495
     496            $total = $eliminados_transients + $eliminados_timeouts;
     497            $mensaje_limpieza = "<div class='notice notice-success is-dismissible'><p><strong>Limpieza completada:</strong> Se eliminaron {$total} registros de bloqueo.</p></div>";
     498        }
     499    }
     500
     501    // Mostrar mensaje si existe
     502    if (!empty($mensaje_limpieza)) {
     503        echo $mensaje_limpieza;
     504    }
     505
    422506    echo "<p><b>Sincronizacion de Perseo Software a WordPress :</b><br> Clientes, Productos, Productos Categorias , Productos Imagenes y  Productos Stock. </p>";
    423507    echo "<p><b>Sincronizacion de WordPress a Perseo Software : </b><br> Clientes, Pedidos.</p>";
     
    425509    echo "<p><b>Datos Servidor </b> <br> Version PHP " . phpversion() . " " . $_SERVER['SERVER_SOFTWARE'] . "</p>";
    426510    echo "<h3> Conexion  Perseo Software </h3>";
    427     /////////////////////////////
    428     /// wp_cron
    429     /*
    430     echo '<pre>';
    431     var_dump(wp_get_schedules());
    432              
    433     var_dump(_get_cron_array());
    434     echo '</pre>';   
    435    */
     511
     512    // Obtener transients activos
     513    $transients_activos = fperseo_obtener_transients_activos();
     514
     515    echo "<hr style='margin: 20px 0;'>";
     516    echo "<h3>Estado de Procesos Cron</h3>";
     517
     518    if (!empty($transients_activos)) {
     519        echo "<div class='notice notice-warning'>";
     520        echo "<p><strong>⚠️ Procesos bloqueados o en ejecución:</strong></p>";
     521        echo "<table class='widefat' style='max-width: 500px;'>";
     522        echo "<thead><tr><th>Proceso</th><th>Estado</th></tr></thead>";
     523        echo "<tbody>";
     524        foreach ($transients_activos as $transient) {
     525            $nombre_proceso = str_replace('_transient_perseo_cron_bloqueo_', '', $transient->option_name);
     526            echo "<tr><td><code>{$nombre_proceso}</code></td><td>🔒 Bloqueado</td></tr>";
     527        }
     528        echo "</tbody></table>";
     529        echo "</div>";
     530    } else {
     531        echo "<div class='notice notice-success'><p>✅ No hay procesos bloqueados. Todo está funcionando correctamente.</p></div>";
     532    }
     533
     534    // 🔹 Botón usando enlace GET en lugar de formulario POST (evita conflictos)
     535    $nonce = wp_create_nonce('perseo_limpiar_transients');
     536    $url_limpiar = admin_url('admin.php?page=mperseo_menupage&perseo_limpiar=1&_wpnonce=' . $nonce);
     537
     538    $btn_class = !empty($transients_activos) ? 'button button-primary' : 'button button-secondary';
     539    $btn_text = !empty($transients_activos) ? '🗑️ Limpiar Bloqueos (' . count($transients_activos) . ')' : '🗑️ Limpiar Bloqueos';
     540    $btn_disabled = empty($transients_activos) ? 'disabled' : '';
     541
     542    echo "<div style='margin-top: 15px;'>";
     543    if (!empty($transients_activos)) {
     544        echo "<a href='{$url_limpiar}' class='{$btn_class}' onclick=\"return confirm('¿Estás seguro de eliminar todos los bloqueos? Solo hazlo si un proceso se quedó colgado.');\">{$btn_text}</a>";
     545    } else {
     546        echo "<button type='button' class='{$btn_class}' disabled>{$btn_text}</button>";
     547    }
     548    echo "<p class='description' style='margin-top: 10px;'>Usa este botón <strong>solo</strong> si un proceso de sincronización se quedó bloqueado y no permite ejecutar nuevas sincronizaciones.</p>";
     549    echo "</div>";
     550
     551    echo "<hr style='margin: 20px 0;'>";
    436552}
    437553function sperseo_seccionencabezado1()
     
    463579    echo $perseo_html;
    464580}
     581
    465582function fperseo_certificado($args)
    466583{
     
    517634function fperseo_servidor($args)
    518635{
    519     $perseo_config = PERSEOCONFIGBASE; //parametros de conexion 
     636    $perseo_config = PERSEOCONFIGBASE; //parametros de conexion
    520637    $perseo_activar = '';
    521638    if (isset($perseo_config['perseotiposoftware'])) {
     
    555672                foreach ($perseo_datosServidores as $servidor) {
    556673                    //  echo $registro['sis_servidoresid'];
    557                     // echo "<br>";                             
     674                    // echo "<br>";
    558675                    $perseo_refr1 = ($perseo_config[$args['label_for']] == ($servidor['dominio'])) ? $perseo_selec : '';
    559676
     
    573690function fperseo_impuestos($args)
    574691{
    575     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     692    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    576693    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    577694    //$perseo_selec='selected';
     
    593710    echo $perseo_html;
    594711}
     712
    595713function fperseo_productos($args)
    596714{
    597     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     715    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    598716    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    599717    $perseo_selec = 'selected';
     
    610728    echo $perseo_html;
    611729}
     730
    612731function fperseo_imagenes($args)
    613732{
    614733
    615     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     734    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    616735    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    617736    $perseo_selec = 'selected';
     
    628747    echo $perseo_html;
    629748}
     749
    630750function fperseo_stock($args)
    631751{
    632     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     752    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    633753    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    634754    $perseo_selec = 'selected';
     
    645765    echo $perseo_html;
    646766}
     767
    647768function fperseo_clientes($args)
    648769{
    649770
    650     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     771    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    651772    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    652773    $perseo_selec = 'selected';
     
    663784    echo $perseo_html;
    664785}
     786
    665787function fperseo_pedidos($args)
    666788{
    667789
    668     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     790    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    669791    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    670792    $perseo_selec = 'selected';
     
    681803    echo $perseo_html;
    682804}
     805
    683806function fperseo_categorias($args)
    684807{
     
    703826}
    704827
    705 
    706 
    707828function fperseo_enviarclientes($args)
    708829{
    709     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     830    $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion
    710831    //condcion si existe valiable los dos puntos caso de sino es valor2=10 ? true : false
    711832    $perseo_selec = 'selected';
     
    740861    echo $perseo_html;
    741862}
     863
    742864function fperseo_sincronizar($args)
    743865{
     
    757879function fperseo_tarifaventa($args)
    758880{
    759     $perseo_config = PERSEOCONFIGBASE; //parametros de conexion
    760     $perseo_parametros = PERSEOCONFIGPARAMETROS; // parametrizacion
     881    $perseo_config = PERSEOCONFIGBASE;
     882    $perseo_parametros = get_option('pluginperseo_parametros');
     883
     884    // 🔹 Validar que sean arrays
     885    if (!is_array($perseo_parametros)) {
     886        $perseo_parametros = [];
     887    }
    761888
    762889    if (!empty($perseo_config['perseotoken'])) {
    763         ///////////////////////////////////////////
    764         //Consulta APi
    765         $perseo_selec       = 'selected';
    766         /////////////////////////////////////
    767         //Verificar pc o web
    768         if ($perseo_config['perseotiposoftware'] == 'WEB') {
    769             // $perseo_urltarifas  =$perseo_config['perseoservidor'].''.'/api/tarifas_consulta';
    770             $perseo_urltarifas  = $perseo_config['perseoservidor'] . '/api/tarifas_consulta';
     890        $perseo_selec = 'selected';
     891
     892        if (isset($perseo_config['perseotiposoftware']) && $perseo_config['perseotiposoftware'] == 'WEB') {
     893            $perseo_urltarifas = $perseo_config['perseoservidor'] . '/api/tarifas_consulta';
    771894        } else {
    772             $perseo_urltarifas  = $perseo_config['perseocertificado'] . '://' . $perseo_config['perseoip'] . '/api/tarifas_consulta';
     895            $perseo_urltarifas = ($perseo_config['perseocertificado'] ?? 'http') . '://' . ($perseo_config['perseoip'] ?? '') . '/api/tarifas_consulta';
    773896        }
    774         $datoKEY = [
    775             'api_key' => $perseo_config['perseotoken']
    776         ];
     897
     898        $datoKEY = ['api_key' => $perseo_config['perseotoken']];
    777899        $perseo_responsetarifas = wp_remote_post($perseo_urltarifas, array(
    778             'method'      => 'POST',
    779             'headers'     => array('Content-Type' => 'application/json'),
    780             'body'        => wp_json_encode($datoKEY)
     900            'method' => 'POST',
     901            'headers' => array('Content-Type' => 'application/json'),
     902            'body' => wp_json_encode($datoKEY)
    781903        ));
    782         // presentar datos
    783         //print_r($perseo_responsetarifas);       
    784         //print_r($perseo_responsetarifas['body']);
    785904
    786905        $perseo_muestra = "";
    787         if (!empty($perseo_responsetarifas)) {
    788             if (is_wp_error($perseo_responsetarifas)) {
    789                 echo "<p>Existe problemas en conexion de Api Perseo<p>";
    790             } else {
    791                 if (!empty($perseo_responsetarifas['body'])) {
    792                     $perseo_datosTarifas = json_decode($perseo_responsetarifas['body'], true); //devuelve
    793                     // si es diferente de vacio
    794                     if (isset($perseo_datosTarifas)) {
    795                         foreach ($perseo_datosTarifas as $registro) {
     906        if (!empty($perseo_responsetarifas) && !is_wp_error($perseo_responsetarifas)) {
     907            if (!empty($perseo_responsetarifas['body'])) {
     908                $perseo_datosTarifas = json_decode($perseo_responsetarifas['body'], true);
     909                if (isset($perseo_datosTarifas) && is_array($perseo_datosTarifas)) {
     910                    foreach ($perseo_datosTarifas as $registro) {
     911                        if (is_array($registro)) {
    796912                            foreach ($registro as $tarifa) {
    797913                                $perseo_refr1 = isset($perseo_parametros[$args['label_for']]) ? (($perseo_parametros[$args['label_for']] == ($tarifa['tarifasid'])) ? $perseo_selec : '') : '';
    798                                 $perseo_muestra =  $perseo_muestra . " <option value='" . $tarifa['tarifasid'] . "' " . $perseo_refr1 . " >" . $tarifa['descripcion'] . "</option>'";
     914                                $perseo_muestra .= " <option value='" . $tarifa['tarifasid'] . "' " . $perseo_refr1 . " >" . $tarifa['descripcion'] . "</option>";
    799915                            }
    800916                        }
    801                     };
    802 
    803                     $perseo_parametros = get_option('pluginperseo_parametros');
    804                     //condcion si existe valiable los dos puntos caso de sino es
    805                     $perseo_parametros[$args['label_for']] = isset($perseo_parametros[$args['label_for']]) ? esc_attr($perseo_parametros[$args['label_for']]) : '';
    806 
    807                     $perseo_html = "<select  class='{$args['class']}' data-custom='{$args['perseo_datopersonalizado']}' name='pluginperseo_parametros[{$args['label_for']}]' >  " . $perseo_muestra . "  </select >";
    808 
    809                     echo $perseo_html;
     917                    }
    810918                }
    811             };
     919
     920                $valor_actual = isset($perseo_parametros[$args['label_for']]) ? esc_attr($perseo_parametros[$args['label_for']]) : '';
     921
     922                $perseo_html = "<select class='{$args['class']}' data-custom='{$args['perseo_datopersonalizado']}' name='pluginperseo_parametros[{$args['label_for']}]'>" . $perseo_muestra . "</select>";
     923                echo $perseo_html;
     924            }
     925        } else {
     926            echo "<p>Existe problemas en conexion de Api Perseo</p>";
    812927        }
    813928    }
    814929}
     930
    815931// Parametro Servidor
    816 
    817 //
    818932function fperseo_tarifaAumento($args)
    819933{
    820     $perseo_config      = PERSEOCONFIGBASE; //parametros de conexion   
    821     $perseo_parametros  = PERSEOCONFIGPARAMETROS; // parametrizacion 
     934    $perseo_config = PERSEOCONFIGBASE;
     935    $perseo_parametros = get_option('pluginperseo_parametros');
     936
     937    // 🔹 Validar que sean arrays
     938    if (!is_array($perseo_parametros)) {
     939        $perseo_parametros = [];
     940    }
     941
    822942    if (!empty($perseo_config['perseotoken'])) {
    823         ///////////////////////////////////////////
    824         //Consulta APi
    825943        $perseo_selec = 'selected';
    826         /////////////////////////////////////
    827         //Verificar pc o web
    828         if ($perseo_config['perseotiposoftware'] == 'WEB') {
    829             $perseo_urltarifas  = $perseo_config['perseoservidor'] . '/api/tarifas_consulta';
     944
     945        if (isset($perseo_config['perseotiposoftware']) && $perseo_config['perseotiposoftware'] == 'WEB') {
     946            $perseo_urltarifas = $perseo_config['perseoservidor'] . '/api/tarifas_consulta';
    830947        } else {
    831             $perseo_urltarifas  = $perseo_config['perseocertificado'] . '://' . $perseo_config['perseoip'] . '/api/tarifas_consulta';
     948            $perseo_urltarifas = ($perseo_config['perseocertificado'] ?? 'http') . '://' . ($perseo_config['perseoip'] ?? '') . '/api/tarifas_consulta';
    832949        }
     950
    833951        $datoKEY = ['api_key' => $perseo_config['perseotoken']];
    834 
    835952        $perseo_responsetarifas = wp_remote_post($perseo_urltarifas, array(
    836             'method'      => 'POST',
    837             'headers'     => array('Content-Type' => 'application/json'),
    838             'body'        => wp_json_encode($datoKEY)
     953            'method' => 'POST',
     954            'headers' => array('Content-Type' => 'application/json'),
     955            'body' => wp_json_encode($datoKEY)
    839956        ));
    840         // print_r($perseo_responsetarifas);
     957
    841958        $perseo_muestra = "";
    842         if (!empty($perseo_responsetarifas)) {
    843             if (is_wp_error($perseo_responsetarifas)) {
    844                 echo "<p>Existe problemas en conexion de Api Perseo<p>";
    845             } else {
    846                 if (!empty($perseo_responsetarifas['body'])) {
    847                     //if (isset($perseo_responsetarifas['body']['tarifas'])){
    848                     $perseo_datosTarifas = json_decode($perseo_responsetarifas['body'], true); //devuelve
    849                     if (isset($perseo_datosTarifas)) {
    850                         foreach ($perseo_datosTarifas as $registro) {
     959        if (!empty($perseo_responsetarifas) && !is_wp_error($perseo_responsetarifas)) {
     960            if (!empty($perseo_responsetarifas['body'])) {
     961                $perseo_datosTarifas = json_decode($perseo_responsetarifas['body'], true);
     962                if (isset($perseo_datosTarifas) && is_array($perseo_datosTarifas)) {
     963                    foreach ($perseo_datosTarifas as $registro) {
     964                        if (is_array($registro)) {
    851965                            foreach ($registro as $tarifa) {
    852966                                $perseo_refr1 = isset($perseo_parametros[$args['label_for']]) ? (($perseo_parametros[$args['label_for']] == ($tarifa['tarifasid'])) ? $perseo_selec : '') : '';
    853                                 $perseo_muestra =  $perseo_muestra . " <option value='" . $tarifa['tarifasid'] . "' " . $perseo_refr1 . " >" . $tarifa['descripcion'] . "</option>'";
     967                                $perseo_muestra .= " <option value='" . $tarifa['tarifasid'] . "' " . $perseo_refr1 . " >" . $tarifa['descripcion'] . "</option>";
    854968                            }
    855969                        }
    856                     };
    857                     //echo $muestra;
    858                     //condcion si existe valiable los dos puntos caso de sino es
    859                     $perseo_parametros[$args['label_for']] = isset($perseo_parametros[$args['label_for']]) ? esc_attr($perseo_parametros[$args['label_for']]) : '';
    860 
    861                     $perseo_html = "<select  class='{$args['class']}' data-custom='{$args['perseo_datopersonalizado']}' name='pluginperseo_parametros[{$args['label_for']}]' >" . $perseo_muestra . "  </select >";
    862 
    863                     echo $perseo_html;
    864                     //}
    865                 } else {
    866                     echo "<p>No existe conexion con Api Perseo<p>";
     970                    }
    867971                }
     972
     973                $valor_actual = isset($perseo_parametros[$args['label_for']]) ? esc_attr($perseo_parametros[$args['label_for']]) : '';
     974
     975                $perseo_html = "<select class='{$args['class']}' data-custom='{$args['perseo_datopersonalizado']}' name='pluginperseo_parametros[{$args['label_for']}]'>" . $perseo_muestra . "</select>";
     976                echo $perseo_html;
    868977            }
     978        } else {
     979            echo "<p>No existe conexion con Api Perseo</p>";
    869980        }
    870981    }
    871982}
    872 
    873 
    874983
    875984/////////////////////////////////////
  • perseo-software/trunk/PluginPerseoClientes.php

    r3270560 r3439783  
    11<?php
    2 $version_Plugin = '32.0';
    3 //define('PERSEO_DIR_PATH', plugin_dir_path(__FILE__));
    4 ////////////////////////////////////////////////////////////////
    5 //////Anadir campos Cedula al registro mediante Woocommerce////
    6 ////// de cedula para guardar  y enviar a perseo       /////
    7 /////////////////////////////////////////////////////////////
    8 /*
    9 <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide" >
    10         <label for="tipoIdentificacion">Tipo</label>
    11         <select class="woocommerce-Input " id="tipoIdentificacion" name="tipoIdentificacion">
    12         <option  value="C">RUC</option>
    13         <option  value="R">Cedula</option>
    14         <option  value="P">Pasaporte</option>
    15         </select >
    16     </p>
    17 */
     2$version_Plugin = '33.0';
    183
    194function campos_adicionales_registro_usuario()
     
    5540        $errors->add('PerseoIdentificacion_error', __(' Identificacion no puede estar vacia', 'textdomain'));
    5641    } else {
    57         //verificar si ya existe esta cedula 
     42        //verificar si ya existe esta cedula
    5843        $perseo_IngresoIdent = $wpdb->get_var("SELECT user.user_id as id FROM {$table_prefix}usermeta as user where user.meta_key='PerseoIdentificacion' and user.meta_value like '%" . $_POST['PerseoIdentificacion'] . "%'");
    5944        //$errors->add('PerseoIdentificacion_error', __('<strong>Error</strong>: Identificacion ya existe-'.$perseo_IngresoIdent, 'textdomain'));
  • perseo-software/trunk/README.md

    r3270560 r3439783  
    1 === PluginPerseo ===
     1=== Perseo Software ===
    22
    33Contributors: Perseo Soft S.A. - Ecuador
    44Donate Link: https://perseo.ec/
    5 Tags: auto publish, content marketing
    6 Requires at least: 1.1
     5Tags: woocommerce, erp, sync, inventory, perseo, accounting, ecommerce
     6Requires at least: 5.0
    77Tested up to: 6.7.2
    88Requires PHP: 7.4
    9 Stable tag: 32.0
     9Stable tag: 33.0
    1010License: GPLv2 or later
    1111License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1212
    13 This Pluing integrates the Accounting System Perseo Web and PC with the store.
     13Integra el Sistema Contable Perseo (Web y PC) con tu tienda WooCommerce. Sincroniza productos, clientes, inventario y pedidos automáticamente.
     14
    1415== Description ==
    1516
    16 [PluginPerseo Content](http://perseo.ec/) is a native WordPress plugin that integrates with the Perseo Accounting System. It has been designed to help you efficiently create and promote the content of your online store by automatically synchronizing the products registered in your system. Run a successful blog while saving tons of time..
     17**Perseo Software** es un plugin nativo de WordPress que conecta tu tienda WooCommerce con el Sistema Contable Perseo, permitiendo una sincronización automática y eficiente de tu negocio.
    1718
    18 Perseo Software Plugin:
     19= ✨ Características Principales =
    1920
    20 -Installation of the WooCommerce Plugin.
     21* **Sincronización de Productos** - Importa automáticamente productos desde Perseo incluyendo precios, stock e imágenes
     22* **Gestión de Clientes** - Sincroniza clientes entre WordPress y Perseo en ambas direcciones
     23* **Control de Inventario** - Mantén tu stock actualizado
     24* **Envío de Pedidos** - Los pedidos de WooCommerce se envían automáticamente a Perseo
     25* **Categorías Automáticas** - Sincroniza categorías, líneas, subcategorías o subgrupos
     26* **Múltiples Tarifas** - Configura precio normal y precio rebajado desde Perseo
     27* **Impuestos** - Sincronización automática de tipos de IVA
    2128
    22 -Synchronization of Perseo to WordPress: clients-categories -products.
     29= 🔄 Sincronización =
    2330
    24 -Synchronization from WordPress to Perseus:
    25 orders.
     31**De Perseo a WordPress:**
     32- Productos (descripción, precios, stock, imágenes)
     33- Categorías / Líneas / Subcategorías / Subgrupos
     34- Clientes
     35- Impuestos (IVA)
    2636
    27 Product images must be square photos. Example 1080x1080px.
     37**De WordPress a Perseo:**
     38- Clientes nuevos
     39- Pedidos (estado "Procesando")
     40
     41= ⚙️ Requisitos =
     42
     43* WordPress 5.0 o superior
     44* WooCommerce instalado y activo
     45* PHP 7.4 o superior
     46* Perseo Web o Perseo PC con API habilitada
     47* Token de API de Perseo
    2848
    2949== Installation ==
    3050
    31 Contact your Perseo Software support.
     511. Ve a **Perseo Software** en el menú de administración
     522. Configura tu conexión (Token, Servidor)
     533. Ve a **Parametrización** y activa las sincronizaciones que necesites
    3254
    3355== Frequently Asked Questions ==
    3456
    35 = A question that someone might have =
     57= ¿Qué versión de Perseo necesito? =
    3658
    37 An answer to that question.
     59El plugin funciona con Perseo Web y Perseo PC. Necesitas tener habilitada la API y un token válido.
    3860
    39 = What about foo bar? =
     61= ¿Cada cuánto tiempo se sincroniza? =
    4062
    41 Answer to foo bar dilemma.
     63Puedes configurar el intervalo de sincronización en minutos desde la Parametrización. Se recomienda entre 30 y 60 minutos.
    4264
    43 == Screenshots ==
     65= ¿Los pedidos se envían automáticamente? =
    4466
    45 1. perseo-1.jpg
    46 2. == Changelog ==
    47    = 32.0 =
     67Sí, los pedidos con estado "Procesando" se envían automáticamente a Perseo en cada sincronización.
    4868
    49 - Correcciones de sincronizacion de imagenes
     69= ¿Qué pasa si un producto se desactiva en Perseo? =
     70
     71El producto se cambia a estado borrador (draft) en WooCommerce y no aparece en la tienda. Si se reactiva en Perseo, volverá a publicarse automáticamente.
     72
     73= ¿Puedo sincronizar solo algunos productos? =
     74
     75Los productos deben tener habilitado "ecommerce" en Perseo para sincronizarse. También puedes filtrar por existencias.
     76
     77= ¿Las imágenes se actualizan automáticamente? =
     78
     79Sí, las imágenes marcadas como "ecommerce" en Perseo se sincronizan automáticamente, incluyendo la imagen destacada y la galería.
    5080
    5181== Changelog ==
     82
     83= 33.0 =
     84* Correcciones con productos inactivos
     85
     86= 32.0 =
     87* Correcciones de sincronización de imágenes
     88
    5289= 31.0 =
     90* Correcciones de sincronización de categorías
     91* Recomendación: Eliminar categorías para re-sincronizar
    5392
    54 - Correcciones de sincronizacion de categorias
    55 - Recomendaciones: Eliminar categorias para que se vuelvan a sincronizar automaticamente.
     93= 30.0 =
     94* Optimización y correcciones varias
    5695
    57 == Changelog ==
    58 = 30.0 =
     96= 29.0 =
     97* Corrección errores tarifas
    5998
    60 - Correcciones de optimización y correcciones varias
     99= 28.0 =
     100* Actualizar campo fecha_sync
    61101
    62 == Changelog ==
    63 = 29.0 =
     102= 27.0 =
     103* Actualización IVA y parámetros
    64104
    65 - Correccion errores tarifas
     105= 26.0 =
     106* Actualización API
    66107
    67 == Changelog ==
    68 = 28.0 =
     108= 25.0 =
     109* Actualización PC
    69110
    70 - Actualizar campo fecha_sync
     111= 24.0 =
     112* Actualización PC
    71113
    72 == Changelog ==
    73 = 27.0 =
     114= 23.0 =
     115* Actualización precios
    74116
    75 - Actualizacion iva y parametros.
    76 
    77 == Changelog ==
    78 = 26.0 =
    79 
    80 - Actualizacion api.
    81 
    82 == Changelog ==
    83 = 25.0 =
    84 
    85 - Actualizacion pc.
    86 
    87 == Changelog ==
    88 = 24.0 =
    89 
    90 - Actualizacion pc.
    91 
    92 == Changelog ==
    93 = 23.0 =
    94 
    95 - Actualizacion precios .
    96 
    97 == Changelog ==
    98 = 22.0 =
    99 
    100 - Actualizacion .
    101 
    102 == Changelog ==
    103 = 21.0 =
    104 
    105 - Actualizacion .
    106 
    107 == Changelog ==
    108 = 20.0 =
    109 
    110 - Actualizacion .
    111 
    112 == Changelog ==
    113 = 17.0 =
    114 
    115 - Actualizacion .
    116 
    117 = 16.0 =
    118 
    119 - Actualizacion .
    120 
    121 = 15.0 =
    122 
    123 - Actualizacion .
    124 
    125 = 14.0 =
    126 
    127 - Actualizacion .
    128 
    129 = 13.0 =
    130 
    131 - Actualizacion .
    132 
    133 = 12.0 =
    134 
    135 - Actualizacion .
    136 
    137 = 11.0 =
    138 
    139 - Actualizacion .
    140 
    141 = 10.0 =
    142 
    143 - Actualizacion .
    144 
    145 = 9.0 =
    146 
    147 - Actualizacion .
    148 
    149 = 8.0 =
    150 
    151 - Actualizacion .
    152 
    153 = 7.0 =
    154 
    155 - Actualizacion .
    156 
    157 = 6.0 =
    158 
    159 - Actualizacion .
    160 
    161 = 5.0 =
    162 
    163 - Actualizacion de correo.
    164 
    165 = 5.0 =
    166 
    167 - Actualizacion de imagenes.
    168 
    169 = 4.0 =
    170 
    171 - Actualizacion de stock.
    172 
    173 = 3.0 =
    174 
    175 - A change since the previous version.
    176 
    177 = 2.0 =
    178 
    179 - A change since the previous version.
    180 - Fixed a pagination bug.
    181 
    182 = 1.1 =
    183 
    184 - A change since the previous version.
    185 - Fixed a pagination bug.
    186 
    187 = 1.0 =
    188 
    189 - New: Basic functionalities for this plugin.
    190 
    191 == Upgrade Notice ==
    192 
    193 = 1.1 =
    194 Actualizacion de imagenes
     117= 22.0 - 1.0 =
     118* Versiones anteriores con mejoras incrementales
  • perseo-software/trunk/includes/PluginPerseo_cron.php

    r3270560 r3439783  
    22class CPerseo_Cron
    33{
    4     private $tarifas_cambiaron = false; // 🔹 Variable para detectar cambios en tarifas
     4    private $tarifas_cambiaron = false; // Variable para detectar cambios en tarifas
    55
    66    private function ejecutar_proceso_con_bloqueo($proceso, $callback)
     
    3232    public function fperseo_inicializador()
    3333    {
    34         //elimina el cron
    3534        $perseo_parametros = get_option('pluginperseo_parametros');
    3635
    37         // echo "-".$perseo_parametros['perseosincronizar'];
    38         //echo "<br>";
     36        // 🔹 Validar que sea array
     37        if (!is_array($perseo_parametros)) {
     38            $perseo_parametros = [];
     39        }
     40
    3941        if (isset($perseo_parametros['perseosincronizar'])) {
    40 
    4142            if ($perseo_parametros['perseosincronizar'] == "") {
    42 
    4343                $perseo_timestamp = wp_next_scheduled('intervalo_perseo');
    44                 wp_unschedule_event($perseo_timestamp, 'intervalo_perseo', 'perseo_cron');
    45                 wp_clear_scheduled_hook('intervalo_perseo', 'perseo_cron');
    46                 //wp_unschedule_event(time(), 'intervalo_perseo');
    47             };
    48             //crea el cron
    49             if (!wp_next_scheduled('perseo_cron')) {
     44                if ($perseo_timestamp) {
     45                    wp_unschedule_event($perseo_timestamp, 'intervalo_perseo');
     46                }
     47                wp_clear_scheduled_hook('intervalo_perseo'); // 🔹 Sin segundo argumento
     48            }
     49
     50            if (!wp_next_scheduled('perseo_cron') && !empty($perseo_parametros['perseosincronizar'])) {
    5051                wp_schedule_event(time() + (intval($perseo_parametros['perseosincronizar']) * 60), 'intervalo_perseo', 'perseo_cron');
    51             };
    52         };
     52            }
     53        }
    5354    }
    5455
    5556    public function fperseo_intervalos($perseo_intervalos)
    5657    {
    57         //sincronizar
    5858        $perseo_parametros = get_option('pluginperseo_parametros');
    59         if (isset($perseo_parametros['perseosincronizar'])) {
    60             if (empty($perseo_parametros['perseosincronizar'])) {
    61                 //$perseo_valorCron=intval(1)*60;
    62             } else {
    63                 $perseo_valorCron = intval($perseo_parametros['perseosincronizar']) * 60;
    64             };
    65 
    66             $perseo_intervalos['intervalo_perseo'] = [
    67                 'interval'  => $perseo_valorCron,
    68                 'display'   => 'Cada tiempo ' . $perseo_parametros['perseosincronizar'] . ' Perseo'
    69             ];
    70 
    71             return $perseo_intervalos;
    72         };
     59
     60        // 🔹 Validar que sea array
     61        if (!is_array($perseo_parametros)) {
     62            $perseo_parametros = [];
     63        }
     64
     65        if (isset($perseo_parametros['perseosincronizar']) && !empty($perseo_parametros['perseosincronizar'])) {
     66            $perseo_valorCron = intval($perseo_parametros['perseosincronizar']) * 60;
     67
     68            // 🔹 Evitar división por cero
     69            if ($perseo_valorCron > 0) {
     70                $perseo_intervalos['intervalo_perseo'] = [
     71                    'interval'  => $perseo_valorCron,
     72                    'display'   => 'Cada ' . $perseo_parametros['perseosincronizar'] . ' minutos Perseo'
     73                ];
     74            }
     75        }
     76
     77        return $perseo_intervalos;
    7378    }
    7479
     
    8489            error_log("[" . date('Y-m-d H:i:s') . "] Cambio detectado en tarifas. Forzando actualización de productos.");
    8590
    86             // 🔹 Marcar que las tarifas cambiaron
     91            // Marcar que las tarifas cambiaron
    8792            $this->tarifas_cambiaron = true;
    8893
    89             // 🔹 Actualizar la fecha de modificación de todos los productos a una fecha menor
     94            // Actualizar la fecha de modificación de todos los productos a una fecha menor
    9095            $fecha_antigua = date('Y-m-d H:i:s', strtotime('-1 day'));
    9196            $wpdb->query("UPDATE {$table_prefix}posts p
     
    270275            }
    271276
    272             // 🔹 Obtener pedidos pendientes de enviar a Perseo (Optimizado con LIMIT 50)
     277            // Obtener pedidos pendientes de enviar a Perseo (Optimizado con LIMIT 50)
    273278            $query_pedidos = "
    274279            SELECT p.ID as codigoPedido, p.post_date, p.post_status, u.ID as user_id, u.user_login, c.*
     
    294299                $perseo_DetallePedido = [];
    295300
    296                 // 🔹 Obtener detalles del pedido (Optimizado con JOIN)
     301                // Obtener detalles del pedido (Optimizado con JOIN)
    297302                $query_detalles = $wpdb->prepare("
    298303                SELECT
     
    312317                foreach ($detalles as $detalle) {
    313318                    $perseo_CodProdP = isset($detalle->attributes) ? unserialize($detalle->attributes) : [];
    314                     $perseo_CodProdP = array_change_key_case($perseo_CodProdP, CASE_LOWER); // 🔹 Convierte todas las claves a minúsculas
     319                    $perseo_CodProdP = array_change_key_case($perseo_CodProdP, CASE_LOWER); // Convierte todas las claves a minúsculas
    315320                    $perseo_DatoIva = isset($detalle->iva) ? floatval($detalle->iva) : 0;
    316321                    $perseo_precio = isset($detalle->price) ? floatval($detalle->price) : 0;
     
    348353                $totales = $this->calcularTotales($productos);
    349354
    350                 // 🔹 Obtener método de pago (Evita errores con IFNULL)
     355                // Obtener método de pago (Evita errores con IFNULL)
    351356                $perseo_TipoMetodoPago = $wpdb->get_var($wpdb->prepare("
    352357                SELECT IFNULL(meta_value, 'Desconocido')
     
    356361            ", $pedido->codigoPedido));
    357362
    358                 // 🔹 Armar cabecera del pedido
     363                // Armar cabecera del pedido
    359364                $perseo_CabeceraPedidos = [
    360365                    'pedidos' => [
     
    394399            }
    395400
    396             // 🔹 Enviar pedidos a Perseo
     401            // Enviar pedidos a Perseo
    397402            $this->enviar_pedido_a_perseo($perseo_registroPedido, $perseo_config);
    398403        });
     
    406411        }
    407412
    408         // 🔹 Construcción de la API URL de Perseo
     413        // Construcción de la API URL de Perseo
    409414        $perseo_urlpedido = ($perseo_config['perseotiposoftware'] === 'WEB')
    410415            ? $perseo_config['perseoservidor'] . '/api/pedidos_crear'
    411416            : $perseo_config['perseocertificado'] . '://' . $perseo_config['perseoip'] . '/api/pedidos_crear';
    412417
    413         // 🔹 Cuerpo de la solicitud
     418        // Cuerpo de la solicitud
    414419        $perseo_InsertarPedido = [
    415420            'api_key' => $perseo_config['perseotoken'],
     
    418423        $perseo_bodypedido = wp_json_encode($perseo_InsertarPedido);
    419424
    420         // 🔹 Enviar a la API de Perseo
     425        // Enviar a la API de Perseo
    421426        $response = wp_remote_post(
    422427            $perseo_urlpedido,
     
    429434        );
    430435
    431         // 🔹 Manejo de errores en la API
     436        // Manejo de errores en la API
    432437        if (is_wp_error($response)) {
    433438            error_log("[" . date('Y-m-d H:i:s') . "] Error en la conexión con Perseo: " . $response->get_error_message());
     
    443448        }
    444449
    445         // 🔹 Marcar pedidos como completados en WooCommerce si fueron aceptados por Perseo
     450        // Marcar pedidos como completados en WooCommerce si fueron aceptados por Perseo
    446451        global $wpdb, $table_prefix;
    447         // 🔹 Actualizar pedidos en WordPress marcándolos como "EnviadoPerseo"
     452        // Actualizar pedidos en WordPress marcándolos como "EnviadoPerseo"
    448453        foreach ($perseo_registroPedido as $pedido) {
    449454            if (!empty($pedido['pedidos']['pedido_wp_id']) && intval($pedido['pedidos']['pedido_wp_id']) > 0) {
     
    499504            $totalProducto = $subtotalConDescuento + $ivaMonto;
    500505
    501             // 🔹 Acumular valores en los totales
     506            // Acumular valores en los totales
    502507            $totales['subtotal'] += $subtotalProducto;
    503508            $totales['descuentoTotal'] += $descuentoMonto;
    504509
    505             // 🔹 Diferenciar por tipo de IVA
     510            // Diferenciar por tipo de IVA
    506511            if ($valoriva > 0) {
    507512                if ($valoriva === 0.05) {
     
    519524            }
    520525
    521             // 🔹 Acumulación de totales generales
     526            // Acumulación de totales generales
    522527            $totales['total'] += $totalProducto;
    523528            $totales['totalItems'] += 1; // Contar cada línea de producto
     
    525530        }
    526531
    527         // 🔹 Calcular subtotal neto total
     532        // Calcular subtotal neto total
    528533        $totales['subtotalNeto'] = $totales['subtotalNetoConIva'] + $totales['subtotalNetoIva5'] + $totales['subtotalNetoSinIva'];
    529534
    530         // 🔹 Aplicar `number_format()` solo al final para evitar errores de precisión
     535        // Aplicar `number_format()` solo al final para evitar errores de precisión
    531536        foreach ($totales as $key => $value) {
    532537            $totales[$key] = number_format(round($value, 3), 3, '.', '');
     
    594599            }
    595600
    596             // 🔹 Obtener todos los identificaciones de clientes existentes en una sola consulta
     601            // Obtener todos los identificaciones de clientes existentes en una sola consulta
    597602            $clientes_existentes = $wpdb->get_col(
    598603                "SELECT meta_value FROM {$table_prefix}usermeta WHERE meta_key = 'PerseoIdentificacion'"
    599604            );
    600605
    601             // 🔹 Convertir el array a un conjunto (más eficiente en búsquedas)
     606            // Convertir el array a un conjunto (más eficiente en búsquedas)
    602607            $clientes_existentes = array_flip($clientes_existentes);
    603608
    604             // 🔹 Procesar los clientes recibidos de la API
     609            // Procesar los clientes recibidos de la API
    605610            $clientes_nuevos = [];
    606611
     
    619624                }
    620625
    621                 // 🔹 Construir los datos para la inserción masiva
     626                // Construir los datos para la inserción masiva
    622627                $nombre_array = explode(' ', $razonsocial);
    623628                $first_name = sanitize_text_field($nombre_array[0] ?? '');
     
    640645            }
    641646
    642             // 🔹 Insertar clientes nuevos
     647            // Insertar clientes nuevos
    643648            foreach ($clientes_nuevos as $cliente) {
    644649                $user_id = wp_insert_user($cliente);
     
    655660        });
    656661    }
    657 
    658     /**
    659      * Enviar email de bienvenida al cliente
    660      */
    661     // private function enviar_email_bienvenida($userdata)
    662     // {
    663     //     $site_url = home_url();
    664     //     $headers = ['Content-Type: text/html; charset=UTF-8'];
    665     //     $subject = "Bienvenido a nuestra plataforma E-Commerce";
    666     //     $message = "
    667     //     <h1>Bienvenido, {$userdata['user_login']}!</h1>
    668     //     <p>Gracias por unirte a nuestra plataforma E-Commerce.</p>
    669     //     <p><strong>Usuario:</strong> {$userdata['user_login']}</p>
    670     //     <p><strong>Contraseña:</strong> {$userdata['user_pass']}</p>
    671     //     <p>Visita nuestra página aquí: <a href='{$site_url}'>{$site_url}</a></p>
    672     //     <p>Atentamente,</p>
    673     //     <p>El equipo de E-Commerce</p>";
    674 
    675     //     wp_mail($userdata['user_email'], $subject, $message, $headers);
    676     // }
    677662
    678663    public function fperseo_categoria()
     
    807792            }
    808793
    809             // 🔹 Construir URL de la API
     794            // Construir URL de la API
    810795            $perseo_urliva = ($perseo_config['perseotiposoftware'] === 'WEB')
    811796                ? $perseo_config['perseoservidor'] . '/api/tipoiva_consulta'
    812797                : $perseo_config['perseocertificado'] . '://' . $perseo_config['perseoip'] . '/api/tipoiva_consulta';
    813798
    814             // 🔹 Consultar API de impuestos
     799            // Consultar API de impuestos
    815800            $perseo_responseiva = wp_remote_post(
    816801                $perseo_urliva,
     
    843828            }
    844829
    845             // 🔹 Obtener todas las clases de impuesto existentes en WooCommerce
     830            // Obtener todas las clases de impuesto existentes en WooCommerce
    846831            $clases_existentes = $wpdb->get_results(
    847832                "SELECT slug FROM {$table_prefix}wc_tax_rate_classes",
     
    850835            $clases_existentes_slugs = array_column($clases_existentes, 'slug');
    851836
    852             // 🔹 Obtener todas las tasas de impuestos ya existentes en WooCommerce
     837            // Obtener todas las tasas de impuestos ya existentes en WooCommerce
    853838            $ivas_existentes = $wpdb->get_results(
    854839                "SELECT tax_rate_id, tax_rate, tax_rate_class FROM {$table_prefix}woocommerce_tax_rates",
     
    856841            );
    857842
    858             // 🔹 Procesar los impuestos recibidos
     843            // Procesar los impuestos recibidos
    859844            foreach ($perseo_datosivas['iva'] as $datoiva) {
    860845                $valor_iva = sanitize_text_field($datoiva['valor']);
    861846                $nombre_iva = sanitize_text_field($datoiva['porcentaje']);
    862847
    863                 // 🔹 Identificar las clases de impuestos especiales
     848                // Identificar las clases de impuestos especiales
    864849                if (strpos(strtolower($nombre_iva), 'no objeto') !== false) {
    865850                    $tax_rate_class = "iva-no-objeto";
     
    873858                }
    874859
    875                 // 🔹 Verificar si la clase de impuesto ya existe en wp_wc_tax_rate_classes
     860                // Verificar si la clase de impuesto ya existe en wp_wc_tax_rate_classes
    876861                if (!in_array($tax_rate_class, $clases_existentes_slugs)) {
    877862                    $wpdb->insert(
     
    883868                }
    884869
    885                 // 🔹 Verificar si el impuesto ya existe en woocommerce_tax_rates
     870                // Verificar si el impuesto ya existe en woocommerce_tax_rates
    886871                $iva_existente = null;
    887872                foreach ($ivas_existentes as $iva) {
     
    893878
    894879                if (!$iva_existente) {
    895                     // 🔹 Insertar nueva tasa de impuesto
     880                    // Insertar nueva tasa de impuesto
    896881                    $wpdb->insert(
    897882                        "{$table_prefix}woocommerce_tax_rates",
     
    960945                }
    961946
    962                 // 🔹 Obtener todos los productos existentes y sus fechas de modificación en una sola consulta
     947                // Obtener todos los productos existentes y sus fechas de modificación en una sola consulta
    963948                $productos_existentes = $wpdb->get_results(
    964949                    "SELECT p.ID AS post_id, pm.meta_value AS perseo_id, p.post_modified
     
    969954                );
    970955
    971                 // 🔹 Convertir el array a un conjunto para búsqueda rápida
     956                // Convertir el array a un conjunto para búsqueda rápida
    972957                $productos_existentes_map = [];
    973958                $productos_fechas = [];
     
    977962                }
    978963
    979                 // 🔹 Listas para productos nuevos y actualizados
     964                // Listas para productos nuevos y actualizados
    980965                $productos_nuevos = [];
    981966                $productos_actualizados = [];
     
    985970                        if ($producto['existenciastotales'] >= $perseo_parametros['perseoexistencias']) {
    986971                            if (isset($productos_existentes_map[$producto['productosid']])) {
    987                                 // 🔹 Obtener la fecha de sincronización del producto en la API
     972                                // Obtener la fecha de sincronización del producto en la API
    988973                                $fecha_sync = date_format(date_create($producto['fecha_sync']), 'Y-m-d H:i:s');
    989974                                $fecha_wp = $productos_fechas[$producto['productosid']];
    990975
    991                                 // 🔹 Forzar actualización si las tarifas han cambiado o si `fecha_sync` es más reciente
     976                                // Forzar actualización si las tarifas han cambiado o si `fecha_sync` es más reciente
    992977                                if ($this->tarifas_cambiaron || $fecha_sync > $fecha_wp) {
    993978                                    $productos_actualizados[] = [
     
    1003988                }
    1004989
    1005                 // 🔹 Procesar productos nuevos
     990                // Procesar productos nuevos
    1006991                if (!empty($productos_nuevos)) {
    1007992                    foreach ($productos_nuevos as $producto) {
     
    1011996                }
    1012997
    1013                 // 🔹 Procesar productos actualizados
     998                // Procesar productos actualizados
    1014999                if (!empty($productos_actualizados)) {
    10151000                    foreach ($productos_actualizados as $item) {
     
    10181003                    error_log("[" . date('Y-m-d H:i:s') . "] Se han actualizado " . count($productos_actualizados) . " productos.");
    10191004                }
     1005
     1006                $this->desactivar_productos_inactivos($wpdb, $table_prefix, $perseo_config);
     1007
    10201008            }
    10211009        });
    1022         // 🔹 Resetear la variable de control después de la ejecución
     1010        // Resetear la variable de control después de la ejecución
    10231011        $this->tarifas_cambiaron = false;
     1012    }
     1013
     1014    private function desactivar_productos_inactivos($wpdb, $table_prefix, $perseo_config)
     1015    {
     1016        error_log("[" . date('Y-m-d H:i:s') . "] Iniciando proceso de desactivación de productos inactivos.");
     1017
     1018        // Construir URL para consulta de productos inactivos
     1019        $perseo_url_inactivos = ($perseo_config['perseotiposoftware'] === 'WEB')
     1020            ? $perseo_config['perseoservidor'] . '/api/productos_consulta_movil'
     1021            : $perseo_config['perseocertificado'] . '://' . $perseo_config['perseoip'] . '/api/productos_consulta_movil';
     1022
     1023        $productos_inactivos = [];
     1024
     1025        // Primera consulta: productos con estado = 0
     1026        $body_estado = [
     1027            'api_key' => $perseo_config['perseotoken'],
     1028            'estado' => '0'
     1029        ];
     1030
     1031        $response_estado = wp_remote_post($perseo_url_inactivos, [
     1032            'method' => 'POST',
     1033            'timeout' => 1800,
     1034            'headers' => ['Content-Type' => 'application/json'],
     1035            'body' => wp_json_encode($body_estado)
     1036        ]);
     1037
     1038        if (!is_wp_error($response_estado) && !empty($response_estado['body'])) {
     1039            $productos_estado_0 = json_decode(wp_remote_retrieve_body($response_estado), true)['productos'] ?? [];
     1040            $productos_inactivos = array_merge($productos_inactivos, $productos_estado_0);
     1041            error_log("[" . date('Y-m-d H:i:s') . "] Productos con estado=0 obtenidos: " . count($productos_estado_0));
     1042        } else {
     1043            error_log("[" . date('Y-m-d H:i:s') . "] Error al obtener productos con estado=0 de Perseo.");
     1044        }
     1045
     1046        // Segunda consulta: productos con ecommerce_estado = 2
     1047        $body_ecommerce = [
     1048            'api_key' => $perseo_config['perseotoken'],
     1049            'ecommerce_estado' => '2'
     1050        ];
     1051
     1052        $response_ecommerce = wp_remote_post($perseo_url_inactivos, [
     1053            'method' => 'POST',
     1054            'timeout' => 1800,
     1055            'headers' => ['Content-Type' => 'application/json'],
     1056            'body' => wp_json_encode($body_ecommerce)
     1057        ]);
     1058
     1059        if (!is_wp_error($response_ecommerce) && !empty($response_ecommerce['body'])) {
     1060            $productos_ecommerce_2 = json_decode(wp_remote_retrieve_body($response_ecommerce), true)['productos'] ?? [];
     1061            $productos_inactivos = array_merge($productos_inactivos, $productos_ecommerce_2);
     1062            error_log("[" . date('Y-m-d H:i:s') . "] Productos con ecommerce_estado=2 obtenidos: " . count($productos_ecommerce_2));
     1063        } else {
     1064            error_log("[" . date('Y-m-d H:i:s') . "] Error al obtener productos con ecommerce_estado=2 de Perseo.");
     1065        }
     1066
     1067        error_log("[" . date('Y-m-d H:i:s') . "] Total productos inactivos obtenidos de API: " . count($productos_inactivos));
     1068
     1069        if (empty($productos_inactivos)) {
     1070            error_log("[" . date('Y-m-d H:i:s') . "] No hay productos inactivos en Perseo.");
     1071            return;
     1072        }
     1073
     1074        // Obtener IDs únicos de productos inactivos de Perseo (evitar duplicados)
     1075        $perseo_ids_inactivos = array_unique(array_column($productos_inactivos, 'productosid'));
     1076
     1077        if (empty($perseo_ids_inactivos)) {
     1078            error_log("[" . date('Y-m-d H:i:s') . "] No se encontraron IDs de productos inactivos.");
     1079            return;
     1080        }
     1081
     1082        // Preparar placeholders para la consulta IN
     1083        $placeholders = implode(',', array_fill(0, count($perseo_ids_inactivos), '%s'));
     1084
     1085        // Obtener posts de WordPress que tienen esos PERSEOID y están publicados
     1086        $query = $wpdb->prepare(
     1087            "SELECT p.ID, pm.meta_value AS perseo_id
     1088         FROM {$table_prefix}posts p
     1089         INNER JOIN {$table_prefix}postmeta pm ON p.ID = pm.post_id
     1090         WHERE pm.meta_key = 'PERSEOID'
     1091         AND pm.meta_value IN ($placeholders)
     1092         AND p.post_status = 'publish'",
     1093            ...$perseo_ids_inactivos
     1094        );
     1095
     1096        $productos_a_desactivar = $wpdb->get_results($query);
     1097
     1098        if (empty($productos_a_desactivar)) {
     1099            error_log("[" . date('Y-m-d H:i:s') . "] No hay productos en WordPress que requieran desactivación.");
     1100            return;
     1101        }
     1102
     1103        error_log("[" . date('Y-m-d H:i:s') . "] Productos a desactivar en WordPress: " . count($productos_a_desactivar));
     1104
     1105        $ids_desactivar = array_column($productos_a_desactivar, 'ID');
     1106
     1107        // Log de IDs que serán desactivados
     1108        error_log("[" . date('Y-m-d H:i:s') . "] IDs de productos a desactivar: " . implode(', ', $ids_desactivar));
     1109
     1110        $desactivados = 0;
     1111
     1112        foreach ($ids_desactivar as $post_id) {
     1113            // Cambiar el estado del producto a 'draft' para que no aparezca en la tienda
     1114            $resultado = $wpdb->update(
     1115                "{$table_prefix}posts",
     1116                [
     1117                    'post_status' => 'draft',
     1118                    'post_modified' => current_time('mysql'),
     1119                    'post_modified_gmt' => current_time('mysql', true)
     1120                ],
     1121                ['ID' => $post_id]
     1122            );
     1123
     1124            if ($resultado !== false) {
     1125                $desactivados++;
     1126                error_log("[" . date('Y-m-d H:i:s') . "] Producto #{$post_id} desactivado correctamente (cambiado a draft).");
     1127            } else {
     1128                error_log("[" . date('Y-m-d H:i:s') . "] Error al desactivar producto #{$post_id}.");
     1129            }
     1130        }
     1131
     1132        // Limpiar caché de WooCommerce
     1133        wc_delete_product_transients();
     1134
     1135        error_log("[" . date('Y-m-d H:i:s') . "] Proceso completado: Se han desactivado {$desactivados} productos.");
    10241136    }
    10251137
     
    10611173        $fecha_sync = date_format(date_create($producto['fecha_sync']), 'Y-m-d H:i:s');
    10621174
    1063         // 🔹 Realizar la actualización en un solo paso
     1175        // Realizar la actualización en un solo paso
    10641176        $wpdb->update("{$table_prefix}posts", [
    10651177            'post_content' => $producto['fichatecnica'],
    10661178            'post_title' => $producto['descripcion'],
    10671179            'post_excerpt' => $producto['descripcion'],
     1180            'post_status' => 'publish',
    10681181            'post_modified' => $fecha_sync,
    10691182            'post_modified_gmt' => '0000-00-00 00:00:00'
    10701183        ], ['ID' => $idPost]);
    10711184
    1072         // 🔹 Usar una sola consulta para actualizar metadatos relevantes
     1185        // Usar una sola consulta para actualizar metadatos relevantes
    10731186        $metadatos = [
    10741187            '_stock' => $producto['existenciastotales'],
     
    10931206        }
    10941207
    1095         // 🔹 Agregar la clase de impuesto según el porcentaje de IVA del producto
     1208        // Agregar la clase de impuesto según el porcentaje de IVA del producto
    10961209        $tax_class = ($producto['porcentajeiva'] == 0) ? 'tasa-cero' : "iva-{$producto['porcentajeiva']}";
    10971210        $metadatos['_tax_class'] = $tax_class;
    10981211        $metadatos['_tax_status'] = 'taxable'; // Asegurar que el producto usa impuestos
    10991212
    1100         // 🔹 Actualizar todos los metadatos en una sola ejecución
     1213        // Actualizar todos los metadatos en una sola ejecución
    11011214        foreach ($metadatos as $key => $value) {
    11021215            update_post_meta($idPost, $key, $value);
    11031216        }
    11041217
    1105         // 🔹 Actualizar categorías solo si es necesario
     1218        // Actualizar categorías solo si es necesario
    11061219        $this->actualizar_categorias_producto($producto, $idPost, $wpdb, $table_prefix, $perseo_parametros);
    11071220
    11081221        if ($this->tarifas_cambiaron == false) {
    1109             // 🔹 Procesar imágenes solo si es necesario
     1222            // Procesar imágenes solo si es necesario
    11101223            if ($perseo_parametros['perseoimagenes'] === 'SI') {
    11111224                $this->procesar_imagenes_producto($producto['productosid'], $idPost, $wpdb, $table_prefix, $perseo_urlimagen, $perseo_config);
     
    11301243        ];
    11311244
    1132         // 🔹 Procesar tarifas
     1245        // Procesar tarifas
    11331246        $tarifas = $producto['tarifas'] ?? [];
    11341247        $tarifa_venta = 0;
     
    11471260        }
    11481261
    1149         // 🔹 Insertar metadatos en una sola consulta (batch insert)
     1262        // Insertar metadatos en una sola consulta (batch insert)
    11501263        $values = [];
    11511264        foreach ($metadatos as $meta) {
     
    11551268        $wpdb->query($query);
    11561269
    1157         // 🔹 Atributos personalizados (serializados)
     1270        // Atributos personalizados (serializados)
    11581271        $attributes = serialize([
    11591272            'ID_Perseo' => ['name' => 'ID_Perseo', 'value' => $producto['productosid'], 'is_visible' => '0'],
     
    11661279        ]);
    11671280
    1168         // 🔹 Tabla de búsqueda rápida `wc_product_meta_lookup`
     1281        // Tabla de búsqueda rápida `wc_product_meta_lookup`
    11691282        $wpdb->insert("{$table_prefix}wc_product_meta_lookup", [
    11701283            'product_id' => $idPost,
     
    11871300    private function actualizar_categorias_producto($producto, $idPost, $wpdb, $table_prefix, $perseo_parametros)
    11881301    {
    1189         // 🔹 Determinar la clave de categoría según los parámetros de configuración
     1302        // Determinar la clave de categoría según los parámetros de configuración
    11901303        $categoria_clave = null;
    11911304        // Mapeo de valores
     
    12141327        }
    12151328
    1216         // 🔹 Obtener todas las categorías existentes en una sola consulta
     1329        // Obtener todas las categorías existentes en una sola consulta
    12171330        static $categorias_map = null;
    12181331        if ($categorias_map === null) {
     
    12231336        }
    12241337
    1225         // 🔹 Buscar la categoría en el mapa precargado
     1338        // Buscar la categoría en el mapa precargado
    12261339        $resProdCat = null;
    12271340        foreach ($categorias_map as $categoria) {
     
    12371350        }
    12381351
    1239         // 🔹 Eliminar relaciones existentes
     1352        // Eliminar relaciones existentes
    12401353        $wpdb->delete("{$table_prefix}term_relationships", ['object_id' => $idPost]);
    12411354
    1242         // 🔹 Insertar nueva relación
     1355        // Insertar nueva relación
    12431356        $wpdb->insert("{$table_prefix}term_relationships", [
    12441357            'object_id' => $idPost,
     
    12501363    private function procesar_imagenes_producto($productoID, $idPost, $wpdb, $table_prefix, $perseo_urlimagen, $perseo_config)
    12511364    {
    1252         // 🔹 Limpiar cache para evitar inconsistencias al agregar nuevas imágenes
     1365        // Limpiar cache para evitar inconsistencias al agregar nuevas imágenes
    12531366        static $imagenes_cache = [];
    12541367        // Forzar la actualización del cache para este producto específico
    12551368        unset($imagenes_cache[$productoID]);
    12561369
    1257         // 🔹 Obtener imágenes del producto desde la API en una sola llamada
     1370        // Obtener imágenes del producto desde la API en una sola llamada
    12581371        if (!isset($imagenes_cache[$productoID])) {
    12591372            $body = ['api_key' => $perseo_config['perseotoken'], 'productosid' => $productoID];
     
    12821395        }
    12831396
    1284         // 🔹 Obtener imágenes ya asociadas al producto
     1397        // Obtener imágenes ya asociadas al producto
    12851398        $imagenes_existentes = $wpdb->get_results($wpdb->prepare(
    12861399            "SELECT ID, guid, post_title FROM {$table_prefix}posts WHERE post_parent = %d AND post_type = 'attachment'",
     
    12921405        wp_mkdir_p($base_upload_path); // Crear el directorio si no existe
    12931406
    1294         // 🔹 Lista para seguimiento de imágenes procesadas
     1407        // Lista para seguimiento de imágenes procesadas
    12951408        $imagenes_procesadas = [];
    12961409        $thumbnail_id = null;
     
    13231436            }
    13241437
    1325             // 🔹 Guardar imagen en el sistema de archivos (siempre, para actualizar contenido)
     1438            // Guardar imagen en el sistema de archivos (siempre, para actualizar contenido)
    13261439            $image_data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $imagen['imagen']));
    13271440            if (file_put_contents($file_path, $image_data) === false) {
     
    13411454                wp_update_attachment_metadata($attachment_id, $attachment_metadata);
    13421455            } else {
    1343                 // 🔹 Insertar la imagen como nuevo adjunto en WordPress
     1456                // Insertar la imagen como nuevo adjunto en WordPress
    13441457                $attachment = [
    13451458                    'post_mime_type' => 'image/png',
     
    13571470                }
    13581471
    1359                 // 🔹 Generar metadatos de la imagen
     1472                // Generar metadatos de la imagen
    13601473                require_once ABSPATH . 'wp-admin/includes/image.php';
    13611474                $attachment_metadata = wp_generate_attachment_metadata($attachment_id, $file_path);
     
    13661479            $imagenes_procesadas[] = $attachment_id;
    13671480
    1368             // 🔹 Asignar como imagen destacada o añadir a la galería
     1481            // Asignar como imagen destacada o añadir a la galería
    13691482            if ($imagen['primera'] == 1) {
    13701483                $thumbnail_id = $attachment_id; // Guardar como imagen destacada
     
    13811494        }
    13821495
    1383         // 🔹 Eliminar imágenes antiguas que ya no existen en la API
     1496        // Eliminar imágenes antiguas que ya no existen en la API
    13841497        foreach ($imagenes_existentes as $id => $img) {
    13851498            if (!in_array($id, $imagenes_procesadas)) {
     
    13921505        error_log("Producto {$productoID}: Procesadas " . count($imagenes_procesadas) . " imágenes, " . count($gallery_ids) . " en galería");
    13931506
    1394         // 🔹 Asignar imagen destacada al producto
     1507        // Asignar imagen destacada al producto
    13951508        if ($thumbnail_id) {
    13961509            update_post_meta($idPost, '_thumbnail_id', $thumbnail_id);
    13971510        }
    13981511
    1399         // 🔹 Asignar galería de imágenes al producto (siempre actualizar toda la galería)
     1512        // Asignar galería de imágenes al producto (siempre actualizar toda la galería)
    14001513        if (!empty($gallery_ids)) {
    14011514            update_post_meta($idPost, '_product_image_gallery', implode(',', $gallery_ids));
Note: See TracChangeset for help on using the changeset viewer.