Você está na página 1de 38

Manual de Referência

Customizações
Abril/1999

Não homologado
Copyright © 1998 DATASUL S.A. Todos os direitos reservados.
Nenhuma parte deste documento pode ser copiada, reproduzida, traduzida ou
transmitida por qualquer meio eletrônico ou mecânico, na sua totalidade ou em
parte, sem a prévia autorização escrita da DATASUL S.A., que reserva-se o
direito de efetuar alterações sem aviso prévio. A DATASUL S.A não assume
nenhuma responsabilidade pelas conseqüências de quaisquer erros ou
inexatidões que possam aparecer neste documento.
DATASUL S.A.
Av. Santos Dumont, 831, Joinville, SC, CEP 89.222-900
i

Índice

Índice................................................................................................................. i

CAPÍTULO 1 Introdução..............................................................................1

CAPÍTULO 2 Application Program Interface - API.....................................3

External Program Call.....................................................................................6


Definição

CAPÍTULO 1

Introdução

O produto Datasul EMS Framework, possui duas tecnologias criadas para


facilitar as customizações, visando padroniza-las e principalmente facilita-las,
sem necessitar de conhecimento da Base de Dados e seus relacionamentos.
Desta forma garantindo também que o acesso e entrada de dados sejam feitos
de maneira correta e precisa..
Definição de
Esquema
Exemplos
Funcionamento

xternal Program Call 3

CAPÍTULO 2

Application Program Interface - API

Basicamente, é um programa que recebe


parâmetros específicos e executa uma determinada
Aplicação
tarefa no Datasul EMS Framework . Esta tarefa Específica
pode ser: uma atualização, um programa que
retorne infromações, que realize um cálculo, que API
gere um gráfico. Datasul
É uma interface aberta para as funções de negócio EMS
do produto. framework

Efetuar a contabilização de um lote de lançamentos provindos de um sistema


remoto;

Gerar movimentos de estoque para um item ou movimentos de


Material/MOB /GGF para uma ordem de produção;

Extrair saldos em estoque de determinados itens;

OK / NOK
Saída
Entrada
API

Acesso Extração
de dados
Datasul-EMS
Documentação
Tipos

A partir da chamada de uma API e entrada dos devidos parâmetros ou de


dados para uma atualização, podem ocorrer três situações:

 a API pode fazer um acesso ao produto Datasul EMS Framework, e


receber uma resposta que podem ser dados lidos da base ou o resultado de
alguma função, este é repassada para o programa chamador.
 a API pode fazer uma extração de dados, gerando um gráfico, um relatório
ou uma consulta.
 a API pode realizar uma função, por exemplo de eliminação de dados e
retornar se a execução foi correta “OK” ou incorreta “NOK”.
Convencional - executa a API passando parâmetros e obtendo resultados.
com Métodos - instancia a API e dispara os seus métodos (procedures internas
ou functions).

Toda API criada pela Datasul possui um padrão que está documentado e a
partir dele que são criadas quaisquer APIs;
Os componentes podem ser:
 Objetivo: O que vai ser gerado pela API, quando deve ser utilizada, para
que função ;
 Os parâmetros de entrada e saída também possuem sua definição, o que
devem passar para a API e o que podem retornar;
 Em caso de ocorrência de erro, quais as mensagens de erro podem ser
retornadas para o programa chamador;
 As documentações de APIs estão no diretório docapi, com o nome da api
mais a extensão .doc;
--- Exemplo

 São passados como parâmetros para a API os atributos e dados


para montagem do gráfico e devolvido uma temp-table com os
possíveis erros.
 A include {UTP/UTAPI001.I} contém as definições das temp-tables
e essa deve ser inclusa no programa gerador de gráficos.
 A exibição do gráfico é feita através da execução da API,
UTP/UTAPI001.P;
Vantagens

xternal Program Call 5

 Exemplo:

API para Geração de Gráficos (v.003)

Nome Físico: utp\utapi001.p


Nome do Include com a definição dos Parâmetros: utp\utapi001.i
Versão de Integração: 003
Objetivo: Criação de gráficos.

Parâmetros de Entrada:
Temp-table tt-atributos:
Na Temp-Table tt-atributos são definidas as características gerais de
apresentação do gráfico.

 As APIs possuem parâmetros de entrada bem definidos e processos que


são executados de maneira correta sobre o produto;
 As APIs são bem documentadas e executam tarefas de acordo com o
objetivo, funcionando para seus usuário como uma caixa preta, ou seja,
estes não precisam saber de que forma o processo é executado, apenas que,
sendo realizadas as entradas corretas, a API executa o processo esperado
de maneira transparente;
 As integrações entre módulos do produto Datasul EMS Framework são
realizadas através das APIs, portanto este é o caminho natural para que
customizadores integrem outras soluções com o produto;
 A tecnologia empregada e as regras de negócio de uma API podem evoluir
fazendo com que o cliente usufrua destes benefícios sem a necessidade de
reescrever1 seus programas;

Portanto, o que as APIs fornecem é uma maior facilidade, rapidez e


produtividade no desenvolvimento de customizações;

1
Quando houver alguma alteração da interface da API esta verifica se o programa
chamador está de acordo com a nova interface, em caso negativo, é emitida uma
mensagem informando que o programa deve ser revisto.
Objetivos
Definição

External Program Call

São chamadas a programas


desenvolvidos pelo usuário, em pontos
pré-definidos do produto, possibilitando a Aplicação
sua adaptação e integração com outras
aplicações. Específica
Constituem-se num
aperfeiçoamento das “Saídas X”
existentes no produto MAGNUS I.00, UPC API
pois os pontos de chamada estão ligados a
eventos da interface com o usuário,
eventos da base de dados (gravação e Datasul
eliminação de registros) ou em pontos
estratégicos em programas de atualização EMS
e cálculo.
Basicamente, uma maior integração
framework
é possibilitada, porque através das EPCs
pode-se interagir com a interface do produto, com a lógica de aplicação e com
os eventos de dicionário de dados.
Com exceção do último tipo de chamada (pontos estratégicos) as demais
chamadas não precisam ser solicitadas para a Datasul, pois já se encontram
disponíveis no produto. Além de que as chamadas em eventos da base de
dados reduzem a necessidade de chamadas em programas de atualização.

 possibilitar a customização e integração do produto Datasul-EMS pelos


usuários, respectivamente, de uma forma padronizada e controlada;
 possibilitar localizações do Datasul-EMS que não devem ser incorporadas
ao produto standard pela própria Datasul;
Tipos de EPCs

xternal Program Call 7

 possibilitar ao usuário a administração de suas customizações,


identificando através do Datasul-EMS, quais programas e tabelas do
produto possuem customização;
 possibilitar a administração de integrações desenvolvidas por usuários da
Datasul sobre o produto Datasul-EMS;

 Customização
Clientes - Necessidades específicas e especialistas
User Program Call - UPC
 Integração
Parceiros - Integrações com outros softwares
Application Partner Program Call – APPC
 UPC + APPC = EPC

EPCs na Interface Através do procedimento de Manutenção de Programas do Datasul-


de Programas EMS (men/men012aa.w), módulo Menu, o usuário pode determinar o caminho
e o nome físico do programa a ser chamado nas UPCs de um determinado
programa do produto. Conforme a tela a seguir:

Exemplo :
 Alterar as características das telas: labels, formatos, cores,
posicionamento, tabulação.
 Implementar novos campos, novos botões com chamada para sub-
programas.

Parâmetros
Tanto o programa UPC quanto o programa APPC recebem os seguintes
parâmetros:

Parâmetro I/O Tipo de Dado Conteúdo


p-ind-event Input Character Indicador de Evento
p-ind-object Input Character Indicador de Objeto
p-wgh-object Input Handle Handle do objeto corrente
p-wgh-frame Input Widget-handle Handle do frame corrente
p-cod-table Input Character Nome da tabela corrente
p-row-table Input Rowid Rowid do registro corrente da tabela

Pode retornar ao programa que o chamou, através do recurso RETURN-


VALUE, o valor ‘NOK’ indicando que o evento que disparou o programa EPC
não deve ser aplicado, isto viabiliza, por exemplo, validações do usuário a
serem executadas no evento VALIDATE, que se encontrarem problemas
podem evitar a confirmação da tela, e consequentemente a atualização de
registros.
Dica: Para saber os eventos que estão chamando a EPC e o valor dos
parâmetros no momento da chamada, pode-se testar fazendo um programa
EPC como o exemplo a seguir:
*******************************************************************/
def input param p-ind-event as char no-undo.
def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.
def var c-objeto as char no-undo.

assign c-objeto = entry(num-entries(p-wgh-object:private-data,


"~/"), p-wgh-object:private-data, "~/").

message "EVENTO" p-ind-event skip


"OBJETO" p-ind-object skip
"NOME OBJ" c-objeto skip
"FRAME" p-wgh-frame skip
"TABELA" p-cod-table skip
"ROWID" string(p-row-table) view-as alert-box.
xternal Program Call 9

Pontos de Chamada Smart


Os pontos de chamada ficam ligados a eventos da interface, estes
eventos não representam necessariamente eventos Progress, mas sim pontos,
chamados de ‘ADM-Events’, dentro da estrutura de SmartObjects.

 para SmartViewers existem chamadas EPC nos seguintes eventos:

Evento SRC Local–Estrutura UIB Include Trata Retorno ?


BEFORE-INITIALIZE Smart.i Adm-initialize include/i-epc018.i Não
INITIALIZE Smart.i Adm-initialize include/i-epc001.i Não
BEFORE-DISPLAY Record.i Adm-display-fields include/i-epc023.i Não
DISPLAY Record.i Adm-display-fields include/i-epc006.i Não
ENABLE Tableio.i Adm-enable-fields include/i-epc004.i Não
AFTER-ENABLE Tableio.i Adm-enable-fields include/i-epc021.i Não
DISABLE Tableio.i Adm-disable-fields include/i-epc005.i Não
AFTER-DISABLE Tableio.i Adm-disable-fields include/i-epc022.i Não
BEFORE-ADD Tableio.i Adm-add-record include/i-epc028.i Não
ADD Tableio.i Adm-add-record include/i-epc011.i Não
UNDO Tableio.i Adm-reset-record include/i-epc012.i Não
AFTER-UNDO Tableio.i Adm-reset-record include/i-epc029.i Não
CANCEL Tableio.i Adm-cancel-record include/i-epc013.i Não
AFTER-CANCEL Tableio.i Adm-cancel-record include/i-epc030.i Não
VALIDATE Tableio.i Adm-assign-record include/i-epc002.i Sim
AFTER-VALIDATE Tableio.i Adm-assign-statement include/i-epc019.i Sim
BEFORE-ASSIGN Tableio.i Adm-assign-statement include/i-epc020.i Sim
ASSIGN Tableio.i Adm-assign-statement include/i-epc003.i Sim
END-UPDATE Tableio.i Adm-end-update include/i-epc010.i Não
AFTER-END-UPDATE Tableio.i Adm-end-update include/i-epc027.i Não
DELETE Tableio.i Adm-delete-record include/i-epc015.i Sim
AFTER-DELETE Tableio.i Adm-delete-record include/i-epc032.i Sim

 para SmartBrowsers devem haver chamadas EPC nos seguintes eventos:

Evento SRC Local Include Trata Retorno ?


VALUE-CHANGED Brschnge.i value-changed include/i-epc016.i Não
AFTER-VALUE-CHANGED Brschnge.i value-changed include/i-epc033.i Não
BEFORE-INITIALIZE Smart.i adm-initialize Include/i-epc034.i Não
INITIALIZE Smart.i adm-initialize Include/i-epc017.i Não
BEFORE-OPEN-QUERY Record.i adm-open-query Include/i-epc035.i Não
AFTER-OPEN-QUERY Record.i adm-open-query Include/i-epc036.i Não

 para Containers devem haver chamadas EPC nos seguintes eventos:

Evento SRC Local Include Trata


Retorno ?
BEFORE-INITIALIZE smart.i adm-initialize Include/i-epc024.i Não
INITIALIZE smart.i adm-initialize Include/i-epc007.i Não
BEFORE-ENABLE smart.i adm-enable Include/i-epc025.i Não
ENABLE smart.i adm-enable Include/i-epc008.i Não
Exemplos

BEFORE-DISABLE smart.i adm-disable Include/i-epc026.i Não


DISABLE smart.i adm-disable Include/i-epc009.i Não
CHANGE-PAGE Containr.i adm-change-page Include/i-epc014.i Não
AFTER-CHANGE-PAGE Containr.i adm-change-page Include/i-epc031.i Não
DESTROY smart.i adm-destroy include/i-epc100.i Não

 No caso do EMS 5, os pontos de chamada estão nos seguintes eventos:

Evento Local Trata Retorno ?


INITIALIZE Depois do view da frame Não
DISPLAY Depois do display da frame Não
ENABLE Depois do enable da frame Não
VALIDATE Depois da chamada da pi de validação Sim
ASSIGN Depois da pi de assign dos campos Sim
BEFORE_DELETE Antes de eliminar o registro Sim
AFTER_DELETE Depois de eliminar o registro Sim

Criar um botão novo em uma window para chamar um subprograma a partir deste;
def input param p-ind-event as char no-undo.
def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

def var wh-button as widget-handle no-undo.


def var c-objeto as char no-undo.

assign c-objeto = entry(num-entries(p-wgh-object:private-


data, "~/"), p-wgh-object:private-data, "~/").

if p-ind-event = "INITIALIZE"
and p-ind-object = "CONTAINER" then do:
create button wh-button
assign frame = p-wgh-frame
width = 4
height = 1.25
row = 1.26
label = "teste"
col = 65
sensitive = yes
visible = yes
triggers:
ON CHOOSE PERSISTENT RUN
upc/testeupc1.p.
end triggers.
end.
xternal Program Call 11

Obs. O evento utilizado para o botão criado, deve necessariamente


chamar um subprograma com persistent run e em caso de parâmetros,
utilizam-se variáveis globais.

Criar um widget novo em uma viewer;

def input param p-ind-event as char no-undo.


def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

def new
global shared var wh-button as widget-handle no-undo.
def new global shared var wh-fill as widget-handle no-
undo.
def new global shared var tx-label as widget-handle no-
undo.
def var c-objeto as char no-undo.

assign c-objeto = entry(num-entries(p-wgh-object:private-


data, "~/"), p-wgh-object:private-data, "~/").

if p-ind-event = "BEFORE-INITIALIZE"
and p-ind-object = "VIEWER"
and c-objeto = "v24ad098.w" then do:
create button wh-button
assign frame = p-wgh-frame
width = 18
height = 1
label = "Assistência Técnica"
row = 3.7
col = 67
visible = yes
sensitive = no
triggers:
ON CHOOSE PERSISTENT RUN upc/demoupc1.p.
end triggers.
create text tx-label
assign frame = p-wgh-frame
format = "x(17)"
width = 6.2
screen-value = "Perfil Marketing:"
row = 2.8
col = 59.5
fgcolor = 1
visible = yes.
create fill-in wh-fill
assign frame = p-wgh-frame
side-label-handle = tx-label:handle
format = "x(20)"
width = 12
height = 0.88
row = 2.7
col = 71
bgcolor = 1
fgcolor = 15
label = "Perfil Marketing:"
visible = yes
sensitive = no.
end.

if p-ind-event = "ENABLE"
and p-ind-object = "VIEWER"
and c-objeto = "v24ad098.w" then do:
assign wh-button:sensitive = yes
wh-fill:sensitive = yes.
end.

if p-ind-event = "DISABLE"
and p-ind-object = "VIEWER"
and c-objeto = "v24ad098.w" then do:
assign wh-button:sensitive = no
wh-fill:sensitive = no.
end.

Encontrar o handle de um widget;

def input param p-ind-event as char no-undo.


def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

def new global shared var wh-button as widget-handle no-


undo.
def new global shared var wh-fill as widget-handle no-
undo.
def new global shared var tx-label as widget-handle no-
undo.
def new global shared var h_campo as widget-handle no-
undo.
def var c-objeto as char no-undo.
def var h_frame as widget-handle no-undo.

assign c-objeto = entry(num-entries(p-wgh-object:private-


data, "~/"), p-wgh-object:private-data, "~/").

if p-ind-event = "DISPLAY"
and p-ind-object = "VIEWER"
and c-objeto = "v24ad098.w" then do:
xternal Program Call 13

DO :
ASSIGN h_Frame = p-wgh-frame:FIRST-CHILD. /* pegando o
Field-Group */
ASSIGN h_Frame = h_Frame:FIRST-CHILD. /* pegando o
1o. Campo */
message h_frame:name view-as alert-box.
DO WHILE h_Frame <> ? :
if h_frame:type <> "field-group" then do:
IF h_Frame:NAME = "nome-mic-reg" THEN
DO :
assign h_campo = h_Frame.
leave.
END.
ASSIGN h_Frame = h_Frame:NEXT-SIBLING.
end.
else do:
assign h_frame = h_frame:first-child.
end.
END.
END.
end.

Dica: Para descobrir o nome de um campo em uma tela, pode-se


utilizar o comando <Ctrl-Alt-4> sobre o campo desejado. Este
comando retorna o nome do campo e da tabela a que ele pertence.
Acessar o valor de um widget;
Após encontrar o handle do campo desejado, utilizando a lógica do
item III, fazer o seguinte:
assign c-valor = h-campo:screen-value.

Obs. Lembre-se, em caso da variável ou campo de tabela que vai


receber o valor do widget não ser do tipo character, o valor do screen-
value deve ser transformado para este tipo, pois o screen-value do
campo sempre é character.

Alterar o valor de um widget;

Após encontrar o handle do campo desejado, utilizando a lógica do


item III, fazer o seguinte:
assign h-campo:screen-value = “Novo Valor”.

Lembre-se que mesmo para campos não character, deve-se utilizar “


”(aspas), pois o valor do screen-value é sempre character.
Ocultar um widget em uma viewer;

Após encontrar o handle do campo desejado, utilizando a lógica do


item III, fazer o seguinte:

assign h-campo:visible = no.

Criar uma viewer dinamicamente;


/* Parameter Definitions
****************************************************/
define input parameter p-ind-event as character.
define input parameter p-ind-object as character.
define input parameter p-wgh-object as handle.
define input parameter p-wgh-frame as widget-handle.
define input parameter p-cod-table as character.
define input parameter p-row-table as rowid.

/* Global Variable Definitions


**********************************************/
define new global shared var adm-broker-hdl as handle no-
undo.
define new global shared var h-folder as handle no-
undo.
define new global shared var h-viewer as handle no-
undo.

/* Variable Definitions
*****************************************************/
define var c-folder as character no-undo.
define var c-objects as character no-undo.
define var h-object as handle no-undo.
define var i-objects as integer no-undo.
define var l-record as logical no-undo initial no.
define var l-group-assign as logical no-undo initial no.

/* Main Block
*************************************************************
**/
if p-ind-event = "INITIALIZE" and p-ind-object = "CONTAINER"
then do:
RUN get-link-handle IN adm-broker-hdl (INPUT p-wgh-
object,
INPUT "PAGE-
SOURCE":U,
OUTPUT c-folder).
assign h-folder = widget-handle(c-folder) no-error.

if valid-handle(h-folder) then do:


xternal Program Call 15

RUN create-folder-page IN h-folder (INPUT 5, INPUT


"Pag. 05":U).
RUN create-folder-label IN h-folder (INPUT 5, INPUT
"Pag. 05":U).

RUN select-page IN p-wgh-object (INPUT 5).

RUN init-object IN p-wgh-object (INPUT "nome externo


da nova viewer ":U, /* Nome do Objeto Viewer */
INPUT p-wgh-frame,
INPUT "Layout = ":U,
OUTPUT h-viewer).

RUN set-position IN h-viewer ( 7.10, 5.00).

RUN get-link-handle IN adm-broker-hdl (INPUT p-wgh-


object,
INPUT
"CONTAINER-TARGET":U,
OUTPUT c-
objects).

do i-objects = 1 to num-entries(c-objects):
assign h-object = widget-handle(entry(i-objects, c-
objects)).

if index(h-object:private-data, "qry") <> 0 and /* Você deve


verificar se e a query principal */
not l-record then do:
assign l-record = yes.

RUN add-link IN adm-broker-hdl (INPUT h-object,


INPUT
"Record":U,
INPUT h-viewer).
end.

if index(h-object:private-data, "vwr") <> 0 and /*


Voce deve verificar se e a viewer principal */
not l-group-assign then do:
assign l-group-assign = yes.

RUN add-link IN adm-broker-hdl (INPUT h-object,


INPUT "Group-
Assign":U,
INPUT h-viewer).
end.
end.

RUN dispatch IN h-viewer ("initialize":U).

RUN select-page IN p-wgh-object (INPUT 1).


end.
end.

Chamar o zoom para um campo criado dinamicamente;


def input param p-ind-event as char no-undo.
def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

def new global shared var wh-fill as widget-handle no-


undo.
def new global shared var tx-label as widget-handle no-
undo.
def var c-objeto as char no-undo.

assign c-objeto = entry(num-entries(p-wgh-object:private-


data, "~/"), p-wgh-object:private-data, "~/").

if p-ind-event = "BEFORE-INITIALIZE"
and p-ind-object = "VIEWER"
and c-objeto = "v24ad098.w" then do:
create text tx-label
assign frame = p-wgh-frame
format = "x(17)"
width = 6.2
screen-value = "Perfil:"
row = 2.8
col = 59.5
fgcolor = 1
visible = yes.
create fill-in wh-fill
assign frame = p-wgh-frame
format = "x(10)"
side-label-handle = tx-label:handle
width = 10
height = 0.88
row = 2.8
col = 65
bgcolor = 1
fgcolor = 15
visible = yes
sensitive = no
triggers:
ON F5 PERSISTENT RUN upc-curso/zoomupc.p.
end triggers.
end.

if p-ind-event = "ENABLE"
and p-ind-object = "VIEWER"
xternal Program Call 17

and c-objeto = "v24ad098.w" then do:


assign wh-fill:sensitive = yes.
end.

if p-ind-event = "DISABLE"
and p-ind-object = "VIEWER"
and c-objeto = "v24ad098.w" then do:
assign wh-fill:sensitive = no.
end.

Para o programa de zoom, que vai chamar um zoom construido no


padrão do EMS 2.0, deve-se fazer o seguinte:
def var wh-pesquisa as widget-handle.
def new global shared var l-implanta as logical init no.
def new global shared var wh-fill as widget-handle no-
undo.
def new global shared var wh-window as handle no-undo.
def new global shared var adm-broker-hdl as handle no-undo.

{include/zoomvar.i &prog-zoom=inzoom/z01in172.w
&proghandle=wh-window
&campohandle=wh-fill
&campozoom=it-codigo}

Pontos de Chamada ThinTemplate


Os pontos de chamada ficam ligados a eventos da interface, estes
eventos não representam necessariamente eventos Progress, mas sim pontos
estratégicos, dentro da estrutura do ThinTemplate. A chamada da EPC é feita
por intermédio da include method/svc/custom/custom.i, e nenhuma das
chamadas de EPC em interface trata retorno de erro.

 para ThinMaintenance existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BEFORE-ADD ADDRECORD
AFTER-ADD ADDRECORD
BEFORE-CANCEL CANCELRECORD
AFTER-CANCEL CANCELRECORD
BEFORE-COPY COPYRECORD
AFTER-COPY COPYRECORD
BEFORE-DELETE DELETERECORD
AFTER-DELETE DELETERECORD
BEFORE-ASSIGN SAVERECORD
AFTER-ASSIGN SAVERECORD
BEFORE-UNDO UNDORECORD
AFTER-UNDO UNDORECORD
BEFORE-CONTROL-TOOL-BAR CONTROLTOOLBAR
AFTER-CONTROL-TOOL-BAR CONTROLTOOLBAR
BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISABLE DISABLEFIELDS
AFTER-DISABLE DISABLEFIELDS
BEFORE-DISPLAY DISPLAYFIELDS
AFTER-DISPLAY DISPLAYFIELDS
BEFORE-ENABLE ENABLEFIELDS
AFTER-ENABLE ENABLEFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE
BEFORE-SAVE-FIELDS SAVEFIELDS
AFTER-SAVE-FIELDS SAVEFIELDS
BEFORE-CHANGE-PAGE CHANGEPAGE
AFTER-CHANGE-PAGE CHANGEPAGE

 para ThinMaintenanceNoNavigation existem chamadas EPC nos seguintes


eventos:

Evento Método Padrão


BEFORE-ADD ADDRECORD
AFTER-ADD ADDRECORD
BEFORE-COPY COPYRECORD
AFTER-COPY COPYRECORD
BEFORE-ASSIGN SAVERECORD
AFTER-ASSIGN SAVERECORD
BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISABLE DISABLEFIELDS
AFTER-DISABLE DISABLEFIELDS
BEFORE-DISPLAY DISPLAYFIELDS
AFTER-DISPLAY DISPLAYFIELDS
BEFORE-ENABLE ENABLEFIELDS
AFTER-ENABLE ENABLEFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE
BEFORE-SAVE-FIELDS SAVEFIELDS
AFTER-SAVE-FIELDS SAVEFIELDS
BEFORE-CHANGE-PAGE CHANGEPAGE
AFTER-CHANGE-PAGE CHANGEPAGE

 para ThinMasterDetail existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BEFORE-DELETE DELETERECORD
AFTER-DELETE DELETERECORD
BEFORE-CONTROL-TOOL-BAR CONTROLTOOLBAR
AFTER-CONTROL-TOOL-BAR CONTROLTOOLBAR
BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISPLAY DISPLAYFIELDS
AFTER-DISPLAY DISPLAYFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE
xternal Program Call 19

BEFORE-VALUE-CHANGED APPLYVALUECHANGED
AFTER-VALUE-CHANGED APPLYVALUECHANGED
BEFORE-CHANGE-PAGE CHANGEPAGE
AFTER-CHANGE-PAGE CHANGEPAGE
BEFORE-OPEN-QUERY OPENQUERY
AFTER-OPEN-QUERY OPENQUERY

 para ThinFormation existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BEFORE-CONTROL-TOOL-BAR CONTROLTOOLBAR
AFTER-CONTROL-TOOL-BAR CONTROLTOOLBAR
BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISPLAY DISPLAYFIELDS
AFTER-DISPLAY DISPLAYFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE
BEFORE-CHANGE-PAGE CHANGEPAGE
AFTER-CHANGE-PAGE CHANGEPAGE

 para ThinFormationNoNavigation existem chamadas EPC nos seguintes


eventos:

Evento Método Padrão


BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISPLAY DISPLAYFIELDS
AFTER-DISPLAY DISPLAYFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE

 para ThinReport existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISABLE DISABLEFIELDS
AFTER-DISABLE DISABLEFIELDS
BEFORE-ENABLE ENABLEFIELDS
AFTER-ENABLE ENABLEFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE

 para ThinWindow existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-DISPLAY DISPLAYFIELDS
Exemplos

AFTER-DISPLAY DISPLAYFIELDS
BEFORE-ENABLE ENABLEFIELDS
AFTER-ENABLE ENABLEFIELDS
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE
BEFORE-CHANGE-PAGE CHANGEPAGE
AFTER-CHANGE-PAGE CHANGEPAGE

 para ThinZoom existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BEFORE-VALUE-CHANGED APPLYVALUECHANGED
AFTER-VALUE-CHANGED APPLYVALUECHANGED
BEFORE-DESTROY-INTERFACE DESTROYINTERFACE
AFTER-DESTROY-INTERFACE DESTROYINTERFACE
BEFORE-INITIALIZE INITIALIZEINTERFACE
AFTER-INITIALIZE INITIALIZEINTERFACE
BEFORE-CHANGE-PAGE CHANGEPAGE
AFTER-CHANGE-PAGE CHANGEPAGE

Criar um widget novo em uma frame;

def input param p-ind-event as char no-undo.


def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

DEF NEW GLOBAL SHARED VAR wh-button AS WIDGET-HANDLE NO-UNDO.


DEF NEW GLOBAL SHARED VAR wh-fill AS WIDGET-HANDLE NO-UNDO.
DEF NEW GLOBAL SHARED VAR tx-label AS WIDGET-HANDLE NO-UNDO.

IF p-ind-event = "AFTER-INITIALIZE" THEN DO:

CREATE BUTTON wh-button


ASSIGN FRAME = p-wgh-frame
WIDTH = 15
HEIGHT = 1
LABEL = "TESTE"
ROW = 4
COL = 10
FONT = 1
VISIBLE = YES
SENSITIVE = NO
TRIGGERS:
ON CHOOSE PERSISTENT RUN epc/trigbotao.p.
END TRIGGERS.

CREATE TEXT tx-label


ASSIGN FRAME = p-wgh-frame
xternal Program Call 21

FORMAT = "x(40)"
WIDTH = 15
SCREEN-VALUE = "Comentário:"
ROW = 2
COL = 10
VISIBLE = YES
FONT = 1.

CREATE FILL-IN wh-fill


ASSIGN FRAME = p-wgh-frame
SIDE-LABEL-HANDLE = tx-label:HANDLE
FORMAT = "x(20)"
WIDTH = 40
HEIGHT = 0.88
ROW = 1.7
COL = 18.5
LABEL = "Comentário:"
VISIBLE = YES
SENSITIVE = NO
FONT = 1.

END.

IF p-ind-event = "BEFORE-ENABLE" THEN DO:


ASSIGN wh-button:SENSITIVE = YES
wh-fill:SENSITIVE = YES.

END.

IF p-ind-event = "BEFORE-DISABLE" THEN DO:


ASSIGN wh-button:SENSITIVE = NO
wh-fill:SENSITIVE = NO.
END.

Obs:No evento (trigger) do botão criado deve-se chamar um subprograma com


persistent run e nesse não utilizar parâmetros, apenas variáveis globais.

Encontrar o handle de um widget;

def input param p-ind-event as char no-undo.


def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

DEF NEW GLOBAL SHARED VAR h-campo AS WIDGET-HANDLE NO-UNDO.

DEF VAR h-objeto AS WIDGET-HANDLE NO-UNDO.


If p-ind-event = “BEFORE-INITIALIZE” THEN DO:

DO:
assign h-objeto = p-wgh-frame:FIRST-CHILD.
assign h-objeto = h-objeto:FIRST-CHILD.
do while valid-handle(h-objeto):
IF h-objeto:TYPE <> "field-group" THEN DO:
IF h-objeto:NAME = "nome-mic-reg" THEN DO:
ASSIGN h-campo = h-objeto.
Leave.
END.
assign h-objeto = h-objeto:NEXT-SIBLING.
END.
ELSE DO:
Assign h-objeto = h-objeto:first-child.
END.
end.
END.

END.

Habilitar o folder;
Somente é possível habilitar o folder se o programa utilizar as páginas fPage0
e fPage1.
def input param p-ind-event as char no-undo.
def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

DEF NEW GLOBAL SHARED VAR h-fpage1 AS HANDLE NO-UNDO.


DEF NEW GLOBAL SHARED VAR h-folder AS HANDLE NO-UNDO.

DEF VAR h-frame AS HANDLE NO-UNDO.

IF p-ind-event = "BEFORE-INITIALIZE" THEN DO:

DO:
assign h-frame = p-wgh-frame:FIRST-CHILD.
assign h-frame = h-frame:FIRST-CHILD.
do while valid-handle(h-frame):
IF h-frame:TYPE <> "field-group" THEN DO:
IF h-frame:NAME = "fPage1" THEN DO:
ASSIGN h-fpage1 = h-frame.
END.
assign h-frame = h-frame:NEXT-SIBLING.
END.
ELSE DO:
LEAVE.
END.
xternal Program Call 23

end.
END.

RUN utp/thinFolder.w PERSISTENT SET h-folder.

RUN setProgramParent IN h-folder (INPUT p-wgh-object).

RUN setOCX IN h-folder (INPUT p-wgh-object:GET-


SIGNATURE("control_load":U) <> "":U) NO-ERROR.

RUN initializeFolders IN h-folder (INPUT p-wgh-frame,


INPUT STRING(h-fpage1),
INPUT "Cadastro",
INPUT 1,
INPUT ?,
INPUT ?,
INPUT ?,
INPUT ?).
RUN setFolder IN h-folder (INPUT 1).
END.

Inserir uma frame;


Somente é possível inserir uma frame quando o folder estiver habilitado.
def input param p-ind-event as char no-undo.
def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

DEF NEW GLOBAL SHARED VAR h-fpage2 AS WIDGET-HANDLE NO-UNDO.

DEF VAR h-objeto AS HANDLE NO-UNDO.

IF p-ind-event = "AFTER-INITIALIZE" THEN DO:

CREATE FRAME h-fPage2


ASSIGN COL = 3.57
ROW = 6.38
WIDTH = 84.43
HEIGHT = 5.88
NAME = "fpage2"
SIDE-LABELS = YES
SENSITIVE = YES
OVERLAY = YES
BGCOLOR = ?
BOX = NO
THREE-D = YES.

assign h-objeto = p-wgh-object.


do while valid-handle(h-objeto):
if h-objeto:FILE-NAME = "utp/thinFolder.w" then
LEAVE.
assign h-objeto = h-objeto:NEXT-SIBLING.
end.

RUN setFolder IN h-objeto (INPUT 1) .

RUN insertFolder IN h-objeto (INPUT ?,


INPUT p-wgh-frame,
INPUT h-fPage2,
INPUT "Ref Call").

End.

Chamar o zoom para um campo criado dinamicamente;


def input param p-ind-event as char no-undo.
def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

Def new global shared var tx-label as widget-handle no-undo.


Def new global shared var wh-fill as widget-handle no-undo.

/*encontrar o handle da frame onde deseja criar o campo*/

IF p-ind-event = "AFTER-INITIALIZE" THEN DO:

CREATE TEXT tx-label


ASSIGN FRAME = h-fPage2 /*handle da frame*/
FORMAT = "x(40)"
WIDTH = 15
SCREEN-VALUE = "Comentário:"
ROW = 2
COL = 10
VISIBLE = YES
FONT = 1.

CREATE FILL-IN wh-fill


ASSIGN FRAME = h-fPage2
SIDE-LABEL-HANDLE = tx-label:HANDLE
FORMAT = "x(20)"
NAME = "comentario"
WIDTH = 40
HEIGHT = 0.88
ROW = 1.7
COL = 18.5
LABEL = "Comentário:"
VISIBLE = YES
SENSITIVE = NO
xternal Program Call 25

FONT = 1
TRIGGERS:
ON "F5":U PERSISTENT RUN epc/epczoom.p.
ON "MOUSE-SELECT-DBLCLICK":U PERSISTENT RUN
epc/epczoom.p.
END TRIGGERS.

WH-FILL:LOAD-MOUSE-POINTER("image/lupa.cur":U).
END.

IF p-ind-event = "BEFORE-ENABLE" THEN DO:


ASSIGN wh-fill:SENSITIVE = YES.

END.

IF p-ind-event = "BEFORE-DISABLE" THEN DO:


ASSIGN wh-fill:SENSITIVE = NO.
END.

Para o programa de zoom, que vai chamar um zoom construído no padrão


ThinTemplate, deve-se fazer o seguinte:
DEF NEW GLOBAL SHARED VAR wh-fill AS WIDGET-HANDLE NO-UNDO.

DEF VAR hProgramZoom AS HANDLE NO-UNDO.

{method/zoomFields.i &ProgramZoom="spp/sp0008a.w"
&FieldZoom1="rep-name"
&frame1="fPage2"
&fieldHandle1=wh-fill}

Buscar registro corrente/atualizar registro de uma DBO;

def input param p-ind-event as char no-undo.


def input param p-ind-object as char no-undo.
def input param p-wgh-object as handle no-undo.
def input param p-wgh-frame as widget-handle no-undo.
def input param p-cod-table as char no-undo.
def input param p-row-table as rowid no-undo.

DEF NEW GLOBAL SHARED VAR wh-fill AS WIDGET-HANDLE NO-UNDO.


DEF NEW GLOBAL SHARED VAR tx-label AS WIDGET-HANDLE NO-UNDO.
DEF NEW GLOBAL SHARED VAR h-fPage1 AS WIDGET-HANDLE NO-UNDO.
DEF NEW GLOBAL SHARED VAR h-bo AS HANDLE NO-UNDO.

{spbo/bosp001.i tt-Customer}

DEF VAR h-objeto AS HANDLE NO-UNDO.


DEF VAR c-comments AS CHAR NO-UNDO.
/*encontrar o handle da frame onde deseja criar o campo*/

IF p-ind-event = "AFTER-INITIALIZE" THEN DO:

CREATE TEXT tx-label


ASSIGN FRAME = h-fPage1 /*handle da frame*/
FORMAT = "x(40)"
WIDTH = 15
SCREEN-VALUE = "Comentário:"
ROW = 2
COL = 10
VISIBLE = YES
FONT = 1.

CREATE FILL-IN wh-fill


ASSIGN FRAME = h-fPage1
SIDE-LABEL-HANDLE = tx-label:HANDLE
FORMAT = "x(20)"
NAME = "comentario"
WIDTH = 40
HEIGHT = 0.88
ROW = 1.7
COL = 18.5
LABEL = "Comentário:"
VISIBLE = YES
SENSITIVE = NO
FONT = 1
TRIGGERS:
ON "F5":U PERSISTENT RUN epc/epczoom.p.
ON "MOUSE-SELECT-DBLCLICK":U PERSISTENT RUN
epc/epczoom.p.
END TRIGGERS.

WH-FILL:LOAD-MOUSE-POINTER("image/lupa.cur":U).

assign h-objeto = p-wgh-object.


do while valid-handle(h-objeto):
if h-objeto:FILE-NAME = "spbo/bosp001.p" then do:
ASSIGN h-bo = h-objeto.
LEAVE.
END.
assign h-objeto = h-objeto:NEXT-SIBLING.
end.

IF VALID-HANDLE(wh-fill) AND
valid-handle(h-bo) THEN DO:
RUN GetCharField IN h-bo (INPUT "comments",
OUTPUT c-comments).
ASSIGN wh-fill:SCREEN-VALUE = c-comments.
END.
END.
Exemplos

xternal Program Call 27

IF p-ind-event = "BEFORE-ENABLE" THEN DO:


Assign wh-fill:SENSITIVE = YES.
END.

IF p-ind-event = "BEFORE-DISABLE" THEN DO:


Assign wh-fill:SENSITIVE = NO.
END.

IF p-ind-event = "BEFORE-DISPLAY" and


VALID-HANDLE(wh-fill) AND
VALID-HANDLE(h-bo) THEN DO:
RUN GetCharField IN h-bo (INPUT "comments",
OUTPUT c-comments).
ASSIGN wh-fill:SCREEN-VALUE = c-comments.
END.

IF p-ind-event = "AFTER-ASSIGN" and


VALID-HANDLE(wh-fill) AND
VALID-HANDLE(h-bo) THEN DO:

RUN GetRecord IN h-bo (OUTPUT TABLE tt-Customer).

FIND FIRST tt-Customer EXCLUSIVE-LOCK NO-ERROR.


ASSIGN tt-Customer.comments = wh-fill:SCREEN-VALUE .

RUN SetRecord IN h-bo (INPUT TABLE tt-Customer).

RUN UpdateRecord IN h-bo.


END.

Pontos de Chamada DBO


A chamada da EPC é feita por intermédio da include method/dboupd.i.
Todas as chamadas de EPC em DBO tratam retorno de erro.
Na EPC de DBO é possível executar todos os métodos disponíveis na
DBO, pois o parâmetro passado é o handle da DBO.

 para as DBOs existem chamadas EPC nos seguintes eventos:

Evento Método Padrão


BeforeCreateRecord CREATERECORD
AfterCreateRecord CREATERECORD
BeforeDeleteRecord DELETERECORD
AfterDeleteRecord DELETERECORD
BeforeUpdateRecord UPDATERECORD
AfterUpdateRecord UPDATERECORD

Atualizar campo(s) de um registro via EPC de DBO;


{include/i-epc200.i} /*Definição tt-EPC*/
{spbo/bosp001.i tt-Customer} /*Definição Temp-table DBO*/

DEF INPUT PARAM p-ind-event AS CHAR NO-UNDO.


DEF INPUT-OUTPUT PARAM TABLE FOR tt-epc.

DEF VAR h-BO AS HANDLE NO-UNDO.

IF p-ind-event = "BeforeUpdateRecord" THEN DO:


FIND FIRST tt-epc WHERE
tt-epc.cod-event = p-ind-event AND
tt-epc.cod-parameter = "OBJECT-HANDLE" NO-LOCK NO-ERROR.
IF AVAIL tt-epc THEN DO:

ASSIGN h-bo = WIDGET-HANDLE(tt-epc.val-parameter).

RUN getRecord IN h-bo (OUTPUT TABLE tt-customer).

FIND FIRST tt-customer EXCLUSIVE-LOCK NO-ERROR.


ASSIGN tt-customer.Address2 = "Rua sem nome".

RUN setRecord IN h-bo (INPUT TABLE tt-customer).


END.
END.

Validar campo(s) de um registro via EPC de DBO (Geração de erro);


{include/i-epc200.i} /*Definição tt-EPC*/
{spbo/bosp001.i tt-Customer} /*Definição Temp-table DBO*/

DEF INPUT PARAM p-ind-event AS CHAR NO-UNDO.


DEF INPUT-OUTPUT PARAM TABLE FOR tt-epc.

DEF VAR h-BO AS HANDLE NO-UNDO.

IF p-ind-event = "AfterUpdateRecord" THEN DO:


FIND FIRST tt-epc WHERE
tt-epc.cod-event = p-ind-event AND
tt-epc.cod-parameter = "OBJECT-HANDLE" NO-LOCK NO-ERROR.
IF AVAIL tt-epc THEN DO:

ASSIGN h-bo = WIDGET-HANDLE(tt-epc.val-parameter).

RUN getRecord IN h-bo (OUTPUT TABLE tt-customer).

FIND FIRST tt-customer NO-LOCK NO-ERROR.


IF tt-customer.comments = "" THEN DO:
CREATE tt-epc.
ASSIGN tt-epc.cod-event = "ERROR"
tt-epc.cod-parameter = "EPC-ERROR"
tt-epc.val-parameter = "O campo comentário deve
ser preenchido.".
EPCs em Gatilhos
de Dicionários de
Dados

xternal Program Call 29

END.
END.
END.

As External Program Calls estão disponíveis em gatilhos (triggers) de


dicionário de dados, nos gatilhos de WRITE (gravação) e DELETE
(eliminação) das tabelas:

EPCs em Gatilhos de WRITE

Para as UPCs, através do procedimento de Manutenção de Tabelas do


Datasul-EMS, módulo Básico (btb/btb006aa.w), o usuário pode determinar o
caminho e o nome físico do programa de customização a ser executado no
gatilho de WRITE de uma determinada tabela do produto. (tabela:
‘tab_dic_dtsul’ atributo: ‘nom_prog_upc_gat_write’).

Para as APPCs, também na tabela ‘tab_dic_dtsul’, o usuário pode


determinar o caminho e o nome físico do programa de integração a ser
executado no gatilho de WRITE através do atributo
‘nom_prog_appc_gat_write’.

Ponto de Chamada

Evento Local Include Trata Retorno ?


WRITE final do gatilho include/i-epc101.i Sim

Parâmetros
EPCs em Gatilhos
de DELETE

Parâmetro I/O Tipo de Dado Conteúdo


p-table buffer buffer de registro Buffer do registro após as alterações
p-old-table buffer buffer de registro Buffer do registro antes das alterações

Pode retornar ao gatilho que o chamou, através do recurso RETURN-


VALUE, o valor ‘NOK’ indicando que o evento não deve ser aplicado,
retornando o erro ao programa que disparou o gatilho. Assim, é possível
através de uma EPC, evitar que um registro de uma determinada tabela seja
atualizado, e interromper um processamento.

Através do procedimento de Manutenção de Tabelas do Banco de


Dados, módulo Básico, o usuário pode determinar o caminho e o nome físico
do programa a ser chamado na UPC dos gatilhos de DELETE de uma
determinada tabela do produto. (tabela: tab_dic_dtsul
atributo:nom_prog_upc_gat_delete), veja o exemplo:

Para as APPCs o atributo ‘nom_prog_appc_gat_delete’ na tabela de


‘tab_dic_dtsul’ deve determinar o caminho e o nome físico do programa a ser
chamado na APPC dos gatilhos de DELETE de uma determinada tabela do
produto.

Ponto de Chamada

Evento Local Include Trata Retorno ?


DELETE após validações e include/i-epc102.i Sim
antes da eliminação em cascata
Sugestão:
EPCs em Pontos
Estratégicos de
Programas

xternal Program Call 31

Parâmetros

Parâmetro I/O Tipo de Dado Conteúdo


p-table Buffer buffer de registro Buffer do registro que será eliminado

Pode retornar ao gatilho de DELETE que o chamou, através do recurso


RETURN-VALUE, o valor ‘NOK’ indicando que o evento não deve ser
aplicado, retornando erro ao programa que disparou o gatilho. Assim, é
possível através de uma EPC, evitar que um registro de uma determinada
tabela seja eliminado, pois possui relacionamentos com outros
desenvolvimentos específicos, por exemplo.

Há situações para customizações e integrações que não são possíveis de


ser resolvidas através de EPCs na interface de programas ou em gatilhos de
dicionário de dados, então são implementados chamadas EPCs em pontos
estratégicos dentro da lógica destes programas do Datasul EMS Framework.
Este tipo de EPC somente pode ser implementada em programas que
não possuam interface com o usuário, quando não há forma de contornar a
necessidade com a utilização de EPCs de dicionário de dados.
Da mesma forma que para as EPCs de interface de programas, o usuário
deve definir o nome e o caminho do programa EPC a ser executado através
dos atributos ‘nom_prog_upc’ e ‘nom_prog_appc’ respectivamente para UPC
e APPC. Assim, para viabilizar uma EPC ,por exemplo no programa de
cálculo do preço médio (cep/ce0401rp.p), o usuário deve cadastrar o sub-
programa, onde foi implementada a chamada EPC, na tabela de programas
‘prog_dtsul’.

Caso houver outra situação de customização, que não seja possível de ser
resolvida através de EPC´s, se propõe:
 a construção de um sucinto programa que seja o SETUP da customização
para cada um de seus clientes (caso for parceiro). Este programa, a
princípio limparia o conteúdo dos campos: ‘prog_dtsul.nom_prog_upc’ e
‘tab_dic_dtsul.nom_prog_upc’ e após faria o registro das customizações
daquele cliente.
 aplicar o programa SETUP de determinado cliente na base sempre que for
realizar um teste com o ambiente daquele cliente.
Parâmetros

Parâmetro I/O Tipo de Dado Conteúdo


p-ind-event Input Character indicador de evento
tt-epc i-o temp-table temporary table com três atributos:
 cod-event (character) – indicador de evento, sempre
o mesmo valor que p-ind-event;
 cod-parameter (character) – código do parâmetro
indicando o que significa o valor do parâmetro;
 val-parameter (character) – valor do parâmetro.

Os valores dos parâmetros ‘p-ind-event’, ‘tt-epc.cod-event’ e ‘tt-


epc.cod-parameter’ são definidos em inglês e sem espaços em branco entre as
palavras, substituindo os espaços em branco pelo caracter traço (-), pois o
produto é internacional e o idioma inglês é mundialmente aceito.
Qualquer um dos tipos de EPC pode retornar ao programa chamador,
através do recurso RETURN-VALUE, o valor ‘NOK’ indicando que o
processamento seja interrompido/cancelado para aquela interação, ou ainda
tenha outro efeito definido sobre o programa chamador.

Exemplo:
 no fonte de um programa sem interface do produto EMS 2.0, a
chamada EPC poderia ser implementada da seguinte forma:

/* Include i-epc200.i: Definição Temp-Table tt-epc e dos


programas de EPCs */
{include/i-epc200.i XX9999}

for each item no-lock:


for each tt-epc where tt-epc.cod-event = "Single-Point".
delete tt-epc.
end.

/* Include i-epc200.i2: Criação de registro para Temp-


Table tt-epc */
{include/i-epc200.i2 &CodEvent='"Single-Point"'
&CodParameter='"item.it-codigo"'
&ValueParameter="item.it-codigo"}

/* Include i-epc200.i2: Criação de registro para Temp-


Table tt-epc */
{include/i-epc200.i2 &CodEvent='"Single-Point"'
&CodParameter='"item rowid"'
&ValueParameter="string(rowid(item))"}
Localização de
Programas
Específicos

xternal Program Call 33

/* Include i-epc201.i: Chamada do programa de EPC */


{include/i-epc201.i "Single-Point"}

if return-value = "NOK" then


/* Exemplo de tratamento de retorno */
undo, leave.
end.

 Já o programa de customização/integração teria o seguinte


tratamento como base o seguinte código fonte:
/* Include i-epc200.i: Definição Temp-Table tt-epc */
{include/i-epc200.i1}

def input param p-ind-event as char no-undo.


def input-output param table for tt-epc.

for each tt-epc no-lock


where tt-epc.cod-event = p-ind-event:

/* Exemplo de uso dos parâmetros */


disp tt-epc.
end.

Objetivo
Especificar a localização para armazenamento de programas
customizados por terceiros.

Implementação
Esta localização deve ser feita a partir de um diretório raiz que deve ter
o nome da empresa que desenvolveu o programa específico. Os diretórios dos
módulos e os nomes dos programas, podem ter o mesmo nome de programas
Datasul.
A diferença fica na chamada destes programas, isto é, para executar um
programa específico e seus sub-programas e includes, deve-se identificar na
chamada destes, o nome do diretório específico, identificando assim, estes
programas como não Datasul.
Este diretório raiz não deve estar sob o diretório do produto, isto é, não
deve ser incluído no diretório do produto Datasul instalado e, sim, em um
diretório de instalação próprio.
No cadastro destes programas no menu, deve-se ter o nome da empresa
que criou o específico, mais o nome do programa como a chave de
identificação. Ainda no cadastro de programas, será necessário colocar o nome
Considerações
Gerais

da empresa que construiu o específico antes do <diretório>/<programa>


desejado como nome externo.
Para finalizar, o PROPATH deve conter sempre o diretório do produto
Datasul em primeiro lugar, isto é, antes do diretório onde estão os específicos.
Para encontrar os programas do específico, basta adicionar ao PROPATH, o
diretório anterior ao nome da empresa que desenvolveu o específico, após o
diretório do produto Datasul.

Exemplo
Caso a empresa XYZ desenvolva programas para o módulo APP, a
localização dos programas específicos desenvolvidos devem ficar em:
C:\EMS20POR\...
C:\<diretório>\XYZ\APP\AP0101.W

Para executar programas Datasul, fazer:


RUN APP\AP0101.W

Para cadastrar o programa no menu, fazer:


Programa : XYZ/AP0101
Nome externo : XYZ/APP/AP0101.W

Para cadastrar uma UPC, fazer:


Programa : XYZ/APP/AP0101.P

O PROPATH fica:

PROPATH = "c:\<datasul>;c:\<diretório>;..."
Obs.: O diretório XYZ está debaixo de c:\<diretório>

a partir do momento que uma EPC for cadastrada para um programa ou


gatilho, sempre que for executado este programa ou gatilho é feita a chamada
para a EPC.
Sendo assim, se a EPC estiver cadastrada de forma incorreta ou não existir, vai
ser gerado um erro Progress, (<programa> was not found (293)).
 nos programas chamados pelas EPCs, em gatilhos de dicionário de dados,
não deve ser solicitado qualquer interação do usuário, ou apresentado
qualquer tipo de tela (frame) ou caixa de mensagem;
xternal Program Call 35

 deve ser feito ainda uma documentação de como construir os programas


EPC, além do descrito acima, e acompanhar a documentação do produto
para o usuários.
 Desaconselhamos que sejam retirados quaisquer objetos(browser, viewer)
de um programa do Datasul EMS utilizando EPCs.
 Deve-se tomar cuidado com eventos para objetos do produto Datasul EMS
Framework, quando se desejar criar um novo evento para um destes
objetos, deve-se contatar o módulo, pois pode-se estar sobrepondo um
evento que é importante para o produto.

Chamar uma EPC de uma trigger de write;


define input parameter buffer p-table for item no-undo.
define input parameter buffer p-old-table for item no-undo.

Find cust-table where cust-table.it-codigo = p-table.it-codigo


then
If not available cust-table then do:
create cust-table.
buffer-copy p-table cust-table.
end.

Chamar uma EPC de uma trigger de delete;


define input parameter buffer p-table for item no-undo.

find cust-table where cust-table.it-codigo = p-table.it-codigo


then
If not available cust-table then do:
create cust-table.
buffer-copy p-table cust-table.
end.

Como acertar TAB-ORDER em uma EPC

Para acertar o tab-order em uma DPC, pode ser feito da seguinte


forma:

Por exemplo, imagine a seguinte frame:

A: [ ]
B: [ ]
C: [ ]

Um programa de customização deve inserir o fill-in D, que está ao lado


de A. Portanto, quando for teclado TAB no fill-in A, ele deverá
posicionar-se no fill-in D.

varD:MOVE-AFTER-TAB-ITEM(varA:HANDLE).

Também, existe o método para mover o fill-in anterior, neste caso:

varD:MOVE-BEFORE-TAB-ITEM(varA:HANDLE).

Você também pode gostar