Saltar a contenido

SG Webservices

Características Técnicas

  • Nombre técnico del módulo: ----
  • Versión: ----

Vistas

Sin vista del módulo

Funcionamiento

Conexión

Para conectarse al ERP a través del protocolo XML-RPC se necesitan los siguientes datos:

  • Url: https://sgpromass.com
  • Db: A01_PROMASS
  • Username: Nombre de usuario con el que se va a conectar a la base de datos
  • Password: Contraseña del usuario

Ejemplo de conexión al sistema desde python:

url = <insert server URL>              
db = <insert database name>      
username = 'admin'     
assword = <insert password for your admin user (default:    admin)>     
import xmlrpclib       
info = xmlrpclib.ServerProxy('<https://sgpromass.com/start>').start()   
url, db, username, password = info['host'], info['database'],  info['user'],    
info['password']

Ejemplo de conexión al sistema desde Java. Para este ejemplo utilizamos la librería Apache XML-RPC. Los ejemplos no incluyen las importaciones porque no se pueden copiar/pegar en el código.

final String url = <insert server URL>,   
            db = <insert database name>,   
        username = "admin",   
        password = <insert password for your admin user (default: admin)>;

final XmlRpcClient client = new XmlRpcClient();    
final XmlRpcClientConfigImpl start_config = new   XmlRpcClientConfigImpl();   
start_config.setServerURL(new URL("<https://demo.openpyme.mx/start>"));   

final Map<String, String> info = (Map<String, String>)client. execute(   
    start_config, "start", emptyList()
);

final String url = info.get("host"),   
            db = info.get("database"),   
        username = info.get("user"),   
        password = info.get("password");

Ejemplo de conexión al sistema desde PHP. Para este ejemplo utilizamos la librería ripcord que provee de una interface simple para consumir servicios XML-RPC. La librería de ripcord requiere que se tenga habilitado el soporte para el protocolo XML-RPC en la instalación de PHP.

Si el servidor del ERP utiliza un protocolo HTTPS será necesario que se habilite la extensión de OpenSSL.

$url = <insert server URL>;   
$db = <insert database name>;   
$username = "admin";   
$password = <insert password for your admin user (default: admin)>;   
require_once('ripcord.php');   
$info = ripcord::client('<https://demo.openpyme.mx/start>')  ->start();  
list($url, $db, $username, $password) =   
array($info['host'], $info['database'], $info['user'], $info['password']);  

Inicio de sesión

Para poder consumir datos del sistema es necesario que se inicie sesión con un usuario.

La dirección xmlrpc/2/common provee acceso a las funcionalidades básicas que no requieren autentificación como es el inicio de sesión mismo. Para autentificar un usuario al sistema se utiliza el método authenticate el cual devuelve el identificador (uid) del usuario autenticado que después puede utilizarse para ejecutar subsecuentes consultas y llamadas.

common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url))   
uid = common.authenticate(db, username, password, {})
int uid = (int)client.execute(     
    common_config, "authenticate", asList(   
        db, username, password, emptyMap()));
$uid = $common->authenticate($db, $username, $password, array());

Llamadas a los métodos

La segunda dirección importante es xmlrpc/2/object que se usa para llamar a los métodos de los diferentes objetos al interior del sistema a través de la función execute_kw.

Para ejecutar una llamada al método execute_kw se tienen que enviar los siguientes parámetros:

  • Nombre de base de datos a utilizar, como una cadena de texto.
  • El identificador de usuario (uid) que se puede obtener a través del método authenticate.
  • La contraseña del usuario como texto.
  • El nombre del objeto, como texto.
  • El nombre del método, como texto.
  • Un arreglo o lista de parámetros que se van a enviar a la función por posición.
  • Un diccionario o arreglo de parámetros que se van a enviar a la función como parámetros nombrados (opcional).

Por ejemplo, para saber si el usuario puede acceder a los registros del objeto res.partner, se puede utilizar la función check_access_rights enviando como parámetros por posición el nombre de la operación a realizar read y el parámetro con nombre raise_exception en True para indicar que queremos una respuesta de Verdadero/Falso en lugar de Verdadero/Error.

models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))    
models.execute_kw(db, uid, password,   
    'res.partner', 'check_access_rights',   
    ['read'], {'raise_exception': False})
final XmlRpcClient models = new XmlRpcClient() {{  
    setConfig(new XmlRpcClientConfigImpl() {{  
        setServerURL(new URL(String.format("%s/xmlrpc/2/  object", url)));  
    }});  
}};  
models.execute("execute_kw", asList(   
    db, uid, password,  
    "res.partner", "check_access_rights",   
    asList("read"),   
    new HashMap() {{ put("raise_exception", false); }}   
));
$models = ripcord::client("$url/xmlrpc/2/object");   
$models->execute_kw($db, $uid, $password,  
    'res.partner', 'check_access_rights',  
    array('read'), array('raise_exception' => false));

Solicitud de cambio de contraseña

Para mandar el correo electrónico de solicitud de cambio de contraseña para un usuario se necesita la siguiente información:

  • login: Correo electrónico utilizado para iniciar la sesión por el usuario y a donde se le va a enviar el correo electrónico con las instrucciones para el cambio de contraseña
  • admin_id: ID del usuario administrador que se va a utilizar para invocar algunas funciones especiales como la recuperación de contraseñas
  • admin_password: Contraseña del usuario administrador que se va a utilizar para invocar algunas funciones especiales como la recuperación de contraseñas
models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))   
models.execute_kw(    
    db,  admin_id,  admin_password,   
    'res.users',   
    'reset_password',   
    [login],   
    {}   
)
final XmlRpcClient models = new XmlRpcClient() {{   
    setConfig(new XmlRpcClientConfigImpl() {{   
        setServerURL(new URL(String.format("%s/xmlrpc/2/  object", url)));   
    }});   
}};   
models.execute("execute_kw", asList(   
    db, admin_id, admin_password,  
    "res.users", "reset_password",   
    asList(login),   
    new HashMap() {}   
));
$models = ripcord::client("$url/xmlrpc/2/object");   
$models->execute_kw($db, $admin_id, $admin_password,   
    'res.users', 'reset_password',   
    array('read'), array()  
);

Mi perfil

Para obtener la información del perfil de usuario. Después de haber iniciado sesión se tiene que buscar el empleado relacionado y posteriormente leer los datos de la siguiente manera:

models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))   
employee_id = models.execute_kw(   
    db,  uid,  password,    
    'hr.employee',    
    'search',    
    [[("user_id", "=", uid)]],    
    {}   
)
employee_data = models.execute_kw(db, uid, password, "hr.employee", "read", [employee_id], {'fields': ["name", "company_id", "address_fiscal_id", "mobile_phone", "birthday", "operating_unit_id", "work_email",     "hr_plaza_id"]})
final XmlRpcClient models = new XmlRpcClient() {{    
    setConfig(new XmlRpcClientConfigImpl() {{      
        setServerURL(new URL(String.format("%s/xmlrpc/2/object", url)));     
    }});    
}};   
final Integer employee_id = (Integer)models.execute   ("execute_kw", asList(   
    db, uid, password,  
    "hr.employee", "search",  
    asList(asList(  
        asList("user_id", "=", uid),   
    )),  
    new HashMap() {}  
));   
asList((Object[])models.execute("execute_kw", asList(  
    db, uid, password,   
    "hr.employee", "read",   
    asList(employee_id),   
    new HashMap() {{  
        put("fields", asList("name", "address_fiscal_id",    "mobile_phone",      
        "birthday", "operating_unit_id",      "work_email", "hr_plaza_id"));    
    }}   
)));
$models = ripcord::client("$url/xmlrpc/2/object");   
$employee_id = $models->execute_kw($db, $uid, $password,    
    'hr.employee', 'search',   
    array(   
        array(   
            array('user_id', '=', $uid)   
    ),   
);   
$models->execute_kw($db, $uid, $password,   
    'hr.employee', 'read',   
    array($employee_id),   
    array('fields'=>array("name", "address_fiscal_id",    "mobile_phone", "birthday", "operating_unit_id",    "work_email", "hr_plaza_id")));

Cambio de contraseña

Para realizar el cambio de contraseña desde un usuario autentificado se requiere:

  • old_password: Cadena de texto conteniendo la contraseña actual del usuario
  • new_password: Cadena de texto conteniendo la nueva contraseña para del usuario

Es tarea del frontend de la aplicación realizar la construcción del formulario de validación que asegure que la nueva contraseña que está enviando el usuario está correcta.

Para realizar el cambio se debe ejecutar la siguiente función:

Python
models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))   
res = models.execute_kw(   
    db,  uid,  password,   
    'res.users',   
    'change_password',   
    [old_password, new_password],    
    {}   
)
Python
True

Mis Nóminas

Para obtener la información de las nóminas se necesitan los siguientes datos:

  • admin_username: Nombre del usuario administrador que se va a utilizar para invocar algunas funciones especiales como la recuperación de contraseñas
  • admin_password: Contraseña del usuario administrador que se va a utilizar para invocar algunas funciones especiales como la recuperación de contraseñas
  • employee_company_id: El id de la compañía a la que pertenece el empleado, se puede obtener desde los datos obtenidos en el perfil.
Python
admin_id = common.authenticate(db, admin_username,      
admin_password, {})     
models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))       
run_ids = models.execute_kw(     
    db,  admin_id,  admin_password,     
    'hr.payslip.run',    
    'search',   
    [[("state", "=", "close"), ("company_id", "=",     employee_company_id)]],    
    {}  
)
Python
[184, 283, 284, 285, 291, 295, 296, 297, 298, 305, 312, 318, 326, 330, 331, 335, 354, 356, 357, 358, 371, 372, 373, 374, 378, 381, 384, 386, 388, 389, 391, 394, 396, 402, 404, 415, 422, 424, 428, 430, 431, 437]

Después de obtener el listado de los lotes se pueden obtener los nombres para mostar la información en pantalla de la siguiente manera:

Python
payslip_runs = models.execute_kw(    
    db, admin_id, admin_password,   
    "hr.payslip.run",    
    "read",   
    [run_ids],    
    {'fields': ["name", "date_start", "date_end"]}
)
Python
[{'date_end': '2021-11-15', 'date_start': '2021-11-01',     'id': 312, 'name': 
'1RA_NOVIEMBRE_2021_FACT_GRUPO'}, {'date_end': '2021-11-30', 'date_start': '2021-11-16', 'id': 335, 'name':     
'2DA_NOVIEMBRE_2021_FACT_GRUPO'}, {'date_end': '2021-12-15', 'date_start': '2021-12-01', 'id': 356, 'name':        
'1RA_DICIEMBRE_2021_FACT_GRUPO'}, {'date_end': '2021-12-31', 'date_start': '2021-12-16', 'id': 372, 'name':       
'2DA_DICIEMBRE_2021_FACT_GRUPO'}, {'date_end': '2022-01-15', 'date_start': '2022-01-01', 'id': 381, 'name': 
'1RA_ENERO_2022_FACT_GRUPO'}, {'date_end': '2022-01-31', 'date_start':
'2022-01-16', 'id': 396, 'name':'2DA_ENERO_2022_FACT_GRUPO'},
{'date_end': '2022-02-15', 'date_start': '2022-02-01', 'id': 415, 'name': 
'1RA_FEBRERO_2022_FACT_GRUPO'}, {'date_end': '2022-02-28', 'date_start': '2022-02-16', 'id': 430, 'name':                  '2DA_FEBRERO_2022_FACT_GRUPO'}]

Con la información obtenida se pueden mostrar los lotes por nombre, por fecha de inicio y fin o por cualquier otra información seleccionada.

Para consultar el listado de los recibos disponibles por lote se requieren los siguientes datos:

  • uid: El identificador de usuario obtenido a través del método authenticate.
  • password: La contraseña del usuario como texto.
  • payslip_run_id: El identificador del lote que se quiere consultar obtenido de la consulta anterior
  • employee_id: El identificador de empleado asociado al usuario obtenido de la información de Mi Perfil
Python
payslip_ids = models.execute_kw(    
    db, uid, password,    
    'hr.payslip',    
    'search',    
    [[("state", "=", "done"), ("employee_id", "=",          employee_id),       
("payslip_run_id", "=", payslip_run_id)]],  
    {}    
)   
payslips = models.execute_kw(   
    db, uid, password,    
    "hr.payslip",    
    "read",    
    [payslip_ids],    
    {'fields': ["name", "date_from", "date_to"]}   
)

Una vez que el usuario seleccionó el lote del cual se quiere consultar los recibos, el listado de recibos disponibles se puede obtener de la siguiente manera:

Python
payslip_id = payslip_ids[0]     
xml_file_ids = models.execute_kw(      
    db, uid, password,      
    'ir.attachment',     
    'search',    
    [[("res_model", "=", "hr.payslip"), ("res_id", "=",     payslip_id), ("file_type", "=", "application/xml")]],     
    {}    
)    
xml_file = models.execute_kw(    
    db, uid, password,     
    "ir.attachment",    
    "read",     
    [xml_file_ids],    
    {"fields_to_read": ["datas"]}   
)

El contenido del archivo está codificado en base64 y se puede leer de la siguiente manera:

Python
file_data = xml_file[0]["datas"].decode("base64")
XML
<?xml version="1.0" encoding="UTF-8"?>     
<cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3"    
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
xmlns:nomina12="http://www.sat.gob.mx/nomina12"          
xsi:schemaLocation="http://www.sat.gob.mx/cfd/3        
http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd  
http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet
/cfd/nomina/nomina12.xsd" Version="3.3" Serie="MISC 2021" Folio="SLIP 
2550.....

De manera similar el archivo PDF se puede obtener de la siguiente manera:

Python
payslip_id = payslip_ids[0]    
pdf_file_ids = models.execute_kw(    
    db, uid, password,   
    'ir.attachment',   
    'search',   
    [[("res_model", "=", "hr.payslip"), ("res_id", "=", payslip_id), ("file_type", "=", "application/pdf")]],     
    {}      
)    
pdf_file = models.execute_kw(         
    db, uid, password,     
    "ir.attachment",    
    "read",   
    [pdf_file_ids],   
    {"fields_to_read": ["datas"]}     
)   
pdf_data = pdf_file[0]["datas"].decode("base64")