Histórico da Página
...
- Empresa Logix 23 == Empresa Protheus 50|10 ou 10 ou seja, a empresa 23 do Logix corresponde a empresa 50 e filial 10 do Protheus.
...
Esta tag deverá estar localizada logo abaixo dos campos da mensagem, que fazem parte da sua composição. O exemplo a seguir é um trecho do schema RefundReason_1_000.json.
Bloco de código | ||||
---|---|---|---|---|
| ||||
(...) <xs:element name="Code" type="xs:string" minOccurs="0" maxOccurs="1"> <xs:annotation> <xs:documentation>Codigo do departamento</xs:documentation> </xs:annotation> </xs:element> <xs:element name="InternalId" type="xs:string" minOccurs="0" maxOccurs="1"> <xs:annotation> <xs:documentation>InternalId do Code</xs:documentation> </xs:documentation> </xs:element> |
Bloco de código | ||
---|---|---|
| ||
CompanyId: "23"
Code: "123"
InternalId: "23|123" |
...
: {
"description": "Código do Motivo",
"type": "string",
"x-totvs": [
{
"product": "PROTHEUS",
"field": "G8P.G8P_CODIGO",
"required": true,
"type": "Char",
"length": "4",
"note": "",
"available": true,
"canUpdate": false
}
]
},
"InternalId": {
"description": "InternalId do Motivo",
"type": "string",
"x-totvs": [
{
"product": "PROTHEUS",
"field": "cEmpAnt+G8P.G8P_FILIAL+G8P.G8P_CODIGO",
"required": true,
"type": "Char",
"length": "136",
"note": "",
"available": true,
"canUpdate": false
}
]
},
(...) |
Suponhamos que em um cenário tenhamos CompanyId com valor 23 e Code com valor 50. O internalId trafegado seguiria então a seguinte lógica:
Bloco de código | ||
---|---|---|
| ||
"CompanyId": "23"
"Code": "50"
"InternalId": "23|50" |
Toda mensagem de evento (quando for UpSert) deverá conter em seu conteúdo de retorno <ReturnContent> campos de InternalId para armazenar a chave interna do gerador do evento e a chave interna gerada no recebedor do evento. A necessidade disso é para que o recebedor da mensagem de evento e o gerador da mensagem de evento tenham conhecimento da chave interna gerada em cada produto. O fluxo abaixo exemplifica este funcionamento, para o cenário de inclusão de um novo Cliente.
Desta forma, a tag <ReturnContent> da mensagem (ainda utilizando RefundReason_1_000.json como exemplo) seria construída da seguinte forma:
Bloco de código | ||
---|---|---|
| ||
(...)
"ReturnContentType": {
"type": "object",
"properties": {
"ListOfInternalId": {
"type": "array",
"items": {
"$ref": "https://raw.githubusercontent.com/totvs/ttalk-standard-message/master/jsonschema/schemas/types/ListOfInternalId_1_000.json#/definitions/ListOfInternalIdType",
"type": "object"
}
}
}
}
|
O ListOfInternalIdType está definido em um arquivo a parte e está estruturado conforme o exemplo abaixo:
Bloco de código | ||
---|---|---|
| ||
(...)
"definitions": {
"ReturnContentWithModelType": {
"type": "object",
"properties": {
"ListOfInternalId": {
"type": "object",
"$ref": "#/definitions/ListOfInternalIdType"
}
}
},
"ListOfInternalIdType": {
"type": "array",
"items": {
"$ref": "#/definitions/InternalIdType",
"type": "object"
}
},
"InternalIdType": {
"type": "object",
"properties": {
"name": {
"description": "Nome da InternalId, este nome será padronizado entre todas as linhas e corresponderá ao nome da própria transação. Exemplo: City, Item, CustomerVendor. Observação: em outras partes da mensagem, que não sejam a tag ListOfInternalId, a regra pode ser diferente. Para mais informações, consulte http://tdn.totvs.com/pages/viewpage.action?pageId=181142263",
"type": "string"
},
"origin": {
"description": "InternalId da origem",
"type": "string"
},
"destination": {
"description": "InternalId do destino",
"type": "string"
}
}
}
}
(...) |
Como este retorno representa a resposta de uma mensagem enviada, deve-se entender a tag "origin" como a InternalId do produto que enviou a mensagem (a origem), e "destination" como a InternalId do produto que foi o destino da mensagem.
Regra para chave estrangeira
A utilização da InternalId se aplica também para chaves estrangeiras. Porém, neste caso a regra é que para cada Tag que representar uma chave estrangeira também exista uma Tag InternalId correspondente.
Bloco de código | ||
---|---|---|
| ||
Mensagem Warehouse
Code
Description
InternalId
Mensagem Item
Code
InternalId
Description
Status
RegisterDate
WarehouseCode
WarehouseInternalId |
Assim a InternalId de chave estrangeira terá o mesmo nome da tag normal – Warehouse para WarehouseCode – mas usando o termo InternalId em vez de Code.
Em qualquer posição que ocorra (sendo chave primária ou estrangeira), a tag InternalId sempre será uma tag type=”xs:string” sem tamanho definido.
Bloco de código | ||||
---|---|---|---|---|
| ||||
<xs:element name="WarehouseInternalId" type="xs:string">
<xs:annotation>
<xs:documentation>InternalId do WarehouseCode</xs:documentation>
</xs:annotation>
</xs:element> |
Para a chave estrangeira o adapter também deverá dar prioridade em resolver o relacionamento pela InternalId. Ou seja, ao receber uma mensagem de Item (seguindo o exemplo), este deve primeiro consultar no seu ferramental de de/para se existe registro correspondente para o WarehouseInternaId recebido, pois este valor já irá fornecer a chave completa correspondente no produto.
Utilização no Adapter
É sabido que cada mensagem única terá um único adapter/versão nos produtos. Com o objetivo de centralizar a regra para composição da chave da InternalId é interessante que cada adapter seja responsável por receber os valores das chaves e concatena-los para a composição da InternalId. Se isto ficar a cargo de cada programa ou adapter que for utilizar o valor, este poderá correr o risco de ser concatenado de formas diferentes em cada ponto em que seja necessário, o que irá prejudicar completamente o funcionamento do recurso.
Ou seja, o adapter da mensagem Item deverá ter um método que recebe os valores da chave e retorne estes concatenados. Ao mesmo tempo que deverá ter um método que recebe o valor da InternalId e retorna o valor correspondente a uma informação da composição desta. Todos os adapters de mensagens que tenham o Item como chave estrangeira utilizarão esta mesma função.
Desta forma, utilizando sempre este mesmo mecanismo onde for necessário, será garantido que o valor será composto sempre da mesma forma e devolvido sempre da mesma forma também.
Exemplo em pseudocódigo (consulte o manual de cada produto para conhecer as funções reais):
Bloco de código | ||
---|---|---|
| ||
Adapter da mensagem Item
AdapterItem.Get_InternalId(cod_empresa, cod_filial, item)
Retorna Empresa + “|” + Filial + “|” + Código
Uso: AdapterItem.Get_InternalId(50,10,123456) = “50|10|123456”
AdapterItem.Get_InternalId_Value(InternalId, Campo)
Retorna <retorna o valor correspondente a posição de “Campo”>
Uso: AdapterItem.Get_InternalId_Value(“50|10|123456”,”cod_empresa”) == “123456” |
"definitions": { | |
"ReturnContentWithModelType": { | |
"type": "object", | |
"properties": { | |
"ListOfInternalId": { | |
"type": "object", | |
"$ref": "#/definitions/ListOfInternalIdType" | |
} | |
} | |
}, | |
"ListOfInternalIdType": { | |
"type": "array", | |
"items": { | |
"$ref": "#/definitions/InternalIdType", | |
"type": "object" | |
} | |
}, | |
"InternalIdType": { | |
"type": "object", | |
"properties": { | |
"name": { | |
"description": "Nome da InternalId, este nome será padronizado entre todas as linhas e corresponderá ao nome da própria transação. Exemplo: City, Item, CustomerVendor. Observação: em outras partes da mensagem, que não sejam a tag ListOfInternalId, a regra pode ser diferente. Para mais informações, consulte http://tdn.totvs.com/pages/viewpage.action?pageId=181142263", | |
"type": "string" | |
}, | |
"origin": { | |
"description": "InternalId da origem", | |
"type": "string" | |
}, | |
"destination": { | |
"description": "InternalId do destino", | |
"type": "string" | |
} | |
} | |
} | |
} |
Desta forma, na tag <ReturnContent> da mensagem as seguintes tags deverão ser criadas:
Bloco de código | ||
---|---|---|
| ||
<xs:include schemaLocation="../types/ListOfInternalId_1_000.xsd"/>
[...]
<xs:element name="ReturnContent" substitutionGroup="AbstractReturnContent">
<xs:complexType>
<xs:sequence>
<xs:element name="ListOfInternalId" type="ListOfInternalIdType" maxOccurs="1" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
|
O ListOfInternalIdType está definido em um arquivo a parte e está estruturado conforme o exemplo abaixo:
Bloco de código | ||
---|---|---|
| ||
<ReturnContent>
<ListOfInternalId>
<InternalId>
<Name>[NomeDaMensagem]</Name> <!-- Considerando a InternalId da mensagem (PK) -->
<Origin>01|123</Origin>
<Destination>55|11|ABC</Destination>
</InternalId>
</ListOfInternalId>
</ReturnContent> |
Como este retorno representa a resposta de uma mensagem enviada, deve-se entender a tag <Origin> como a InternalId do produto que enviou a mensagem (a origem), e <Destination> como a InternalId do produto que foi o destino da mensagem.
Regra para chave estrangeira
A utilização da InternalId se aplica também para chaves estrangeiras. Porém, neste caso a regra é que para cada Tag que representar uma chave estrangeira também exista uma Tag InternalId correspondente.
Bloco de código | ||
---|---|---|
| ||
Mensagem Warehouse
Code
Description
InternalId
Mensagem Item
Code
InternalId
Description
Status
RegisterDate
WarehouseCode
WarehouseInternalId |
Assim a InternalId de chave estrangeira terá o mesmo nome da tag normal – Warehouse para WarehouseCode – mas usando o termo InternalId em vez de Code.
Em qualquer posição que ocorra (sendo chave primária ou estrangeira), a tag InternalId sempre será uma tag type=”xs:string” sem tamanho definido.
Bloco de código | ||||
---|---|---|---|---|
| ||||
<xs:element name="WarehouseInternalId" type="xs:string">
<xs:annotation>
<xs:documentation>InternalId do WarehouseCode</xs:documentation>
</xs:annotation>
</xs:element> |
Para a chave estrangeira o adapter também deverá dar prioridade em resolver o relacionamento pela InternalId. Ou seja, ao receber uma mensagem de Item (seguindo o exemplo), este deve primeiro consultar no seu ferramental de de/para se existe registro correspondente para o WarehouseInternaId recebido, pois este valor já irá fornecer a chave completa correspondente no produto.
Utilização no Adapter
É sabido que cada mensagem única terá um único adapter/versão nos produtos. Com o objetivo de centralizar a regra para composição da chave da InternalId é interessante que cada adapter seja responsável por receber os valores das chaves e concatena-los para a composição da InternalId. Se isto ficar a cargo de cada programa ou adapter que for utilizar o valor, este poderá correr o risco de ser concatenado de formas diferentes em cada ponto em que seja necessário, o que irá prejudicar completamente o funcionamento do recurso.
Ou seja, o adapter da mensagem Item deverá ter um método que recebe os valores da chave e retorne estes concatenados. Ao mesmo tempo que deverá ter um método que recebe o valor da InternalId e retorna o valor correspondente a uma informação da composição desta. Todos os adapters de mensagens que tenham o Item como chave estrangeira utilizarão esta mesma função.
Desta forma, utilizando sempre este mesmo mecanismo onde for necessário, será garantido que o valor será composto sempre da mesma forma e devolvido sempre da mesma forma também.
Exemplo em pseudocódigo (consulte o manual de cada produto para conhecer as funções reais):
...
title | Exemplo |
---|
...