Esta es una aplicación funcional que desarrollé durante mi primera pasantía. Lo pongo aquí para brindarle a cualquier desarrollador un punto de partida. Desafortunadamente, no se ejecutará si lo prueba localmente porque esta aplicación se creó utilizando un servicio local privado en mi lugar de trabajo. Sin embargo, espero que el código sea útil para alguien.
La mayor parte del código útil se encuentra en el archivo LaborDB, dentro de la carpeta DB, donde muestra cómo conectarse a la API y otras cosas. Por favor, tenga en cuenta que eliminé algunos valores confidenciales de variables/constantes clave, como contraseñas y nombres de usuario. Además, esta herramienta realiza conexiones a diferentes bases de datos que no tienen nada relacionado con la API de INFOR VISUAL.
Esta es la lista de DLL necesarias para utilizar la API:
Este es el conjunto de configuración utilizado. Para configurar esto, seleccione el proyecto en el Explorador de soluciones (Visual Studio) y luego debería aparecer la opción.
Antes de realizar cualquier modificación en esta herramienta, se requieren algunos conceptos para comprender mejor cómo funciona.
###BOLETOS
En primer lugar, los asientos que realizan los empleados se denominan tickets y existen dos tipos, indirectos y directos.
Indirecto
Los tickets indirectos no tienen ninguna ORDEN DE TRABAJO relacionada. Si se analiza más de cerca la tabla LABOR_TICKET, una columna es crucial para determinar si un ticket es indirecto o directo: WORKORDER_BASE_ID. Este campo es NULL para cada ticket indirecto y la columna INDIRECT_ID siempre es obligatoria.
Directo
Los tickets directos siempre tienen una ORDEN DE TRABAJO relacionada. En este caso, las columnas WORKORDER_BASE_ID, WORKORDER_LOT_ID, WORKORDER_SPLIT_ID, WORKORDER_SUB_ID Y OPERATION_SEQ_NO siempre son obligatorias.
Conexión a la API
Para conectarnos a la API utilizamos la clase Dbms llamando a su método OpenDirect. Como proceso de obtención de datos de una base de datos SQL, debes abrir, preparar, ejecutar y cerrar la conexión.
//get the product
public static Model.WorkOrderModel getWorkOrderId(string baseId, string instance)
{
//open con to the api
conOpen();
Model.WorkOrderModel wo = new Model.WorkOrderModel();
string query = "Select BASE_ID, LOT_ID, SPLIT_ID, STATUS FROM VMFG.WORK_ORDER WHERE USER_9 LIKE '%,' + ? + ',%'";
GeneralQuery gen = null;
gen = new GeneralQuery(instName);
gen.Prepare("WORK_ORDER", query);
gen.Parameters[0] = baseId;
gen.Execute();
if (gen.Tables["WORK_ORDER"].Rows.Count > 0)
{
wo.baseId = gen.Tables["WORK_ORDER"].Rows[0]["BASE_ID"].ToString();
wo.lotId = gen.Tables["WORK_ORDER"].Rows[0]["LOT_ID"].ToString();
wo.splitId = gen.Tables["WORK_ORDER"].Rows[0]["SPLIT_ID"].ToString();
wo.status = gen.Tables["WORK_ORDER"].Rows[0]["STATUS"].ToString();
}
Dbms.Close(instName);
return wo;
}
Para abrir una conexión a la API llame a la función conOpen. Esta es una función auxiliar.
public static void conOpen()
{
Dbms.OpenDirect(instName, provider, "", source, user, password);
}
Recuperando datos
La forma más genérica de obtener datos de la base de datos mediante la API es mediante la clase GeneralQuery.
GeneralQuery gen = new GeneralQuery(instName);
gen.Prepare("WORKORDER", "Select BASE_ID, SUB_ID, PART_ID FROM VMFG.WORK_ORDER WHERE BASE_ID = ?");
gen.Parameters[0] = baseId;
gen.Execute();
Lectura de registros devueltos
Los datos devueltos después de llamar al método Execute() se almacenan en el mismo objeto utilizado para solicitarlo.
if (gen.Tables["WORKORDER"].Rows.Count > 0)
{
for (var i = 0; i <= gen.Tables["WORKORDER"].Rows.Count - 1; i++)
{
workOrders.Add(gen.Tables["WORKORDER"].Rows[i]["SUB_ID"].ToString() + " " + gen.Tables["WORKORDER"].Rows[i]["PART_ID"].ToString());
}
Dbms.Close(instName);
return workOrders;
}
Lectura de registros devueltos con funciones SQL
En los casos en que la consulta contiene funciones SQL, la forma de acceder a los datos devueltos cambia.
Model.DatePeriodModel dp = new Model.DatePeriodModel();
GeneralQuery gen = null;
gen = new GeneralQuery(instName);
gen.Prepare("ACCOUNT_PERIOD", "SELECT MIN(BEGIN_DATE) FROM VMFG.ACCOUNT_PERIOD WHERE STATUS = 'A' AND YEAR(BEGIN_DATE) = YEAR(GETDATE()) AND CALENDAR_ID = 'BACH'");
gen.Execute();
if (gen.Tables["ACCOUNT_PERIOD"].Rows.Count > 0)
{
dp.min = DateTime.Parse(gen.Tables["ACCOUNT_PERIOD"].Rows[0]["Column1"].ToString());
}
Guardar datos
Solo hay dos ocasiones en las que se guardan datos en esta solución: al guardar un ticket nuevo y al guardar modificaciones en un ticket existente. La clase LaborDB contiene tres métodos en total relacionados con el almacenamiento de datos.
Ahorro de billetes DIRECTOS E INDIRECTOS
Para guardar un nuevo ticket utilizamos la clase LaborTicket, tenga en cuenta que se requiere tener una instancia de conexión a la API. Tanto para los boletos indirectos como para los directos, el proceso es el mismo, solo que difiere en el conjunto de información que se guarda (consulte la información de BOLETOS arriba).
//open con to the api
conOpen();
//new labor ticket
LaborTicket ticket = new LaborTicket(instName);
ticket.Prepare();
//preparing the data
DataRow dr = (DataRow)ticket.NewRunLaborRow(1);
dr["BASE_ID"] = baseId;
dr["LOT_ID"] = lotId;
dr["SPLIT_ID"] = splitId;
dr["SUB_ID"] = leg;
dr["SEQ_NO"] = Int32.Parse(opn);
dr["TRANSACTION_TYPE"] = "RUN";
dr["EMPLOYEE_ID"] = employeeId;
dr["HOURLY_COST"] = hourlyCost;
dr["HOURS_WORKED"] = hoursworked;
dr["MULTIPLIER_1"] = overtime.Equals("OT") ? 1.500 : 1.000;
dr["TRANSACTION_DATE"] = date;
dr["SHIFT_DATE"] = date;
dr["SITE_ID"] = "BACH";
//api method to save
try
{
ticket.Save();
}
catch (Exception ex)
{
Dbms.Close(instName);
}
Dbms.Close(instName);
Actualización de tickets DIRECTOS e INDIRECTOS
Para actualizar un ticket usamos la clase EditLaborTicket. El proceso es similar al de guardar un ticket nuevo. La diferencia es que para actualizar un ticket se requiere su ID.
//open con to the api
conOpen();
//new edit labor ticket
EditLaborTicket editTicket = new EditLaborTicket(instName);
editTicket.Prepare();
//preparin the data
DataRow dr;
dr = (DataRow)editTicket.NewEditLaborRow(ticketId);
dr["SITE_ID"] = "BACH";
dr["INDIRECT_ID"] = indirectId;
dr["HOURS_WORKED"] = hoursWorked;
dr["MULTIPLIER_1"] = overtime.Equals("OT") ? 1.500 : 1.000;
//api method to save
try
{
editTicket.Save();
}
catch
{
Dbms.Close(instName);
}
Dbms.Close(instName);
Eliminación de tickets DIRECTOS e INDIRECTOS
Para eliminar un ticket utilizamos la clase DeleteLaborTicket. Sólo necesitas informar el id del ticket.
//open con to the api
conOpen();
//new delete labor ticket
DeleteLaborTicket deleteTicket = new DeleteLaborTicket(instName);
deleteTicket.Prepare();
//preparing the data
DataRow dr;
dr = (DataRow)deleteTicket.NewDeleteLaborRow(ticketId);
//api method to delete
try
{
deleteTicket.Save();
}
catch
{
Dbms.Close(instName);
}
Dbms.Close(instName);