WEB ERP Latin America

TEMPLATE POST

Un ejemplo de cliente

Para este ejemplo vamos a construir una pequeña aplicación PHP que primero interrogará a webERP para obtener una lista completa de las ubicaciones de existencias disponibles, las construirá en una lista desplegable HTML y luego permitirá que un usuario ingrese un código de artículo de existencias y devuelva la cantidad de existencias de ese artículo en la ubicación seleccionada. Usaremos PHP para simplificar, pero cualquier lenguaje que tenga una biblioteca xmlrpc (casi todos los idiomas) se puede usar para escribir un cliente.
En primer lugar necesitamos la biblioteca xmlrpc, por lo que copiamos el subdirectorio xmlrpc de webERP a este nuevo proyecto.
El código básico se verá así, y se guardará en un archivo llamado index.php:

<html>
    <head>
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    </head>
    <body>
        <form action="index.html" method="post">
            Stock Code:<input type="text" name="StockID" /><br />
            Location:<select name="location">
            <?php // Here will go the available stock locations from webERP?>
            </select><br />
            <input type="submit" name="submit" value="Submit" />
        </form>
    </body>
</html>

Como su nombre indica, las llamadas a la función xmlrpc se realizan enviando un archivo XML con el nombre de la función y los parámetros al servidor, y reciben un archivo XML del servidor.

Para ayudar con esto, la biblioteca phpxmlrpc que webERP usa (y la usaremos también para nuestro cliente) contiene métodos para codificar nuestra llamada de función como XML y para descodificar el XML que recibimos de regreso.

En primer lugar, debemos incluir la biblioteca xmlrpc en nuestro archivo, por lo que inmediatamente antes del HTML, necesitamos lo siguiente:

<?php
    include "xmlrpc/lib/xmlrpc.inc";
    $xmlrpc_internalencoding="UTF-8";
    include "xmlrpc/lib/xmlrpcs.inc";
?>

Para rellenar el cuadro desplegable con las ubicaciones de existencias se utiliza la función API denominada webERP.xmlrpc_GetLocationList (). Esta función toma dos parámetros, un ID de usuario válido para la instancia webERP y la contraseña para este usuario. El uso de las credenciales de demostración es admin/weberp. Además, el archivo ipa_php.php debe tener el $api_databasename configurado como el nombre de la base de datos en la instalación webERP de destino.

La función para obtener las ubicaciones de inventario se verá así, y estará en la parte inferior del archivo, dentro de una sección de código PHP (es decir, <?Php?>).

function GetLocations() {

    //Encode the user/password combination
    $UserID = php_xmlrpc_encode("admin");
    $Password = php_xmlrpc_encode("webERP");

    //Create a client object to use for xmlrpc call
    $Client = new xmlrpc_client("http://localhost/webERP/api/api_xml-rpc.php");

    //Create a message object, containing the parameters and the function name
    $Message = new xmlrpcmsg("webERP.xmlrpc_GetLocationList", array($UserID, $Password));


El error más común simplemente no devuelve ninguna autorización sin información acerca de por qué esto ha sucedido. La mayoría de las llamadas webERP API/XML-RPC devuelve una matriz que contiene dos elementos, el primero - $Response[0] que contiene un código entero, y el segundo el resultado de la llamada, si se espera uno. Si el código entero es cero, esto indica éxito. Cualquier otro código indica un error. Estos son los errores y los códigos que se devuelven para representarlos:

NoAuthorization

No autorizado

 1

 IncorrectDebtorNumberLength

Longitud incorrecta del número de deudor

1000

 DebtorNoAlreadyExists

El deudor ya no existe

1001

 IncorrectDebtorNameLength

Longitud incorrecta del nombre del deudor

1002

 InvalidAddressLine

Línea de dirección inválida

1003

 CurrencyCodeNotSetup

Código de moneda no configurado

1004

 SalesTypeNotSetup

Tipo de venta no configurado

1005

 InvalidClientSinceDate

Cliente inválido desde fecha

1006

 HoldReasonNotSetup

Mantener la razón no configurada

1007

 PaymentTermsNotSetup

Condiciones de pago no configuradas

1008

 InvalidDiscount

Descuento no válido

 1009

 InvalidPaymentDiscount

Descuento de pago no válido

1010

 InvalidLastPaid

Último pago no válido

 1011

 InvalidLastPaidDate

Última fecha de pago no válida

1012

 InvalidCreditLimit

Límite de crédito inválido

1013

 InvalidInvAddrBranch

Dirección de sucursal inválida

 1014

 InvalidDiscountCode

Código de descuento inválido

1015

 InvalidEDIInvoices

Factura no válida para el intercambio electrónico de datos

1016

 InvalidEDIOrders

Órdenes no válidas para el intercambio electrónico de datos

1017

 InvalidEDIReference

Referencia no válida para el intercambio electrónico de datos

1018

 InvalidEDITransport

Transporte no válido para el intercambio electrónico de datos

1019

 InvalidEDIAddress

Dirección no válida para el intercambio electrónico de datos

1020

InvalidEDIServerUser

Usuario del servidor no válido para el intercambio electrónico de datos

1021

InvalidEDIServerPassword

Contraseña del servidor no válida para el intercambio electrónico de datos

1022

InvalidTaxRef

Referencia Fiscal inválida

 1023

InvalidCustomerPOLine

Línea de pedido de compra no válida

1024

DatabaseUpdateFailed

Error al actualizar la base de datos

1025

NoDebtorNumber

Sin número de deudor

 1026

DebtorDoesntExist

El deudor no existe

 1027

IncorrectBranchNumberLength

Longitud incorrecta del número de sucursal

1028

BranchNoAlreadyExists

El número de la sucursal ya no existe

1029

IncorrectBranchNameLength

Nombre de la sucursal incorrecto

1030

InvalidEstDeliveryDays

Número de días estimados de entrega inválidos

1031

AreaCodeNotSetup

Código de área no configurado

1032

SalesmanCodeNotSetup

Código de vendedor no configurado

1033

InvalidFwdDate

Fecha inválida de envío

 1034

InvalidPhoneNumber

Número telefónico inválido

 1035

InvalidFaxNumber

Número de fax inválido

 1036

InvalidContactName

Nombre del contacto inválido

 1037

InvalidEmailAddress

Dirección de Correo Electrónico inválido

 1038

LocationCodeNotSetup

El código de locación no configurado

1039

TaxGroupIdNotSetup

Grupo de impuesto no configurado

1040

ShipperNotSetup

Transportista no configurado

 1041

InvalidDeliverBlind

Entrega no válida

 1042

InvalidDisableTrans

Transporte inválido ó deshabilitado

 1043

InvalidSpecialInstructions

Instrucciones especiales inválidas

 1044

InvalidCustBranchCode

Código Inválido de sucursal del cliente

1045

BranchNoDoesntExist

Sucursal no existente

 1046

StockCodeDoesntExist

El código de inventario no existe

1047

StockCategoryDoesntExist

Categoría de inventario no existe

1048

IncorrectStockDescriptionLength

La longitud de la descripción de inventario es incorrecta

1049

IncorrectUnitsLength

La longitud de las unidades es incorrecta

1050

IncorrectMBFlag

Marca incorrecta corredor mercantil

 1051

InvalidCurCostDate

Fecha de costo actual inválido

1052

InvalidActualCost

Costo actual inválido

 1053

InvalidLowestLevel

Nivel mínimo inválido

 1054

InvalidDiscontinued

Inválido discontinuado

 1055

InvalidEOQ

Cantidad económica de pedido inválida

1056

InvalidVolume

Volumen inválido

 1057

InvalidKgs

Cantidad de kilogramos invalida

 1058

IncorrectBarCodeLength

Longitud incorrecta del código de barras

1059

IncorrectDiscountCategory

Categoría de descuento incorrecta

 1060

TaxCategoriesDoesntExist

Las categorías de impuesto no existen

1061

InvalidSerialised

Serializado inválido

 1062

IncorrectAppendFile

Archivo adjunto incorrecto

 1063

InvalidPerishable

Asignación de perecedero inválido

 1064

InvalidDecmalPlaces

Cantidad de decimales inválidos

 1065

IncorrectLongStockDescriptionLength

Longitud incorrecta de la descripción del archivo largo

1066

StockCodeAlreadyExists

Código de inventario ya existente

1067

TransactionNumberAlreadyExists

Número de transacción ya existente

1068

InvalidTranDate

Fecha de la transacción inválida

1069

InvalidSettled

Arreglo inválido

 1070

IncorrectReference

Referencia incorrecta

 1071

IncorrectTpe

 Tipo Incorrecto

 1072

InvalidOrderNumbers

Número de pedido inválido

1073

  InvalidExchangeRate

Tasa de cambio inválido

1074

  InvalidOVAmount

 Cantidad OV inválida

 1075

  InvalidOVGst

 Gst OV inválido

 1076

  InvalidOVFreight

 Carga OV inválida

 1077

  InvalidDiffOnExchange

Diferecial cambiario inválido

 1078

  InvalidAllocation

Asignación invalida

 1079

  IncorrectInvoiceText

Texto de factura incorrecto

 1080

  InvalidShipVia

Embarque inválido

 1081

  InvalidEdiSent

Envío de intercambio electrónico de datos no válido

1082

  InvalidConsignment

Envío no válido

 1083

  InvalidLastCost

Último costo no válido

 1084

  InvalidMaterialCost

Costo de material no válido

1085

  InvalidLabourCost

Mano de obra no válida

 1086

  InvalidOverheadCost

Costo de gastos generales inválidos

1087

  InvalidCustomerRef

Referencia de cliente inválida

 1088

  InvalidBuyerName

Nombre de comprador inválido

 1089

  InvalidComments

Comentarios inválidos

 1090

  InvalidOrderDate

Fecha de pedido inválida

1091

  InvalidDeliverTo

Entrega inválida

 1092

  InvalidFreightCost

Gastos de flete no válidos

1094

  InvalidDeliveryDate

Fecha de entrega no válida

1095

  InvalidQuotationFlag

Bandera de oferta inválida

 1096

  OrderHeaderNotSetup

Encabezado de orden no configurado

1097

  InvalidUnitPrice

Pecio unitario inválido

 1098

  InvalidQuantity

Cantidad inválida

 1099

  InvalidDiscountPercent

Porcentaje de descuento no válido

1100

  InvalidNarrative

Narrativa inválida

 1101

  InvalidItemDueDate

Fecha de vencimiento de artículo no válido

1102

  InvalidPOLine

Línea de orden de compra no válida

1103

  GLAccountCodeAlreadyExists

El código de cuenta contable ya existe

1104

  IncorrectAccountNameLength

La longitud del nombre de la cuenta es incorrecta

1105

  AccountGroupDoesntExist

Grupo de cuentas no existe

1106

  GLAccountSectionAlreadyExists

Sección de cuenta contable ya existe

1107

  IncorrectSectionNameLength

La longitud del nombre de la sección es incorrecta

1108

  GLAccountGroupAlreadyExists

Grupo de cuentas contable ya existe

1109

  GLAccountSectionDoesntExist

Seccion de cuenta contable no existe

1110

  InvalidPandL

 PandL inválido

 1111

  InvalidSequenceInTB

Balance de comprobación de secuencia no válido

 1112

  GLAccountGroupDoesntExist

Grupo de cuenta contable no existe

1113

  InvalidLatitude

Latitud inválida

 1114

  InvalidLongitude

Longitud inválida

 1115

  CustomerTypeNotSetup

Tipo de cliente no configurado

1116

  NoPricesSetup

Precio no configurado

 1117

  InvalidInvoicedQuantity

Cantidad de factura no válida

1118

  InvalidActualDispatchDate

Fecha de envío actual no válida

1119

  InvalidCompletedFlag

 Bandera completa no válida

 1120

 InvalidCategoryID

Identificación de categoría inválida

 1121

  InvalidCategoryDescription

Descripción de categoría inválida

 1122

InvalidStockType

Tipo de inventario inválido

 1123

GLAccountCodeDoesntExists

Código de cuenta contable no existe

1124

StockCategoryAlreadyExists

Categoría de inventario si existe

1125

SupplierNoAlreadyExists

 Proveedor ya no existe

1126

IncorrectSupplierNameLength

La longitud del nombre del proveedor es incorrecta

1127

InvalidSupplierSinceDate

 Proveedor inválido desde fecha

1128

InvalidBankAccount

Cuenta bancaria no válida

 1129

InvalidBankReference

Referencia bancaria no válida

 1130

InvalidBankPartics

 Partidas de banco inválida

 1131

InvalidRemittanceFlag

 Bandera de remesas inválida

 1132

FactorCompanyNotSetup

Factor de la compañía no configurado

1133

SupplierNoDoesntExists

El proveedor no existe

 1134

InvalidSuppliersUOM

El proveedor no válida para la unidad de medida

1135

InvalidConversionFactor

Factor de conversión no válido

1136

InvalidSupplierDescription

Descripción del proveedor inválida

 1137

InvalidLeadTime

Tiempo de entrega no válido

1138

InvalidPreferredFlag

 Bandera preferida no válida

 1139

StockSupplierLineDoesntExist

Línea del proveedor de inventario no existe

1140

InvalidRequiredByDate

Fecha requerida inválida

 1141

InvalidStartDate

Fecha de inicio no válida

1142

InvalidCostIssued

Costo emitido no válido

 1143

InvalidQuantityRequired

Cantidad requerida no válida

 1144

InvalidQuantityReceived

Cantidad recibida no válida

 1145

InvalidStandardCost

Costo Estándar no válido

 1146

IncorrectSerialNumber

Número de serie incorrecto

 1147

WorkOrderDoesntExist

La orden de trabajo no existe

1148

InvalidIssuedQuantity

Cantidad emitida no válida

 1149

InvalidTransactionDate

Fecha de transacción no válida

1150

InvalidReceivedQuantity

Cantidad recibida no válida

 1151

ItemNotControlled

Artículo no controlado

 1152

ItemSerialised

Artículo serializado

 1153

BatchNumberDoesntExist

Número de lote no existe

1154

BatchIsEmpty

El lote está vacío

 1155

NoSuchArea

No hay tal área

 1156

NoSuchSalesMan

Ningún vendedor

 1157

NoCompanyRecord

Sin registro de empresa

 1158

NoReadOrder

Sin orden de lectura

 1159

NoReadOrderLines

Sin líneas de orden de lectura

1160

NoTaxProvince

Provincia sin impuestos

 1161

TaxRatesFailed

Tasas de impuestos fallidas

 1162

NoReadCustomerBranch

No lee sucursal de cliente

 1163

NoReadItem

No lee artículo

 1164

MustBeReceiptOrCreditNote

Debe ser recibo o nota de crédito

 1165

NoTransactionToAllocate

Sin transacción para asignar

 1166

Como puede ver el código de error 1 indica "Sin Autorización", que será devuelto el error si el nombre de usuario o la contraseña son incorrectos y también si el nombre de la base de datos que se utilizá en la llamada a la API no se ha especificado correctamente en el archivo de webERP/api/api_php.php en la variable:

$api_DatabaseName="weberpdemo";

Para detectar los errores creamos una variable de sesión para contener cualquier mensaje de error que ocurra, de modo que podamos mostrarlo al usuario. Entonces el código de inicialización en la parte superior de index.php se convierte en:

<?php

include "xmlrpc/lib/xmlrpc.inc";
$xmlrpc_internalencoding="UTF-8";
include "xmlrpc/lib/xmlrpcs.inc";
$_SESSION["Errors"] = array();
?>

Y luego en la parte inferior de la salida tenemos un bucle a la salida de estos errores:

foreach ($_SESSION["Errors"] as $Error) {
echo $Error;
}

Ahora sólo necesitamos capturar ese error. Necesitamos poner este código en la parte inferior de la función GetLocations () para que ahora lea:

if ($ReturnValue[0] == 0) {
return $ReturnValue[1];
} elseif ($ReturnValue[0] == 1) {
    $_SESSION["Errors"][] = "Incorrect login/password credentials used";
}

Ahora ejecute el comando index.php de nuevo en su navegador y obtendra un resultado similar al siguiente:

Sólo debemos poner este código al fondo de nuestras otras funciones, y entonces todos podrán detectar este error.

Ahora bien, si ponemos la contraseña correcta en index.php debería funcionar como antes.

Ahora intente ingresar un código de inventario que no sepa"si existe y ver qué pasa. Ingresé un código de pieza llamado" incorrecto "y esto es lo que verá:

Esta no es una salida muy útil, así que necesitamos detectar este error. Una mirada rápida aquí muestra que el código de error 1047 es "StockCodeDoesntExist" y esto debe ser devuelto si el código que ingresamos es incorrecto. Por lo tanto, debemos capturar el error 1047 en la función GetStockQuantity (). El código al final de esta función ahora se convierte en:

 } elseif ($ReturnValue[0] == 1) {

      $_SESSION["Errors"][] = "Incorrect login/password credentials used";

} elseif ($ReturnValue[0] == 1047) { $_SESSION["Errors"][] = "The stock code you entered does not exist";

}

Así que ahora la función es verificar que el usuario/contraseña es correcto, y también verificar que el código de inventario sea correcto y proporcionar información útil en caso de cualquier problema. Podríamos continuar y comprobar si existen otros errores, pero esto debería ser suficientes por ahora.

Para ello necesitamos una función similar a la que utilizamos para extraer la matriz de códigos de ubicación. Aquí está el código completo:

 functionLocationName($LocationCode) {

//Encodethe data items
$UserID = php_xmlrpc_encode("admin");
        $Password = php_xmlrpc_encode("webERP");
$Code = php_xmlrpc_encode($LocationCode);

        //Create a client object to use for xmlrpc call and set its debug level to zero
        $Client = new xmlrpc_client("http://localhost/webERP/api/api_xml-rpc.php");
        $Client->setDebug(0);

        //Create a message object, containing the parameters and the function name
        $Message = new xmlrpcmsg("webERP.xmlrpc_GetLocationDetails", array($Code, $UserID, $Password));

        //Use the client object to send the message object to the server, returning the response
        $Response = $Client->send($Message);

        //Decode the response and return the array
        $ReturnValue = php_xmlrpc_decode($Response->value());
if ($ReturnValue[0] == 0) {
return $ReturnValue[1]["locationname"];
}
    }

La primera sección codifica los parámetros como XML. Los dos primeros parámetros son siempre la combinación de ID de usuario/contraseña, y para esta llamada de función necesitamos un tercer parámetro, que es el código de la ubicación del que se necesita el nombre. La segunda sección es idéntica a la función anterior y crea una instancia de la clase de cliente XML-RPC. En la tercera sección se crea una instancia de la clase de mensaje, con el primer parámetro que es el nombre completo de la función de la API que se llama, en este caso webERP.xmlrpc_GetLocationDetails, y luego el segundo parámetro es una matriz de los parámetros codificados, (código de ubicación, contraseña del usuario). Este mensaje se envía al servidor, y la respuesta decodifica en una matriz llamada $ReturnValue.

Como la última vez, el primer elemento de la matriz indica si la función tuvo éxito (un cero) o cualquier otro entero para un código de error. El segundo elemento es una matriz asociativa de detalles para esa ubicación. La clave de cada elemento es el nombre del campo para ese valor. En nuestro caso sólo queremos el nombre de la ubicación, por lo que devolveremos el elemento ["locationname"]. Si fuera el número de teléfono que nos interesaba, simplemente devolveríamos el elemento ["tel"].

Cambiando la línea en el HTML donde llenamos el cuadro desplegable para:

Echo <option value =“. $ LocationCode.">. LocationName ($ LocationCode). "</ Option>";

El nombre completo de la ubicación aparece en el menú desplegable de la lista, pero el valor devuelto por el formulario sigue siendo sólo el código

Todo lo que queda para completar nuestro cliente, es escribir un código de inventario en el cuadro de texto, enviar el formulario y devolver la cantidad de existencias para ese código en la ubicación elegida. Primero necesitamos insertar algún código PHP en el HTML para manejar el formulario que se envia:

if (isset($_POST["submit"])) {
echo "The quantity of " . $_POST["StockID"] . " at " . $_POST["location"] . " is : " . GetStockQuantity($_POST["StockID"], $_POST["location"]);
}

Como se puede ver esto llama a otra función de PHP - GetStockQuantity () - que recupera la cantidad de existencias para el artículo requerido en la ubicación requerida. Observando la referencia de la función API en el manual, la función API que necesitamos es webERP.xmlrpc_GetStockBalance. Sin embargo, esta vez hay una pequeña adición que necesitamos ya que esta función devuelve una matriz que contiene los saldos de inventario en todas las ubicaciones para el artículo de inventario determinado.

El código completo de la función PHP es:

function GetStockQuantity($StockID, $LocationCode) {

    //Encode the data items
    $UserID = php_xmlrpc_encode("admin");
    $Password = php_xmlrpc_encode("webERP");
    $StockCode = php_xmlrpc_encode($StockID);

    //Create a client object to use for xmlrpc call and set its debug level to zero
    $Client = new xmlrpc_client("http://localhost/webERP/api/api_xml-rpc.php");
    $Client->setDebug(0);
    //Create a message object, containing the parameters and the function name
    $Message = new xmlrpcmsg("webERP.xmlrpc_GetStockBalance", array($StockCode, $UserID, $Password));
    //Use the client object to send the message object to the server, returning the response
    $Response = $Client->send($Message);
    //Decode the response and return the array
    $ReturnValue = php_xmlrpc_decode($Response->value());
if ($ReturnValue[0] == 0) {
      $Items = $ReturnValue[1];
for ($i=0; $i<sizeOf($Items); $i++) {
if ($Items[$i]["loccode"]==$LocationCode) {
return $Items[$i]["quantity"];
            }
        }
    }

No voy a pasar por esto en detalles, ya que es casi lo mismo que las funciones anteriores. La última sección es la clave:

$ReturnValue = php_xmlrpc_decode($Response->value());
if ($ReturnValue[0] == 0) {
        $Items = $ReturnValue[1];
for ($i=0; $i<sizeOf($Items); $i++) {
if ($Items[$i]["loccode"]==$LocationCode) {
return $Items[$i]["quantity"];
            }
        }
    }

Aquí el RPC devuelve una matriz de ubicaciones con las cantidades de inventario para cada ubicación, y filtra la ubicación que necesitamos.

Mostrando que hemos devuelto los números correctos.