Integração ao SAP ERP, usando o Django-python como exemplo, usando o protocolo oData (restante)

Boa tarde, Habr!

O tópico da integração de sistemas grandes, como o SAP, com sistemas pequenos, mas mais flexíveis, por assim dizer, era tirar o melhor de ambos.

Em particular, meu exemplo descreverá a integração do SAP ERP com o Django.

Desafio


Devido aos diversos sistemas de controle introduzidos pelo nosso amado estado: Egais, Mercury e muito mais, muitas empresas começaram a adaptar seus sistemas pesados ​​e a colocá-lo de sistemas levemente desajeitados (para grandes empresas) a novas condições. Não direi quais adaptei em particular, mas o pensamento sempre girou em minha mente - criar um sistema de rastreamento unificado para tudo, com base em uma plataforma separada.

Meios


Não demorando muito tempo para escolher quais ferramentas levar, escolhi: Linguagem de programação Python - tendo em vista a abundância de bibliotecas com tudo e com tudo, a plataforma Django, não pergunte por que o Django, não o Flask ou Odoo. Já levei o Odoo para a plataforma e queria estudar um deles, peguei o primeiro, bem, não sei por que, provavelmente por causa de sua maior simplicidade. Sistema ERP para o desenvolvimento do SAP- bem, aqui eu realmente não tinha escolha, porque Eu trabalho para uma empresa integradora de SAP, portanto, tenho conhecimento e acesso às caixas de proteção desse sistema, para que eu tenha todas as condições para fazer com calma meu trabalho sem impedimentos.

Frontend django


A primeira coisa que comecei foi formular uma tarefa específica e escrevê-la em um pedaço de papel, geralmente aconselho a todos antes de codificar algo, descrever o processo, e é MUITO importante que você mude em movimento, mude também na descrição.

Aqui está a primeira versão MUITO grosseira da descrição do programa.
Processo de saída

1) A entrega é criada.

2) Ao passar paletes pelo portão - Operação automática e operação semi-automática

a. Operação automática / Quando um palete passa pelo portão, o programa solicita pela RFC no sistema WMS informações sobre que tipo de entrega é, seu número e envia uma resposta de identificação à entrega ao sistema WMS (possivelmente confirma tarefas de armazém (tarefas de picking) para isso paletes e todos os investimentos). Também verifica todos os selos com informações no sistema WMS

b. Operação semiautomática / O operador digita o número da entrega / máquina no sistema de portões e conduz os paletes através do portão, o sistema de portões envia uma solicitação de cada palete ao sistema WMS para verificar os selos no interior.

3) A composição da entrega é enviada ao sistema contábil

Processo de entrada

1) A entrega é criada.

2) Passagem de paletes através do portão

3) Uma solicitação é enviada ao sistema contábil sobre a composição do contas a receber no depósito atual

4) A composição interna da palete de selos fiscais é verificada com base neste sistema contábil

5) Um sinal é enviado ao sistema WMS para descarregar paletes.

Tabelas necessárias :

Portão:
Identificador
Armazém:
Descrição do produto
Mensagem de passagem :

Título:
Hora, sistema, número do armazém, ID do portão.
Posição:
Carimbo do imposto especial de consumo, hora do registo, vinculação do título
Mensagem de composição do ERP (entrega)

Título:
Hora, sistema, número de entrega,
Posição:
Material, selo, número de palete (se houver)

Mensagem agregada (com base nos dados do ERP) :

Título:

Hora, sistema, número do depósito, identificador do portão, número da remessa do sistema de contabilidade, sinal de direção (saída de entrada), sinal do script de verificação, número da máquina, número do portão do armazém,

Posição: Selo, número do palete (opcional), material (opcional), número da remessa, número da máquina, número do item no documento, lote (opcional), embalagem (opcional)
Em seguida, comecei a aprender Django e a desenhar um processo e um esquema de banco de dados.
Como se viu no Django, a criação de modelos de tabela é muito fácil e conveniente, é algo como isto:

class SapOptions(models.Model): name = models.CharField(verbose_name=' ', max_length=50) baseurl = models.CharField(max_length=500, verbose_name='Url  ', help_text = 'URL  ,  ,  :"https://moses1005:44300/sap/opu/odata/sap/ZLS_SUPPLYCHAIN_SRV/"')#  URL sapset = models.CharField(default='Enter Sapset', max_length=100, verbose_name=' ()') mandt = models.CharField(max_length=3, verbose_name='') user = models.CharField(max_length=15, verbose_name='       ') passwd = models.CharField(max_length=15, verbose_name='') verify = models.BooleanField(default=False, help_text = '   ') def __str__(self): return ': '+self.name + ',  : '+self.mandt class Gates(models.Model): from mainAPP.sap_connector import get_lgorts_fromsap ident = models.CharField(verbose_name='', max_length=10, help_text='',unique=True) wh = models.CharField(verbose_name='  ', default='',max_length=10, help_text='   WMS') help = models.CharField(verbose_name='', default='',max_length= 500,help_text=' , ,  ,   ') try: lgorts = get_lgorts_fromsap() except: lgorts = [('No Connect', 'No Connect'),] lgort = models.CharField(verbose_name='',default='0000', max_length=20, choices=lgorts) def __str__(self): return self.ident +' : '+self.wh+' : '+self.help 

Depois disso, eu já entendi como extrair diretórios do SAP, para que a integração parecesse completamente "perfeita", a palavra-chave "parecesse", mas mais sobre isso mais tarde.

Então, depois de aprender o Django (matou alguns hoje à noite), escrevi uma interface para inserir informações e enviá-las ao SAP ERP.

A primeira tela para inserir informações de aceitação é assim:



  • Armazém - integração direta com o SAP ERP com uma breve descrição,
  • Entrega do ERP - uma entrega do SAP ERP é inserida e é verificada na entrada (é feita uma solicitação à SAP se existe ou não essa entrega,
  • TTN - tudo está claro aqui (carta de porte),
  • Número do parceiro - este é o número do parceiro do SAP ERP, o campo é opcional, é feito para o futuro para encontrar uma entrega,
  • Identificador da embalagem - Esse é um dos campos mais importantes; esse é o número do palete ou da embalagem.

Além disso, a interface é adaptada para um terminal móvel (TSD)



Os campos são criados de tal maneira que após cada pressionar ENTER, o cursor pula para o próximo campo de entrada, de modo que seria conveniente escanear todas as informações do TTN, Gate, Pallet.

Depois de digitalizar o último campo ou clicar em "Salvar", a tela será exibida na caixa de diálogo para inserir os identificadores de cada produto:



Campos:

  1. Essa é a tela da lista de identificadores enviados pelo próprio sistema EGAIS, onde os vermelhos são os identificadores que ainda não foram verificados, amarelo são os identificadores que foram verificados, mas não estavam na mensagem EGAIS, e os verdes são os enviados pelo EGAIS e foram verificados
  2. Digitando identificadores, aqui também está o botão "+", necessário para a aparência de outro campo, etc.
  3. Exibir mensagens de erro, se houver.

Implementação de integração:


Para a integração do Django, tudo é claro: “descanso” é simples de implementar, mas no SAP ERP, tive que ler um pouco).

Então, como isso é feito, como não é muito difícil

1) É necessário criar uma classe de integração para implementação, respectivamente um pacote de desenvolvimento para ela. Isso é feito na transação SEGW



2) Após criar a classe, você precisa definir o Modelo de Dados, existem várias opções, criar seus próprios campos ou clicar em SAP na tabela. Isso significa que, antes de criar um modelo de dados para integração, você precisa criar uma tabela para os dados, isso é feito na transação SE11 e como fazer isso pode ser encontrado na Internet. Então, como a estrutura,



Eu gosto da estrutura da tabela que eu já criei



3) Aqui está o trabalho que fizemos:



Clique em "Gerar" .A classe gerou a estrutura necessária para a integração e nós trabalharemos com ela.

4) Em seguida, em nossa guia Implementação de serviço, nossa estrutura aparece com todos os métodos disponíveis, em particular:

a. Create - Método para criar um registro em nossa tabela de acordo com os dados enviados de fora
b. Delete- Método para excluir registros por identificador
c. GetEntity - Método de solicitação de registro único
d. GetEntitySet - Método para obter vários registros por critérios
e Atualização - Método de modificação de registros
De fato, todos esses métodos são bastante abstratos, mas é claro que existem diferenças

5) Após gerar a classe, criamos uma lista de classes na ramificação Artefatos de Tempo de Execução, selecione aquela com DPC_EXT no final


Clique duas vezes para entrar na própria classe

6) Depois de entrar na lista de métodos de classe, no final, você verá uma lista de todos os métodos, certifique-se de redefini-lo, caso contrário, após a próxima alteração no modelo de dados, tudo será apagado, me deparei com isso, era um insulto ...


Por exemplo, mostrarei a implementação de Create



Tudo é muito simples, IT_KEY_TAB é alimentado na entrada e, com base nesses dados, implementamos algumas ações, neste código, um registro regular na tabela ou saída de erro, que será transferida para o Django. A saída da criação bem-sucedida é gravada na estrutura ER_ENTITY.

7) Testando nossa interface na transação / IWFND / MAINT_SERVICE, longa. Entramos nele, localizamos nossa classe e clicamos em "SAP Gateway Client"



Estamos essencialmente abertos com o EMULATOR de solicitações da web GET \ POST \ PUT \ DELETE, somente da SAP,

PS: você pode testar o serviço criado em qualquer coisa., Estou testando no programa carteiro



É assim que a solicitação get se parece: "GetEntitySet"
/ sap / opu / odata / sap / ZLS_SUPPLYCHAIN_SRV / ZLS_INBOUND_HEADSet? $ format = json
Onde:
/ ZLS_SUPPLYCHAIN_SRV / - Esta é a nossa classe criada
/ ZLS_INBOUND_HEADSet é o nosso modelo de dados,
format = json é o formato de dados que obtemos, a escolha de xml ou json, eu escolho json, porque é por isso que é mais conveniente para mim.

8) Da mesma forma, escrevemos métodos

O que temos, criamos uma frente no Django, criamos uma interface no lado SAP
Agora precisamos reviver tudo, e é no lado do Django que escrevemos os métodos:

1) O método de criação de uma sessão, para efetuar login, obter scrf-token e já mais
retire as informações necessárias do banco de dados usando nossa interface configurada ou crie uma nova
registro. Para fazer isso, crie um arquivo separado no Django, chamei-o de Sap_connector.py e descrevi
nele estão os principais métodos.

 def sap_createSession(): #     oDATA from scanner.models import SapOptions #   SAP sap_opt = SapOptions.objects.all()[0] #       s = requests.Session() s.headers.update({'Connection': 'keep-alive', 'X-CSRF-TOKEN': 'Fetch'}) auth = (sap_opt.user, sap_opt.passwd) try: r = s.get(sap_opt.baseurl, auth=auth,verify=sap_opt.verify) except: message = "    %s %s"%(sap_opt.mandt, sap_opt.name) return ('NO TOKEN', 'NoSession', message) token = r.headers['x-csrf-token'] session = s sess = (token, session, None) return sess 

2) Método de verificação de entrega no SAP ERP

 def sap_delivery_verify(token, session, delivery): #      ERP from scanner.models import SapOptions, Gates sap_opt = SapOptions.objects.all()[0] s = session format = '?$format=json' set = 'likpSet' url = sap_opt.baseurl + set + "('"+delivery+"')"+format headers = {'Content-type': 'application/json;charset=utf-8', 'X-CSRF-TOKEN': token} #      auth = (sap_opt.user, sap_opt.passwd) # auth get = s.get(url, headers=headers, auth=auth,verify=sap_opt.verify)#   if get.status_code ==200: delivery_out = json.loads(get.text).get('d').get('Vbeln') return (True, 'OK') else: error_text = json.loads(get.text).get('error').get('message').get('value') return (False, error_text) 

3) O método de integração de armazéns SAP com o Django

 def get_lgorts_fromsap(): from scanner.models import SapOptions session = sap_createSession() #   token = session[0] session = session[1] sap_opt = SapOptions.objects.all()[0] #   s = session format = '?$format=json' set = 't001lSet' url = sap_opt.baseurl + set +format headers = {'Content-type': 'application/json;charset=utf-8', 'X-CSRF-TOKEN': token} #      auth = (sap_opt.user, sap_opt.passwd) # auth get = s.get(url, headers=headers, auth=auth,verify=sap_opt.verify)#   jdata = json.loads(get.text) lgorts = [] for l in jdata.get('d').get('results'): l.get('lgort') lgorts.append((l.get('Lgort'),l.get('Lgort'))) return lgorts 

E sua segunda parte na parte dos modelos:

 class Gates(models.Model): from mainAPP.sap_connector import get_lgorts_fromsap ident = models.CharField(verbose_name='', max_length=10, help_text='',unique=True) wh = models.CharField(verbose_name='  ', default='',max_length=10, help_text='   WMS') help = models.CharField(verbose_name='', default='',max_length= 500,help_text=' , ,  ,   ') try: #   SAP lgorts = get_lgorts_fromsap() except: lgorts = [('No Connect', 'No Connect'),] lgort = models.CharField(verbose_name='',default='0000', max_length=20, choices=lgorts) def __str__(self): return self.ident +' : '+self.wh+' : '+self.help 

A integração é assim: quando eu crio um novo armazém nas configurações do Django, o sistema exibe os armazéns do SAP ERP que atualmente são criados lá no campo do armazém.



4) Método para criar um novo registro no SAP ERP

 def sap_connect(token, session, data): from scanner.models import SapOptions, Gates #      SAP ERP sap_opt = SapOptions.objects.all()[0] s = session delivery = data.get('delivery') url = sap_opt.baseurl + sap_opt.sapset #  URL +    headers = {'Content-type': 'application/json;charset=utf-8', 'X-CSRF-TOKEN': token} #      auth = (sap_opt.user, sap_opt.passwd) # auth data =json.dumps({"d":{ "Mandt": sap_opt.mandt, "Lgort": Gates.objects.get(id=data.get('gates')).wh, "Vbeln":data.get('delivery'), "Mark": data.get('mark'), "Matnr": "", "Posnr": "", "Mbl": "", "InbDicid":"AAAAAAAAAAAAAAAAAAAAAA==", "DocExt": data.get('ttn'), "Exidv": data.get('pack') }}) try: r2 = s.post(url, data=data, headers=headers, auth=auth) except: return (False, '   ') if r2.status_code ==201: print(' %s   '%(delivery)) return (True, '  %s : '%delivery) else: print('  %s   '%(delivery)) text = r2.text SO = soup(text) s = SO.find_all("message")[0].text return (False, s) 

Na verdade, nós apenas fazemos uma solicitação POST e escrevemos os dados no formato json lá

Conclusão


Criamos um programa integrado ao SAP ERP, com um cenário simples,
O carro chega, inserimos informações em cada palete na interface, o programa verifica se todos os dados foram inseridos corretamente e fornece informações sobre o que deve ser e o que já foi inserido. Depois de inserir os dados, ele relata o que foi feito e transfere os dados para o SAP ERP. Além disso, essa interface é adaptada a partir de interfaces de entrada de dados móveis, o que é importante para armazéns com terminais de coleta de dados (TSD). Após a transferência de dados para o ERP, o sistema também salva todos os dados em que armazém, qual identificador veio, que tipo de identificador, quem o aceitou e assim por diante.

Como resultado, temos um programa para processar identificadores de produtos recebidos e enviados na empresa, enquanto 90% de todo o trabalho é realizado precisamente em um sistema externo integrado ao sistema principal.

No futuro, ele precisa ser finalizado para a manutenção de lotes recebidos, números de série e outras coisas, e ainda mais próximo da integração com a SAP, por exemplo, para criar um lançamento de recebimentos dessa interface, bem, este é um pensamento para o desenvolvimento :)

PS: Não pintei o código ABAP ou python-django desta solução de trabalho, não pintei as configurações de modelo Django ou html, mas me concentrei na integração com o SAP ERP para mostrar que criar um módulo para conectar-se a um sistema tão grande como o SAP não é difícil. Eu fui a esse sistema, se incluirmos o estudo do Django por cerca de 4 noites.

Obrigado a todos pela atenção, serei grato por críticas construtivas!

Source: https://habr.com/ru/post/pt426611/


All Articles