Esta é uma aplicação funcional que desenvolvi durante meu primeiro estágio. Estou colocando aqui para dar a qualquer desenvolvedor um ponto de partida. Infelizmente, ele não será executado se você tentar localmente porque este aplicativo foi feito usando um serviço local privado no meu local de trabalho. No entanto, espero que o código seja útil para alguém.
A maior parte do código útil está no arquivo LaborDB - dentro da pasta DB - onde mostra como conectar-se à API e outras coisas. Por favor, lembre-se de que removi alguns valores confidenciais de variáveis/constantes principais, como senhas e nomes de usuário. Além disso, esta ferramenta fez conexões com diferentes bancos de dados que não possuem nada relacionado à API do INFOR VISUAL.
Esta é a lista de DLLs necessárias para usar a API:
Este é o conjunto de configuração utilizado. Para configurar isso, selecione o projeto no Solution Explorer (Visual Studio) e a opção deverá aparecer.
Antes de qualquer modificação nesta ferramenta, alguns conceitos são necessários para entender melhor como ela funciona.
###INGRESSOS
Primeiramente, os lançamentos feitos pelos funcionários são chamados de tickets e existem dois tipos, indiretos e diretos.
Indireto
Os tickets indiretos não possuem nenhuma ORDEM DE TRABALHO relacionada a ele. Se olharmos mais de perto a tabela LABOR_TICKET, uma coluna é crucial para determinar se um ticket é indireto ou direto: WORKORDER_BASE_ID. Este campo é NULL para todo ticket indireto e a coluna INDIRECT_ID é sempre obrigatória.
Direto
Os tickets diretos sempre possuem uma ORDEM DE TRABALHO relacionada a ele. Neste caso, as colunas WORKORDER_BASE_ID, WORKORDER_LOT_ID, WORKORDER_SPLIT_ID, WORKORDER_SUB_ID E OPERATION_SEQ_NO são sempre obrigatórias.
Conectando-se à API
Para conectar-se à API utilizamos a classe Dbms chamando seu método OpenDirect. Conforme o processo de obtenção de dados de um banco de dados SQL você deve abrir, preparar, executar e fechar a conexão.
//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 uma conexão com a API chame a função conOpen. Esta é uma função auxiliar.
public static void conOpen()
{
Dbms.OpenDirect(instName, provider, "", source, user, password);
}
Recuperando dados
A maneira mais genérica de obter dados do banco de dados usando a API é usando a classe 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();
Lendo registros retornados
Os dados retornados após a chamada do método Execute() são armazenados no mesmo objeto usado para solicitá-lo.
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;
}
Lendo registros retornados com funções SQL
Nos casos em que a consulta contém funções SQL a forma de acessar os dados retornados muda.
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());
}
Salvando dados
Existem apenas duas ocasiões em que os dados são salvos nesta solução: ao salvar um novo ticket e ao salvar modificações em um ticket existente. A classe LaborDB contém três métodos no total relacionados ao salvamento de dados.
Salvando tickets DIRETOS E INDIRETOS
Para salvar um novo ticket utilizamos a classe LaborTicket, observe que é necessário ter uma instância de conexão com a API. Tanto para tickets indiretos quanto diretos o processo é o mesmo, diferindo apenas no conjunto de informações que estão sendo salvas (ver informações dos TICKETS acima).
//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);
Atualização de tickets DIRETOS e INDIRETOS
Para atualizar um ticket usamos a classe EditLaborTicket. O processo é semelhante ao salvar um novo ticket. A diferença é que para atualizar um ticket é necessário o seu 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);
Excluindo tickets DIRETOS e INDIRETOS
Para excluir um ticket usamos a classe DeleteLaborTicket. Você só precisa informar o id do 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);