Software Lab

SageCRM v7.2 – Direcciones. Dirección de Trabajo (business) por defecto.

Jun
20

¿Cómo predeterminar al crear una nueva dirección que esta sea de tipo TRABAJO?

Creamos una función Javascript y la cargamos en el arranque de la pantalla de alta de direcciones con el siguiente código:

 

<script type=»text/JavaScript»>

window.onload=function aa() {
document.getElementsByName(«AdLi_TypeBusiness»)[0].checked = true;
}
</script>

 

El resultado será un pantalla como esta:

Captura

 

 

Sencillo y útil.

Se aceptan comentarios y sugerencias.

SageCRM v7.1 – Rellenar Población y Provincia entrando solo el campo Código Postal.

Ene
22

Una aplicación del artículo precedente en el que utilizamos el ‘Google Maps API Geocode web service’ para traer a la ficha de Direcciones Postales de Sage CRM, en tiempo real, los datos de Población y Provincia entrando el Código Postal.

Empleando este procedimiento no necesitaremos mantener una tabla de códigos postales en nuestro propio sistema.

En este vídeo mostramos el resultado. Como verás una vez introducido el código postal la población y la provincia se rellenan dinámicamente. Tanto en la creación de un nuevo registro como en la modificación de un registro existente.

A continuación el lugar de Sage CRM donde incrustamos la función JavaScript para activar la llamada al WS de Google que nos devuelve en tiempo real la Población y Provincia dinámicamente al entrar el Código Postal…

Sin-título-1

 

 

Sin-título2

La función está operativa solo para códigos postales de España (ES), pero con una pequeña modificación del país en la cadena de la url de llamada al Web Service se puede adaptar para cargar datos postales de otras naciones.

La solución invoca al motor de datos de Google que le pide sean devueltos en formato Json. Hay dos formatos disponibles: XML y JSON. Nosotros para este primer ejemplo hemos resuelto hacerlo con Json.

Código JavaScript de nuestra función:

<script type=»text/javascript»>
function cpostal() {
    (function() {
        var Lib = {
            ajax: {
                xhr: function() {
                    var instance = new XMLHttpRequest();
                    return instance;
                },
                getJSON: function(options, callback) {
                    var xhttp = this.xhr();
                    options.url = options.url || location.href;
                    options.data = options.data || null;
                    callback = callback ||
                    function() {};
                    options.type = options.type || ‘json’;
                    var url = options.url;
                    if (options.type == ‘jsonp’) {
                        window.jsonCallback = callback;
                        var $url = url.replace(‘callback=?’, ‘callback=jsonCallback’);
                        var script = document.createElement(‘script’);
                        script.src = $url;
                        document.body.appendChild(script);
                    }
                    xhttp.open(‘GET’, options.url, true);
                    xhttp.send(options.data);
                    xhttp.onreadystatechange = function() {
                        if (xhttp.status == 200 && xhttp.readyState == 4) {
                            callback(xhttp.responseText);
                        }
                    };
                }
            }
        };
        window.Lib = Lib;
    })()
        var valor =  document.getElementById(‘addr_postcode’).value ;
        Lib.ajax.getJSON({
            url: ‘http://maps.google.com/maps/api/geocode/json?address=’+valor+’&components=country:ES&sensor=false’,
            type: ‘jsonp’
        }, function(jsondata) {
            var info = JSON.parse(jsondata);
            var poblacion = info.results[0].address_components[1].long_name;
            var provincia = info.results[0].address_components[2].long_name;
            EntryForm.addr_city.value = poblacion;
            EntryForm.addr_state.value = provincia;
        });
}
</script>

Una vista en el navegador de una consulta en al Google Maps API Geocode solicitada en JSON y devuelta en tiempo real seleccionando el código postal ‘35001’ de España ‘ES’.

http://maps.googleapis.com/maps/api/geocode/json?address=35001&components=country:ES&sensor=true

Sin-título3

 

Como complemento a la solución anterior acompañamos también el código incluyendo la petición que nos sea devuelta en formato de datos XML:

<script type=»text/JavaScript»>
//xml parse
//API google maps service
//IE,chrome,firefox,safari
//@angel_torre 2014 feb
//input cpostal,request google maps api,retrieve city and state.
function cpostal() {
var valor = document.getElementById(‘addr_postcode’).value;
fichXML = ‘http://maps.google.com/maps/api/geocode/xml?address=’+valor+’&components=country:ES&sensor=false’;
var xhr = new XMLHttpRequest();
xhr.open(‘GET’,fichXML,false);
xhr.onreadystatechange = function() {
if (xhr.readyState==4) {
var xmlDoc = xhr.responseText;
var pos0 = xmlDoc.indexOf(«<long_name>»);
if (pos0!=-1) {
var pos1 = xmlDoc.indexOf(«<long_name>»,pos0+1);
var pos2 = xmlDoc.indexOf(«</long_name>»,pos1+1);
var prim = xmlDoc.slice(pos1+11,pos2);
var pos3 = xmlDoc.indexOf(«<long_name>»,pos2+1);
var pos4 = xmlDoc.indexOf(«</long_name>»,pos3+1);
var segu = xmlDoc.slice(pos3+11,pos4);
document.forms[0].addr_city.value = prim;
EntryForm.addr_city.value = prim;
document.forms[0].addr_state.value = segu;
EntryForm.addr_state.value = segu;
}
}
}
xhr.send(null);
}
</script>

 

Ejemplo de formato de los datos recibidos de Google en XML

 

Captura

 

Espero tus sugerencias y comentarios, siempre bienvenidos.
Gracias por tu atención.

 

Recuperar población y provincia dando el código postal usando google maps api geocode

Ene
21

Presentamos una herramienta desarrollada en código javascript para html5 que realiza el siguiente proceso:

Dando un código postal español válido nos devuelve su población y su provincia.

Para ello hemos utilizado el  ‘Google Maps Api Geocode’. Se trata de un webservice de Google que devuelve todos los datos de una dirección postal en formato de datos XML o JSON estructurado.

Para nuestra herramienta hemos preferido trabajar con el modelo de datos JSON por compatibilidad y facilidad de  integración con código JavaScript.

La documentación de Google sobre este Web Service tan útil se encuentra en https://developers.google.com/maps/documentation/geocoding/?hl=es

Y nuestro código html con los scripts incrustados es:

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Recuperar población y provincia dando el código postal usando google maps api, by @angel_torre</title>
</head>
<body>
<script type=»text/javascript»>
function locationvars(){
var src = String( window.location.href ).split(‘=’)[1];
//var vrs = src.split(‘&’);
//var arr = [];
//for (var x = 0, c = vrs.length; x < c; x++)
//{
// arr[x] = vrs[x].split(‘=’)[1];
//};
return src;
}
</script>
<script type=»text/javascript»>
(function() {
var Lib = {
ajax: {
xhr: function() {
var instance = new XMLHttpRequest();
return instance;
},
getJSON: function(options, callback) {
var xhttp = this.xhr();
options.url = options.url || location.href;
options.data = options.data || null;
callback = callback ||
function() {};
options.type = options.type || ‘json’;
var url = options.url;
if (options.type == ‘jsonp’) {
window.jsonCallback = callback;
var $url = url.replace(‘callback=?’, ‘callback=jsonCallback’);
var script = document.createElement(‘script’);
script.src = $url;
document.body.appendChild(script);
}
xhttp.open(‘GET’, options.url, true);
xhttp.send(options.data);
xhttp.onreadystatechange = function() {
if (xhttp.status == 200 && xhttp.readyState == 4) {
callback(xhttp.responseText);
}
};
}
}
};
window.Lib = Lib;
})()
var valor = locationvars() ;
Lib.ajax.getJSON({
url: ‘http://maps.google.com/maps/api/geocode/json?address=’+valor+’&components=country:ES&sensor=false’,
type: ‘jsonp’
}, function(jsondata) {
document.querySelector(‘#codigo’).innerHTML=jsondata;
var info = JSON.parse(jsondata);
//document.querySelector(‘#codigos2’).innerHTML=(info.results.address_components[0].long_name);
var poblacion = info.results[0].address_components[1].long_name;
var provincia = info.results[0].address_components[2].long_name;
document.querySelector(‘#codigo2’).innerHTML = poblacion;
document.querySelector(‘#codigo3’).innerHTML = provincia;
});
</script>
Recuperar población y provincia dando el código postal usando google maps api, by @angel_torre<br><br>
<form name=»entrada» onsubmit=»locationvars()»>
<label>Codigo Postal</label><input type=»text» id=»codposid» name=»codigopostal»><input type=»submit» value=»Ok»><br><br>
</form>
<div id=»codigo2″></div><br>
<div id=»codigo3″></div><br>
<div id=»codigo»></div><br>
</body>
</html>

Confío en que esta herramienta sea útil. Hemos utilizado solo una muy pequeña función de este API, no obstante te animo a que lo utilices a fondo, ya que Google ha realizado una importante labor de documentación que  por no tener coste no deja de tener un gran valor.

Para cualquier comentario o sugerencia, no dudes en contactar.

 

SageCRM v7.1 – Consultar una Procedure de SQL con JavaScript (server-side)

Feb
17

En este ejemplo vamos a analizar cómo lanzar una query de SQL, perteneciente a un procedimiento almacenado de Sage CRM, sirviéndonos de una función JavaScript que se ejecuta automáticamente al acceder a un formulario.

Esta función, que solo se puede ejecutar del lado del server (server-side), nos va a servir para devolvernos los valores de los campos que necesitamos incorporar en el formulario.

El jScript se puede insertar como código en una función ‘OnChange’ o en una función ‘OnCreate’ de html:

<script language=»JavaScript»>
window.attachEvent(«onload», seed);
// cuando se entra al formulario y al modificar el campo de seleccion
function grab(){
var dato;
dato = document.getElementById(«_HIDDENquot_comisionistaTEXT»).value;
return dato;
}
function getComiAddr(){
var strSQL,myQuery,dato1,CRM;
strSQL = «USE [CRM] GO «;
strSQL += «DECLARE    @return_value int,»;
strSQL += »        @xaddr_address1 varchar(100), «;
strSQL += »        @xaddr_address2 varchar(100), «;
strSQL += »        @xaddr_address3 varchar(100), «;
strSQL += »        @xaddr_address4 varchar(100), «;
strSQL += »        @xaddr_address5 varchar(100), «;
strSQL += »        @xaddr_city varchar(100), «;
strSQL += »        @xaddr_country varchar(100), «;
strSQL += »        @xaddr_postcode varchar(100), «;
strSQL += »        @xaddr_state varchar(100) «;
strSQL += «EXEC    @return_value = [dbo].[getCOMP_ADDRESS] «;
strSQL += »     @xprod_comisionista = » + document.getElementById(«quot_comisionista»).value + «, «;
strSQL += »        @xaddr_address1 = @xaddr_address1 OUTPUT, «;
strSQL += »        @xaddr_address2 = @xaddr_address2 OUTPUT, «;
strSQL += »        @xaddr_address3 = @xaddr_address3 OUTPUT, «;
strSQL += »        @xaddr_address4 = @xaddr_address4 OUTPUT, «;
strSQL += »        @xaddr_address5 = @xaddr_address5 OUTPUT, «;
strSQL += »        @xaddr_city = @xaddr_city OUTPUT, «;
strSQL += »        @xaddr_country = @xaddr_country OUTPUT, «;
strSQL += »        @xaddr_postcode = @xaddr_postcode OUTPUT, «;
strSQL += »        @xaddr_state = @xaddr_state OUTPUT «;
strSQL += «SELECT    @xaddr_address1 as N’@xaddr_address1′, «;
strSQL += »        @xaddr_address2 as N’@xaddr_address2′, «;
strSQL += »        @xaddr_address3 as N’@xaddr_address3′, «;
strSQL += »        @xaddr_address4 as N’@xaddr_address4′, «;
strSQL += »        @xaddr_address5 as N’@xaddr_address5′, «;
strSQL += »        @xaddr_city as N’@xaddr_city’, «;
strSQL += »        @xaddr_country as N’@xaddr_country’, «;
strSQL += »        @xaddr_postcode as N’@xaddr_postcode’, «;
strSQL += »        @xaddr_state as N’@xaddr_state’ «;
strSQL += «SELECT    ‘Return Value’ = @return_value «;
strSQL += «GO»;
myQuery = CRM.CreateQueryObj(strSQL,»»);
myQuery.ExecSQL();
dato1 = myQuery.FieldValue(«@xaddr_address1»);
//alert(dato1);
return dato1;
}
function seed(){
EntryForm.quot_comis_emp.value = grab();
EntryForm.quot_comis_addr1.value = getComiAddr();
}
</script>

Y el procedimiento almacenado que crearemos en MsSqlServer:

//STORED PROCEDURE

USE CRM
GO

CREATE PROCEDURE getCOMP_ADDRESS
        @xprod_comisionista INT,
        @xaddr_address1 varchar(100) OUTPUT,
        @xaddr_address2 varchar(100) OUTPUT,
        @xaddr_address3 varchar(100) OUTPUT,
        @xaddr_address4 varchar(100) OUTPUT,
        @xaddr_address5 varchar(100) OUTPUT,
        @xaddr_city varchar(100) OUTPUT,
        @xaddr_country varchar(100) OUTPUT,
        @xaddr_postcode varchar(100) OUTPUT,
        @xaddr_state varchar(100) OUTPUT
    AS
    BEGIN
        select top 1 @xaddr_address1 = a.addr_address1
        , @xaddr_address2 = a.addr_address2
        , @xaddr_address3 = a.addr_address3
        , @xaddr_address4 = a.addr_address4
        , @xaddr_address5 = a.addr_address5
        , @xaddr_city = a.addr_city
        , @xaddr_country = a.addr_country
        , @xaddr_state = a.addr_state
        , @xaddr_postcode = a.addr_postcode
        from address a, address_link ali
        where ali.adli_companyid = @xprod_comisionista
        and a.addr_addressid = ali.adli_addressid
        and ali.adli_personid is null and a.addr_deleted is null
    END
  
Para concluir, solo recordar que estas funciones solo se pueden ejecutar del lado del server; no funcionan del lado del cliente. Para ejecutar funciones del lado del cliente que accedan desde html directamente a base de datos podemos utilizar Ajax. Pero eso lo veremos en otro artículo.

Gracias por dejar tu comentario.

 

SageCRM v7.1 – Trucos para formatear los campos en pantalla.

Dic
02

Con SageCRM tenemos una ventana abierta a la programación con javascript y con ASP. Desde las funciones OnChange y OnCreate de las pantallas y listas podemos desencadenar las funciones javascript que se van a procesar en tiempo real del lado del cliente.

Código para modificar el color de la etiqueta en un formulario:

[Screen.OnCreate]

if (Values(«comp_pr_informatica»))
    {
    Caption = «<font color=’red’>»+CRM.GetTrans(«colnames»,»comp_pr_informatica»)+»:</font>»;

Código para modificar valores de las etiquetas de campos:

[Definición de campos]

<span style=»color:red»>PRODUCTOS:</span><br /><span style=»color:black»>Informática Pr</span>;

 

¿Deseas compartir con nosotros alguno de tus trucos de codificación?

 

 

SageCRM 7.1 – Descuentos en cascada en líneas de Presupuestos

Oct
01

Solo podemos acceder a modificar los campos de líneas o elementos de un presupuesto en modo de edición en el lado del cliente. Esto se consigue mediante programación a nivel de pantalla-campo empleando las funcion onload y onchange del formulario HTML.

Si tienes necesidad de realizar funciones de recálculo en líneas de presupuestos, esta es tu lista de tareas a realizar:

1. Crear campos nuevos en la tabla ‘Elementos de Presupuesto’ (entidad de segundo nivel)

2. Añadir todos los campos nuevos a la pantalla de resumen de elementos de presupuesto

3. Crear las funciones JavaScript (ver más abajo un ejemplo)

4. Hacer las llamadas a las funciones desde los campos adecuados para que se realicen los cálculos en tiempo real y se registren dentro del presupuesto.

En nuestro ejemplo tenemos 3 descuentos en linea de documento que se incluyen en en la fórmula de descuento en cascada con el fin de que el cálculo sea similar a como lo hacen algunos ERPs como es el caso de Sage100.

Script de Contenido Personalizado:

<script language=»JavaScript»>
window.attachEvent(«onload», calculatodo);
function calculo(){
var precio,precio0,precio1,precio2,d1,d2,d3,valor,valor1;
precio = «0,00»;
precio = document.getElementById(«_Dataquit_listprice»).innerHTML;
precio0 = precio.replace(«EUR&nbsp;»,»»);
precio1 = precio0.replace(«.»,»»);
precio2 = parseFloat(precio1.replace(«,»,».»));
d1 = document.getElementById(«quit_dto1»).value;
d1 = parseFloat(d1.replace(«,»,».»));
d2 = document.getElementById(«quit_dto2»).value;
d2 = parseFloat(d2.replace(«,»,».»));
d3 = document.getElementById(«quit_dto3»).value;
d3 = parseFloat(d3.replace(«,»,».»));
//calculo unitario ‘Total Menos Descuento Unitario’
valor = precio2 * (1-(d1/100)) * (1-(d2/100)) * (1-(d3/100));
valor = valor.toFixed(2);
valor1 = valor.replace(«.»,»,»);
return valor1;
}
function calculo2(){
var valor2,valor3,valor4,cant;
valor2 = document.getElementById(«quit_totdiscu»).value;
valor2 = parseFloat(valor2.replace(«,»,».»));
cant = document.getElementById(«quit_quantity»).value;
cant = parseFloat(cant.replace(«,»,».»));
//calculo unitario * cantidad = base imponible linea
valor3 = valor2 * cant;
valor3 = valor3.toFixed(2);
valor4 = valor3.replace(«.»,»,»);
return valor4;
}
function calculatodo(){
if(document.EntryForm.quit_totdiscu &&  document.EntryForm.quit_totdisc){ //nos aseguramos de que existen los campos – Estamos en modo edición.
EntryForm.quit_totdiscu.value= calculo();
EntryForm.quit_totdisc.value= calculo2();
EntryForm.quit_quotedprice.value=EntryForm.quit_totdiscu.value;
}
}
</script>

La función de llamada para realizar el cálculo es  ‘jscript: calculatodo();’ que hay que poner en el componente OnChange de los campos modificables que intervienen en la fórmula.

 

 

SageCRM 7.1 – Automatización de campo texto con valor de campo selección de búsqueda avanzada

Sep
26

Sabemos que el valor que devuelve un campo de selección de búsqueda avanzada es integer, es decir, el identificador del registro de la entidad primaria a la que apunta. El dato de la selección no tiene que pertenecer a la identidad del contexto en el que estamos, por lo tanto no tenemos acceso implícito a sus campos.

Por ejemplo, en un campo de selección de empresa, el valor que devuelve no es el nombre (varchar), sino el identificador (int).

Pero podemos hacer uso de las funciones JavaScript de captura de datos del formulario para que en tiempo real, del lado del cliente, tomemos el texto del campo de selección y lo utilicemos para almacenarlo en otro campo varchar creado por nosotros.

El ejemplo está focalizado en la tabla de presupuestos (Quotes).

Estos son nuestros campos creados:

Ambos campos los hemos ubicado en la cabecera de presupuestos con el propósito de utilizar la entidad de empresa para seleccionar a un comisionista alternativo diferente a la empresa de la oportunidad de ventas en curso.

Al desplegar en el campo ‘Empresa Comisionista’ y seleccionar una empresa el programa rellena automáticamente el campo Empresa con el nombre de la misma.

Tengamos en cuenta que el valor texto no se pude tomar del contexto del presupuesto, que es una empresa diferente, y por lo tanto tiene una complicación mayor pues el dato que se guarda en el campo Empresa Comisionista es un integer.

La pantalla de Resumen de Presupuestos la hemos preparado así:

El script de contenido personalizado:

<script language=»JavaScript»>
window.attachEvent(«onload», seed);
//funciona al entrar al formulario y al modificar el campo de seleccion
function grab(){
var dato;
dato = document.getElementById(«_HIDDENquot_comisionistaTEXT»).value;
return dato;
}
function seed(){
EntryForm.quot_comis_emp.value = grab();
}
</script>

Eso es todo.
Se agradecen comentarios y sugerencias.

 

 

SageCRM 7.1 – Cómo formatear campos de texto con separadores de millares

Sep
11

En algunas ocasiones tenemos un campo no numérico que queremos formatear con separadores de millar sin convertirlo en numérico, es decir, sin convertir el campo texto en numérico entero o float (decimal).

En SageCRM 7.1 se hace así:

En la pantalla de entrada de datos de la entidad seleccionamos el campo en el que deseamos introducir la función de formateo.

En el ‘Script de Modificación’ introducimos la función

jscript: format(this)

 

En el ‘Contenido de Script personalizado’ introducimos la función:

<script>

function format(input)
{
var num = input.value.replace(/\./g,»»);
if(!isNaN(num)){
num = num.toString().split(«»).reverse().join(«»).replace(/(?=\d*\.?)(\d{3})/g,»$1.»);
num = num.split(«»).reverse().join(«»).replace(/^[\.]/,»»);
input.value = num;
}

else{ alert(«Solo se permiten numeros»);
input.value = input.value.replace(/[^\d\.]*/g,»»);
}
}

</script>

El resultado es que al editar el campo en cuestión el programa se encarga de rellenar automáticamente los puntos de los millares, comprobando además si introducimos un caracter no numérico y rechazándolo.

Antes …

 

… y después

 

En una misma pantalla se puede utilizar la función para varios campos diferentes, haciendo una llamada en cada campo a la función ‘jscript: format(this);’ siempre dentro de ‘Script de Modificación’.

 

SageCRM 7.1 – Formatear campos con máscaras

Jul
16

Este artículo explica cómo formatear un campo de texto con una máscara predefinida.

En el ejemplo tenemos un nuevo campo de tipo TEXTO (alfanumérico) de 5 posiciones que queremos se rellene con ceros («00000»)  por la izquierda en la introducción. De tal modo que si ingresamos «56» la máscara nos convierta el valor a «00056» en tiempo real.

Para solucionarlo entraremos en la pantalla de entrada de la entidad Empresa y utilizaremos un JavaScript con la función de relleno de ceros y una llamada a la función en el campo a modificar, como se muestra en el siguiente ejemplo:

 

 

 

El resultado en la pantalla de Entrada de Empresa es el siguiente:

 

Tecleo ’56’

 

Pulso 1 vez la tecla tabulador <TAB>

La propiedad OnChange le envía el valor tecleado a la función Jscript, devolviéndome el valor deseado: