Definições Gerais
Estamos propondo a criação de um Identificador Global de Recursos para as entidades trafegadas entre os ERP's da TOTVS afim de substituir o uso de "Internal ID" em todas as integrações SOAP e REST.
Pré-requisitos
As marcas deverão atender os seguintes pré-requisitos:
- Devem respeitar a sintaxe de URI descrita na RFC-3986;
- Devem respeitar a sintaxe de URN descrita na RFC-8141;
- Devem respeitar a definição de UUID descrita na RFC-4122;
- Devem respeitar a definição de JSON descrita na RFC-8259;
Termos e Nomenclaturas
Os termos "DEVE", "NÃO DEVE", "REQUERIDO", "PODE", "NÃO PODE", "DEVERIA", "NÃO DEVERIA", "RECOMENDADO", "NÃO RECOMENDADO" e "OPCIONAL" devem ser interpretados como descritos na BCP-14, RFC-2119 e RFC-8174.
Informações |
title |
---|
Recursos | Recursos podem ser compreendidos como as Entidades que são trafegadas através das mensagens padronizadas a partir do EAI dos ERP's da TOTVS. |
Definições da Regra de Negócio
Em termos gerais, o ERP de onde se origina a entidade a ser trafegada através do EAI (RM, Datasul, Protheus, Logix) irá realizar a geração do UUID v4, que identificará este recurso através de todas as linhas de produtos que compartilhem esta integração.
Iremos adotar o padrão de compatibilidade total com as mensagens atualmente em uso, sendo assim, mesmo que uma mensagem não utilize a estrutura proposta, os EAIs irão processar estas mensagens através do funcionamento legado utilizando o de-para na entidade "InternalId" para identificar o recurso.
Nossa proposta inicial é de se utilizar UUID's (Universally Unique Identifier), também conhecidos por GUID's (Globally Unique IDentifier), como URN (Uniform Resource Name) de entidades sendo trafegadas entre os ERP's da TOTVS.
Informações |
---|
|
Um UUID é composto por 128 bits de informação e não requer um processo de geração centralizado. |
Uma das principais razões pela escolha do UUID é que, além de sua geração poder ser descentralizada e automatizada, o algoritmo de geração do UUID suporta geração concorrente de até 10 milhões de registros por segundo por máquina, permitindo seu uso até como identificador de transações.
Informações |
title |
---|
Para sua informação | Exemplo de uma representação em texto de um UUID como URN: urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 |
Foi escolhida a versão 4 (UUID v4) por se tratar de um algoritmo que utiliza geração de valores randômicos e que não se baseia no MAC Address da máquina que realiza a geração do identificador (UUID v1).
Funcionamento
Elaboramos duas propostas de implementação para o Identificador Global de Recursos
Proposta 1
Todas as linhas irão adequar seus adapters para enviar o Identificador Global de Recursos através da entidade "InternalId" no conteúdo de uma mensagem padronizada.
Proposta 2
Todas as linhas irão adequar seus adapters para enviar Todos os adapters deverão estar preparados para receber o Identificador Global de Recursos através da entidade "GlobalId" no conteúdo de uma mensagem padronizada.e retornar este mesmo identificador nas tags "Origin" e "Destination" do elemento "InternalId" de forma que a migração possa ocorrer de forma gradativa.
Image Added
Estrutura
A especificação atual das mensagens será alterada para discriminar o tipo de identificador de recursos sendo utilizado na mensagem disparada.
SOAP/XML
CabeçalhoIremos incluir um atributo "GlobalIdTypeglobalType" no elemento nos elementos "MessageInformationInternalId" do conteúdo da mensagem padronizada
Bloco de código |
---|
|
<xs:attribute name="GlobalIdTypeglobalType" type="xs:string" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="UUID"></xs:enumeration>
<xs:enumeration value="INTERNALIDuuid"></xs:enumeration>
<xs:enumeration value="internalid"></xs:enumeration>
<xs:enumeration value="uuid"></xs:enumeration></xs:restriction>
</xs:attribute> |
Especificação do elemento "InternalId"
Bloco de código |
---|
|
<xs:element name="InternalId" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="globalType" type="xs:string" use="optional">
</xs:restriction>
</xs:simpleType>
</xs:attribute> |
Bloco de código |
---|
|
<xs:element name="MessageInformation" type="MessageInformationType" /> |
Bloco de código |
---|
|
<xs:restriction base="xs:string">
<xs:complexType name="MessageInformationType">
<xs:annotation>:enumeration value="UUID"></xs:enumeration>
<xs:documentation>
<xs:enumeration value="uuid"></xs:enumeration>
Bloco com informações sobre a origem da mensagem. </xs:restriction>
</xs:attribute>
</xs:complexType>
</xs:element> |
Especificação do elemento "ListOfInternalId"
Bloco de código |
---|
|
documentation>
</xs:annotation>
<xs:complexType name="ListOfInternalIdType">
<xs:sequence>
<xs:element name="UUIDInternalId" type="UUIDTypeInternalIdType" minOccurs="1" maxOccurs="1unbounded" />
</xs:sequence>
<xs:annotation></xs:complexType>
<xs:complexType name="InternalIdType">
<xs:documentation>
attribute name="globalType" type="xs:string" use="optional">
<xs:restriction base="xs:string">
Define um identificador universal para esta
<xs:enumeration value="UUID"></xs:enumeration>
mensagem. Duas mensagens não podem ter o mesmo<xs:enumeration value="uuid"></xs:enumeration>
</xs:restriction>
</xs:attribute>
<xs:sequence>
UUID e este valor permanece sempre o mesmo, seja<xs:element name="Name" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
no aplicativo que gera a mensagem, seja no que
<xs:documentation>
recebe.
Nome da InternalId, este nome será padronizado como o nome
</xs:documentation>
</xs:annotation>
que esta internalId teria como chave extrangeira de </xs:element>uma mensagem.
<xs:element name="Type" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xsExemplo:documentation>
IdentificaPara o tipo de mensagem: a. Businessentidade Item: ItemInternalId
Message: Mensagem “real”, sobre um evento
City: CityInternalId
ocorrido (quando for de saída) ou de atualização
CustomerVendor: CustomerVendorInternalId
do produto (quando entrada). Pode ser de dois
</xs:documentation>
subtipos (ver atributos da tag BusinessMessage): </xs:annotation>
</xs:element>
i. Transaction<xs:element Mensagem utilizada para fins dename="Origin" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
replicação de dados que contém um evento
<xs:documentation>InternalId da origem</xs:documentation>
ocorrido no sistema (upsert ou delete). Se
</xs:annotation>
</xs:element>
<xs:element name="Destination" type="xs:string" recebido, resulta na execução da operação sobre
minOccurs="0" maxOccurs="1">
<xs:annotation>
na base de dados. Se Enviado, significa<xs:documentation>InternalId que odo destino</xs:documentation>
</xs:annotation>
sistema de origem está notificando esta </xs:element>
</xs:sequence>
</xs:complexType> |
Exemplos
Utilização da entidade "InternalId" em mensagens padronizadas para identificar recursos globais
Bloco de código |
---|
|
operação. Transactions refletem a atividade de<BusinessContent>
<InternalId globalType="uuid">f81d4fae-7dec-11d0-a765-00a0c91e6bf6</InternalId>
uma aplicação (CrUD) tendem a ser utilizadas de <OrderPurpose>1</OrderPurpose>
<CompanyId>4</CompanyId>
forma assíncrona. ii. Request: Mensagem
<CompanyInternalId globalType="uuid">19dfb9b3-901c-48ce-9954-2cb147ec4fe8</CompanyInternalId>
<BranchId>1</BranchId>
<CustomerOrderId>4|</CustomerOrderId>
utilizada para solicitar a execução de um
<RegisterDate></RegisterDate>
<PaymentTermCode>4|001</PaymentTermCode>
procedimento. Este procedimento pode<OrderId>5652</OrderId>
ser uma
<UserInternalId>mestre</UserInternalId>
<PaymenTermCode></PaymenTermCode>
consulta (getOrders, countCustomers), cálculo
<CurrencyCode></CurrencyCode>
<CurrencyId></CurrencyId>
(calculateTaxes) ou atualização do banco de
<Observation></Observation>
<ListOfCreditDocument></ListOfCreditDocument>
dados (updateAverageCost). Requests promovem o
<DeliveryAddress>
<City></City>
compartilhamento de serviços e tendem a ser<State>
<StateCode></StateCode>
utilizados de forma síncrona. b. Receipt: Quando
<StateInternalId></StateInternalId>
a mensagem for</State>
recebida de forma assíncrona, o
</DeliveryAddress>
<Discounts>
produto devolve um recibo com status de
<Discount>0</Discount>
</Discounts>
recebimento e com o UUID de rastreabilidade da<SalesOrderItens>
<Item>
mensagem dentro do produto que recebeu c.
<OrderItem>1</OrderItem>
Response: Mensagem retornada pelo processamento <CompanyId>4</CompanyId>
<BranchId></BranchId>
da Business Message. Pode trazer apenas o status
<OrderId>5652</OrderId>
(OK ou não), a lista de<itemunitofmeasure></itemunitofmeasure>
erros (se houver) ou
<InternalId globalType="uuid">95a81989-e487-4012-b8e2-b5ae97d3e078</InternalId>
informações relevantes (como número de pedido
<ItemCode></ItemCode>
gerado, por exemplo). Pode ser devolvida na<ItemInternalId globalType="uuid">7371ec73-3062-476d-93cf-251560d130da</ItemInternalId>
<CostCenter>4|</CostCenter>
chamada de uma business message (quando
<UnityPrice></UnityPrice>
síncrono) ou enviada de forma assíncrona.
<TotalPrice></TotalPrice>
</xs:documentation> <Quantity></Quantity>
</xs:annotation>
<xs:simpleType><Observation></Observation>
<xs:restriction<UnitOfMeasureInternalId baseglobalType="xs:string">uuid">5eeba464-3748-41a6-a5f7-1cff2ca69aeb</UnitOfMeasureInternalId>
<xs:enumeration value<WarehouseInternalId globalType="BusinessMessage"></xs:enumeration>uuid">c3507b85-a799-42b0-8e71-07cf886ec781</WarehouseInternalId>
<FreightValue></FreightValue>
<xs:enumeration value="Response"></xs:enumeration>
<ListOfApportionOrderItem></ListOfApportionOrderItem>
<xs:enumeration value="Receipt"></xs:enumeration>
<ItemDiscounts>
</xs:restriction>
</xs:simpleType><ItemDiscount></ItemDiscount>
</xs:element>
</ItemDiscounts>
<xs:element name="Transaction" minOccurs="1" maxOccurs="1">
</Item>
<xs:annotation>
</SalesOrderItens>
</BusinessContent> |
Utilização da entidade "ListOfInternalId" em mensagens padronizadas para identificar recursos globais
Bloco de código |
---|
|
<TOTVSMessage>
<MessageInformation version="1.000">
<xs:documentation><UUID>6403aa6a-700d-a535-c567-8ea0be5c9142</UUID>
<Type>Response</Type>
<Transaction>CONTRACT</Transaction>
<StandardVersion>1.000</StandardVersion>
<SourceApplication>PADRAO_EAI2</SourceApplication>
<CompanyId>01</CompanyId>
Identifica<BranchId>1U</BranchId>
o nome da transação que esta mensagem<Product name="PROTHEUS" version="12"></Product>
<GeneratedOn>2018-01-08T16:53:45</GeneratedOn>
<DeliveryType>Sync</DeliveryType>
</MessageInformation>
<ResponseMessage>
<ReceivedMessage>
contém. Exemplo: Branch.<SentBy>RM</SentBy>
<UUID>bf920a68-8263-4e1a-8076-2084a55e69d2</UUID>
<Event>Upsert</Event>
</xs:documentation>
<MessageContent><![CDATA[
<?xml version="1.0" encoding="utf-8"?>
<TOTVSMessage>
<MessageInformation version="1.000">
</xs:annotation><UUID>bf920a68-8263-4e1a-8076-2084a55e69d2</UUID>
<Type>BusinessMessage</Type>
<xs:simpleType><Transaction>CONTRACT</Transaction>
<StandardVersion>1.000</StandardVersion>
<SourceApplication>RM</SourceApplication>
<xs:restriction base="xs:string">
<CompanyId>1</CompanyId>
<BranchId>1</BranchId>
<Product <xs:whiteSpace value="collapse"></xs:whiteSpace>name="RM" version="12.1.17.0" />
<GeneratedOn>2018-01-08T18:53:40</GeneratedOn>
<DeliveryType>Sync</DeliveryType>
</xs:restriction>
MessageInformation>
<BusinessMessage>
<BusinessEvent>
<<Entity>CONTRACT</xs:simpleType>Entity>
<<Event>Upsert</xs:element>Event>
</BusinessEvent>
<xs:element name="ContextName" type="xs:string" minOccurs="0" maxOccurs="1"> <BusinessContent>
<xs:annotation><RMENTITYNAME>MCNT</RMENTITYNAME>
<xs:documentation><InternalId globalType="uuid">f555297a-951f-415d-8672-4a08f2251d40</InternalId>
<CompanyId>1</CompanyId>
Campo opcional que identifica o(s) contexto(s) associado(s)
a transação. O contexto pode ser o módulo que gerou a
mensagem, pode identificar a integração entre aplicativos,
enfim, pode ser qualquer informação que permita delimitar
a mensagem, de modo a orientar o roteamento da mensagem
ou o recebimento.
Exemplos: Financeiro, Datasul CRM, Manufatura, APS-Logix, etc.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="StandardVersion" minOccurs="1" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\d+.\d+"></xs:pattern>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="SourceApplication" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
Identifica, dentre os aplicativos integrados,
qual instância gerou a mensagem.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"></xs:whiteSpace>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="CompanyId" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>Representa o id da empresa do usuário que enviou a mensagem.</xs:documentation>
</xs:annotation></xs:element>
<xs:element name="BranchId" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Representa o id do estabelecimento do usuário que enviou a mensagem.</xs:documentation>
</xs:annotation></xs:element>
<xs:element name="UserId" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Representa o id do usuário que enviou a mensagem. </xs:documentation>
</xs:annotation></xs:element>
<xs:element name="Enterprise" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Representa, para o Protheus, o valor da empresa no sistema </xs:documentation>
</xs:annotation></xs:element>
<xs:element name="BusinessUnit" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Representa, para o Protheus, o valor da unidade de negócios </xs:documentation>
</xs:annotation></xs:element>
<xs:element name="CompanySharingMode" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Indica o modo de compartilhamento no nível da Empresa. C para Compartilhada e E para Exclusiva.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="C"></xs:enumeration>
<xs:enumeration value="E"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="BusinessUnitySharingMode" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Indica o modo de compartilhamento no nível da Unidade de Negócio. C para Compartilhada e E para Exclusiva.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="C"></xs:enumeration>
<xs:enumeration value="E"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="BranchSharingMode" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Indica o modo de compartilhamento no nível da Filial. C para Compartilhada e E para Exclusiva.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="C"></xs:enumeration>
<xs:enumeration value="E"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Product" maxOccurs="1" minOccurs="1">
<xs:annotation>
<xs:documentation>
Define qual o produto que originou esta
mensagem. Não confundir o produto com a
instância (atributo de TOTVSMessage).
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="name" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
Nome do Produto.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="version" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>
Versão do Produto
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="GeneratedOn" type="xs:dateTime" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
Registra a data e hora em que a mensagem foi
gerada. Observe que este campo é do tipo
datetime e que é sugerido que se acrescente a
identificação do fuso horário. Caso a informação
de fuso não esteja presente, os sistemas
entenderão o horário como GMT-0.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="DeliveryType" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>Forma de entrega da mensagem que foi gerada. Será definida por quem entrega a mensagem.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Sync"></xs:enumeration>
<xs:enumeration value="Async"></xs:enumeration>
<xs:enumeration value="sync"></xs:enumeration>
<xs:enumeration value="async"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
<xs:attribute name="version" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\d+.\d+.\d+"></xs:pattern>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="GlobalIdType" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="UUID"></xs:enumeration>
<xs:enumeration value="INTERNALID"></xs:enumeration>
<xs:enumeration value="internalid"></xs:enumeration>
<xs:enumeration value="uuid"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType> |
Conteúdo
Especificação do tipo 'UUIDType'
Bloco de código |
---|
|
<xs:simpleType name="UUIDType">
<xs:restriction base="xs:string">
<xs:pattern value="\w{8}-\w{4}-\w{4}-\w{4}-\w{12}"></xs:pattern>
</xs:restriction>
</xs:simpleType> |
Proposta 1
Especificação da entidade "InternalId"
Bloco de código |
---|
|
<xs:element name="InternalId" type="UUIDType" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
Define um identificador universal para este
recurso. Todas as mensagens que enviem um mesmo
recurso terão o mesmo UUID e este valor permanece
sempre o mesmo, seja no aplicativo que gera a
mensagem, seja no que recebe.
</xs:documentation>
</xs:annotation>
</xs:element> |
Proposta 2
Especificação da entidade "GlobalId"
Bloco de código |
---|
|
<xs:element name="GlobalId" type="UUIDType" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
Define um identificador universal para este
recurso. Todas as mensagens que enviem um mesmo
recurso terão o mesmo UUID e este valor permanece
sempre o mesmo, seja no aplicativo que gera a
mensagem, seja no que recebe.
</xs:documentation>
</xs:annotation>
</xs:element> |
REST/JSON
Cabeçalho
Iremos incluir um atributo "GlobalIdType" no 'Header' da mensagem
Bloco de código |
---|
|
{ "GlobalIdType" : "string" } |
Bloco de código |
---|
|
{
"Header" : {
<ProjectInternalId globalType="uuid">a82462a7-481b-4839-b525-272184f86cb6</ProjectInternalId>
"UUID" : "d6bbfa63-ca27-e2ac-0b14-101970f59a5b", <ContractNumber>333333</ContractNumber>
"Type" : "BusinessMessage",
</BusinessContent>
</BusinessMessage>
</TOTVSMessage>
]]></MessageContent>
</ReceivedMessage>
"SubType" : "event",<ProcessingInformation>
"Transaction" : "CostCenter",<ProcessedOn>2018-01-08T16:53:45</ProcessedOn>
<Status>ok</Status>
"Version" : "2.000", </ProcessingInformation>
"SourceApplication": "P1299",<ReturnContent>
"ProductName" : "PROTHEUS",<ListOfInternalId>
"ProductVersion" : "12.1.17",<InternalId globalType="uuid">
"CompanyId" : "99", <Name>Contract</Name>
"BranchId" : "01", <Origin>f555297a-951f-415d-8672-4a08f2251d40</Origin>
"GeneratedOn" : "2017-11-14T11:47:00-03:00",<Destination>f555297a-951f-415d-8672-4a08f2251d40</Destination>
"DeliveryType" : "async",</InternalId>
</ListOfInternalId>
"GlobalIdType" : "uuid"
}
} |
Conteúdo
Proposta 1
Especificação da entidade "InternalId"
Bloco de código |
---|
|
{ "InternalId" : "string" } |
</ReturnContent>
</ResponseMessage>
</TOTVSMessage> |
REST/JSON
Iremos incluir a propriedade "uuid" no elemento "InternalId" da mensagem padronizada para representar uma mensagem trafegando um identificador globalUtilização da entidade "InternalId" em mensagens padronizadas
Bloco de código |
---|
|
{
"Contentuuid" : {
"CompanyIdtype" : "99string",
}
} |
Especificação do elemento "InternalId"
Bloco de código |
---|
|
{
"BranchId" : "01",
"CompanyInternalIdInternalId" : "99",{
"Codetype" : ["ABC001object", "string"]
"InternalIdproperties" : "f81d4fae-7dec-11d0-a765-00a0c91e6bf6",
{
"RegisterSituationuuid" : "Active",{
"Name" : "Centro de Custo ABC001",
"ShortCodetype" : "ABC001string",
"SPED" : true,
}
"Class" : 2
}
} |
Proposta 2
Especificação da entidade "GlobalId"
Bloco de código |
---|
|
{ "GlobalId" : "string" }
} |
Exemplos
Utilização da entidade "
GlobalIdInternalId" em mensagens padronizadas para identificar recursos globais
Bloco de código |
---|
|
{
"Content" : {
"GlobalId" : "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
"CompanyId" : "99",
"BranchId" : "01",
"CompanyInternalId" : "99",
"Code" : "ABC001",
"InternalId" : "99|ABC001"{"uuid": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"},
"RegisterSituation" : "Active",
"Name" : "Centro de Custo ABC001",
"ShortCode" : "ABC001",
"SPED" : true,
"Class" : 2
}
} |