Manuais
PHC GO Regras de Negócio
 

Introdução

Este artigo pretende ajudar na transição da framework de PHC CS para a framework de addons de PHC GO, nomeadamente criar regras de negócio para novos ecrãs e tabelas de utilizador, assim como regras para a customização de ecrãs e tabelas existentes na aplicação.

Existem vários artigos da série Usa PHC CS com o intuito de facilitar a transição da programação da framework PHC CS em Visual FoxPro para a framework PHC GO em .NET Framework, utilizando Visual Basic.

Recomenda-se a leitura dos artigos pela ordem indicada, de forma a apresentar as diversas tecnologias e técnicas de programação em sequência crescente de complexidade e funcionalidade.



Regras de Negócio

No PHC GO, na opção GO Studio – Toolbox – Regras de Negócio, é possível adicionar código de backend associado a diferentes momentos de interação com uma entidade. Por exemplo, pode definir código para ser executado ao criar, alterar ou eliminar um registo, ou até mesmo para realizar ações baseadas nesse registo sem que os seus dados sejam alterados. Um caso comum é a criação de uma fatura com base num cliente específico.

Os momentos (eventos) disponíveis estão listados no campo Tipo de Código, sendo que esta lista pode variar consoante a tabela selecionada no campo Entidade. A maioria destes eventos corresponde a uma rota, semelhante a um URL, que representa uma possível navegação no browser onde a aplicação está a ser executada.

Isto significa que, para começar a criar um novo registo, é possível, no ecrã correspondente, acionar o botão Novo Registo, localizado no topo da página. Em alternativa, pode também introduzir diretamente no browser a rota correspondente, como se estivesse a escrever um endereço de internet.

Rotas

As rotas começam com o endereço de internet de uma instalação específica do PHC GO, que, no nosso exemplo, será:

  • http://localhost/GO


A seguir deve ser acrescentada a rota desejada, essa a rota começa pela gateway HTML e, se pretendemos navegar para um ecrã, acrescentamos o código MAINFORM, seguido do nome da entidade sem o prefixo VO. No caso de entidades do utilizador, deve ser adicionado o código CUSTOM antes do nome da entidade.

Para abrir um ecrã existem duas rotas, uma para abrir em modo de lista e outra rota para abrir em modo de consulta. Estas duas rotas não estão associadas a eventos específicos e existem apenas como navegações de frontend.

  • Abrir um ecrã em modo de lista
    http://localhost/GO/html/mainform/custom/u0000_album

    * Código PHC CS  Visual FoxPro

    =doread("CL","SCL")
    =dobytimer(" do usrform with 'u_album' ")

    ' Código PHC GO – Typescript

    ' the SDK function <navigateToMainform> only needs the entity name
    ' and can understand whether it is a system entity or a user entity

    ' http://localhost/GO/html/mainform/cl
    sdk.navigateToMainform('CL')

    ' http://localhost/GO/html/mainform/custom/u0000_album
    sdk.navigateToMainform('u0000_album')

  • Abrir um ecrã em modo de consulta
    http://localhost/GO/html/mainform/custom/u0000_album/view;stamp= Z_20240505155423284756456

    ' Código PHC GO – Typescript
    sdk.navigateToMainform('CL',0,'view','Z_20240505155423284756456')

    sdk.navigateToMainform('u0000_album',0,'view','Z_20240505155423284756456')


Nota: No PHC GO, existe o conceito de a aplicação memorizar o estado anterior. Isto significa que, por exemplo, se o utilizador esteve anteriormente no ecrã de clientes a consultar um determinado registo, mais tarde, quando o código da aplicação solicitar uma navegação para o ecrã de clientes no modo de lista, o ecrã abrirá ainda no modo de consulta.

Rotas - Security

A configuração de perfis de acesso para os utilizadores da aplicação consiste, na prática, em negar o acesso a determinadas rotas presentes na lista da aplicação. Por exemplo, se for negado o acesso à funcionalidade de introdução no ecrã de clientes, quando o utilizador tentar abrir esse ecrã, o botão de introdução ficará desativado ou invisível.

Contudo, essa restrição visual não é suficiente para impedir o acesso. É essencial negar explicitamente a rota de introdução para o ecrã de clientes, garantindo que mesmo que o utilizador tente inserir manualmente o endereço no browser, a aplicação continue a negar essa navegação.

Além disso, é fundamental implementar as mesmas restrições do lado do backend. As chamadas aos serviços também utilizam rotas, e é necessário impedir o acesso a essas rotas por parte de aplicações externas que possam usar a rota de introdução de clientes.

Esta abordagem assegura uma camada adicional de segurança e evita acessos indevidos tanto no frontend quanto no backend.

Resumindo, as rotas podem ser ativadas de quatro formas:

  • Escrevendo diretamente um endereço no browser.
  • Através da interação do utilizador com a aplicação frontend.
  • Execução de código em add-ons utilizando o SDK de frontend.
  • Uma aplicação externa efetuar um pedido HTTP ao backend.

Eventos ao nível do ecrã

No PHC CS, existem diversos eventos associados ao trabalho com o ecrã de uma entidade, permitindo implementar lógica personalizada em várias fases da interação do utilizador com o ecrã. No entanto, devido à natureza distinta da aplicação no PHC GO, a correspondência desses eventos pode variar:

  • Alguns eventos do PHC CS têm uma correspondência direta no PHC GO, permitindo implementar funcionalidades equivalentes.
  • Outros eventos são realizados no PHC GO através de eventos com nomes ou comportamentos diferentes, que oferecem resultados semelhantes, mas adaptados à arquitetura e funcionalidades da nova plataforma.
  • Por fim, existem eventos que não estão disponíveis no PHC GO, devido a limitações ou diferenças na abordagem da framework.

Estes fatores devem ser considerados ao planear a transição de personalizações do PHC CS para o PHC GO.

  • Evento Introduzir (Check)
  • Evento Introduzir

    Estes dois eventos são representados num único em PHC GO, o evento: Ao Introduzir, se for retornado uma mensagem de erro a criação de novo registo é cancelada, neste caso será o equivalente ao (Check).

  • Evento Alterar (Check)

    Corresponde ao evento: Ao Alterar, se for retornado uma mensagem de erro o ecrã não entra em modo de alteração, ficando em modo de consulta.
  • Evento Apagar (Check)
  • Evento Apagar

    Estes dois eventos são representados num único em PHC GO, o evento: Ao Apagar, se for retornado uma mensagem de erro o apagar do registo é cancelado, neste caso será o equivalente ao (Check).

  • Evento Apagar (Fim)

    Corresponde ao evento: Após Gravar, no PHC GO o apagar é na realidade uma gra que o registo está marcado como Deleted.

  • Evento Gravar (Check)
  • Evento Gravar

    Estes dois eventos são representados num único em PHC GO, o evento: Ao Gravar, se for retornado uma mensagem de erro a gravação do registo não é efetuada, continuando o mesmo em modo de alteração no frontend, neste caso será o equivalente ao (Check).

  • Evento Gravar (Fim)

    Corresponde ao evento: Após Gravar, este evento ocorre após a gravação com sucesso do registo, quer este esteja inicialmente marcado como Inserted, Updated ou Deleted.

  • Evento Refrescar

    É um evento apenas de frontend, explicado no manual: Usa PHC – Ecrãs e Tabelas no tópico Dados Gerais – Comportamento.

    ' Código PHC GO – Typescrip

    function updateConfig(currentRecord: GenericVO): void {

    sdk.setReadonly('rarity', !sdk.User.esa);

    }

  • Evento Init
  • Evento Ativar
  • Evento Clique
  • Evento Duplo Clique
  • Evento Dimensionar
  • Evento Mover
  • Evento Desativar
  • Evento Cancelar
  • Evento Fim

    Não existe correspondência destes eventos do PHC CS com os eventos disponíveis no PHC GO.


Evento - Ao Introduzir

Este evento é acionado quando o backend recebe um pedido para criar um novo registo numa entidade de sistema ou de utilizador.

http://localhost/GO/html/mainform/custom/u0000_album/new

* Código PHC CS  Visual FoxPro

m.mb_clorigem = "INTRO"
=doread("CL","SCL")

m.mb_u_albumorigem = "INTRO"
=dobytimer(" do usrform with 'u_album' ")

' Código PHC GO – Typescript

sdk.navigateToMainform('CL',0,'new')
sdk.navigateToMainform('u0000_album',0,'new')

' Código PHC GO – VB.NET

Function OnAdding(itemVO As U0000_AlbumVO,
duplicating As Boolean) As List(Of MessageVO)

Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


O evento também ocorre quando é solicitado um novo registo a partir de um já existente na base de dados (Duplicação), nesta situação o parâmetro duplicating tem o valor true.

html/mainform/custom/u0000_album/new;stamp=Z_20240505155423284756456

* Código PHC CS  Visual FoxPro

m.mb_clorigem = "DUPLI"
=doread("CL","SCL")

m.mb_u_albumorigem = "DUPLI"
=dobytimer(" do usrform with 'u_album' ")

' Código PHC GO – Typescript

sdk.navigateToMainform('u0000_album',0,'new','Z_20240505155423284756456')

' Código PHC GO – VB.NET

Function OnAdding(itemVO As U0000_AlbumVO,
duplicating As Boolean) As List(Of MessageVO)

Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


Após a execução do pedido no backend, e em caso de sucesso, é retornado o novo registo que existe apenas em memória, ou seja, ainda não foi gravado na base de dados. Este momento é ideal para atribuir valores por defeito ao registo, caso sejam necessários.

No caso de customização de uma tabela existente na aplicação (ou seja, uma tabela de sistema e não uma tabela criada pelo utilizador), o processo ocorre em duas etapas:

  • Primeiro, é executado o evento de sistema correspondente (Introduzir ou Duplicar).
  • Se não forem geradas mensagens de erro durante a execução do evento de sistema, o >evento do utilizador (este evento) é então acionado.

Neste evento não é necessário criar o registo, ele é fornecido no parâmetro itemVO. O registo já está preparado para introdução (Operation = Inserted), com o valor único (STAMP) já preenchido, neste caso no campo u0000_albumstamp.

Evento - Ao Introduzir com Referência

http://localhost/GO/html/mainform/ft/99/new;sourceEntityName= u0000_album;sourceStamp=Z_20240505155423284756456

Este evento é acionado quando o backend recebe um pedido para criar um novo registo numa entidade de sistema ou de utilizador, tendo como origem outro registo de uma entidade diferente, já existente na base de dados.

' Código PHC GO – Typescript

sdk.createRecordFromReference('u0000_album','Z_20240505155423284756456','Ft',99,[{line1:
'esta é a primeira linha'}, {Line2: 'esta é a segunda linha'}])


Quando este evento é acionado, é possível enviar informações adicionais. Neste caso, enviamos um array com duas posições, em que cada posição contém um objeto com uma propriedade e o respetivo valor.

Estas informações adicionais ficam disponíveis no parâmetro payload, na propriedade com o mesmo nome. Para aceder facilmente a este objeto, pode ser utilizado o método utilitário GetValue(Of T).

' Código PHC GO – VB.NET

Function OnFromReference(itemVO As FtVO,
oriItemVO As U0000_AlbumVO,
payload As InstanceFromReference) As List(Of MessageVO)

Dim listMsg As New List(Of MessageVO)

' itemVO.ndoc = 99 (serie)
' oriItemVO.u0000_albumstamp = 'Z_20240505155423284756456'

' payload.GetValue(Of String)("origin") = u0000_album
' payload.GetValue(Of String)("originstamp") = Z_20240505155423284756456
' payload.GetValue(Of Decimal)("docid") = 99
' payload.GetValue(Of String)("destination") = FT
'
' Dim myPayload as Object = payload.GetValue(Of Object)("payload")
' myPayload.line1 = esta é a primeira linha
' myPayload.line2 = esta é a segunda linha

Return listMsg
End Function


Estrutura da classe InstanceFromReference.

' Código PHC GO – VB.NET

Class InstanceFromReference
Property origin As String
Property originstamp As String
Property docid As Decimal
Property destination As String
Property payload As Object

Function GetValue(Of T)(key As String) As T
End Class


Quando este evento ocorre, o evento Ao Introduzir é executado primeiro, seguido deste evento. Assim, para o parâmetro ItemVO, já foram aplicadas todas as operações descritas anteriormente no evento ao introduzir.

Uma particularidade é que, quando a origin e destination do parâmetro Payload são os mesmos, o evento Ao Introduzir, é executado no modo de duplicação.

Na chamada, no código de frontend, indicamos apenas o nome da entidade de origem e o respetivo stamp único. Neste ponto, a aplicação fornece, no parâmetro oriItemVO, o registo correspondente, já retornado da base de dados.

Com origem no ecrã de Álbuns criar um novo Artigo:


' Código PHC GO  Typescript

function runAction(currentRecord: GenericVO, currentSeries?: GenericVO): void {
sdk.createRecordFromReference("u0000_album",currentRecord.u0000_albumstamp,"st",0)
}

function isActionAvailable(currentRecord: GenericVO, currentSeries?: GenericVO): boolean {
return (currentRecord.stref === "")
}

' Código PHC GO – VB.NET

Function OnFromReference(itemVO As STVO, oriItemVO As U0000_ALBUMVO,
payload As InstanceFromReference) As List(Of MessageVO)

Dim listMsg As List(Of MessageVO) = New List(Of MessageVO)

itemVO.u0000_st_album.albumstamp = oriItemVO.u0000_albumstamp
itemVO.design = String.Format("Álbum: {0} ({1})",oriItemVO.nome,oriItemVO.singername)

Return listMsg
End Function


Com origem no ecrã de Álbuns criar uma nova Fatura:


' Código PHC GO  Typescript

function runAction(currentRecord: GenericVO, currentSeries?: GenericVO): void {
const ftserie = sdk.readParameter("u0000album_ft_serie");

if (ftserie !== null && ftserie !== "")
{
sdk.createRecordFromReference("u0000_album",
currentRecord.u0000_albumstamp,
"ft", Number(ftserie))
}
}

function isActionAvailable(currentRecord: GenericVO, currentSeries?: GenericVO): boolean {
const ftserie = sdk.readParameter("u0000album_ft_serie");
return (currentRecord.stref !== "" && ftserie !== null && ftserie !== "")
}

' Código PHC GO – VB.NET

Public Function OnFromReference(itemVO As FTVO, oriItemVO As U0000_ALBUMVO,
payload As InstanceFromReference) As List(Of MessageVO)

Dim listMsg As List(Of MessageVO) = New List(Of MessageVO)

Dim itemFt as FtVO = DirectCast(itemVO,FtVO)

Dim itemFi as FiVO = itemFt.AddChild(Of FiVO)()

itemFi.ref = oriItemVO.stref

ActEntity(itemFt)

Return listMsg
End Function


Evento - Ao Alterar

http://localhost/GO/html/mainform/custom/u0000_album/edit;stamp=Z_2024050515542328 4756456

Este evento é acionado quando o backend recebe um pedido para entrar em modo de alteração de um registo, numa entidade de sistema ou de utilizador.

' Código PHC GO – Typescript

sdk.navigateToMainform('u0000_album',0,'edit','Z_20240505155423284756456')

' Código PHC GO – VB.NET

Function OnEditing(itemVO As U0000_AlbumVO,
runWarningRules As Boolean) As List(Of MessageVO)

Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


Evento - Ao Apagar

http://localhost/GO/html/mainform/custom/u0000_album/delete;stamp=Z_20240505155423 284756456

Este evento é acionado quando o backend recebe um pedido para eliminar um registo de uma entidade de sistema ou de utilizador.

Caso a eliminação seja permitida, o registo é imediatamente excluído da base de dados, ou seja, não é necessário acionar o evento Ao Gravar.

A tarefa de eliminar o registo da base de dados, é realizada automaticamente neste evento. No entanto, se a eliminação for bem-sucedida, o evento Após Gravar é executado.

' Código PHC GO – VB.NET

Public Function OnDelete(itemVO As U0000_AlbumVO,
runWarningRules As Boolean) As List(Of MessageVO)

Dim listMsg As List(Of MessageVO) = New List(Of MessageVO)

If itemVO.rarity
If not SDK.User.getCurrentInfo.esa
listMsg.Add(new MsgError("Only administrators have access to delete rare albums."))
End If
End If

Return listMsg
End Function

Public Function OnDelete(itemVO As U0000_SINGERVO,
runWarningRules As Boolean) As List(Of MessageVO)

Dim listMsg As List(Of MessageVO) = New List(Of MessageVO)

If SDK.Query.ExistRecord("u0000_album",
New FilterItem("singerstamp='"+itemVO.singerstamp+"'"))

listMsg.Add(New MsgError("Cannot delete because exists in albums."))
End If

Return listMsg
End Function


Evento - Ao Gravar

Este evento é acionado quando o backend recebe um pedido para gravar um registo de uma entidade de sistema ou de utilizador na base de dados.

Importa referir que esta rota não está disponível no frontend. O evento ocorre automaticamente quando, através de código, é chamado o serviço de gravação no backend ou, de forma interativa, quando é acionada a ação do botão de gravação no ecrã.

' Código PHC GO – VB.NET

Function OnSave(itemVO As U0000_AlbumVO,
runWarningRules As Boolean) As List(Of MessageVO)

Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


Evento - Ao executar Trigger na gravação

Este evento é acionado automaticamente pela aplicação após a execução bem-sucedida das regras de negócio associadas ao evento Ao Gravar.

Posteriormente, o evento é executado em memória, ou seja, os triggers da aplicação PHC GO são processados em memória e não diretamente na base de dados. Apenas após a execução bem-sucedida deste processo é iniciada a fase de gravação na base de dados.
Importa referir que esta rota não está disponível no frontend. O evento ocorre automaticamente quando, através de código, é chamado o serviço de gravação no backend ou, de forma interativa, quando é acionada a ação do botão de gravação no ecrã.

' Código PHC GO – VB.NET

Function OnTriggers(itemVO As U0000_AlbumVO) As List(Of MessageVO)
Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


Evento - Após Gravar

Este evento é acionado automaticamente pela aplicação após a execução bem-sucedida das regras de negócio associadas ao evento Ao Gravar, e após execução bem sucedida do evento: Ao executar Trigger na gravação.

Importa referir que esta rota não está disponível no frontend. O evento ocorre automaticamente quando, através de código, é chamado o serviço de gravação no backend ou, de forma interativa, quando é acionada a ação do botão de gravação no ecrã.

' Código PHC GO – VB.NET

Function OnAfterSave(itemVO As U0000_AlbumVO) As List(Of MessageVO)
Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


Na gravação de um novo artigo, verificamos se essa ação teve origem na criação por referência da entidade de álbuns, para atualizar os campos desnormalizados na entidade álbum referentes ao artigo criado.

' Código PHC GO – VB.NET

Function OnAfterSave(itemVO As STVO) As List(Of MessageVO)
Dim listMsg As List(Of MessageVO) = New List(Of MessageVO)

Dim itemSt as FrameworkStVO = DirectCast(itemVO, FrameworkStVO)

' create the album controller
Dim albumBiz as SDKBiz = SDK.Business.CreateBiz("u0000_album")
If albumBiz Is Nothing

' After recording, the error messages can no longer cancel
' the previous recording moment, which is why we chose
' to save this situation in the error log.
SDK.Debug.LogError("The album business is not available.")

Return listMsg
End If

If itemSt.Operation = OperationEnum.Inserted

' we will only update the denormalized fields
' in the album if one was chosen for the reference
If Not itemSt.u0000_st_album.albumstamp.isVoid()

' get the album
Dim albumItem as u0000_albumVO = SDK.Query.GetEntityByStamp(Of
u0000_albumVO)(itemSt.u0000_st_album.albumstamp)

' update
If albumItem IsNot Nothing
albumItem.stref = itemSt.ref
albumItem.stdesign = itemSt.ref + " - " + itemSt.design

' save
If albumBiz.Save(albumItem).HasErrors
SDK.Debug.LogError("Error saving the album.")
End If
End If
End If
End If

Return listMsg
End Function


Evento - A Pedido

Este evento é acionado quando o backend recebe um pedido para executar código a partir de um ID único associado ao código.

Esta rota não está disponível no frontend. Para executar o código pretendido, é necessário chamar o serviço correspondente no backend.

  • SDK de frontend: sdk.runBusinessRuleOnDemand
  • SDKBiz de backend: SDKBiz.RunCode

' Código PHC GO – VB.NET

Function OnRunCode(itemVO As U0000_AlbumVO,
payload As Object,
Optional runWarningRules As Boolean) As List(Of MessageVO)

Dim listMsg As New List(Of MessageVO)

Return listMsg
End Function


Eventos ao nível do componente

Além dos eventos ao nível do ecrã, que são desencadeados por ações gerais do utilizador (como introduzir, alterar ou apagar), existem também eventos ao nível dos componentes. Estes eventos são ativados quando o utilizador interage diretamente com um componente específico incluído no desenho do ecrã de uma entidade.

No PHC CS, existem diversos eventos associados ao trabalho com componentes, permitindo implementar lógica personalizada em várias fases da interação do utilizador com o componente. No entanto, devido à natureza distinta da aplicação no PHC GO, a correspondência desses eventos pode variar:

  • Alguns eventos do PHC CS têm uma correspondência direta no PHC GO, permitindo implementar funcionalidades equivalentes.
  • Outros eventos são realizados no PHC GO através de eventos com nomes ou comportamentos diferentes, que oferecem resultados semelhantes, mas adaptados à arquitetura e funcionalidades da nova plataforma
  • Por fim, existem eventos que não estão disponíveis no PHC GO, devido a limitações ou diferenças na abordagem da framework.

Estes fatores devem ser considerados ao planear a transição de personalizações do PHC CS para o PHC GO.

  • Evento Tecla Pressionada

    Corresponde ao evento: Ao Sincronizar, existe uma particularidade em relação a este evento: Tecla Pressionada, apenas existe para componentes que não sejam colunas de grelha

  • • Evento Após Atualizar
  • Evento Após não Atualizado

    Corresponde ao evento: Ao Sincronizar, existe uma particularidade em relação a este evento: Após Atualizar, apenas existe para componentes que sejam colunas de grelha.

    Em relação ao evento: Após não Atualizado, não existe correspondência com eventos do PHC GO.

  • Evento Refrescar

    No PHC GO, o evento refrescar existe apenas ao nível do ecrã, e pode ser usado para colocar o código que em PHC CS se usava no refrescar do componente. É um evento apenas de frontend, explicado no manual: Usa PHC – Ecrãs e Tabelas no tópico Dados Gerais – Comportamento.

    ' Código PHC GO – Typescript

    function updateConfig(currentRecord: GenericVO): void {

    sdk.setReadonly('rarity', !sdk.User.esa);

    }


  • Evento Init
  • Evento ao Entrar
  • Evento ao Sair
  • Evento MouseEnter
  • Evento MouseMove
  • Evento MouseWheel
  • Evento MouseLeave
  • Evento Clique
  • Evento Clique Direito
  • Evento Duplo Clique

    Não existe correspondência destes eventos do PHC CS com os eventos disponíveis no PHC GO.


Para o componente Grelha do PHC CS existe mais alguns eventos específicos, que são:

  • Evento Apagar (Check)
  • Evento Apagar

    Estes dois eventos são representados num único em PHC GO, o evento: Ao Apagar na Grelha,

  • Evento Introduzir (Check)
  • Evento Introduzir

    Estes dois eventos são representados num único em PHC GO, o evento: Ao Sincronizar,

  • Evento Antes mudar Linha/Coluna
  • Evento Depois mudar Linha/Coluna

    Não existe correspondência destes eventos do PHC CS com os eventos disponíveis no PHC GO.


Evento - Ao Sincronizar

No PHC GO quando existe uma alteração num componente presente no ecrã, ou numa grelha de edição, o evento executado no backend é uma sincronização entre os valores em cache no backend e os valores que estão a ser modificados no frontend.

' Código PHC GO – VB.NET

Function OnSync(masterVO As U0000_AlbumVO,
changedItems As List(Of EntityChangeOperation)) As List(Of MessageVO)


No parâmetro masterVO é sempre recebido a entidade principal do ecrã, independente se a alteração foi efetuada num componente do ecrã ou num componente de uma grelha também presente nesse ecrã.

Este parâmetro é fornecido quando queremos rapidamente consultar algo da entidade principal do ecrã, embora se consiga obter a mesma informação através da entidade que foi alvo de modificação no frontend, essa entidade é obtida através do parâmetro changedItems.

O parâmetro changedItems é uma lista de alterações efetuadas no frontend, tendo a seguinte estrutura:

' Código PHC GO – VB.NET

Class EntityChangeOperation

#Region "Properties"

''' <summary>
''' Contains the type of the changed entity, e.g.: FrameworkClVO
''' </summary>
ReadOnly Property entityType() As Type

''' <summary>
''' Contains the base type of the changed entity, e.g.: ClVO
''' </summary>
ReadOnly Property baseType() As Type

''' <summary>
''' Indicates whether it is a user entity.
''' </summary>
ReadOnly Property isUserType() As Boolean

''' <summary>
''' Record changed.
''' </summary>
Property entity() As GenericVO

''' <summary>
''' Changed field name.
''' </summary>
Property field() As String = ""

''' <summary>
''' Original value of the field.
''' </summary>
Property oldValue() As Object

''' <summary>
''' Current value of the field.
''' </summary>
Property newValue() As Object

#End Region

#Region "Methods"

''' <summary>
''' Returns the original value of the field in typed format.
''' </summary>
Function GetOldValue(Of T)() As T

#End Region

End Class


Este evento é executado quando a alteração é efetuada num componente disponível no ecrã (entidade principal) e também quando a alteração é efetuada num componente de uma grelha de edição presente no ecrã (entidade de coleção).

Deste modo, no caso de entidade principal conter coleções, devemos neste código utilizar uma estrutura para identificar em primeiro lugar qual a entidade que foi alvo de alteração.

' Código PHC GO – VB.NET

Function OnSync(masterVO As U4902_AlbumVO,
changedItems As List(Of EntityChangeOperation)) As List(Of MessageVO)

Select Case changedItems.First.baseType
Case GetType(u4902_AlbumVO)

Case GetType(u4902_MusicaVO)
End Select

End Function


Se ocorrer modificações em duas entidades no frontend, e for chamado o evento do backend com todas as alterações efetuadas, a aplicação encarrega-se, neste caso, de correr esta função duas vezes, assim temos a garantia que todos os registos da lista changedItems são do mesmo tipo de entidade.

Podemos assim aplicar: First á lista recebida, tendo a garantia que o tipo do primeiro item é igual a todos os outros que possam existir na lista. Ficando ao critério do programador, se coloca a lógica deste evento dentro dos Case respetivos, ou se aqui, por questões de organização do código, coloca apenas chamadas a funções criadas em bibliotecas de servidor, explicadas mais à frente neste manual no Tópico: Bibliotecas de Servidor.

' Código PHC GO – VB.NET

Function OnSync(masterVO As U0000_AlbumVO,
changedItems As List(Of EntityChangeOperation)) As List(Of MessageVO)

' result
Dim listMsg As New List(Of MessageVO)

' change item
Dim changedItem As EntityChangeOperation = Nothing

' what was changed?
Select Case changedItems.First.baseType

' was it the main entity?
Case GetType(u0000_AlbumVO)
' current item
Dim myAlbum As u0000_AlbumVO = Nothing

' verify that the name field was changed in this interaction
changedItem = changedItems.GetChangedItemByField(myAlbum, "nome")

' if the changedItem object is different from Nothing
' indicates that there was a change to the name field
' myAlbum become the the record being changed in the frontend
If changedItem IsNot Nothing Then
If myAlbum.nome.isVoid()
listMsg.add(new MsgError("The album name must be filled."))
End If
End If

' was it the music collection?
Case GetType(u0000_MusicaVO)

' current item
Dim myMusic As u0000_MusicVO = Nothing

' verify that the name field was changed in this interaction
changedItem = changedItems.GetChangedItemByField(myMusic, "nome")
If changedItem IsNot Nothing Then
If myMusic.nome.isVoid()
listMsg.add(new MsgError("The name of the music must be filled."))
End If
End If

End Select

Return listMsg
End Function


Existe extensões que facilitam o trabalho das listas de EntityChangeOperation:

' Código PHC GO – VB.NET

Function GetChangedItemByField(field As String) As EntityChangeOperation

Function GetChangedItemByField(Of T)(ByRef entity As T, field As String) As
EntityChangeOperation

Function GetChangedItemByFields(Of T)(ByRef entity As T, ParamArray fields() As String) As
EntityChangeOperation

Function RemoveChanged(field As String) As List(Of EntityChangeOperation)


Existe situações em que após termos verificado que determinado campo for alterado, recorrendo à extensão GetChangedItemByField, é necessário remover da lista a alteração que possa existir a outro campo específico, recorrendo á extensão: RemoveChanged.

Na sincronização da entidade de faturação, existe dois blocos de código, um para a alteração do número de cliente, e outro para a alteração do nome do cliente, nesses blocos, após a busca do cliente pelo valor alterado, ambos chamam o mesmo código de atualização da fatura com o novo cliente.

Acontece que no frontend da aplicação do PHC GO, quando se altera o número de cliente na fatura, ainda no frontend, é também alterado o nome do cliente, e após estas duas alterações á chamado o evento do backend: Ao Sincronizar.

Assim, no backend, após a execução do bloco de código da alteração do número do cliente, limpamos a alteração do nome de cliente, porque nesse momento o novo cliente já se encontra atualizado na fatura, com os IVAs e descontos definidos na sua ficha, não existindo por isso, necessidade de correr o bloco de alteração do nome.

' Código PHC GO – VB.NET

' no / estab
changedItem = changedItems.GetChangedItemByFields(itemVO, "no", "estab")
If changedItem IsNot Nothing Then

...

changedItems.RemoveChanged("nome")
End If

' nome
changedItem = changedItems.GetChangedItemByField(itemVO, "nome")
If changedItem IsNot Nothing Then

...

End If


No PHC GO quando se apaga um registo numa grelha de coleção da entidade principal do ecrã, é executado o evento: Ao Apagar na Grelha, mas quando se cria um registo nessa mesma grelha é este evento: Ao Sincronizar que é executado. Existe uma técnica de distinguir uma alteração de uma criação de registo.

Essa técnica consiste em perguntar á lista de alterações, se o campo que identifica unicamente o registo na base de dados (stamp) foi alterado, pois só no momento de criação, esse campo devolve true para alterações.

Após isso, se for alterado outro campo na entidade da coleção, o nome da música por exemplo, na segunda chamada ao evento, o campo de stamp vai retornar false para alterações.

' Código PHC GO – VB.NET

Function OnSync(masterVO As U0000_AlbumVO,
changedItems As List(Of EntityChangeOperation)) As List(Of MessageVO)

' result
Dim listMsg As New List(Of MessageVO)

' change item
Dim changedItem As EntityChangeOperation = Nothing

' what was changed?
Select Case changedItems.First.baseType

' was it the music collection?
Case GetType(u0000_MusicaVO)

' current item
Dim myMusic As u0000_MusicVO = Nothing

' was a new line created?
changedItem = changedItems.GetChangedItemByField(myMusic, "u0000_musicstamp")
If changedItem IsNot Nothing Then

' option 1
listMsg.add(new MsgInfo("Congratulations, you are adding a new song to the
album: " + myMusic.ParentVO.nome))

' option 2
listMsg.add(new MsgInfo("Congratulations, you are adding a new song to the
album: " + masterVO.nome))

End If

End Select

Return listMsg
End Function


Neste exemplo podemos observar outro pormenor, o uso de ParentVO ou masterVO, as duas técnicas resultam na mesma ação, aceder á entidade principal do ecrã, há situações em que pode ser preferível usar masterVO.

Por exemplo, no caso da coleção de linhas de uma fatura, cada linha tem outra coleção de impostos. Supondo que o estávamos a trabalhar com a entidade de impostos, fica mias fácil escrever masterVO.nome do que impostosVO.ParentVO.ParentVO.nome.

Evento - Ao Apagar na Grelha

No PHC GO quando se apaga um registo numa grelha de coleção da entidade principal do ecrã, o frontend chama automaticamente o evento Ao Sincronizar, enviando a entidade principal, com todas as suas coleções, contendo todos os registos menos os que foram removidos.

Desta forma, permite ao backend identificar os registos apagados e executar este evento apenas para esses registos removidos, caso nessa chamada também exista alterações a registos ainda existentes nas coleções, também é executado o evento Ao Sincronizar para os registos correspondentes.

span style="color: #75715e">' Código PHC GO – VB.NET

Function OnSyncDelete(masterVO As U0000_AlbumVO,
changedItems As List(Of EntityChangeOperation)) As List(Of MessageVO)


Este evento é executado sempre que ocorre a eliminação de registos em qualquer tipo de coleção. Durante a sua execução, o parâmetro changedItems contém todos os registos eliminados da respetiva coleção. Embora o frontend não envie diretamente estes registos, eles são recuperados da cache existente no backend.

Como os registos foram eliminados, e não modificados, não há necessidade de utilizar as funções de extensão anteriormente descritas. A única ação requerida é percorrer a lista de registos e aceder aos seus valores para realizar a operação desejada.

Exemplo de utilização:

Se a operação pretendida for uma validação que determine que o registo não pode ser eliminado, deve-se alterar a propriedade Operation para None. Esta ação impede que o registo seja removido, mantendo-o na cache do backend e devolvendo-o ao frontend.

Caso seja permitido eliminar o registo, não é necessário efetuar qualquer modificação, uma vez que este já está marcado com a propriedade Operation = Deleted.

span style="color: #75715e">' Código PHC GO – VB.NET

Function OnSyncDelete(masterVO As U0000_AlbumVO,
changedItems As List(Of EntityChangeOperation)) As List(Of MessageVO)

' result
Dim listMsg As New List(Of MessageVO)

' what type was changed?
Select Case changedItems.First.baseType

' was it the music collection?
Case GetType(u0000_MusicaVO)

' deleted item - option 1
For Each musicItem in (From pk In changedItems Select DirectCast(pk.entity, FiVO))

' option 1
If musicItem.nome.EqualsWithIgnoreCase() = "Not Deleted"
listMsg.add(new MsgError("You can't delete this song"))
End If

' option 2
If musicItem.nome.ToLower() = "not deleted"
listMsg.add(new MsgError("You can't delete this song"))
End If

' option 3
If musicItem.nome.ToUpper() = "NOT DELETED"
listMsg.add(new MsgError("You can't delete this song"))
End If

' option 4
Select Case musicItem.nome.ToUpper()
Case "NOT DELETED"
listMsg.add(new MsgError("You can't delete this song"))

Case Else
listMsg.add(new MsgInfo("you deleted the song: " + musicItem.nome))
End Select
Next

' deleted item - option 2
For Each changeItem in changedItems
Dim musicItem as u0000_MusicaVO = DirectCast(changeItem.entity, FiVO)



Next

End Select

Return listMsg
End Function


Regras do Utilizador

No PHC CS esta funcionalidade está disponível em: Supervisor – Framework PHC – Regras do Utilizador, que permite programar uma regra para correr ao gravar ou ao apagar um registo numa determinada entidade.

É semelhante aos eventos, nos ecrãs de PHC CS, Evento Gravar (Check), Evento Gravar, Evento Apagar (Check) e Evento Apagar, na aplicação PHC GO como já referenciado estes momentos são mapeados para as regras de negócio do tipo Ao Gravar e Ao Apagar.

Portanto o código programado nesta opção do PHC CS deve ser migrado para os respetivos eventos do PHC GO.

Bibliotecas de Servidor

No PHC CS, existe uma funcionalidade acessível através de: Supervisor - Framework PHC - Funções de Utilizador. Esta funcionalidade permite criar e gerir diversas funções personalizadas, constituindo uma biblioteca de funções utilitárias que podem ser reutilizadas na programação das restantes funcionalidades da framework.

No PHC GO, a funcionalidade equivalente encontra-se acessível através de: GO Studio - Toolbox - Bibliotecas de Servidor. Esta ferramenta permite não só criar funções utilitárias, como também organizá-las em classes que agrupam funcionalidades específicas.

Principais características:

  • Organização em Classes: As funções podem ser agrupadas em classes para facilitar a organização e a reutilização de código, promovendo uma estrutura mais limpa e eficiente.
  • Namespace exclusivo: Todas as classes e funções residem no espaço de utilizador u0000_Space, sendo que cada desenvolvedor de Add-Ons tem o seu próprio namespace exclusivo.
  • Este isolamento elimina colisões de nomes entre funções ou classes criadas por diferentes desenvolvedores, bem como com as funções nativas da aplicação PHC GO.
  • Reutilização segura: O namespace individual garante que cada conjunto de funcionalidades personalizadas pode ser implementado sem interferir com outros AddOns ou com a aplicação base.


As bibliotecas de utilizador são especialmente úteis para:

  • Centralizar lógica comum que pode ser invocada em diferentes contextos.
  • Reduzir redundância no código, promovendo uma manutenção mais simples e eficiente
  • Implementar cálculos, validações ou outras operações específicas de forma consistente em toda a aplicação.


Esta biblioteca torna-se uma ferramenta poderosa para personalizar e estender as funcionalidades da framework PHC GO, adaptando-a às necessidades específicas de cada cliente ou projeto.

Eventos do Utilizador

No PHC CS esta funcionalidade está disponível em: Supervisor – Framework PHC – Eventos do Utilizador, que permite programar um evento para um determinado ecrã.

Na aplicação PHC GO, esta funcionalidade é suportada nas: Bibliotecas de Servidor, onde a classe criada deve herdar da classe nativa da aplicação: EntityEvents.

Esta classe suporta os eventos do PHC CS: Introduzir, Alterar, Apagar e Consultar, e disponibiliza outros existentes na aplicação PHC GO.

No caso do PHC GO, o código aqui programado é totalmente de backend e, consoante o evento escutado, pode funcionar:

  • Sincronamente: Neste modo, é possível cancelar a ação original através de mensagens de erro.
  • Assincronamente: O evento corre num thread separado, sem impactar a performance da operação.


Quando o evento é executado de forma assíncrona, não existe qualquer meio de retornar feedback para o utilizador através de mensagens. Por esse motivo, também não é possível cancelar a ação original.

Esta classe escuta eventos com origem no frontend ou no backend. Por exemplo, através de código de backend, numa outra funcionalidade da framework, pode-se criar um registo numa entidade. Como a classe EntityEvents está permanentemente a escutar eventos que ocorrem no backend, o código desta classe será executado também nesse contexto.

Outra característica da classe EntityEvents é a sua capacidade de escutar eventos de todas as entidades existentes na aplicação. Em cada função, é possível identificar o tipo de entidade que acionou o evento e atuar de forma adequada, conforme a lógica necessária.

Public Class EntityEvents
Inherits Pnp

#Region "Business"

Public Overridable Sub OnAdding(itemVO As BusinessVO,
duplicating As Boolean,
lstMsg As List(Of MessageVO))

End Sub
Public Overridable Sub OnDuplicating(itemVO As BusinessVO,
lstMsg As List(Of MessageVO))

End Sub
Public Overridable Sub OnFromReference(itemVO As BusinessVO,
oriItemVO As Object,
valuesItem As InstanceFromReference,
lstMsg As List(Of MessageVO))

End Sub
Public Overridable Sub OnEditing(itemVO As BusinessVO,
runWarningRules As Boolean,
lstMsg As List(Of MessageVO))

End Sub
Public Overridable Sub OnDelete(itemVO As BusinessVO,
runWarningRules As Boolean,
lstMsg As List(Of MessageVO))

End Sub
Public Overridable Sub OnSave(itemVO As BusinessVO,
runWarningRules As Boolean,
lstMsg As List(Of MessageVO))

End Sub
Public Overridable Sub OnAfterSave(itemVO As BusinessVO,
triggersVOs As List(Of BusinessVO))

End Sub
Public Overridable Sub OnRequery(itemVO As BusinessVO)

End Sub
Public Overridable Sub OnAction(entityType As Type,
actionItem As ActionVO,
filter As ActionFilterVO,
recordItem As BusinessVO)

End Sub

#End Region

#Region "SlVO"

Public Overridable Sub OnSlUpdate(slMovements As List(Of SlVO))
End Sub

#End Region

End Class


A classe monitoriza os eventos mencionados anteriormente, funcionando da seguinte forma: no arranque do backend da aplicação, é construída uma lista interna com todas as classes que herdam de EntityEvents (Inherits EntityEvents), sejam elas classes nativas do PHC GO ou criadas por Add-Ons instalados.

Por exemplo, quando ocorre o evento: Ao Introduzir, a aplicação percorre essa lista, inicializa cada uma das classes, e verifica se estas contêm o método correspondente ao evento em questão, devidamente marcado como: Overrides. Caso o método exista, o respetivo código é executado. Após a execução, a instância da classe é enviada para o garbage collector, garantindo a sua destruição e libertação de recursos da aplicação.

Deste modo, o programador apenas precisa de criar a classe e implementar o Overrides apenas nos eventos desejados. A partir daí, é a própria aplicação PHC GO que se encarrega de monitorizar os eventos base, instanciar as classes, executar o código e finalizar o processo automaticamente.

Esta classe utiliza a técnica de plug and play (Inherits Pnp), permitindo ao programador centralizar o seu código de inicialização e finalização. Para isso, pode usar o método Pluging para executar o código de inicialização e o método UnPluging para o código de finalização. Desta forma, este tipo de lógica fica concentrado num único local, evitando repetições no início e no final de cada método marcado como Overrides.

Public Class Pnp

#Region "Methods"

Public Overridable Function Pluging() As Boolean
Return True
End Function

Public Overridable Sub UnPluging()
End Sub

#End Region

End Class


Por exemplo, podemos verificar se a instalação onde o Add-On está a ser executado, está numa edição superior ou igual a: Advanced, utilizando a função do SDK de backend para esse fim. Este código é fornecido a título de exemplo, já que na construção dos Add-Ons se pode configurar estes requisitos mínimos para que o Add-On possa ser instalado numa aplicação PHC GO do cliente final.

Public Class MyEntityEvents

Inherits EntityEvents

#Region "Pnp"

Public Overrides Function Pluging() As Boolean
Return SDK.System.IsEditionAvailable(Gamas.Advanced)
End Function

#End Region

End Class


EntityEvents - Ao Introduzir


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs when the process of creating a record of a new entity is started,
''' this moment also occurs when duplicating an existing record in the database,
''' since duplication is understood as a creation,
''' with the difference that certain values of the registration
''' are already filled out.
''' </summary>
'''
''' <para name="itemVO">
''' It is the new instance to be created in the database.
''' </para>
'''
''' <para name="duplicating">
''' Indicates whether we are in the presence of a duplication or not.
''' </para>
'''
''' <para name="lstMsg">
''' If we want to cancel the operation in progress, we must add an error
''' message to this parameter,
''' if instead of the type of error, we add an information message for example,
''' the operation will continue to execute and the message will be shown
''' in the frontend to the user who triggered it the operation
''' </para>
'''
''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnAdding(itemVO As BusinessVO,
duplicating As Boolean,
lstMsg As List(Of MessageVO))

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then
End If
End Sub
End Class


EntityEvents – Ao Introduzir com Referência


Public Class MyEntityEvents
Inherits EntityEvents

''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnFromReference(itemVO As BusinessVO,
oriItemVO As Object,
valuesItem As InstanceFromReference,
lstMsg As List(Of MessageVO))

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then

End If
End Sub
End Class


EntityEvents – Ao Duplicar


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs when the process of duplicate a record from an existing entity is started.
''' </summary>
'''
''' <para name="itemVO">
''' It is the new instance to be created in the database,
''' with the values filled in from the record already existing in the database
''' from which the duplication operation was started
''' </para>
'''
''' <para name="lstMsg">
''' If we want to cancel the operation in progress, we must add an error
''' message to this parameter,
''' if instead of the type of error, we add an information message for example,
''' the operation will continue to execute and the message will be shown
''' in the frontend to the user who triggered it the operation
''' </para>
'''
''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnDuplicating(itemVO As BusinessVO,
lstMsg As List(Of MessageVO))

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then

End If
End Sub
End Class


EntityEvents – Ao Alterar


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs when the process of change a record from an existing entity is started.
''' </summary>
'''
''' <para name="itemVO">
''' It is the record of the entity in the database from which the
''' change operation was started.
''' </para>
'''
''' <para name="runWarningRules">
''' Indicates whether we want to run warning type rules, which are
''' shown in the frontend as a yes or no question.
''' </para>
'''
''' <para name="lstMsg">
''' If we want to cancel the operation in progress, we must add an error
''' message to this parameter,
''' if instead of the type of error, we add an information message for example,
''' the operation will continue to execute and the message will be shown
''' in the frontend to the user who triggered it the operation
''' </para>
'''
''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnEditing(itemVO As BusinessVO,
runWarningRules As Boolean,
lstMsg As List(Of MessageVO))

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then

End If
End Sub
End Class


EntityEvents – Ao Apagar


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs when the process of delete a record from an existing entity is started.
''' </summary>
'''
''' <para name="itemVO">
''' It is the record of the entity in the database from which the
''' delete operation was started.
''' </para>
'''
''' <para name="runWarningRules">
''' Indicates whether we want to run warning type rules, which are shown
''' in the frontend as a yes or no question.
''' </para>
'''
''' <para name="lstMsg">
''' If we want to cancel the operation in progress, we must add an error
''' message to this parameter,
''' if instead of the type of error, we add an information message for example,
''' the operation will continue to execute and the message will be shown
''' in the frontend to the user who triggered it the operation
''' </para>
'''
''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnDelete(itemVO As BusinessVO,
runWarningRules As Boolean,
lstMsg As List(Of MessageVO))

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then

End If
End Sub
End Class


EntityEvents – Ao Gravar


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs when the process of save a record from an entity is started,
''' the result of this operation may be the creation of a new entity in the database
''' or the updating of some values of an entity that already exists in the database.
''' </summary>

''' <para name="itemVO">
''' It is the record of the entity in the database from which the save
''' operation was started.
''' </para>
'''
''' <para name="runWarningRules">
''' Indicates whether we want to run warning type rules, which are shown
''' in the frontend as a yes or no question.
''' </para>

''' <para name="lstMsg">
''' If we want to cancel the operation in progress, we must add an error
''' message to this parameter,
''' if instead of the type of error, we add an information message for example,
''' the operation will continue to execute and the message will be shown
''' in the frontend to the user who triggered it the operation
''' </para>

''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnSave(itemVO As BusinessVO,
runWarningRules As Boolean,
lstMsg As List(Of MessageVO))
' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)
Case GetType(u0000_SingerVO)
End Select
' option 2
If TypeOf itemVO Is u4902_AlbumVO Then
End If
End Sub
End Class


EntityEvents – Após Gravar


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs after a Insert, Update or Delete operation has been
''' successfully performed on the database.
''' </summary>
'''
''' <para name="itemVO">
''' It is the record of the entity in the database from which
''' the operation was finished,
''' the Operation property of itemVO indicates what kind
''' of previous operation happened,
''' Insert, Update or Delete
''' </para>
'''
''' <para name="triggersVOs">
''' These are the records that were created or modified in the triggers
''' the Operation property of itemVO indicates what kind
''' of previous operation happened,
''' Insert, Update or Delete
''' </para>
'''
''' <remarks>
''' This event is asynchronous type

'''
''' The reason for this is to gain performance on the
''' operation performed previously in the database.
''' </remarks>
Public Overrides Sub OnAfterSave(itemVO As BusinessVO,
triggersVOs As List(Of BusinessVO))
' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)
Case GetType(u0000_SingerVO)
End Select
' option 2
If TypeOf itemVO Is u4902_AlbumVO Then
End If
End Sub
End Class



Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs after a Query operation, from frontend, has executed on the database.
''' </summary>
'''
''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overrides Sub OnRequery(itemVO As BusinessVO)

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then

End If
End Sub
End Class


EntityEvents – Ao executar Ação


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs after a Action operation has executed on the entity.
''' </summary>
'''
''' <remarks>
''' This event is synchronous type
''' </remarks>
Public Overridable Sub OnAction(entityType As Type,
actionItem As ActionVO,
filter As ActionFilterVO,
recordItem As BusinessVO)

' option 1
Select Case itemVO.GetType
Case GetType(u4902_AlbumVO)

Case GetType(u0000_SingerVO)
End Select

' option 2
If TypeOf itemVO Is u4902_AlbumVO Then

End If
End Sub
End Class


EntityEvents – Ao atualizar Stock


Public Class MyEntityEvents
Inherits EntityEvents

''' <summary>
''' Occurs after an update of stock movements (SlVO)
''' which normally occurs in an asynchronous process after
''' saving a document that moves stocks.
''' </summary>
'''
''' <para name="slMovements">
''' Is the list of records of type SlVO that were updated in this process,
''' note that the Operation property of the record is always equal to (0) - None,
''' it is not possible to know in this event if the stock movement
''' was created or updated, we only have access to the current values
''' recorded in the database.
''' </para>
'''
''' <remarks>
''' This event is asynchronous type.
''' </remarks>
Public Overrides Sub OnSlUpdate(slMovements As List(Of SlVO))

End Sub
End Class