App PO UI no Protheus e Navegador
Se você quer criar um app Angular que rode tanto no Protheus quanto no navegador, este guia passo a passo vai te ajudar a configurar tudo…
App PO UI no Protheus e Navegador

Se você quer criar um app Angular que rode tanto no Protheus quanto no navegador, este guia passo a passo vai te ajudar a configurar tudo, desde a instalação até a integração completa. Vamos lá!
Link para acesso do repositório no GitHub contendo o código que iremos construir: welersonfrr/po-project
Configuração do Angular
Instalação do Angular CLI e PO-UI
Para começar, precisamos configurar o ambiente Angular e instalar as bibliotecas essenciais para que o projeto funcione corretamente com o Protheus. Vamos criar um novo projeto e preparar tudo para que possamos evoluir nas próximas etapas.
npx -p @angular/cli@17
ng new po-project --skip-install
Escolha as opções padrão:
- Stylesheet: CSS
- SSR e SSG: Não
Entrando na pasta do projeto
cd po-project
Instalando as dependências
npm i @totvs/protheus-lib-core@17
ng add @po-ui/ng-components@17 # Escolha SideMenu = Yes
ng add @po-ui/ng-templates
Abrindo o projeto no VSCode
code .
Criando e ajustando arquivos
Agora que temos o projeto configurado, é hora de criar e ajustar alguns arquivos que garantirão a comunicação entre o Angular e o Protheus. Essas configurações vão desde o tratamento de erros até a recepção de parâmetros do Protheus.
Corrigindo erro do provider window
Arquivo: src/app/app.config.ts
providers: [
… // Demais providers
{ provide: "Window", useValue: window },
]
Detectando a origem da execução
Arquivo: src/app/app.component.ts
import { ProtheusLibCoreModule, ProAppConfigService } from '@totvs/protheus-lib-core';
imports: [
ProtheusLibCoreModule,
... // Demais imports
]
constructor(private proAppConfigService: ProAppConfigService) {
if (this.proAppConfigService.insideProtheus()) {
// Executando no Protheus
} else {
// Executando via Browser
}
}
Criando arquivo para receber parâmetros do Protheus
Arquivo: src/assets/preload/advpltojs.js
(codeType, content) => {
console.log(`Preload - codeType: ${codeType} - content: ${content}`);
if (codeType == 'filiaisComAcesso') {
sessionStorage.setItem('FILIAIS', content);
}
if (codeType == 'currentFilial') {
sessionStorage.setItem('currentFilial', content);
}
if (codeType == 'currentEmpresa') {
sessionStorage.setItem('currentEmpresa', content);
}
}
Configuração do ambiente
A configuração do ambiente é essencial para garantir que nosso app funcione corretamente tanto em desenvolvimento quanto em produção. Vamos definir as variáveis de ambiente necessárias para cada caso.
Desenvolvimento
Arquivo: src/environments/environment.ts
export const environment = {
ambiente: "browser",
url: "URL_REST_DO_SEU_AMBIENTE",
path: {
login: "/api/oauth2/v1/token/",
defaults: "/api/protheus/session/v1/defaults"
},
}
Produção
Arquivo: src/environments/environment.producao.ts
export const environment = {
ambiente: "protheus",
url: "URL_REST_DO_SEU_AMBIENTE",
path: {
login: "/api/oauth2/v1/token/",
defaults: "/api/protheus/session/v1/defaults"
},
}
Ajustes no angular.json para o Build
Substituir em projects > po-project > architect > build > options:
"outputPath": "dist/po-project"
Por:
"outputPath": {
"base": "dist/po-project",
"browser": ""
},
Adicionar em projects > po-project > architect > build > configurations:
"protheus": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.producao.ts"
}
]
}
Com isso, ao rodar ng serve, o app deve estar acessível no navegador.
Configuração do login
Para permitir o acesso seguro ao sistema, precisamos configurar um fluxo de autenticação. Aqui, como exemplo, iremos criar os componentes de login e home, configurar as rotas e garantir que a autenticação funcione corretamente.
Utilizaremos o template PoPageLogin: (https://po-ui.io/documentation/po-page-login)
Criando os componentes
ng g c pages/home
ng g c pages/login
Configurando as rotas
Editaremos nossas rotas para apontar para cada elemento:
Arquivo: src/app/app.routes.ts
export const routes: Routes = [
{ path: "", component: HomeComponent },
{ path: "index.html", redirectTo: "" },
{ path: "login", component: LoginComponent }
];
Alteramos o conteúdo da linha 7 do app.component.html
Aqui é onde nossas rotas serão construídas preservando tudo que está ao redor, como nome da aplicação e sidemenu
Arquivo: src/app/app.component.html
Substituir a linha contendo:
<p> AppName page </p>
Por:
<router-outlet></router-outlet>
Nesse momento, ao salvar, veremos no nosso navegador o conteúdo presente em home.component.html
No arquivo src/app/pages/login.component.html, adicione a chamada do template:
<po-page-login/>
- Lembrando de inserir no login.component.ts o import “PoPageLoginModule”
Se navegarmos na nossa aplicação até a rota “/login” veremos que se encontra de forma estranha

Isso se dá por conta do router-outlet, corrigiremos isso agora:
No arquivo src/app/app.component.ts faça as seguintes alterações:
Declarar o router no constuctor:
constructor(
private router: Router,
... // Demais variaveis
)
Declarar a variavel: excludedRoutes:
excludedRoutes = ['/login']; // Adicione rotas que não devem exibir os wrappers
E finalmente a função:
isExcludedRoute(): boolean {
return this.excludedRoutes.includes(this.router.url);
}
No arquivo src/app/app.component.htmlfaremos as seguintes alteraçoes:
Substituir
<div class="po-wrapper">
Por
<div *ngIf="!isExcludedRoute(); else noWrapper" class="po-wrapper">
Adicionar após o fechamento da ultima <div>
<ng-template #noWrapper>
<router-outlet></router-outlet>
</ng-template>
Com isso nossa rota login ficará fora dos encapsulamentos e será propriamente a página
Tratamento para realização do login via navegador
Nos arquivos de login faremos as seguintes alteraçoes:
Arquivo: src/app/pages/login.component.ts
Declaração e função:
loginSubmit(data: any) {
console.log(data);
}
Arquivo: src/app/pages/login.component.html
Inclusão da chamada dentro da tag:
<po-page-login
(p-login-submit)="loginSubmit($event)"
/>
Com isso ao preenchermos os campos de login e senha e clicar no botao entrar, veremos nosso usuario e senha no console do navegador

Configuração do service de login
Declararemos agora o sevice responsável por realizar a solicitação do Token de autenticação para o protheus
ng g s services/login/login
Alteraremos nosso então criado LoginService da seguinte forma
Arquivo: src/app/services/login/login.service.ts
No constructor iremos adicionar junto aos seus respectivos imports:
constructor (
public httpClient: HttpClient,
private router: Router,
private notification: PoNotificationService
)
Declararemos também as seguintes funções junto aos seus Imports:
submitLogin(data: any) {
const uri = environment.url + environment.path.login
const params: HttpParams = new HttpParams()
.set('grant_type','password')
.set('username', data.login)
.set('password', data.password)
this.httpClient.post(uri, null, { params }).subscribe(
{
next:
(res)=>{
this.updateToken(res)
},
error:
(error: any) => {
this.notification.warning('Usuário ou senha incorretos! por favor verifique.')
},
complete:
() => {
this.notification.success('Login realizado com sucesso!')
this.router.navigate(["/"])
}
}
)
return
}
updateToken(data: any) {
sessionStorage.setItem('ERPTOKEN', JSON.stringify(data))
}
getAccessToken() {
const erpToken = sessionStorage.getItem('ERPTOKEN')
if (erpToken == null) {
this.notification.warning('Por favor realize o login!')
this.router.navigate(["/login"])
} else {
return JSON.parse(erpToken).access_token
}
}
Agora retornaremos ao nosso login.component.ts para algumas alterações:
Arquivo: src/app/pages/login/login.component.ts
Declaramos nosso constructor com seu respectivo import:
constructor (
private loginService: LoginService
)
Adicionamos na nossa função loginSubmit a seguinte chamada:
loginSubmit(data: any) {
console.log(data);
this.loginService.submitLogin(data)
}
Realizadas as alterações, ao retornar para o navegador na rota “/login” você pode testar fazer login com um usuario incorreto e outro correto, você deverá ver os seguintes casos:

Usuario ou senha incorretos

Login realizado corretamente — navega até a home
Outra novidade é que ao abrir o devtools, navegando até a aba Aplicativo, no Armazenamento de sessão, estará presente o ERPTOKEN

Validação de usuario logado
Agora iremos validar se o nosso usuario está logado!
Retornaremos ao arquivo app.component
Arquivo: src/app/app.component.ts
Iremos incluir no constructor o Login Service:
private loginService: LoginService
Colocaremos dentro do if:
// Executando no protheus
this.proAppConfigService.loadAppConfig();
this.router.navigate(['/'])
E no else:
// Executando via Browse
this.loginService.getAccessToken()
Assim ao acessar o app via protheus o loadAppConfig() ficará responsável pelo preenchimento do ERPTOKEN nativamente, enquanto que o acesso por navegador será redirecionado para o login.
Agora prepararemos para chamada de dados de uma API para exemplo de uso do access_token.
Preparação para uso de api
Criamos um interceptor para carregar a autenticação no header das requisiçoes rest, evitando trabalho de carrega-la a cada requisição:
ng g s services/interceptor/interceptor
Vamos fazer as alteraçoes no entao criado InterceptorService
Arquivo: src/app/services/interceptor/interceptor.service.ts
- Faça as importações conforme necessário:
Substituir:
export class InterceptorService {
Por:
export class InterceptorService implements HttpInterceptor {
Adicionar no constructor:
private loginService: LoginService
Declarar a função:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const access_token = this.loginService.getAccessToken()
const clone_request = req.clone({
setHeaders: {
Authorization: `Bearer ${access_token}`
}
})
return next.handle(clone_request)
}
Alteraremos agora o arquivo app.config.ts para que nosso interceptor atue:
Arquivo: src/app/app.config.ts
Pequena alteração no provider:
providers: [
... // Demais providers
provideHttpClient(
withInterceptorsFromDi() // Incluir dentro dos parenteses
),
{provide: HTTP_INTERCEPTORS, useClass: InterceptorService, multi: true}, // Incluir esta linha
... // Demais providers
]
Com isso qualquer requisição http realizada no escopo da aplicação irá carregar consigo o access_token no Header.
Vamos fazer nossa requisição
Criamos mais um service que ficará responsável pela chamada da api:
ng g s services/api/api
No novo ApiService criado vamos fazer as alterações, realizando os imports necessários.
Arquivo: src/app/services/api/api.service.ts
Incluimos no constructor:
private httpClient: HttpClient
Declaramos a função:
getData() {
const url = environment.url + environment.path.defaults
return this.httpClient.get(url)
}
No HomeComponent faremos as alterações juntamente com os imports necessários:
Arquivo: src/app/pages/home/home.component.ts
Importamos o Po Module para uso dos componente da PO-UI
imports: [
PoModule
],
Declaramos uma variável data
data: string = ''
Declaramos o ApiService no constructor
private apiService: ApiService
Declaramos a função getData() responsável por capturar os valores:
getData() {
this.apiService.getData().subscribe({
next:
(req: any) => {
console.log(req); // Verifique no console o retorno completo da api
this.data = req.base_date // O retorno base_date será impresso na tela
},
error:
(err: any) => { },
complete:
() => { }
})
}
Arquivo: src/app/pages/home/home.component.html
Aqui faremos o disparo da chamada da função e impressão na tela
<p>{{data}}</p>
<po-button (p-click)="getData()" p-label="Button"/>
Com isso nosso app esta totalmente preparado para uso pelo navegador!!
Preparação para uso no Protheus
Agora que nosso app está pronto para ser utilizado no navegador, é hora de prepará-lo para rodar dentro do Protheus. Isso envolve a geração dos arquivos necessários e a integração com a plataforma.
Build do projeto
ng build -c protheus
Após a compilação, uma pasta chamada dist será gerada na raiz do projeto. Dentro dela, haverá uma subpasta com o nome da aplicação definida no output-path. Esta pasta deverá ser preparada para uso no Protheus.
Preparação dos arquivos
- Compacte a pasta em formato
.zip:po-project.zip - Renomeie a extensão para
.app:po-project.app - Compile esse arquivo
.appno ambiente Protheus (Se estiver utilizando o VS Code, pode ser necessário incluir a extensão.appna lista de extensões permitidas para compilação).
Criando a função ADVPL
Agora vamos criar uma função ADVPL para chamar a aplicação Angular dentro do Protheus.
Arquivo: TEST001.prw
#include "protheus.ch"
User Function TEST001()
FwCallApp("po-project")
Return
Static Function JsToAdvpl(oWebChannel, cType, cContent)
Local cFCAcss := ''
Local i
if (FWUsrEmp(__cUserID)[1] == '@@@@')
for i := 1 to Len(LoadFils())
cFCAcss += LoadFils()[i] + '-'
next
else
for i := 1 to Len(FWUsrEmp(__cUserID))
cFCAcss += SubString(FWUsrEmp(__cUserID)[i], 3, 6) + '-'
next
endif
oWebChannel:AdvPLToJS('filiaisComAcesso', cFCAcss)
oWebChannel:AdvPLToJS('currentFilial', cFilAnt)
oWebChannel:AdvPLToJS('currentEmpresa', cEmpAnt)
Return .T.
Essa função permite chamar o app Angular pelo menu do Protheus e transferir dados entre o Protheus e a aplicação Angular.
O responsável pela chamada é apenas o FwCallApp, a Static Function JsToAdvplé responsável pela comunicação com o arquivo AdvplToJs presente no app angular.
Neste projeto o AdvplToJsnão foi utilizado mas já esta pronto para uso conforme necessidade.
Acesso via navegador
Com a aplicação configurada, podemos acessá-la via navegador utilizando a seguinte URL:
http://<IP_SERVIDOR_PROTHEUS>:<PORTA>/app-root/po-project/
Por exemplo:
http://127.0.0.1:1234/app-root/po-project/
Considerações finais
Certifique-se de que o servidor Protheus está corretamente configurado para servir aplicações web e que as permissões estão ajustadas conforme necessário.
Agora que finalizamos todas as configurações, temos um app Angular funcional que pode ser acessado tanto via navegador quanto pelo Protheus. Esse tipo de integração permite criar aplicações modernas e responsivas aproveitando o poder do Angular enquanto mantém a compatibilidade com os processos do ERP Protheus.
Se tiver dúvidas ou problemas durante a implementação, revise cada etapa cuidadosamente e consulte a documentação oficial do PO-UI e do Protheus para obter mais detalhes.
Espero que este guia tenha sido útil para você. Boa codificação!
메타데이터
- post_id
- 7bb725faad76
- slug
- app-po-ui-no-protheus-e-navegador-7bb725faad76
- url
- https://medium.com/@contato.welerson/app-po-ui-no-protheus-e-navegador-7bb725faad76
- canonical_url
- https://medium.com/@contato.welerson/app-po-ui-no-protheus-e-navegador-7bb725faad76
- author_url
- https://medium.com/@contato.welerson
- status
- ok
- fetched_at
- 2026-06-28 10:39:35