Herramientas Informaticas

Categoría: SAP

🚀 Mejora PRO en SAP Business One: Validaciones Inteligentes de Odómetro y Horómetro

Entrada fija

Si trabajas con SAP Business One y manejas maquinaria o activos… esto te va a ahorrar MUCHOS dolores de cabeza 👇


🤯 El problema

Errores genéricos como:

❌ “Debe indicar el Odómetro al producto Aceite hidráulico”

Y tú:

  • 🤔 ¿Cuál línea?
  • 🤔 ¿Qué activo?
  • 🤔 ¿Dónde corrijo?

Resultado:

  • ⏳ Pierdes tiempo
  • 😤 Corriges mal
  • 🔁 El error vuelve a salir

💡 La solución

Ahora los mensajes muestran:

  • ✅ Código del activo
  • ✅ Nombre del activo
  • ✅ Línea exacta

🔥 Ejemplo:

Debe indicar el Odómetro al activo EQ-001 – Excavadora CAT (Línea 3)


🧠 ¿Qué se hizo?

  • ✔ Se usa el activo desde OcrCode
  • ✔ Se hace fallback al artículo si no hay activo
  • ✔ Se corrige LineNum + 1

🔧 Código completo listo para pegar

IF (:transaction_type = 'A') AND :object_type = '60' AND error_message = 'Ok'
THEN  

     select 
       max(
         case 

           when ifnull(t1."U_TypeMov",'') = '' 
                and ifnull(t1."BaseType",0) <> 202 then 
             'Seleccione el tipo de movimiento'

           when ifnull(t2."QryGroup11",'N') = 'Y' 
                and ifnull(t1."OcrCode",'') = '' 
                and ifnull(t1."U_TypeMov",'') = 'CONSUMO' then 
             'El articulo ' || t1."Dscription" || ' se especifico que debe seleccionarse la maquinaria'

           when ifnull(t4."QryGroup9",'N') = 'Y' 
                and ifnull(t2."QryGroup11",'N') = 'Y' 
                and ifnull(t1."U_Odometro",0) = 0 
                and ifnull(t1."U_TypeMov",'') = 'CONSUMO' then 
             'Debe indicar el Odometro al activo ' 
             || IFNULL(t4."ItemCode", t2."ItemCode")
             || ' - ' || IFNULL(t4."ItemName", t2."ItemName")
             || ' (Línea ' || (ifnull(t1."LineNum",0) + 1) || ')'

           when ifnull(t4."QryGroup9",'N') = 'N' 
                and ifnull(t1."U_Odometro",0) <> 0 then 
             'Quite el valor del campo Odometro en el activo ' 
             || IFNULL(t4."ItemCode", t2."ItemCode")
             || ' - ' || IFNULL(t4."ItemName", t2."ItemName")
             || ' (Línea ' || (ifnull(t1."LineNum",0) + 1) || ')'

           when ifnull(t4."QryGroup8",'N') = 'Y' 
                and ifnull(t2."QryGroup11",'N') = 'Y' 
                and ifnull(t1."U_Horometro",0) = 0  
                and ifnull(t1."U_TypeMov",'') = 'CONSUMO' then 
             'Debe indicar el Horometro al activo ' 
             || IFNULL(t4."ItemCode", t2."ItemCode")
             || ' - ' || IFNULL(t4."ItemName", t2."ItemName")
             || ' (Línea ' || (ifnull(t1."LineNum",0) + 1) || ')'

           when ifnull(t4."QryGroup8",'N') = 'N' 
                and ifnull(t1."U_Horometro",0) <> 0 then 
             'Quite el valor del campo Horometro en el activo ' 
             || IFNULL(t4."ItemCode", t2."ItemCode")
             || ' - ' || IFNULL(t4."ItemName", t2."ItemName")
             || ' (Línea ' || (ifnull(t1."LineNum",0) + 1) || ')'

           when ifnull(t2."QryGroup11",'N') = 'Y' 
                and (ifnull(t4."QryGroup8",'N') = 'Y' or ifnull(t4."QryGroup9",'N') = 'Y') 
                and ifnull(t1."U_Empleado",0) = 0  
                and ifnull(t1."U_TypeMov",'') = 'CONSUMO' then 
             'Debe indicar el empleado que recibe el producto ' || t1."Dscription"

           when ifnull(t2."QryGroup11",'N') = 'Y' 
                and (ifnull(t4."QryGroup8",'N') = 'Y' or ifnull(t4."QryGroup9",'N') = 'Y') 
                and ifnull(t1."U_HoraMovto",0) = 0  
                and ifnull(t1."U_TypeMov",'') = 'CONSUMO' then 
             'Debe indicar la hora en que se recibe el producto ' || t1."Dscription"

           when ifnull(t2."QryGroup11",'N') = 'Y' 
                and (ifnull(t4."QryGroup8",'N') = 'Y' or ifnull(t4."QryGroup9",'N') = 'Y') 
                and LENGTH(ifnull(t1."U_HoraMovto",0)) < 3  
                and ifnull(t1."U_TypeMov",'') = 'CONSUMO' then 
             'Verifique la hora del producto ' || t1."Dscription"

           else '' 
         end
       ) ERROR
     INTO error_message
     from OIGE t0
     inner join IGE1 t1 on t0."DocEntry" = t1."DocEntry"
     inner join OITM t2 on t2."ItemCode" = t1."ItemCode"
     left join OITM t4 on t4."ItemCode" = t1."OcrCode"
     left join "QUA_PermisosWhsUser" t3 
           on t3."WhsCode" = t1."WhsCode" 
          and t3."userId"  = t0."UserSign"
     where t0."DocEntry" = :list_of_cols_val_tab_del;

     IF IFNULL(:error_message, N'') <> N'' THEN 
        error := -10046;
     ELSE 
        error_message := N'Ok';
     END IF;
END IF;

📈 Beneficios

  • 🔥 Mensajes claros
  • 🔥 Menos errores
  • 🔥 Más productividad
  • 🔥 Mejor control de activos

🧩 Conclusión

Pequeño cambio… GRAN impacto 🚀

Tu sistema pasa de:

❌ Confuso
✅ Profesional y claro


💬 ¿Quieres más mejoras como esta?

Puedo ayudarte con:

  • ⚙️ Validaciones avanzadas
  • 🚀 Optimización de SQL
  • 🧠 Automatización en SAP

Solo dime 👇

🔒 Cómo validar documentos copiados en SAP Business One usando SBO_SP_TransactionNotification (Guía completa)

Entrada fija

🔒 Cómo validar documentos copiados en SAP Business One usando SBO_SP_TransactionNotification (Guía completa)

En SAP Business One es muy común que los usuarios copien documentos para agilizar procesos. Por ejemplo, copiar una Salida de Mercancía y convertirla en una Entrada de Mercancía.

Sin embargo, esto puede generar un problema serio: los usuarios podrían modificar las líneas del documento (cambiar cantidades, precios o incluso eliminar artículos) antes de guardar.

Esto rompe la integridad de los datos del inventario.

La buena noticia es que SAP Business One permite evitar esto usando el procedimiento almacenado SBO_SP_TransactionNotification.

En esta guía aprenderás:

  • ✅ Qué es SBO_SP_TransactionNotification
  • ✅ Cómo validar documentos copiados
  • ✅ Cómo impedir cambios en líneas
  • ✅ Cómo evitar eliminar o agregar artículos
  • ✅ Cómo detectar si un documento fue copiado desde otro
  • ✅ Ejemplo completo listo para usar

📌 ¿Qué es SBO_SP_TransactionNotification?

SBO_SP_TransactionNotification es un procedimiento almacenado que se ejecuta automáticamente cada vez que se crea, actualiza o elimina un documento en SAP Business One.

Esto permite validar reglas de negocio personalizadas antes de que el documento se guarde.

Por ejemplo:

  • 🚫 Bloquear precios incorrectos
  • 🚫 Impedir documentos incompletos
  • 🚫 Validar campos obligatorios
  • 🚫 Evitar cambios en documentos copiados

Si una validación falla, SAP muestra un mensaje al usuario y el documento no se guarda.


🏗️ Cómo funciona la copia de documentos en SAP Business One

Cuando copias un documento en SAP Business One, el sistema guarda referencias al documento original.

Por ejemplo:

  • Salida de mercancía → Entrada de mercancía

Las tablas involucradas son:

DocumentoEncabezadoDetalle
Salida de mercancíaOIGEIGE1
Entrada de mercancíaOIGNIGN1

La relación entre documentos se guarda en las líneas del documento destino.


🔗 Campos que conectan los documentos

Cuando un documento se copia, SAP guarda estos campos en la tabla del detalle:

CampoDescripción
BaseEntryDocEntry del documento origen
BaseLineLínea del documento origen
BaseTypeTipo de documento origen
BaseRefNúmero visible del documento origen

Esto permite reconstruir la relación entre documentos.


📊 Ejemplo de relación entre documentos

Supongamos que existe esta salida de mercancía:

OIGE
DocEntry = 120
DocNum = 4500

Detalle:

IGE1
DocEntry = 120
LineNum = 0
ItemCode = ITEM001
Quantity = 5

Luego se crea una entrada copiando ese documento:

IGN1
DocEntry = 300
BaseEntry = 120
BaseLine = 0
BaseType = 60

Esto indica que la entrada proviene de esa salida.


⚠️ Problema común en SAP Business One

Cuando un usuario copia un documento, puede modificar datos antes de guardarlo:

  • ✏️ Cambiar cantidades
  • ✏️ Cambiar precios
  • ✏️ Eliminar líneas
  • ✏️ Agregar artículos

Esto puede provocar inconsistencias en inventario y contabilidad.


🎯 Objetivo de nuestra validación

La validación debe impedir:

  • ❌ eliminar líneas
  • ❌ agregar líneas
  • ❌ cambiar artículo
  • ❌ cambiar descripción
  • ❌ cambiar cantidad
  • ❌ cambiar precio
  • ❌ cambiar almacén
  • ❌ cambiar centro de costo

Pero solo cuando el documento proviene de una Salida de Mercancía.


🧠 Detectar si un documento fue copiado

La forma más sencilla es revisar si el campo BaseEntry tiene valor.

SELECT BaseEntry
FROM IGN1
WHERE DocEntry = :DocEntry

Si el valor existe, el documento proviene de otro.


🧾 Código completo de validación

IF :object_type = '59' AND (:transaction_type = 'A' OR :transaction_type = 'U') THEN

DECLARE v_base_doc INT;
DECLARE v_lineas_base INT;
DECLARE v_lineas_doc INT;
DECLARE v_changes INT;

SELECT TOP 1 "BaseEntry"
INTO v_base_doc
FROM "IGN1"
WHERE "DocEntry" = :list_of_cols_val_tab_del;

IF v_base_doc IS NOT NULL THEN

SELECT COUNT(*)
INTO v_lineas_base
FROM "IGE1"
WHERE "DocEntry" = v_base_doc;

SELECT COUNT(*)
INTO v_lineas_doc
FROM "IGN1"
WHERE "DocEntry" = :list_of_cols_val_tab_del;

IF v_lineas_base <> v_lineas_doc THEN
error := -9200;
error_message := 'No se permite eliminar o agregar lineas del documento copiado.';
END IF;

SELECT COUNT(*)
INTO v_changes
FROM "IGN1" A
JOIN "IGE1" B
ON A."BaseEntry" = B."DocEntry"
AND A."BaseLine" = B."LineNum"
WHERE A."DocEntry" = :list_of_cols_val_tab_del
AND (
IFNULL(A."ItemCode",'') <> IFNULL(B."ItemCode",'')
OR IFNULL(A."Dscription",'') <> IFNULL(B."Dscription",'')
OR IFNULL(A."Quantity",0) <> IFNULL(B."Quantity",0)
OR IFNULL(A."Price",0) <> IFNULL(B."Price",0)
OR IFNULL(A."WhsCode",'') <> IFNULL(B."WhsCode",'')
OR IFNULL(A."OcrCode",'') <> IFNULL(B."OcrCode",'')
);

IF v_changes > 0 THEN
error := -9201;
error_message := 'No se permite modificar las lineas del documento base.';
END IF;

END IF;

END IF;

🧪 Cómo probar la validación

Para verificar que todo funcione:

  1. Crear una salida de mercancía
  2. Copiarla a entrada de mercancía
  3. Intentar cambiar cantidad
  4. Intentar borrar una línea
  5. Intentar agregar una línea

Si la validación funciona correctamente, SAP mostrará un mensaje de error.


💡 Consejos profesionales

Los consultores SAP suelen aplicar estas recomendaciones:

  • 🔹 Validar siempre BaseType
  • 🔹 Comparar líneas con BaseLine
  • 🔹 Bloquear cambios críticos
  • 🔹 Usar mensajes claros para el usuario

🚀 Beneficios de esta validación

  • ✔ Evita errores humanos
  • ✔ Protege la integridad del inventario
  • ✔ Mantiene trazabilidad entre documentos
  • ✔ Mejora auditorías
  • ✔ Reduce inconsistencias contables

📚 Conclusión

El procedimiento SBO_SP_TransactionNotification es una herramienta poderosa para implementar reglas de negocio en SAP Business One.

Con la validación adecuada puedes garantizar que los documentos copiados mantengan exactamente la misma información que el documento original.

Esto mejora la calidad de los datos, reduce errores y asegura que el inventario refleje la realidad operativa de la empresa.

Si trabajas con SAP Business One, dominar este procedimiento es una habilidad clave para cualquier consultor o desarrollador.

💡 Implementar controles como este puede ahorrar muchos problemas en producción.

Guía Definitiva: Conectividad PHP a SAP HANA en Linux (Drivers Nativos)

Entrada fija

Cómo eliminar la dependencia de drivers de pago y configurar una conexión profesional, gratuita y permanente.


Introducción

En el desarrollo de aplicaciones que interactúan con SAP Business One, la conectividad desde entornos Linux suele ser un desafío técnico. Muchos desarrolladores optan por drivers de terceros que, si bien son funcionales, requieren licencias costosas o expiran tras periodos de prueba.

Esta publicación detalla el proceso paso a paso para instalar el HDB Client oficial de SAP y configurar el gestor unixODBC para lograr una integración transparente con PHP, manteniendo la compatibilidad total con servidores Windows.

1. Preparación del Entorno

Antes de comenzar, debemos instalar las dependencias necesarias para que Linux pueda gestionar conexiones ODBC y para que PHP pueda comunicarse con ellas.

sudo apt-get update
sudo apt-get install unixodbc unixodbc-dev php-odbc

Tras la instalación, es vital reiniciar el servidor web para cargar el módulo ODBC:

sudo systemctl restart apache2

2. Instalación del SAP HANA Client (HDBClient)

El driver nativo de SAP es una librería de alto rendimiento (libodbcHDB.so). No busques un instalador .deb; SAP proporciona un script de instalación propio.

  1. Descarga el paquete HDB CLIENT LINUX X86_64.
  2. Descomprime y entra en la carpeta mediante la terminal.
  3. Ejecuta el instalador con privilegios de superusuario:
sudo ./hdbinst

Por defecto, el software se ubicará en /usr/sap/hdbclient/. Esta ruta será nuestra referencia para la configuración.

3. Registro del Driver en el Sistema

Linux utiliza el archivo /etc/odbcinst.ini para saber qué drivers están disponibles. Aquí es donde solucionaremos de forma global los problemas de certificados SSL y X.509.

Edita el archivo: sudo nano /etc/odbcinst.ini y pega lo siguiente:

[SAP_HANA_NATIVE]
Description = SAP HANA Driver Oficial
Driver      = /usr/sap/hdbclient/libodbcHDB.so
Setup       = /usr/sap/hdbclient/libodbcHDB.so
UsageCount  = 1
# Desactivación de cifrado para evitar errores de comunicación
encrypt                = false
sslValidateCertificate = false

4. Configuración del DSN (Data Source Name)

El DSN es el alias que usará tu código PHP. Al definirlo en /etc/odbc.ini, abstraes la dirección IP y el puerto de tu código fuente.

Edita el archivo: sudo nano /etc/odbc.ini:

[MI_DSN_SAPHANA]
Driver     = SAP_HANA_NATIVO
ServerNode = 192.168.x.x:30015
User       = TU_USUARIO_DB
Password   = TU_CONTRASEÑA_DB

Importante: Borra cualquier archivo oculto en tu carpeta personal (~/.odbc.ini) para asegurar que el sistema lea la configuración global de /etc/.

5. Prueba de Fuego desde Terminal

Antes de probar en la web, usamos la herramienta isql. Esta prueba valida que los archivos INI son correctos y que el firewall permite la conexión.

isql -v MI_DSN_SAPHANA TU_USUARIO_DB 'TU_CONTRASEÑA'

Si observas el mensaje + Connected! +, tu sistema operativo ya está hablando con SAP HANA.

6. Implementación en PHP

Gracias a esta configuración, tu código PHP se mantiene limpio y profesional. No necesitas strings de conexión kilométricos, solo el nombre del DSN.

<?php
$dsn      = "MI_DSN_SAPHANA";
$usuario  = "TU_USUARIO_DB";
$password = 'TU_CONTRASEÑA_COMPLEJA'; // Usar comillas simples para evitar errores con caracteres especiales

$conexion = odbc_connect($dsn, $usuario, $password);

if ($conexion) {
    echo "Conexión establecida con éxito a SAP HANA.";
    // Ejemplo de consulta
    $result = odbc_exec($conexion, "SELECT 'Conexión Exitosa' FROM DUMMY");
    print_r(odbc_fetch_array($result));
} else {
    echo "Error de conexión: " . odbc_errormsg();
}
?>

7. Mantenimiento de Compatibilidad con Windows

Una de las mayores ventajas de este método es la portabilidad. Si tu servidor de producción es Windows y tu entorno de desarrollo es Linux:

  • En Windows: Crea un DSN de Sistema con el nombre MI_DSN_SAPHANA desde el Administrador de Datos ODBC.
  • En Linux: Mantén el DSN con el mismo nombre en /etc/odbc.ini.

Resultado: El mismo archivo PHP funcionará en ambos sistemas sin modificar una sola línea de código.

Conclusión

Configurar drivers nativos requiere un poco más de trabajo manual que usar instaladores automáticos de pago, pero los beneficios son claros: estabilidad, gratuidad y control total sobre la seguridad de la conexión. Al centralizar la configuración en los archivos del sistema, permitimos que nuestras aplicaciones PHP sean más robustas y fáciles de mantener.

Creado con WordPress & Tema de Anders Norén