sábado, 21 de abril de 2018

Error con archivos TypeScript (TS) al abrir portal de InforCRM en Visual Studio

Si al abrir un portal de InforCRM en Visual Studio aparece un error de que no encuentra módulos de Type Script o relacionados a archivos TS, la solución es entrar en el administrador de paquetes de NuGet y agregar el "Microsoft.TypeScript.Compiler".

sábado, 12 de septiembre de 2015

Autogenerando aplicaciones de Codeigniter con AppLighter

jueves, 27 de noviembre de 2014

Send 2 SLX en Thunderbird, desde Linux!

Siempre he sentido que para Linux hay muy poco soporte con SalesLogix, por lo que decidí crear mi propia funcionalidad de "Send2SLX" para Thunderbird.

Para usar este "Add-on" es necesario tener el portal de SData funcionando.

Aquí hay un video de cómo funciona y cómo se configura:


Este es el "Add-on" si lo desean probar:  ThunderBAR v1.0.0 by Scorpile

viernes, 10 de octubre de 2014

CrystalReports y un Stored Procedure con parametro DateTime

Los que hayan intentado correr desde Crystal Reports un Stored Procedure que utilice parámetros Date o DateTime, habrán notado que sale un error ("CONVERT" algo...).

El tema es que Crystal siempre que reemplaza el parámetro le coloca CONVERT(DATETIME,'2014-01-01 00:00:00',120) lo cual *NO* es válido en un Stored Procedure en MSSQL.  Por qué? porque en un SP no se pueden utilizar funciones en los parámetros.

Afortunadamente hay un pequeño truco que pueden aplicar!

Paso 1, cambiamos o creamos nuestro SP para que el parámetro sea VARCHAR(100).  Voy a colocar un SP de ejemplo para que se hagan a la idea de lo que pueden hacer:

CREATE PROCEDURE [sysdba].[MISPROC]    @fechaini VARCHAR(100) AS
BEGIN
 SET NOCOUNT ON;
 CREATE TABLE #FECHAS(FI DATETIME)
 DECLARE @qry NVARCHAR(200)
 SET @qry = 'INSERT INTO #FECHAS (FI) VALUES (' + @fechaini + ')'
 EXEC (@qry )
 SELECT FI FROM #FECHAS
 DROP TABLE #FECHAS
END


Creo que ya deben ir notando el truco.  Sigamos.

Paso 2, Creamos nuestro reporte en Crystal.

Creamos la conexión (esto funciona usando el SalesLogix OLEDB Provider e incluso si es un reporte que usa el SQL Native Client) y seleccionamos "Agregar comando" (OJO! vamos a escribir, no confundan con seleccionar directamente el Stored Procedure de la lista que está abajo!) y escribimos el nombre de nuestro SP seguido del parámetro, pero el parámetro lo colocamos entre doble comillas (Si! dobles, no simples):

MISPROC "{?@fechaini}"

Inmediatamente, definimos el parámetro en la derecha.  En el nombre debe decir exactamente @fechaini (en el campo del query pusimos {?@fechaini}).  Además le colocamos tipo FechaHora (o Fecha).

Ahora aceptan y Crystal debería pedirles una fecha por primera vez.  La colocan y al aceptar, en la lista de tablas debería aparecerles "Comando" y dentro el (o los) campo definido (en mi ejemplo es FI).  Pueden arrastrar el campo al informe y previsualizarlo.

Cómo funciona?  Si se fijan en el código, estoy construyendo una tabla temporal para guardar el valor final del parámetro que quiero pasar al SP.  Luego construyo un query en una variable y lo ejecuto con "EXEC", así que el valor del parámetro ya estará en la tabla temporal y podré usarlo cuando quiera, ya sea directo de la tabla, o haciendo un select para asignarlo a otra variable.


lunes, 10 de marzo de 2014

Auto cerrar el cliente de SalesLogix en inactividad (auto logoff auto logout)

Muchas veces en las implementaciones es necesario incorporar una funcionalidad para "auto cerrar" el cliente de SalesLogix cuando el usuario deja de utilizarlo.

En vista de que el cliente no trae esta funcionalidad directamente de la caja, aquí les traigo un programita en NET que se encarga de hacerlo.  Si analizan el código verán que esto aplica para cualquier aplicación, no únicamente SalesLogix, y si lo modifican un poco, pueden hacer "logoff" de la sesión del usuario en lugar de "matar" el EXE... todo depende de ustedes.

Les voy a mostrar puntualmente como monitorear y automatizar el cierre, pero cómo ejecutan el monitor cuando SalesLogix se abre se los dejo a su criterio.  Además, les estoy compartiendo el prototipo inicial aunque 100% funcional, así que no hay comentarios y parte del código puede no verse tan "lindo", por favor no critiquen!

Para esto utilicé Visual Basic NET 2010.  No recuerdo si tuve que añadir una referencia a Microsoft.VisualBasic.Compatibility.dll pero el código funciona perfectamente bien sin modificarle nada!

Primero, creamos un formulario en nuestra aplicación y le insertamos un ListBox que se llamará "List1".  Le agregamos un timer "Timer1" con intervalo de 50, y un "Timer2" con intervalo de 1000.

Luego en el código del formulario pegamos lo siguiente:

Option Strict Off
Option Explicit On
Imports VB = Microsoft.VisualBasic

Friend Class Form1
    Inherits System.Windows.Forms.Form
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Short
    Dim timeout As Short
    Dim start As Short
    Dim hwnd As Integer = 0

    Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
        Me.Hide()
    End Sub 
   
    Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
        On Error GoTo Err
        start = 0
        Me.ShowInTaskbar = False
        timeout = CDbl(VB.Command()) * 60
        Exit Sub
err:
        timeout = 300
    End Sub

    Private Sub Timer1_Tick(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Timer1.Tick
        Dim i As Object
        Dim lngBufferLen As Integer
        Dim strClassName As String
        Dim lngResult As Integer

        For i = 0 To 255
        If GetAsyncKeyState(i) Then              
            End If
        Next i
        Dim auxhwnd As Integer = GetForegroundWindow()
        lngBufferLen = GetWindowTextLength(auxhwnd) + 1
        strClassName = Space(lngBufferLen)
        lngResult = GetWindowText(auxhwnd, strClassName, lngBufferLen)
        strClassName = VB.Left(strClassName, lngBufferLen - 1)
       
        If InStr(1, strClassName, "Sage SalesLogix") > 0 Then
            hwnd = auxhwnd
            For i = 0 To 255
                If GetAsyncKeyState(i) Then
                    List1.Items.Add("Tecla o Mouse - " & strClassName & " Handle: " & auxhwnd.ToString)
                    start = 0
                End If
            Next i
        End If
    End Sub
   
    Private Sub Timer2_Tick(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Timer2.Tick
        On Error GoTo salida
        start = start + 1
        If start = timeout Then
            If hwnd <> 0 Then
                Dim pid As Integer
                GetWindowThreadProcessId(hwnd, pid)
                Dim xproc As Process = Process.GetProcessById(pid)
                xproc.Kill()
                MsgBox("Se ha cerrado el SalesLogix porque ha llegado al tiempo límite de inactividad!", vbInformation, "Inactividad Detectada")
            End If
            End
        End If
        Exit Sub
salida:
    End Sub

End Class


Ahora, creamos un módulo que yo llamé "Module1" y le pegamos lo siguiente:

Option Strict Off
Option Explicit On
Module Module1
    Public Declare Function GetForegroundWindow Lib "user32" () As Integer
    Public Declare Function GetWindowTextLength Lib "user32"  Alias "GetWindowTextLengthA"(ByVal hwnd As Integer) As Integer
    Public Declare Function GetWindowText Lib "user32"  Alias "GetWindowTextA"(ByVal hwnd As Integer, ByVal lpString As String, ByVal cch As Integer) As Integer
    Public Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpdwProcessID As Integer) As Integer

End Module

Listo! Prueben abriendo un SalesLogix, luego ejecuten el programa.  Si vieron el Form Load, notarán que si al ejecutarlo lo hacen con un número, estarán estableciendo el tiempo en minutos del "time out" que cierra el SalesLogix.  Si no lo establecen, se va por default a 5 minutos.

Si hacen clic con el ratón, o presionan alguna tecla, verán en el ListBox como va registrando la actividad, y luego del tiempo establecido de no usarlo, pues lo cerrará.

El truco con el programita, es que SalesLogix debe estar "en foco" en algún momento mientras se monitorea para que se pueda recoger el "hwnd" del EXE, pero les digo que desde que lo uso, nunca nadie ha reportado que el SalesLogix se ha mantenido abierto luego de la cantidad de minutos establecida.

Si esta entrada te sirvió, porfa, haz clic a algún anuncio y míralo un par de segundos... ;)

lunes, 28 de octubre de 2013

Importar data a SalesLogix sin Scribe ni Inaport - Herramienta gratis

Siempre se dice que es necesario importar la data utilizando las claves que maneja SalesLogix, y ciértamente, aunque funciona insertar un valor numérico convertido a cadena, la verdad que se ve muy poco profesional trabajar de esta manera.

Se me ha dado un par de ocasiones, que en la implementación es necesario cargar maestros de datos con gran número de registros (10,000 ó +) que me han pasado en un Excel y por alguna razón, no he tenido disponibilidad de usar ni Scribe ni Inaport.

Para fines educativos, he creado una herramienta que permite generar un número determinado de registros, y luego por "query" de base de datos, he realizado los "updates".

Para descargar la herramienta lo puedes hacer de GitHub https://github.com/scorpile/Development donde también encontrarás el código fuente.  Eso si! Es una herramienta que hice muy rápido y no hice el "error handling" así que no critquen!

Primero necesitamos importar todos los registros que deseemos cargar del Excel a SQL u Oracle.  Yo lo he conseguido creando la tabla auxiliar (a la que llamaré TEST) y colocando los campos que corresponden a las columnas en el Excel.  Luego he creado una fórmula en Excel para crear una sentencia p.ej: "INSERT INTO TEST (ACCOUNT,CONTACT,EMAIL,MAINPHONE) VALUES ('VALOR','VALOR','VALOR','VALOR')" y he concatenado las columnas para que se registren los valores.  Propagando la fórmula hasta abajo, he logrado conseguir insertar todos mis valores.



Luego abrimos la herramienta:


Llenamos los datos del Servidor (ya se que dice Serevidor, fue un "typo" y ya les dije que fue algo rápido).  Este es el de SLX y no el de BD.  Igual el conector y el pass del usuario Admin.

Colocamos la tabla que en este caso utilizaré Account, utilizaré el campo USERFIELD1 para enlazar, y en este caso es necesario marcar el checkbox "Utilizar" del SECCODEID ya que la tabla Account tiene habilitada la seguridad.  Colocamos una cantidad N de registros a insertar.

Al final, presionamos el botón "Realizar la Inserción" y el programa se conectará a SalesLogix e insertará la cantidad especificada de registros en la tabla especificada, y en el campo de enlace, colocará valores como "SLXKey1, SLXKey2, SLXKey3 ... SLXKeyN".

Por último, realizamos el update con el siguiente "query":

UPDATE SYSDBA.ACCOUNT SET SYSDBA.ACCOUNT.ACCOUNT = AUX.ACCOUNT FROM
(
SELECT 'SlxKey' + CAST (ROW_NUMBER () OVER (ORDER BY CAMPO) + 3 AS varchar) AS ID,ACCOUNT FROM SYSDBA.TEST
) AS AUX WHERE SYSDBA.ACCOUNT.USERFIELD1 = AUX.ID


Mucho cuidado!  Como pueden apreciar, estamos actualizando el valor de Account.Account con el valor del campo Valor en la tabla auxiliar "Test".  Obvio los demás campos los ponemos en el mismo update.

Si no se tiene cuidado con lo que se está haciendo, en lugar de una ayuda lo que vamos es a destruir nuestra tabla.

Lo que deben tener cuidado es con valores en los campos que ya contengan la comilla simple " ' " en cuyo caso, desde el Excel las reemplazarían por doble comilla simple (2 veces ' ).

jueves, 11 de abril de 2013

Instalar Knowledge Sync 8 en Windows 2008 R2 (64 bits)

Rápido y directo.

Necesitarás tener instalado el runtime de Visual Basic 5 (Msvbvm50.exe) y el Jet 3.5 (el Jet35sp3.exe funciona perfecto) antes de empezar a instalar Knowledge Sync.
Luego procedemos con el IM64.exe y el KS_Setup_V81e.exe.
En este punto realizamos la migración de la base de datos si es necesaria.
Además es necesario el archivo VB5DB.dll el cual deben obtener de una versión anterior de Windows que tengan a la mano, o si se sienten aventureros, pueden bajar el dll de uno de los ya conocidos sitios de DLL's que hay en internet.
Este dll lo copian en C:\Windows\SysWOW64 y lo registran con el regsvr32.exe que está en esa misma carpeta.  Esto es muy importante!
Si no instalan el VB5DB.dll, no van a poder editar ni crear conexiones nuevas en Knowledge Sync.
Por último, no olviden que Knowledge Sync trabaja con ODBC, por lo que para administrarlos debemos ejecutar el odbcad32.exe que está en C:\Windows\SysWOW64.
Si creamos los ODBC desde la herramienta de ODBC que está entre las "Herramientas Administrativas", estaremos haciéndolo para aplicaciones de 64 bits, y cunando estemos en Knowledge Sync nos vamos a volver locos buscando los ODBC y lógico que nunca van a aparecer.