Mostrando postagens com marcador framework. Mostrar todas as postagens
Mostrando postagens com marcador framework. Mostrar todas as postagens

quarta-feira, 1 de outubro de 2014

WorkShop 01 - Preactor API

Resolução workshop 01:

Irei mostrar a resolução do workshop em tópicos, seguindo uma sequencia lógica de trabalho, ok?

1º - Dentro de meu projeto Olá Mundo, eu criei uma classe contendo exatamente as mesmas propriedades do arquivo CSV:
 public class Apontamento
    {
        private string _ordem;
        private string _recurso;
        private string _status;
        private DateTime _dataDeInicio;
        private DateTime _dataDeFim;

        public string Ordem
        {
            get { return _ordem; }
            set { _ordem = value; }
        }

        public string Recurso
        {
            get { return _recurso; }
            set { _recurso = value; }
        }

        public string Status
        {
            get { return _status; }
            set { _status = value; }
        }

        public DateTime DataDeInicio
        {
            get { return _dataDeInicio; }
            set { _dataDeInicio = value; }
        }

        public DateTime DataDeFim
        {
            get { return _dataDeFim; }
            set { _dataDeFim = value; }
        }

        public override bool Equals(object obj)
        {
            if (obj is DBNull) return false;
            if (obj == null) return false;
            var m = (Apontamento) obj;
            return m.Ordem == _ordem;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
2º Criei uma função para ler os dados do arquivo CSV e passar os valores para uma lista de Apontamentos:
 private IList getApontamentosByFileCSV(string pathFile)
        {
            try
            {
                IList apos = new List();

                if (!File.Exists(pathFile))
                {
                    MessageBox.Show("O arquivo de Apontamento não foi encontrado.");
                    return new List();
                }
                StreamReader rd = new StreamReader(pathFile, Encoding.Default);
                try
                {
                    var count = 0;
                    while (!rd.EndOfStream)
                    {
                        count++;
                        var linha = rd.ReadLine();
                        if (count == 1) continue;
                        if (string.IsNullOrEmpty(linha)) continue;

                        var colunas = linha.Split(';');
                        Apontamento iten = new Apontamento();
                        iten.Ordem = colunas[0];
                        iten.Recurso = colunas[1];
                        iten.Status = colunas[2];
                        iten.DataDeInicio = parseDate(colunas[3]);
                        iten.DataDeFim = parseDate(colunas[4]);

                        apos.Add(iten);
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                  rd.Close();  
                }


                return apos;
            }
            catch (Exception ex)
            {
                throw new Exception("Falha ao recuperar os dados do arquivo CSV:" + Environment.NewLine + ex.Message);
            }
        }
3º Criei um método que faz a comunicação com o Preactor, recebe a lista de apontamentos baseado no arquivo CSV e grava na tabela do Preactor:
OBS: a diferença entre este novo método e o OláMundo (Run) é um novo parâmetro que foi adicionado a função, "ref string arquivo". Eu achei essa forma mais simples configurar o nome e local onde o arquivo csv se encontra, mas você poderia também ter deixa o caminho e nome do arquivo fixos em seu projeto, ok?


 public int ImportApontamento(ref PreactorObj preactorComObject, ref object pespComObject, ref string arquivo)
        {
            IPreactor preactor = PreactorFactory.CreatePreactorObject(preactorComObject);
            try
            {
                //RECUPERAR OS DADOS DO ARQUIVO CSV
                IList itens = getApontamentosByFileCSV(arquivo);
                if (itens.Count == 0) return 0;

                //LIMPAR TABELA DE APONTAMENTOS
                preactor.Clear("Apontamento");

                preactor.DisplayStatus("Apontamentos","Importando arquivos de apontamentos.");
                var count = itens.Count;
                var i = 0;
                preactor.UpdateStatus(i, count);
                //INSERIR O GRUPO DE REGISTROS
                foreach (var iten in itens)
                {
                    i++;
                    preactor.UpdateStatus(i, count);
                    //CRIAR UM NOVO REGISTRO NA TABELA DE APONTAMENTOS
                    int record = preactor.CreateRecord("Apontamento");

                    //ESCREVER NA TABELA APONTAMENTOS
                    preactor.WriteField("Apontamento", "Ordem", record, iten.Ordem);
                    if (!string.IsNullOrEmpty(iten.Recurso))
                        preactor.WriteField("Apontamento", "Recurso", record, iten.Recurso);
                    if (!string.IsNullOrEmpty(iten.Status))
                        preactor.WriteField("Apontamento", "Status", record, iten.Status);
                    if (iten.DataDeInicio != DateTime.MinValue)
                        preactor.WriteField("Apontamento", "Data de Início", record, iten.DataDeInicio);
                    if (iten.DataDeFim != DateTime.MinValue)
                        preactor.WriteField("Apontamento", "Data de Fim", record, iten.DataDeFim);
                }
                preactor.DestroyStatus();
                //VAMOS SALVAR OS DADOS NA TABELA DO PREACTOR
                preactor.Commit("Apontamento");
                MessageBox.Show("Seus dados foram importados com sucesso!");
            }
            catch (Exception ex)
            {
                preactor.DestroyStatus();
                MessageBox.Show("Falha ao importar os Apontamentos:" + Environment.NewLine + ex.Message);
            }

            return 0;

        }
4º Criei um botão no arquivo de configuração prmdf, já fizemos isso no olá mundo.


5º Cadastrei a ação dentro do Preactor conforme a ação Olá Mundo, acompanhe o passo a passo:

clique em Editar
Clique em "Novo Registro" em seguida "Adicionar->", digite o nome "arquivo" E clique Ok


Vá para o Menu Script de Eventos => Script de Eventos


Clique em "Parameters.."

Clique Sobre o nome "arquivo"


No campo "File Name", adicione o caminho e o nome do arquivo que iremos importar

6º Vamos Testar nossa ação, vá no Visual Studio e aparte a tecla de atalho "F5", e vamos debugar nosso código:



Com isso encerramos nosso primeiro WorkShop, não detalhei as ações pois elas são bem simples, igual uma receita de bolo, basta seguir o passo-a-passo que não tem erro.

Se houver algum dúvida sobre esse workshop me escreva besaleel@msn.com ou faça um comentário aqui no blog que responderei o mais breve possível.

Se preferir faça o download da solução completa do WorkShop 01.

segunda-feira, 29 de setembro de 2014

Treinamento Preactor APS – Interface de customização API

Para quem não sabe o que é o Preactor:

O Preactor é um sistema avançado para planejamento e sequenciamento do Produção. Sua função é distribuir as ordens de produção ao longo do tempo, levando em consideração N variáveis que possam interferir no processo de produção do produto final.

Os softwares APS são ferramentas especializadas em soluções avançadas de planejamento e programação de operações, capazes de levar em consideração, praticamente todas as variáveis e restrições inerentes ao ambiente produtivo, gerando planos de produção viáveis e factíveis.

O que veremos neste treinamento?

O objetivo desse treinamento é dar orientação básicas sobre o API de desenvolvimento da Preactor. Para isso iremos trabalhar os seguintes tópicos:
  • ·         Funções de Leitura e escrita;
  • ·         Criando Scripts de Integração;
  • ·         Gerando Relatórios para o Preactor;
  • ·         Criando Regras de Sequenciamento personalizadas;

O Preactor está na versão 12 sp1 mas como essa versão está apresentando alguns bugs, o treinamento estará focado na versão mais estável do Preactor 11 sp 2, mas se você preferir, poderá utilizar a versão mais nova do sistema sem grandes problemas.

NOTA, os bugs da versão 12.1 encontrados são:

  • ·         Falha na função TestOperation, entra em loop infinito quando há ordens com quantidade zero sequenciados ou se o testeOP for realizado nessa ordem;
  • ·         Falha na Função GetProcessQuantity, entra em loop infinito quando há ordens com quantidade zero sequenciados ou se o testeOP for realizado nessa ordem;
  • ·         Falha na Função FindMathRecord, Ela não encontra o valor buscado quando o campo que estamos realizando a busca for uma EVALUATE field;
  • ·         Estouro de Memória: Em alguns casos o mal uso de funções recursivas tem causado estou de memória física e o software é fechado;


Requisitos do sistema:

  • SQL Server Express 2008 R2 ou superior – Download
  • Preactor 11.2 – Download
  • Visual Studio Express 2008 ou Superior – Download

Links para download das versões mais recentes do Preactor:



Agora vamos ao que interessa:

PARTE 1 - Configurando o ambiente de trabalho;
PARTE 2 - Lendo e escrevendo dados nas tabelas do Preactor;
PARTE 3 - Buscando e Atualizando dados do Preactor;
PARTE 4 - Manipulando o quadro de Gantt e Criando uma regra de sequenciamento Personalizada - Treinamento API Preactor;

sexta-feira, 1 de agosto de 2014

SAP .Net Connector 3.0 - Net Framework 4.0 - Executando uma RFC e lendo os dados de uma tabela - Parte 3

Parte 3


Para encerrar o tutorial veremos como acessar os dados de uma RFC e como gravar dados em uma tabela dentro da RFC. Para isso daremos continuidade ao nosso projeto.

Serei bem direto nessa etapa pois creio que o código fonte fala por si só.


Lendo os dados de uma tabela

1º criei um classe de nome Material para receber os dados da tabela que iremos ler:

Public Class Material
    Private _code As String
    Private _descricao As String
    Private _quantidade As Double

    Public Property Code As String
        Get
            Return _code
        End Get
        Set(value As String)
            _code = value
        End Set
    End Property

    Public Property Descricao As String
        Get
            Return _descricao
        End Get
        Set(value As String)
            _descricao = value
        End Set
    End Property

    Public Property Quantidade As Double
        Get
            Return _quantidade
        End Get
        Set(value As Double)
            _quantidade = value
        End Set
    End Property
End Class

2º criei um método dentro da classe RfcTableReader de nome getMateriais, onde iremos ler os dados da tabela SAP e montar uma lista de materias:


Public Function getMateriais(ByRef rfcFunction As IRfcFunction) As IList(Of Material)
        Try
            'RECUPERANDO A TABELA TB_MATERIAIS DA RFC
            Dim rfcTabMateriais As IRfcTable = rfcFunction.GetTable("TB_MATERIAIS")
            'CRIANDO UMA LISTA QUE IRÁ CONTER DOS DADOS LIDOS DA RFC-TABLE
            Dim itens As IList(Of Material) = New List(Of Material)

            'EXECUTANDO O LOOP DOS DADOS DA TABELA SAP
            For Each row As IRfcStructure In rfcTabMateriais
                Dim it As New Material
                'TESTANDO SE O EXISTE VALOR NA VARIAVEL SAP
                If Not (IsDBNull(row.GetValue("DSCODE"))) Then
                    it.Code = row.GetString("DSCODE")
                End If
                If Not (IsDBNull(row.GetValue("DSDESCRIPT"))) Then
                    it.Descricao = row.GetString("DSDESCRIPT")
                End If
                If Not (IsDBNull(row.GetValue("DSQUANT"))) Then
                    it.Quantidade = row.GetString("DSQUANT")
                End If
                'VERIFICANDO SE O MATERIAL POSSUI CÓDIGO
                If Not String.IsNullOrEmpty(it.Code) Then
                    itens.Add(it) 'ADD REGISTRO A LISTA
                End If
            Next
            Return itens
        Catch exSap As RfcAbapRuntimeException
            Throw New Exception("ABAP error run Time: " & exSap.Message)
        Catch exSap As RfcAbapBaseException
            Throw New Exception("ABAP base error" & exSap.Message)
        Catch ex As Exception
            Throw
        End Try
    End Function


leia atentamente os comentários que estão dentro da função para que você tenha maior conhecimento da mesma, ok?

3º Executando a RFC e lendo os dados da tabela Material utilizando o que criamos até o momento:

Antes alguns detalhes importantes,
Criando uma instancia IRfcFunction, ela serve para executar todos os comandos da RFC e dentro dela estão contidas todas as tabelas, parametros etc dessa função.
No nosso exemplo iremos chamar a RFC "FRC_MATERIAL":
Dim rfcFunction As IRfcFunction = repositorio.CreateFunction("RFC_MATERIAL")

Após chamar a RFC é necessário a passagens dos parametros da função, caso necessário, como data, período, usuário, lote etc, cada RFC possui seus próprios parâmetros.
rfcFunction.SetValue("DATA", Now)
rfcFunction.SetValue("USER", "camilo.correa.silva.silva")

Para finalizar essas observações, após definir a RFC, passar os devidos parâmetros, basta invocar a função, ou executa-la. Para isso você irá utilizar a função "invoke" e passar para ela as configurações de acesso definidas na segunda parte desse tutorial [ 2ª parte ].
rfcFunction.Invoke(dest)

Veja como ficou nosso código:
   Public Sub LerDadosRFC()
        Try
            '1º - MONTAR OS PARAMETROS PARA CONEXÃO SAP
            Dim con As New SAPConnect()
            'A FUNÇÃO REGISTER ABRE A CONEXÃO COM SAP
            RfcDestinationManager.RegisterDestinationConfiguration(con)
            Dim dest As RfcDestination = RfcDestinationManager.GetDestination("homologacao")
            Dim repositorio As RfcRepository = dest.Repository
            Try
                'CHAMANDO A RFC - PASSANDO PARAMETROS
                Dim rfcFunction As IRfcFunction = repositorio.CreateFunction("RFC_MATERIAL")

                'PASSANDO OS PARAMETROS DE LEITURA DA RFC
                rfcFunction.SetValue("DATA", Now)
                rfcFunction.SetValue("USER", "camilo.correa.silva.silva")

                'EXECUTANDO A RFC
                rfcFunction.Invoke(dest)

                'CHAMANDO A FUNÇÃO QUE LÊ OS DADOS CONTIDOS NA TABLE DA RFC
                Dim materiais As IList(Of Material) = getMateriais(rfcFunction)

            Catch exSap As RfcAbapRuntimeException
                Throw New Exception("ABAP error run Time: " & exSap.Message)
            Catch exSap As RfcAbapBaseException
                Throw New Exception("ABAP base error" & exSap.Message)
            Catch ex As Exception
                Throw
            Finally
                'FECHA A CONEXÃO COM SAP
                RfcDestinationManager.UnregisterDestinationConfiguration(con)
            End Try

        Catch exSap As RfcCommunicationException
            Throw New Exception("Falha na comenicação com SAP: " & exSap.Message)
        Catch exSap As RfcLogonException
            Throw New Exception("Falha no Login: " & exSap.Message)
        Catch ex As Exception
            Throw New Exception("Erro: " & vbCrLf & ex.Message)
        End Try
    End Sub

4º Gravando dados em uma tabela do SAP

As funções para leitura e gravação são bem parecidas e intuitivas, por exemplo, para se ler um campo de uma tabela SAP getValue("NOME DO CAMPO"), para se escrever em um campo, setValue("NOME DO CAMPO", valor). 
Dito isso, existe apenas um comando a mais que deve ser inserido para gerar uma nova linha na tabela SAP antes de inserirmos os valores, que é o comando "Append()"

Veja logo baixo como ficou nosso código de gravação em uma tabela SAP:

 Public Sub GravarDadosRFC(ByVal materiais As IList(Of Material))
        Try

            '1º - MONTAR OS PARAMETROS PARA CONEXÃO SAP
            Dim con As New SAPConnect()
            'A FUNÇÃO REGISTER ABRE A CONEXÃO COM SAP
            RfcDestinationManager.RegisterDestinationConfiguration(con)
            Dim dest As RfcDestination = RfcDestinationManager.GetDestination("homologacao")
            Dim repositorio As RfcRepository = dest.Repository
            Try
                'CHAMANDO A RFC - PASSANDO PARAMETROS
                Dim rfcFunction As IRfcFunction = repositorio.CreateFunction("RFC_MATERIAL")

                'PASSANDO OS PARAMETROS DE LEITURA DA RFC
                rfcFunction.SetValue("DATA", Now)
                rfcFunction.SetValue("USER", "camilo.correa.silva.silva")

                'INSTANCIANDO A TABELA MATERIAL
                Dim rfcTabMateriais As IRfcTable = rfcFunction.GetTable("TB_MATERIAIS")

                'INSERINDO OS REGISTROS DA TABELA DO SAP
                For Each material As Material In materiais
                    'CRIAR UM NOVO REGISTRO NA TABELA
                    rfcTabMateriais.Append()
                    'PASSANDO OS VALORES PARA TABLE
                    rfcTabMateriais.SetValue("DSCODE", material.Code)
                    rfcTabMateriais.SetValue("DSDESCRIPT", material.Descricao)
                    rfcTabMateriais.SetValue("DSQUANT", material.Quantidade)
                Next

                'EXECUTANDO A RFC e INSERINDO OS VALORES
                rfcFunction.Invoke(dest)
              
            Catch exSap As RfcAbapRuntimeException
                Throw New Exception("ABAP error run Time: " & exSap.Message)
            Catch exSap As RfcAbapBaseException
                Throw New Exception("ABAP base error" & exSap.Message)
            Catch ex As Exception
                Throw
            Finally
                'FECHA A CONEXÃO COM SAP
                RfcDestinationManager.UnregisterDestinationConfiguration(con)
            End Try

        Catch exSap As RfcCommunicationException
            Throw New Exception("Falha na comenicação com SAP: " & exSap.Message)
        Catch exSap As RfcLogonException
            Throw New Exception("Falha no Login: " & exSap.Message)
        Catch ex As Exception
            Throw New Exception("Erro: " & vbCrLf & ex.Message)
        End Try
    End Sub



Conclusão


Podemos perceber que para fazer uma integração com SAP via RFC é bem simples. Para isso você deve saber meia dúzia de comandos e ter uma código bem estruturado.

Espero que tenha conseguido ajudar pessoas que como eu tiveram dificuldade de fazer sua primeira integração .Net com SAP.

Se existir alguma dúvida sobre meu código basta me escrever ou postar um comentário, ok?

Para finalizar, como eu havia prometido, segue o link para download da solução que desenvolvemos para esse tutorial:

[ Solução .Net 4.0, visual Studio 2010 RFC Tutorial ]
senha para desconpacta: besaleel.blogspot.com.br

SAP .Net Connector 3.0 - Net Framework 4.0 - Executando uma RFC e lendo os dados de uma tabela - Parte 2

PARTE 2


A segunda parte do tutorial trata da conexão com SAP utilizando as bibliotecas que incorporamos em nosso projeto.

De forma bem direta iremos iniciar criando em nossa solução um arquivo de configuração contendo as informações necessárias para nós realizarmos um conexão bem sucedida com SAP, ok?

Esse arquivo de configuração é o app.config, se fosse um projeto web poderia ser o web.config, ok?

Dentro das tags vamos guardar nossas informações de configuração.


Agora vamos criar as funções necessárias para se conectar com o SAP


Na realidade iremos precisar apenas de criar um classe e implementar os métodos de uma interface do sapncon de nome IDestinationConfiguration. Os métodos exigidos pela classe que iremos implementar são responsáveis pelo controle da conexão com o SAP.

São eles:
GetParameters(), IDestinationConfiguration_ChangeEventsSupported(), ChangeEventsSupported(), ConfigurationChanged()

Iremos trabalhar apenas no GetParameters, veja a implementação da classe logo abaixo:
Imports System.Configuration
Imports SAP.Middleware.Connector

Public Class SAPConnect
Implements IDestinationConfiguration

''' ''' Monta a estrutura de conexão com o SAP de acordo com o "DestinationName" que pode ser tratado com servidor,
''' em nosso caso temos um servidor de Homologação de dados e um de Produção.
'''
''' Nome da Instancia ou Servidor
''' Destino da conexão
''' Besaleel 2014-08-01
Public Function GetParameters(ByVal destinationName As String) As RfcConfigParameters Implements IDestinationConfiguration.GetParameters
Try
Dim conf As RfcConfigParameters = New RfcConfigParameters()
If destinationName.Equals("homologacao") Then
Dim hostH = ConfigurationManager.AppSettings.Get("ServidorSap")
Dim numbH = ConfigurationManager.AppSettings.Get("NumeroSap")
Dim sysH = ConfigurationManager.AppSettings.Get("SistemaSap")
Dim userH = ConfigurationManager.AppSettings.Get("UsuarioSAP")
Dim passH = ConfigurationManager.AppSettings.Get("PassWordSAP")
Dim clieH = ConfigurationManager.AppSettings.Get("ClienteSAP")
Dim langH = ConfigurationManager.AppSettings.Get("IdiomaSAP")


With conf
.Add(RfcConfigParameters.AppServerHost, hostH)
.Add(RfcConfigParameters.SystemNumber, numbH)
.Add(RfcConfigParameters.SystemIDs, sysH)
.Add(RfcConfigParameters.User, userH)
.Add(RfcConfigParameters.Password, passH)
.Add(RfcConfigParameters.Client, clieH)
.Add(RfcConfigParameters.Language, langH)
End With
Return conf
End If
'PRODUÇÃO
Dim host = ConfigurationManager.AppSettings.Get("ServidorSap")
Dim numb = ConfigurationManager.AppSettings.Get("NumeroSap")
Dim sys = ConfigurationManager.AppSettings.Get("SistemaSap")
Dim user = ConfigurationManager.AppSettings.Get("UsuarioSAP")
Dim pass = ConfigurationManager.AppSettings.Get("PassWordSAP")
Dim clie = ConfigurationManager.AppSettings.Get("ClienteSAP")
Dim lang = ConfigurationManager.AppSettings.Get("IdiomaSAP")


With conf
.Add(RfcConfigParameters.AppServerHost, host)
.Add(RfcConfigParameters.SystemNumber, numb)
.Add(RfcConfigParameters.SystemIDs, sys)
.Add(RfcConfigParameters.User, user)
.Add(RfcConfigParameters.Password, pass)
.Add(RfcConfigParameters.Client, clie)
.Add(RfcConfigParameters.Language, lang)
End With
Return conf
Catch ex As Exception
Throw New Exception("Falha ao abrir conexão:" & vbCrLf & ex.Message)
End Try
End Function

Public Function IDestinationConfiguration_ChangeEventsSupported() As Boolean Implements IDestinationConfiguration.ChangeEventsSupported
Return True
End Function

Public Function ChangeEventsSupported() As Boolean
Return True
End Function

Public Event ConfigurationChanged As RfcDestinationManager.ConfigurationChangeHandler Implements IDestinationConfiguration.ConfigurationChanged
End Class

Alguns comentários sobre a classe
vejam que o método GetParameters recebe uma variável "destinationName", que é responsável por dizer qual é o servidor SAP que iremos nos conectar. Em nosso exemplo apesar de recuperarmos os dados para acesso de um único lugar, eu simulei o acesso a um servidor de Homologação (Testes) e a um servidor de produção. Com isso através da variável "destinationName" você poderá ter N instancias para N servidores SAP, ok?


Conexão com SAP

'NÃO ESQUEÇA DE IMPORTAR A BIBLIOTECA SAP
Imports SAP.Middleware.Connector

Public Class RfcTableReader
    Public Sub LerDadosRFC()
        Try

            '1º - MONTAR OS PARAMETROS PARA CONEXÃO SAP
            Dim con As New SAPConnect()
            'A FUNÇÃO REGISTER ABRE A CONEXÃO COM SAP
            RfcDestinationManager.RegisterDestinationConfiguration(con)
            'MONTA OS PARAMETROS DO SERVIDOR SAP QUE IREMOS CONECTAR
            Dim dest As RfcDestination = RfcDestinationManager.GetDestination("homologacao")
            Dim repositorio As RfcRepository = dest.Repository
            Try
                'AQUI SEGUE O CÓDIGO FONTE PARA EXECUTAR A RFC
                'LER TABLES
                'GRAVAR TABLES
                'PASSAR PARAMETROS
                '...

            Catch exSap As RfcAbapRuntimeException
                Throw New Exception("ABAP error run Time: " & exSap.Message)
            Catch exSap As RfcAbapBaseException
                Throw New Exception("ABAP base error" & exSap.Message)
            Catch ex As Exception
                Throw
            Finally
                'FECHA A CONEXÃO COM SAP
                RfcDestinationManager.UnregisterDestinationConfiguration(con)
            End Try

        Catch exSap As RfcCommunicationException
            Throw New Exception("Falha na comenicação com SAP: " & exSap.Message)
        Catch exSap As RfcLogonException
            Throw New Exception("Falha no Login: " & exSap.Message)
        Catch ex As Exception
            Throw New Exception("Erro: " & vbCrLf & ex.Message)
        End Try
    End Sub

End Class

Foi utilizado try catch para controlar a conexão, para não deixarmos conexões abertas

No fim deste tutorial eu irei disponibilizar o código fonte para download.

Parte 3