<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arquivos ADVPL - REST &#8211; Sem Preju</title>
	<atom:link href="https://sempreju.com.br/category/advpl/advpl-rest/feed/" rel="self" type="application/rss+xml" />
	<link>https://sempreju.com.br/category/advpl/advpl-rest/</link>
	<description>Conhecimento Gratuito</description>
	<lastBuildDate>Tue, 12 Jan 2021 00:57:11 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.2</generator>
	<item>
		<title>CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 3</title>
		<link>https://sempreju.com.br/crud-fornecedor-usando-po-ui-angular-e-erp-protheus-part-3/</link>
					<comments>https://sempreju.com.br/crud-fornecedor-usando-po-ui-angular-e-erp-protheus-part-3/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Mon, 01 Feb 2021 13:33:10 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=889</guid>

					<description><![CDATA[<p>Olá pessoal. Nos post anterior vimos: Parte 1 &#8211; Como configurar, testar API no Protheus e listar fornecedores no Angular (PO.UI) aqui. Parte 2 &#8211; Como criar o formulário para inclusão de fornecedor aqui. Dando continuidade na nossa série de criar um CRUD em PO.UI, vamos agora criar as ações<a class="moretag" href="https://sempreju.com.br/crud-fornecedor-usando-po-ui-angular-e-erp-protheus-part-3/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/crud-fornecedor-usando-po-ui-angular-e-erp-protheus-part-3/">CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 3</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Olá pessoal.</p>
<p>Nos post anterior vimos:</p>
<ul>
<li>Parte 1 &#8211; Como configurar, testar API no Protheus e listar fornecedores no Angular (PO.UI) <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/">aqui</a>.</li>
<li>Parte 2 &#8211; Como criar o formulário para inclusão de fornecedor <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/">aqui</a>.</li>
</ul>
<p>Dando continuidade na nossa série de criar um CRUD em PO.UI, vamos agora criar as ações de editar e excluir um fornecedor.</p>
<p>Vamos começar com a <strong>exclusão</strong>, para isso vamos usar a mesma API mas o verbo agora será <b>DELETE </b>ao invés de <strong>GET </strong>ou <strong>POST</strong>. Vamos primeiro testar nossa API e consultar se nosso backend está funcionando corretamente (essa etapa é opcional), para isso vamos usar novamente o Postman, apontando para nossa API passaremos o código + loja do fornecedor como parâmetro na URL, ficando assim, <em>http://localhost:8084/rest/api/crm/v1/customerVendor/2/</em><strong><em>A2_COD+A2_LOJA</em></strong><em>(no lugar de A2_COD+A2_LOJA informe um fornecedor e loja que exista em seu ambiente, e também troque o ip e porta do backend para os seus dados)</em>  como no print abaixo.</p>
<p><img fetchpriority="high" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/02/delete_crud_angular_protheus.jpg" alt="" width="683" height="696" class="aligncenter wp-image-891" srcset="https://sempreju.com.br/wp-content/uploads/2021/02/delete_crud_angular_protheus.jpg 807w, https://sempreju.com.br/wp-content/uploads/2021/02/delete_crud_angular_protheus-295x300.jpg 295w, https://sempreju.com.br/wp-content/uploads/2021/02/delete_crud_angular_protheus-768x782.jpg 768w" sizes="(max-width: 683px) 100vw, 683px" /></p>
<p>A resposta deverá ser um arquivo JSON com a mensagem de registro deletado com sucesso, se tudo ocorreu corretamente aqui, vamos começar a tratar nosso frontend para usar a mesma API.</p>
<p>&nbsp;</p>
<p id="1b51" class="gl gm do gn b go jw gq gr gs jx gu gv gw jy gy gz ha jz hc hd he ka hg hh hi dh ci" data-selectable-paragraph="">A Primeira etapa do FrontEnd será ajustar o componente de lista fornecedores para adicionar duas novas ações para cada item na lista(editar e excluir), para isso altere o arquivo supplier-list.component.ts e deixe como o código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { PoNotificationService, PoTableAction } from '@po-ui/ng-components';
import { SupplierListService } from './supplier-list.service';

@Component({
  selector: 'app-supplier-list',
  templateUrl: './supplier-list.component.html',
  styleUrls: &#x5B;'./supplier-list.component.css']
})
export class SupplierListComponent implements OnInit {

  supplierList: Array&amp;amp;lt;any&amp;amp;gt; = new Array();
  colunasTable: Array&amp;amp;lt;any&amp;amp;gt; = new Array();

  //Parte 3 
  //Adicionado ação deleter e editar
  actions: Array&amp;amp;lt;PoTableAction&amp;amp;gt; = &#x5B;
    { action: this.updateSupplier.bind(this), icon: 'po-icon-edit', label: 'Alterar Fornecedor'},
    { action: this.deleteSupplier.bind(this), icon: 'po-icon-delete', label: 'Excluir Fornecedor' }
  ];

  //Parte 3 
  //método para editar
  updateSupplier(row: any) {
    console.log('Edit');
    const supplierId = row.code + row.storeId;
    this.router.navigate(&#x5B;`/supplierform/${supplierId}/${row.type}`]);
  }
    
  //Parte 3 
  //método para deleter o fornecedor
  deleteSupplier(row: any) {
    console.log('deleteSupplier');
    const supplierId = row.code + row.storeId;
    this.SupplierListService
    .deleteSupplier(supplierId, row.type)
    .subscribe(() =&amp;amp;gt; {
      this.updateSupplierList(); //atualiza a lista
      this.poNotification.success('o Fornecedor foi excluido com sucesso');
    }
    , err =&amp;amp;gt; this.poNotification.error(err)); //exibe erro 
  }
  constructor(private SupplierListService: SupplierListService,
    private router: Router,
    private poNotification: PoNotificationService) { }

  ngOnInit(): void {
    this.updateSupplierList(); //busca a lista de fornecedores do nosso Api
    this.colunasTable = this.SupplierListService.getColumns(); //atualiza as colunas que queremos ser listadas em nossa tabela.
  }
  //Metódo responsável por se isncrever no serviço e atualizar a lista de fornecedores
  updateSupplierList(): void {
    this.SupplierListService.getSupplierList().subscribe(response =&amp;amp;gt; {
      this.supplierList = response.items;
    });
  }
}</pre>
<p>Foram incluídos:</p>
<ul>
<li>Nova variável chamada <em>actions</em> com as ações que desejamos em nossa lista.</li>
<li>Novos métodos
<ul>
<li><strong>updateSupplier</strong>, será responsável por atualizar um fornecedor (opção de editar).</li>
<li>
<div>
<div><span><strong>deleteSupplier</strong>, será responsável por deletar um fornecedor.</span></div>
<div></div>
</div>
</li>
</ul>
</li>
</ul>
<p>Agora devemos ajustar o arquivo supplier-list.service.ts e incluir o método responsável por enviar para nossa API a requisição de exclusão, o arquivo final deve ficar como o código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { PoTableColumn } from '@po-ui/ng-components';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SupplierListService {

  ApiRest = 'http://localhost:8084/rest/api/crm/v1/customerVendor'; //Endereço da nossa API responsável por lista os fornecedores
  
  constructor(private http: HttpClient) { }

  //Método responsável por buscar e listar nossos fornecedores
  getSupplierList(): Observable&lt;any&gt; {
    return this.http.get(this.ApiRest + `/2`); //supplier
  }

  
  //Método para remover Fornecedor
  deleteSupplier(Id: string, type: string = '2') {
    return this.http.delete(this.ApiRest + `/${type}/${Id}`);
  }


  //Método responsável por converter em nomes mais legiveis para usuário
  getColumns(): Array&lt;PoTableColumn&gt; {
    return &#x5B;
      { property: 'code', label: 'Código'},
      { property: 'storeId', label: 'Loja' },
      { property: 'name', label: 'Nome' },
      { property: 'strategicCustomerType', label: 'Fisica/Juridica' ,
        type: 'label', //part3 add 
        labels: &#x5B;
          { value: 'F',color: 'color-08', label: 'Física' },
          { value: 'J', color: 'color-12',label: 'Juridica' }
        ] },
      { property: 'registerSituation', label: 'Situação' ,
      type: 'label', //part3 add 
      labels: &#x5B;
        { value: '1', color: 'color-07', label: 'Inativo' },
        { value: '2', color: 'color-11', label: 'Ativo' },
        { value: '3', color: 'color-09', label: 'Cancelado' },
        { value: '4', color: 'color-12', label: 'Pendente' },
        { value: '5', color: 'color-08', label: 'Suspenso' }
      ]  },
    ];
  }
}
</pre>
<p>E para finalizar a opção de excluir, vamos alterar o arquivo supplier-list.component.html e no component po-table adicionar as nossas ações, o arquivo final deve ficar como o código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
&lt;po-page-default p-title=&quot;Lista de Fornecedores&quot;&gt;
    &lt;po-table
      p-container=&quot;light&quot;
      &#x5B;p-columns]=&quot;colunasTable&quot;
      &#x5B;p-items]=&quot;supplierList&quot;
      &#x5B;p-actions]=&quot;actions&quot;&gt;&lt;!--  adicionado part 3 --&gt;
    &lt;/po-table&gt;
  &lt;/po-page-default&gt;
</pre>
<p>Para finalizarmos nossa série e fazer a edição de um registro, vamos precisar primeiramente incluir uma nova rota (vamos reutilizar o mesmo form de inclusão mas agora vamos receber na URL o código + loja do fornecedor, para isso no arquivo app-routing.module.ts, vamos criar uma nova rota que receberá 2 parâmetros, um o ID do nosso fornecedor e outro para o tipo (nosso caso será sempre 2 = fornecedor, mas poderíamos editar facilmente um cliente por exemplo), o arquivo final deve ficar como o código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SupplierListComponent } from './supplier-list/supplier-list.component';
import { SupplierFormComponent } from './supplier-form/supplier-form.component';
const routes: Routes = &#x5B;
  { path: '', component: SupplierListComponent },
  { path: 'supplier', component: SupplierListComponent }, //lista de fornecedor
  { path: 'supplierform', component: SupplierFormComponent }, //form do fornecedor - Incluir
  { path: 'supplierform/:id/:type', component: SupplierFormComponent }, //form do fornecedor - Editar
];
@NgModule({
  imports: &#x5B;RouterModule.forRoot(routes)],
  exports: &#x5B;RouterModule]
})
export class AppRoutingModule { }
</pre>
<p>Alteraremos também o arquivo supplier-form.component.ts, nele vamos precisar:<br />
No ngOninit, vamos verificar se em nossa URL temos os parametros ID e Tipo (criados na nossa rota) se encontrar significa que estamos editando um fornecedor e nesse caso vamos carregar os dados do fornecedor e mudar o titulo da página.<br />
Vamos criar a ação no novo botão &#8220;atualizar&#8221; para confirmar alterações em um forncedor (esse botão será criado no HTML do form, logo abaixo).</p>
<p>O arquivo supplier-form.component.ts deve ficar como o código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { PoDynamicFormField, PoNotificationService } from '@po-ui/ng-components';
import { Supplier } from '../model/supplierModel';
import { SupplierFormService } from './supplier-form.service';
import { first } from 'rxjs/operators';

@Component({
  selector: 'app-supplier-form',
  templateUrl: './supplier-form.component.html',
  styleUrls: &#x5B;'./supplier-form.component.css']
})
export class SupplierFormComponent implements OnInit {

  //fields: Array&lt;PoDynamicFormField&gt; = &#x5B;]; //campos &quot;dinamicos&quot; para usar no formulário
  supplier: Supplier = new Supplier();//model de um fornecedor
  supplierValues = {    type: 2, code: &quot;&quot;, storeId: &quot;&quot;, shortName: &quot;&quot;, name: &quot;&quot;, strategicCustomerType: &quot;J&quot;, entityType: &quot;J&quot;,
  number: &quot;&quot;, address: &quot;&quot;, zipCode: &quot;&quot;, stateId: &quot;&quot;, stateInternalId: &quot;&quot;, registerSituation: &quot;1&quot;,
  stateDescription: &quot;&quot;, complement: &quot;&quot;, district: &quot;&quot;, cityCode: &quot;&quot;, cityDescription: &quot;&quot;}; //array com os valores do fomulário
  supplierType: string | any = '2'; //no nosso exemplo será sempre 2=fornecedor, mas poderia ser 1=cliente
  supplierId: string | any;
  title = 'Inclusão de Fornecedor';

  constructor(private supplierFormService: SupplierFormService, //servico do form
    private poNotification: PoNotificationService, //usar as notificações do PO.UI
    private route: ActivatedRoute,
    private router: Router,
  ) { }

  ngOnInit(): void {
    //define valores padrão para formulário
    this.supplierValues = {
      type: 2, code: &quot;&quot;, storeId: &quot;&quot;, shortName: &quot;&quot;, name: &quot;&quot;, strategicCustomerType: &quot;J&quot;, entityType: &quot;J&quot;,
      number: &quot;&quot;, address: &quot;&quot;, zipCode: &quot;&quot;, stateId: &quot;&quot;, stateInternalId: &quot;&quot;,registerSituation: &quot;1&quot;,
      stateDescription: &quot;&quot;, complement: &quot;&quot;, district: &quot;&quot;, cityCode: &quot;&quot;, cityDescription: &quot;&quot;
    }
    this.route.paramMap.subscribe(parameters =&gt; {
      this.supplierId = parameters.get('id');
      this.supplierType = parameters.get('type');
    });

    if (this.supplierId) { //se tem o ID na URL, significa alteração
      this.title = 'Alteração de Fornecedor';
      this.setFormValue(); //atribui os valores do API para o formulário
    }
  }

  //Método para inserir um novo fornecedor
  insertSupplier(): void {
    this.getSupplierFromForm();
    this.supplierFormService.postNewSupplier(JSON.stringify(this.supplier)) //grava o novo fornecedor
      .pipe(first())
      .subscribe(() =&gt; {
        this.poNotification.success('Fornecedor foi inserido com Sucesso');
        this.router.navigate(&#x5B;'/supplier']); //redireciona para lista de fornecedor
      }, err =&gt; {
        //se error devolve o erro do Backend para o usuário
        let messErr = JSON.parse(err.error.errorMessage);
        this.poNotification.error(`Erro código ${messErr.code},  ${decodeURIComponent(escape(messErr.message))}, detalhe: ${decodeURIComponent(escape(messErr.detailedMessage))}.`)
      }
        
        ); //exibe erro ao inserir fornecedor
  }

   //alimenta o modelo de dados
  private getSupplierFromForm(): void {
    // dados pessoais
    this.supplier.code = this.supplierValues.code;
    this.supplier.storeId = this.supplierValues.storeId;
    this.supplier.name = this.supplierValues.name;
    this.supplier.shortName = this.supplierValues.shortName;
    this.supplier.strategicCustomerType = this.supplierValues.strategicCustomerType;
    this.supplier.entityType = this.supplierValues.entityType;
    this.supplier.type = this.supplierValues.type;
    this.supplier.registerSituation = this.supplierValues.registerSituation;

    // Endereço
    this.supplier.address.address = this.supplierValues.address;
    this.supplier.address.city.cityCode = this.supplierValues.cityCode;
    this.supplier.address.city.cityDescription = this.supplierValues.cityCode;
    this.supplier.address.city.cityInternalId = this.supplierValues.cityCode;
    this.supplier.address.state.stateId = this.supplierValues.stateId;
    this.supplier.address.state.stateInternalId = this.supplierValues.stateId;



  }

  //part 3
  //Método para editar um fornecedor
  updateSupplier(): void {
    this.getSupplierFromForm(); //seta no modelo fornecedor os valores do Formulário para então enviar para API
    this.supplierFormService
      .putSupplier(this.supplier.code + this.supplier.storeId, JSON.stringify(this.supplier), this.supplierType)
      .pipe(first())
      .subscribe(() =&gt; {
        this.poNotification.success('Fornecedor alterado com Sucesso');
        this.router.navigate(&#x5B;'/supplier']);//redireciona para lista de fornecedor
      }, err =&gt; this.poNotification.error(err));//exibe erro ao editar fornecedor
  }


  //part 3
  //Método para atribuir valores aos campos para formulário
  private setFormValue(): void {
    this.supplierFormService
      .getSupplier(this.supplierId, this.supplierType)
      .pipe(first())
      .subscribe((supplier:Supplier) =&gt; {
        console.log(supplier);
        this.supplierValues.code = supplier.code;
        this.supplierValues.storeId = supplier.storeId;
        this.supplierValues.name = supplier.name;
        this.supplierValues.shortName = supplier.shortName;
        this.supplierValues.strategicCustomerType = supplier.strategicCustomerType;
        this.supplierValues.entityType = supplier.strategicCustomerType;
        this.supplierValues.type = supplier.type;
        this.supplierValues.registerSituation = supplier.registerSituation;
        // Endereço
        this.supplierValues.address = supplier.address.address;
        this.supplierValues.cityCode = supplier.address.city.cityCode;
        this.supplierValues.cityCode = supplier.address.city.cityDescription;
        this.supplierValues.cityCode = supplier.address.city.cityInternalId;
        this.supplierValues.stateId = supplier.address.state.stateId;
        this.supplierValues.stateId = supplier.address.state.stateInternalId;

      });

  }



  //array para definir os nomes dos campos do formulário
  fields: Array&lt;PoDynamicFormField&gt; = &#x5B;
    {
      property: 'code',
      label: 'Código',
      divider: 'Dados Pessoais',
      maxLength: 6
    },
    {
      property: 'storeId',
      label: 'Loja',
      maxLength: 2
    },
    {
      property: 'name',
      label: 'Nome',
      maxLength: 40
    },
    {
      property: 'shortName',
      label: 'Nome Reduzido',
      maxLength: 20
    },
    {
      property: 'strategicCustomerType',
      label: 'Tipo do cliente',
      options: &#x5B;
        { label: 'Cons. Final', value: 'F' },
        { label: 'Produtor Rural', value: 'L' },
        { label: 'Revendedor', value: 'R' },
        { label: 'Solidario', value: 'S' },
        { label: 'Exportação', value: 'X' }
      ]
    },
    {
      property: 'entityType',
      label: 'Tipo da entidade',
      options: &#x5B;
        { label: 'Juridica', value: 'J' },
        { label: 'Fisica', value: 'F' }
      ]
    },
    {
      property: 'registerSituation', //Campo: A1_MSBLQL / A2_MSBLQL  == Status: 1 - Ativo, 2 - Inativo, 3 - Cancelado, 4 - Pendente, 5 -Suspenso
      label: 'Situação(MSBLQL)',
      options: &#x5B;
        { label: 'Inativo', value: '1' },
        { label: 'Ativo', value: '2' }
      ]
    },
    {
      property: 'type',
      label: 'Tipo',
      options: &#x5B;
        { label: 'Cliente', value: 1 },
        { label: 'Fornecedor', value: 2 }
      ]
    },
    {
      property: 'zipCode',
      label: 'CEP',
      divider: 'Endereço',
      maxLength: 9
    },
    {
      property: 'address',
      label: 'Endereço'
    },
    {
      property: 'cityCode',
      label: 'Cidade',
      options: &#x5B;
        { label: 'Adolfo', value: '00204' },
        { label: 'São José do Rio Preto', value: '49805' },
        { label: 'José Bonifácio', value: '25706' },
        { label: 'Joinville', value: '09102' }
      ]
    },
    {
      property: 'stateId',
      label: 'Estado',
      options: &#x5B;
        { label: 'Santa Catarina', value: 'SC' },
        { label: 'São Paulo', value: 'SP' },
        { label: 'Rio de Janeiro', value: 'RJ' },
        { label: 'Minas Gerais', value: 'MG' }
      ]
    },
    /*{
      property: 'branchId',
      label: 'Filial',
      divider: 'Sistemico'
    },
    {
      property: 'companyInternalId',
      label: 'Empresa'
    }*/
  ]
}
</pre>
<p><span>Agora a ultima etapa é ajustar o html que irá exibir os dados do nosso formulário para o usuário, para isso, edite o arquivo supplier-form.component.html, nele temos dois botões que serão exibidos em momentos diferentes, um para inclusão (action insertSupplier) e outro para alteração(updateSupplier), o que controlará quando cada um deve aparecer é a variavel no *ngIf, e deixe com a seguinte informação:</span></p>
<pre class="brush: xml; light: false; title: ; toolbar: true; notranslate">
&lt;po-page-default &#x5B;p-title]=&quot;title&quot;&gt;
  &lt;po-dynamic-form #dynamicForm &#x5B;p-fields]=&quot;fields&quot; &#x5B;p-value]=&quot;supplierValues&quot;&gt;
  &lt;/po-dynamic-form&gt;

  &lt;div class=&quot;thf-row&quot;&gt;
    &lt;po-button class=&quot;thf-md-3&quot; 
    *ngIf=&quot;!this.supplierId&quot; 
    p-label=&quot;Inserir&quot; 
    (p-click)=&quot;insertSupplier()&quot;&gt;
    &lt;/po-button&gt;
  &lt;/div&gt;

  &lt;po-button 
    *ngIf=&quot;this.supplierId&quot; 
    class=&quot;thf-md-3&quot; 
    p-label=&quot;Atualizar Fornecedor&quot; 
    (p-click)=&quot;updateSupplier()&quot;&gt;
  &lt;/po-button&gt;
&lt;/po-page-default&gt;
</pre>
<p>Após todas essas etapas, ao acessar o endereço <a href="http://localhost:4200/supplier">http://localhost:4200/supplier</a>, deve ser exibida a lista de fornecedores, se clicarmos nas ações e em excluir, o mesmo deve ser removido e a lista carregada, se selecionarmos a opção editar, o formulário deve ser aberto com os dados preenchidos, o resultado final da lista será semelhante ao print abaixo:</p>
<p><img decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/02/lista-forneedores.jpg" alt="" width="1366" height="337" class="aligncenter size-full wp-image-894" srcset="https://sempreju.com.br/wp-content/uploads/2021/02/lista-forneedores.jpg 1366w, https://sempreju.com.br/wp-content/uploads/2021/02/lista-forneedores-300x74.jpg 300w, https://sempreju.com.br/wp-content/uploads/2021/02/lista-forneedores-1024x253.jpg 1024w, https://sempreju.com.br/wp-content/uploads/2021/02/lista-forneedores-768x189.jpg 768w" sizes="(max-width: 1366px) 100vw, 1366px" /></p>
<p>&nbsp;</p>
<p>O código fonte desse e de outros exemplos podem ser encontrados em nosso <a href="https://github.com/llrafaell/SemPreju-Exemplos">git</a> oficial.</p>
<p><em>Post interessantes:</em></p>
<p>Aprenda a instalar o Protheus no Windows <a href="https://sempreju.com.br/tag/instalarprotheuswindows/">aqui</a>.</p>
<p>Aprenda a instalar o Protheus no Linux <a href="https://sempreju.com.br/tag/instalarprotheuslinux/">aqui</a>.</p>
<p>configurar serviço rest <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">aqui</a>.</p>
<p>Retornar datas por extenso <a href="https://sempreju.com.br/datas-por-extenso-no-protheus/">aqui</a>.</p>
<p>Barras de progresso <a href="https://sempreju.com.br/como-fazer-barras-de-progresso-no-advpl/">aqui</a>.</p>
<p>Dúvidas e sugestões, entre em contato.</p>
<p>Obrigado e até a próxima!</p>
<p>O post <a href="https://sempreju.com.br/crud-fornecedor-usando-po-ui-angular-e-erp-protheus-part-3/">CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 3</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/crud-fornecedor-usando-po-ui-angular-e-erp-protheus-part-3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 2</title>
		<link>https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/</link>
					<comments>https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Tue, 12 Jan 2021 14:25:09 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=864</guid>

					<description><![CDATA[<p>Olá pessoal No post anterior(veja aqui), configuramos nosso ambiente e criamos a listagem de fornecedores, vamos agora continuar com os próximos passos. Vamos agora criar a rotina para cadastrar um novo fornecedor, para isso vamos usar a mesma API mas o verbo agora será POST ao invés de GET. Vamos<a class="moretag" href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/">CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 2</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Olá pessoal</p>
<p>No post anterior(veja <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/">aqui</a>), configuramos nosso ambiente e criamos a listagem de fornecedores, vamos agora continuar com os próximos passos. Vamos agora criar a rotina para cadastrar um novo fornecedor, para isso vamos usar a mesma API mas o verbo agora será <strong>POST</strong> ao invés de <strong>GET</strong>. Vamos primeiro testar nossa API e consultar se nosso backend está funcionando corretamente (essa etapa é opcional), para isso vamos usar novamente o Postman.</p>
<p>Desta vez usaremos o verbo post a url apontando para nossa API e o Body da requisição será um arquivo do tipo JSON com os dados do fornecedor que queremos incluir, como no print abaixo.</p>
<p><img decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/01/post.jpg" alt="" width="623" height="679" class="aligncenter wp-image-868" srcset="https://sempreju.com.br/wp-content/uploads/2021/01/post.jpg 768w, https://sempreju.com.br/wp-content/uploads/2021/01/post-275x300.jpg 275w" sizes="(max-width: 623px) 100vw, 623px" /></p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
 {            
    &quot;type&quot;: 2,
    &quot;code&quot;: &quot;805539&quot;,
    &quot;storeId&quot;: &quot;01&quot;,    
    &quot;shortName&quot;: &quot;FORN 1              &quot;,
    &quot;name&quot;: &quot;FORNECEDOR 99                           &quot;   ,
    &quot;strategicCustomerType&quot;: &quot;J&quot;,
    &quot;entityType&quot;:&quot;J&quot;,
    &quot;address&quot;: {
                &quot;address&quot;: &quot;RUA SEMPREJU                            &quot;,
                &quot;state&quot;: {
                    &quot;stateId&quot;: &quot;SP&quot;,
                    &quot;stateInternalId&quot;: &quot;SP&quot;
                },
                &quot;city&quot;: {
                    &quot;cityCode&quot;: &quot;00204&quot;
                }
            }
}       

</pre>
<p>A resposta deverá ser um arquivo JSON com todos os dados no nosso fornecedor, se tudo ocorreu corretamente aqui, vamos começar a tratar nosso frontend para usar a mesma API.</p>
<h1 data-selectable-paragraph=""></h1>
<h1 id="6833" class="jb jc do av aw jd je gq jf jg jh gu ji jj jk jl jm jn jo jp jq jr js jt ju jv ci" data-selectable-paragraph="">Criando Formulário para Inclusão do Fornecedor</h1>
<p id="1b51" class="gl gm do gn b go jw gq gr gs jx gu gv gw jy gy gz ha jz hc hd he ka hg hh hi dh ci" data-selectable-paragraph="">A Primeira etapa do FrontEnd será criar o módulo, o serviço e o componente que iremos trabalhar<span>, vamos executar os seguintes comandos(um de cada vez):</span></p>
<blockquote>
<p id="16d9" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph=""><em class="kb">ng generate module supplier-form</em></p>
<p id="d260" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph=""><em class="kb">ng generate service supplier-form\supplier-form</em></p>
<p id="a2eb" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph=""><em class="kb">ng generate component supplier-form</em></p>
</blockquote>
<p data-selectable-paragraph=""><span>Após isso deverá ter sido criada em seu projeto uma estrutura parecida com a imagem abaixo.</span></p>
<p data-selectable-paragraph=""><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/01/CRUD-PO.UI-Form.jpg" alt="" width="373" height="210" class="aligncenter size-full wp-image-872" srcset="https://sempreju.com.br/wp-content/uploads/2021/01/CRUD-PO.UI-Form.jpg 373w, https://sempreju.com.br/wp-content/uploads/2021/01/CRUD-PO.UI-Form-300x169.jpg 300w" sizes="(max-width: 373px) 100vw, 373px" /></p>
<p id="c793" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph="">Antes de iniciarmos a codificação do nosso service e compomente, vamos criar alguns models para refletir o formato da entidade na TOTVS(Entidade Fornecedor retornada pelo WS, criamos somente os campos que vamos usar aqui no WS o correto seria criar a entidade toda). Para isso criamos uma pasta em nosso projeto chama model, e dentro dela os arquivos abaixo:</p>
<blockquote>
<p data-selectable-paragraph="">supplierModel.ts</p>
</blockquote>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { Address } from './addressModel';

export class Supplier {
    companyInternalId: string;
    code: string ;
    name: string;
    storeId: string ;
    shortName: string;
    strategicCustomerType: string;
    registerSituation: string;
    type: number;
    entityType: string;
    address: Address = new Address();
    constructor(obj = {}) {
        Object.assign(this, obj);
    }
}
</pre>
<blockquote>
<p data-selectable-paragraph="">addressModel.ts</p>
</blockquote>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { State } from './stateModel';
import { City } from './cityModel';

export class Address {
  address: string ;
  number: string ;
  zipCode: string ;
  complement: string ;
  district: string ;
  city: City = new City();
  state: State = new State();
  constructor(obj = {}) {
    Object.assign(this, obj);
}
}
 </pre>
<blockquote>
<p data-selectable-paragraph="">cityModel.ts</p>
</blockquote>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
export class City {
    cityCode: string ;
    cityInternalId: string ;
    cityDescription: string ;
    constructor(obj = {}) {
        Object.assign(this, obj);
    }
  }
 </pre>
<blockquote>
<p data-selectable-paragraph="">stateModel.ts</p>
</blockquote>
<pre class="brush: xml; light: false; title: ; toolbar: true; notranslate">
export class State {
    stateId: string ;
    stateInternalId: string ;
    stateDescription: string ;
    constructor(obj = {}) {
        Object.assign(this, obj);
    }
  }
 
</pre>
<p>O resultado final deverá ser uma para como o print abaixo:<br />
<img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/01/model_CRUD_PO.UI_.jpg" alt="" width="346" height="131" class="aligncenter size-full wp-image-874" srcset="https://sempreju.com.br/wp-content/uploads/2021/01/model_CRUD_PO.UI_.jpg 346w, https://sempreju.com.br/wp-content/uploads/2021/01/model_CRUD_PO.UI_-300x114.jpg 300w" sizes="(max-width: 346px) 100vw, 346px" /></p>
<p>&nbsp;</p>
<p>Criaremos a seguir a rota para o nosso novo componente, para isso edite o arquivo<em> app-routing.module.ts</em> e adicione as informações do novo componente, abaixo o resultado deve ser semelhante ao fonte abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';


import { SupplierListComponent } from './supplier-list/supplier-list.component';
import { SupplierFormComponent } from './supplier-form/supplier-form.component';

const routes: Routes = &#x5B;
  { path: '', component: SupplierListComponent },
  { path: 'supplier', component: SupplierListComponent }, //lista de fornecedor
  { path: 'supplierform', component: SupplierFormComponent }, //form do fornecedor - inlcuir
];

@NgModule({
  imports: &#x5B;RouterModule.forRoot(routes)],
  exports: &#x5B;RouterModule]
})
export class AppRoutingModule { }
</pre>
<p><span>Agora só falta incluirmos nosso novo componente dentro do arquivo <em>app.module.ts</em> para podermos iniciar a codificação do formulário, o resultado final será semelhante ao código abaixo:</span></p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PoModule } from '@po-ui/ng-components';
import { RouterModule } from '@angular/router';
import { PoNotificationModule  } from '@po-ui/ng-components';
import { PoDynamicModule } from '@po-ui/ng-components';
import { PoButtonModule } from '@po-ui/ng-components';
import {PoTemplatesModule  } from '@po-ui/ng-templates';

//incluir o componente para lista de fornecedores
import { SupplierListComponent } from './supplier-list/supplier-list.component';
import { SupplierFormComponent } from './supplier-form/supplier-form.component'; //formulario de inclusão/alteração

@NgModule({
  declarations: &#x5B;
    AppComponent,SupplierListComponent,SupplierFormComponent
  ],
  imports: &#x5B;
    PoNotificationModule,PoDynamicModule,PoButtonModule  ,PoTemplatesModule,
    BrowserModule,
    AppRoutingModule,
    PoModule,
    RouterModule.forRoot(&#x5B;])
  ],
  providers: &#x5B;],
  bootstrap: &#x5B;AppComponent]
})
export class AppModule { }

</pre>
<p>&nbsp;</p>
<p><span>No arquivo supplier-form.service.ts vamos criar o serviço responsável por enviar para nossa API os dados de um novo fornecedor para ser registrado, por agora esse aquivo é bem simples e somente realizar um post na API, abaixo o fonte que usamos(atenção para o endereço do seu backend):</span></p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { Supplier } from '../model/supplierModel';

@Injectable({
  providedIn: 'root'
})
export class SupplierFormService {

 //Endereço de nosso backend
  ApiRest = 'http://localhost:8084/rest/api/crm/v1/customerVendor';
  
  constructor(private http: HttpClient) { }
  
  //Metódo para criar um novo Fornecedor
  postNewSupplier(body: string) {
    return this.http.post(this.ApiRest, body );
  }

}

</pre>
<p>&nbsp;</p>
<p><span>No arquivo supplier-form.component.ts vamos criar o nosso tratamento do formulário, vamos usar o componente do PO.UI chamado <a href="https://po-ui.io/documentation/po-dynamic-form"><em>po-dynami-form</em></a>  que facilita bastante a criação de formulário, no nosso componente vamos definir as colunas do formulário através do array <em>fields</em> , o método </span>getSupplierFromForm, será responsável de pegar as informações no form e incluir no modelo &#8220;Supplier&#8221; (json esperado pela nossa API), e o método insertSupplier, será o reponsavel de chamar nosso serviço de post na API e apresetar mensagem de sucesso (em caso de sucesso, vamos redirecionar o usuári para nossa lista de fornecedores) ou falha, o código final deverá ser semelhante ao fonte abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { PoDynamicFormField, PoNotificationService } from '@po-ui/ng-components';
import { Supplier } from '../model/supplierModel';
import { SupplierFormService } from './supplier-form.service';
import { first } from 'rxjs/operators';

@Component({
  selector: 'app-supplier-form',
  templateUrl: './supplier-form.component.html',
  styleUrls: &#x5B;'./supplier-form.component.css']
})
export class SupplierFormComponent implements OnInit {

  //fields: Array&amp;amp;lt;PoDynamicFormField&amp;amp;gt; = &#x5B;]; //campos &quot;dinamicos&quot; para usar no formulário
  supplier: Supplier = new Supplier();//model de um fornecedor
  supplierValues = {    type: 2, code: &quot;&quot;, storeId: &quot;&quot;, shortName: &quot;&quot;, name: &quot;&quot;, strategicCustomerType: &quot;J&quot;, entityType: &quot;J&quot;,
  number: &quot;&quot;, address: &quot;&quot;, zipCode: &quot;&quot;, stateId: &quot;&quot;, stateInternalId: &quot;&quot;,
  stateDescription: &quot;&quot;, complement: &quot;&quot;, district: &quot;&quot;, cityCode: &quot;&quot;, cityDescription: &quot;&quot;}; //array com os valores do fomulário
  supplierType: string | any = '2'; //no nosso exemplo será sempre 2=fornecedor, mas poderia ser 1=cliente
  supplierId: string | any;
  title = 'Inclusão de Fornecedor';

  constructor(private supplierFormService: SupplierFormService, //servico do form
    private poNotification: PoNotificationService, //usar as notificações do PO.UI
    private route: ActivatedRoute,
    private router: Router,
  ) { }

  ngOnInit(): void {
    //define valores padrão para formulário
    this.supplierValues = {
      type: 2, code: &quot;&quot;, storeId: &quot;&quot;, shortName: &quot;&quot;, name: &quot;&quot;, strategicCustomerType: &quot;J&quot;, entityType: &quot;J&quot;,
      number: &quot;&quot;, address: &quot;&quot;, zipCode: &quot;&quot;, stateId: &quot;&quot;, stateInternalId: &quot;&quot;,
      stateDescription: &quot;&quot;, complement: &quot;&quot;, district: &quot;&quot;, cityCode: &quot;&quot;, cityDescription: &quot;&quot;
    }
  }

  //Método para inserir um novo fornecedor
  insertSupplier(): void {
    this.getSupplierFromForm();
    this.supplierFormService.postNewSupplier(JSON.stringify(this.supplier)) //grava o novo fornecedor
      .pipe(first())
      .subscribe(() =&amp;amp;gt; {
        this.poNotification.success('Fornecedor foi inserido com Sucesso');
        this.router.navigate(&#x5B;'/supplier']); //redireciona para lista de fornecedor
      }, err =&amp;amp;gt; {
        //se error devolve o erro do Backend para o usuário
        let messErr = JSON.parse(err.error.errorMessage);
        this.poNotification.error(`Erro código ${messErr.code},  ${decodeURIComponent(escape(messErr.message))}, detalhe: ${decodeURIComponent(escape(messErr.detailedMessage))}.`)
      }
        
        ); //exibe erro ao inserir fornecedor
  }
  //alimenta o modelo de dados
  private getSupplierFromForm(): void {
    // dados pessoais
    this.supplier.code = this.supplierValues.code;
    this.supplier.storeId = this.supplierValues.storeId;
    this.supplier.name = this.supplierValues.name;
    this.supplier.shortName = this.supplierValues.shortName;
    this.supplier.strategicCustomerType = this.supplierValues.strategicCustomerType;
    this.supplier.entityType = this.supplierValues.entityType;
    this.supplier.type = this.supplierValues.type;
    // sistemicos
   // this.supplier.branchId = this.supplierValues.branchId;
   // this.supplier.companyInternalId = this.supplierValues.companyInternalId;
    // Endereço
    this.supplier.address.address = this.supplierValues.address;
    this.supplier.address.city.cityCode = this.supplierValues.cityCode;
    this.supplier.address.city.cityDescription = this.supplierValues.cityCode;
    this.supplier.address.city.cityInternalId = this.supplierValues.cityCode;
    this.supplier.address.state.stateId = this.supplierValues.stateId;
    this.supplier.address.state.stateInternalId = this.supplierValues.stateId;
  }

  //array para definir os nomes dos campos do formulário
  fields: Array&amp;amp;lt;PoDynamicFormField&amp;amp;gt; = &#x5B;
    {
      property: 'code',
      label: 'Código',
      divider: 'Dados Pessoais',
      maxLength: 6
    },
    {
      property: 'storeId',
      label: 'Loja',
      maxLength: 2
    },
    {
      property: 'name',
      label: 'Nome',
      maxLength: 40
    },
    {
      property: 'shortName',
      label: 'Nome Reduzido',
      maxLength: 20
    },
    {
      property: 'strategicCustomerType',
      label: 'Tipo do cliente',
      options: &#x5B;
        { label: 'Cons. Final', value: 'F' },
        { label: 'Produtor Rural', value: 'L' },
        { label: 'Revendedor', value: 'R' },
        { label: 'Solidario', value: 'S' },
        { label: 'Exportação', value: 'X' }
      ]
    },
    {
      property: 'entityType',
      label: 'Tipo da entidade',
      options: &#x5B;
        { label: 'Juridica', value: 'J' },
        { label: 'Fisica', value: 'F' }
      ]
    },
    {
      property: 'registerSituation',
      label: 'Situação',
      options: &#x5B;
        { label: 'Inativo', value: '1' },
        { label: 'Ativo', value: '2' }
      ]
    },
    {
      property: 'type',
      label: 'Tipo',
      options: &#x5B;
        { label: 'Cliente', value: 1 },
        { label: 'Fornecedor', value: 2 }
      ]
    },
    {
      property: 'zipCode',
      label: 'CEP',
      divider: 'Endereço',
      maxLength: 9
    },
    {
      property: 'address',
      label: 'Endereço'
    },
    {
      property: 'cityCode',
      label: 'Cidade',
      options: &#x5B;
        { label: 'Adolfo', value: '00204' },
        { label: 'São José do Rio Preto', value: '49805' },
        { label: 'José Bonifácio', value: '25706' },
        { label: 'Joinville', value: '09102' }
      ]
    },
    {
      property: 'stateId',
      label: 'Estado',
      options: &#x5B;
        { label: 'Santa Catarina', value: 'SC' },
        { label: 'São Paulo', value: 'SP' },
        { label: 'Rio de Janeiro', value: 'RJ' },
        { label: 'Minas Gerais', value: 'MG' }
      ]
    },
    /*{
      property: 'branchId',
      label: 'Filial',
      divider: 'Sistemico'
    },
    {
      property: 'companyInternalId',
      label: 'Empresa'
    }*/
  ]
}
</pre>
<p><span>Agora a ultima etapa é ajustar o html que irá exibir os dados do nosso formulário para o usuário, para isso, edite o arquivo supplier-form.component.html, e deixe com a seguinte informação:</span></p>
<pre class="brush: xml; light: false; title: ; toolbar: true; notranslate">
&lt;po-page-default &#x5B;p-title]=&quot;title&quot;&gt;
    &lt;po-dynamic-form #dynamicForm
    &#x5B;p-fields]=&quot;fields&quot;
    &#x5B;p-value]=&quot;supplierValues&quot;&gt;
    &lt;/po-dynamic-form&gt;

    &lt;div class=&quot;thf-row&quot;&gt;
        &lt;po-button
          class=&quot;thf-md-3&quot;
          *ngIf=&quot;!this.supplierId&quot;
          p-label=&quot;Inserir&quot;
          (p-click)=&quot;insertSupplier()&quot;&gt;
        &lt;/po-button&gt;
    &lt;/div&gt;
&lt;/po-page-default&gt;
</pre>
<p>Após todas essas etapas, ao acessar o endereço <a href="http://localhost:4200/supplierform">http://localhost:4200/supplierform</a>, deve ser exibida o form permitindo a inclusão em nosso backend e exibindo os erros encontrados se existirem, o resultado final será semelhante ao print abaixo:</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/01/form_fornecedor_po.ui_.jpg" alt="" width="1360" height="481" class="aligncenter size-full wp-image-883" srcset="https://sempreju.com.br/wp-content/uploads/2021/01/form_fornecedor_po.ui_.jpg 1360w, https://sempreju.com.br/wp-content/uploads/2021/01/form_fornecedor_po.ui_-300x106.jpg 300w, https://sempreju.com.br/wp-content/uploads/2021/01/form_fornecedor_po.ui_-1024x362.jpg 1024w, https://sempreju.com.br/wp-content/uploads/2021/01/form_fornecedor_po.ui_-768x272.jpg 768w" sizes="(max-width: 1360px) 100vw, 1360px" /></p>
<pre></pre>
<p>&nbsp;</p>
<p>O código fonte desse e de outros exemplos podem ser encontrados em nosso <a href="https://github.com/llrafaell/SemPreju-Exemplos">git</a> oficial.</p>
<p><em>Post interessantes:</em></p>
<p>Aprenda a instalar o Protheus no Windows <a href="https://sempreju.com.br/tag/instalarprotheuswindows/">aqui</a>.</p>
<p>Aprenda a instalar o Protheus no Linux <a href="https://sempreju.com.br/tag/instalarprotheuslinux/">aqui</a>.</p>
<p>configurar serviço rest <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">aqui</a>.</p>
<p>Retornar datas por extenso <a href="https://sempreju.com.br/datas-por-extenso-no-protheus/">aqui</a>.</p>
<p>Barras de progresso <a href="https://sempreju.com.br/como-fazer-barras-de-progresso-no-advpl/">aqui</a>.</p>
<p>Dúvidas e sugestões, entre em contato.</p>
<p>Obrigado e até a próxima!</p>
<p>O post <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/">CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 2</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 1</title>
		<link>https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/</link>
					<comments>https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Tue, 05 Jan 2021 13:40:13 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=846</guid>

					<description><![CDATA[<p>Olá pessoal Hoje vou iniciar uma série onde vamos demonstrar como realizar manutenção no cadastro de fornecedor (CRUD) usando o REST e a Angular (com PO.UI). Usamos como referência o seguinte post. Primeiro vamos realizar as configurações necessárias para nosso projeto, nessa etapa vamos precisar: Serviço REST configurado e rodando,<a class="moretag" href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/">CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 1</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Olá pessoal</p>
<p>Hoje vou iniciar uma série onde vamos demonstrar como realizar manutenção no cadastro de fornecedor (CRUD) usando o REST e a Angular (com PO.UI).</p>
<p>Usamos como referência o seguinte <a href="https://medium.com/totvsdevelopers/consumindo-api-s-totvs-e-criando-um-crud-utilizando-o-portinari-ui-novo-thf-b6552302b299">post</a>.</p>
<p>Primeiro vamos realizar as configurações necessárias para nosso projeto, nessa etapa vamos precisar:</p>
<ol>
<li>Serviço REST configurado e rodando, para isso temos um post onde explicamos essa configuração, pode ser encontrado <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">aqui</a>. Caso queira criar um WS (não precisamos para este post) pode ser encontrado <a href="https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/">aqui</a>.</li>
<li>Criar novo projeto angular, para isso precisamos dos seguintes passos:
<ol>
<li><strong>Node.js</strong> &#8211; Responsável por administrar os pacotes NPM para a instalação do Angular em batch (linha de comando). Para assegurar que a instalação ocorreu bem, no Prompt de Comando rode o seguinte comando <span style="color: #0000ff;"><em><strong>npm -v</strong></em></span>, deverá aparecer a versão que foi instalada do npm (administrador de pacotes do Node.js).</li>
<li><strong>Instalar Angular CLI</strong> &#8211; Responsável por nos ajudar a iniciar um projeto ou adicionar novas funcionalidades a projetos existentes. Para isso basta rodar no Prompt de Comando: <span style="color: #0000ff;"><strong><span class="pln">npm install </span><span class="pun">&#8211;</span><span class="pln">g </span><span class="lit">@angular</span><span class="pun">/</span><span class="pln">cli</span></strong></span></li>
<li><strong>Projeto Angular</strong> &#8211; Executar o comando CLI <code>ng new</code><span> e informar o nome do nosso projeto, no nosso exemplo usaremos o seguinte: <em><strong><span style="color: #0000ff;">ng new CRUD_Cliente</span></strong></em></span></li>
<li><strong>Adicionar o PO.UI</strong> (Biblioteca de componentes baseado no Angular, poderiamos utilizar qualquer outra biblioteca como <a href="https://ng.ant.design/docs/introduce/en">Ant</a>, <a href="https://material.angular.io/">Material</a>, <a href="https://ng-bootstrap.github.io/#/home">Bootstrap,</a> entre outras), Utilizando o comando<span> </span><code _ngcontent-llg-c306="">ng add</code><span> </span>do<span> </span>Angular CLI, vamos adicionar o<span> </span><strong _ngcontent-llg-c306="">Po</strong><span> </span>em seu projeto e o mesmo se encarregará de configurar o tema, instalar o pacote e importar o módulo do<span> </span><strong _ngcontent-llg-c306="">Po</strong>. Execute o comando abaixo na pasta raiz do seu projeto(dentro da pasta do nosso projeto CRUD_CLiente): <span style="color: #0000ff;"><em><strong> ng add @po-ui/ng-components.</strong></em></span></li>
<li>Agora podemos <strong>testar nosso aplicativo</strong> angular para isso no Prompt de Comando, digite: ng serve (pode demorar alguns minutos na primeira execução), após acesso em seu navegador http://localhost:4200/ você deverá ver a página de boas vindas do angular.</li>
<li><strong>Instalar Postman</strong> &#8211; O postman nos ajuda a realizar a consulta na API do protheus sem necessidade de desenvolver nenhum código.</li>
</ol>
</li>
</ol>
<p>Agora que temos os requisitos configurados, precisamos encontrar a API que será responsável para este nosso CRUD. No site <span>o </span><a href="https://api.totvs.com.br/" class="ez hj" rel="noopener nofollow">api.totvs.com.br</a><span>, podemos ver todas as API disponíveis e realizar filtros para localizarmos a que nos interessa mais, em nosso caso encontramos a API <a href="https://api.totvs.com.br/apidetails/CustomerVendor_v1_000.json">Cliente/Fornecedor.</a></span></p>
<p>&nbsp;</p>
<hr />
<p>Vamos agora começar a nossa aplicação Angular para nosso CRUD, primeiramente vamos listar todos os nossos fornecedores que existe no ERP (usando a API).</p>
<p data-selectable-paragraph="">Para testar nosso backend antes de usa-lo no angular, vamos abrir o postman e verificar se a API está respondendo corretamente (esse passo é opcional, eu gosto sempre de isolar pois assim tenho certeza que meu backend esta funcionado e se tiver algum problema é em meu frontend). Para isso no postman, informe a URL onde seu serviço REST esta respondendo, para minha configuração é:</p>
<blockquote>
<p data-selectable-paragraph="">http://localhost:8084/rest/api/crm/v1/customerVendor/2</p>
</blockquote>
<p data-selectable-paragraph="">Deverá ser exibido como resposta no formato Json com os dados dos nossos fornecedores, confirme o print abaixo.</p>
<p data-selectable-paragraph=""><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/01/Captura-de-tela-2021-01-04-143833.png" alt="" width="1595" height="778" class="aligncenter size-full wp-image-854" srcset="https://sempreju.com.br/wp-content/uploads/2021/01/Captura-de-tela-2021-01-04-143833.png 1595w, https://sempreju.com.br/wp-content/uploads/2021/01/Captura-de-tela-2021-01-04-143833-300x146.png 300w, https://sempreju.com.br/wp-content/uploads/2021/01/Captura-de-tela-2021-01-04-143833-1024x499.png 1024w, https://sempreju.com.br/wp-content/uploads/2021/01/Captura-de-tela-2021-01-04-143833-768x375.png 768w, https://sempreju.com.br/wp-content/uploads/2021/01/Captura-de-tela-2021-01-04-143833-1536x749.png 1536w" sizes="(max-width: 1595px) 100vw, 1595px" /></p>
<p data-selectable-paragraph=""><em>O ultimo parâmetro da url significa:</em></p>
<ul>
<li><em>Valor 2, diz para minha API que eu quero somente os fornecedores,;</em></li>
<li><em>Valor 1, diz para minha API que eu quero somente os clientes; </em></li>
<li><em>Valor 3 ou vazio, diz para minha API que eu quero </em><em>todos os clientes e fornecedores.</em></li>
</ul>
<p>para isso vamos para o Angular (aqui usaremos o VS Code) e usando as facilidades do angular CLI, vamos criar um novo módulo que será responsável por essa tarefa, para isso dentro no nosso projeto usando o Prompt de Command, vamos executar os seguintes comandos(um de cada vez):</p>
<blockquote>
<p id="05f0" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph=""><em class="kb">ng generate module supplier-list</em></p>
<p id="719e" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph=""><em class="kb">ng generate service supplier-list\supplier-list</em></p>
<p id="d48f" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph=""><em class="kb">ng generate component supplier-list</em></p>
<p>&nbsp;</p></blockquote>
<p>Após isso deverá ter sido criada em seu projeto uma estrutura parecida com a imagem abaixo.</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2021/01/angular_supplier.png" alt="Angular protheus fornecedor" width="309" height="440" class="aligncenter size-full wp-image-853" srcset="https://sempreju.com.br/wp-content/uploads/2021/01/angular_supplier.png 309w, https://sempreju.com.br/wp-content/uploads/2021/01/angular_supplier-211x300.png 211w" sizes="(max-width: 309px) 100vw, 309px" /></p>
<p data-selectable-paragraph="">Após a criação das rotinas, criaremos o serviço de listagem de fornecedores. Para isso, podemos acessar o arquivo<span> </span><em class="kb">supplier-list.service.ts</em><span> </span>e vamos criar o método que irá buscar estas informações no<span> </span><em class="kb">backend</em>.</p>
<p id="504a" class="gl gm do gn b go gp gq gr gs gt gu gv gw gx gy gz ha hb hc hd he hf hg hh hi dh ci" data-selectable-paragraph="">Também criei dentro do service um método para alterar e definir os nomes das colunas, o arquivo supplier-list.service.ts deverá ter o seguinte conteúdo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { PoTableColumn } from '@po-ui/ng-components';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class SupplierListService {

  ApiRest = 'http://localhost:8084/rest/api/crm/v1/customerVendor/2'; //Endereço da nossa API responsável por lista os fornecedores
  
  constructor(private http: HttpClient) { }

  //Método responsável por buscar e listar nossos fornecedores
  getSupplierList(): Observable&lt;any&gt; {
    return this.http.get(this.ApiRest);
  }

  //Método responsável por converter em nomes mais legiveis para cliente
  getColumns(): Array&lt;PoTableColumn&gt; {
    return &#x5B;
      { property: 'code', label: 'Código'},
      { property: 'storeId', label: 'Loja' },
      { property: 'name', label: 'Nome' },
      { property: 'strategicCustomerType', label: 'Fisica/Juridica' },
      { property: 'registerSituation', label: 'Situação' },
    ];
  }

}
</pre>
<p>&nbsp;</p>
<p>Agora que temos o serviço responsável por buscar os dados na API, vamos configurar nosso component para pegar utilizar os dados recebidos no servido e disponibilizar para nossa interface, no arquivo suppliur-list.components.ts, deverá ter a seguinte informação:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { PoNotificationService } from '@po-ui/ng-components';
import { SupplierListService } from './supplier-list.service';

@Component({
  selector: 'app-supplier-list',
  templateUrl: './supplier-list.component.html',
  styleUrls: &#x5B;'./supplier-list.component.css']
})
export class SupplierListComponent implements OnInit {

  supplierList: Array&lt;any&gt; = new Array();
  colunasTable: Array&lt;any&gt; = new Array();

  constructor(private SupplierListService: SupplierListService,
    private router: Router,
    private poNotification: PoNotificationService) { }

  ngOnInit(): void {
    this.updateSupplierList(); //busca a lista de fornecedores do nosso Api
    this.colunasTable = this.SupplierListService.getColumns(); //atualiza as colunas que queremos ser listadas em nossa tabela.
  }
  //Metódo responsável por se isncrever no serviço e atualizar a lista de fornecedores
  updateSupplierList(): void {
    this.SupplierListService.getSupplierList().subscribe(response =&gt; {
      this.supplierList = response.items;
    });
  }
}

</pre>
<p>Agora devemos ajustar o html que irá exibir os dados para o usuário, para isso, edite o arquivo supplier-list.component.html, inclua a deixe com a seguinte informação:</p>
<pre class="brush: xml; light: false; title: ; toolbar: true; notranslate">
&lt;po-page-default p-title=&quot;Lista de Fornecedores&quot;&gt;
    &lt;po-table
      p-container=&quot;light&quot;
      &#x5B;p-columns]=&quot;colunasTable&quot;
      &#x5B;p-items]=&quot;supplierList&quot;&gt;
    &lt;/po-table&gt;
  &lt;/po-page-default&gt;

</pre>
<p>Após essas etapas, só precisamos criar a <a href="https://angular.io/guide/router">rota</a> no angular responsável por mostrar nosso html, para isso edite o arquivo app-routing.modules.ts e inclua as informações do nosso novo componente, como o código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';


import { SupplierListComponent } from './supplier-list/supplier-list.component';

const routes: Routes = &#x5B;
  { path: '', component: SupplierListComponent },
  { path: 'supplier', component: SupplierListComponent }, //lista de fornecedor
];

@NgModule({
  imports: &#x5B;RouterModule.forRoot(routes)],
  exports: &#x5B;RouterModule]
})
export class AppRoutingModule { }

</pre>
<p>Devemos ainda verificar o arquivo app.component.html para garantir que está exibindo as informações da nossa roda, esse arquivo deve ter o seguinte conteúdo:</p>
<pre class="brush: xml; light: false; title: ; toolbar: true; notranslate">
&lt;div class=&quot;container&quot;&gt;
  &lt;router-outlet&gt;&lt;/router-outlet&gt;
&lt;/div&gt;
</pre>
<p>Agora só falta incluírmos nosso novo componente dentro do arquivo app.module.ts, o resultado final será semelhante ao código abaixo:</p>
<pre class="brush: jscript; light: false; title: ; toolbar: true; notranslate">
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PoModule } from '@po-ui/ng-components';
import { RouterModule } from '@angular/router';
import { PoNotificationModule  } from '@po-ui/ng-components';
import { PoDynamicModule } from '@po-ui/ng-components';
import { PoButtonModule } from '@po-ui/ng-components';
import {PoTemplatesModule  } from '@po-ui/ng-templates';

//incluir o componente para lista de fornecedores
import { SupplierListComponent } from './supplier-list/supplier-list.component';

@NgModule({
  declarations: &#x5B;
    AppComponent,SupplierListComponent
  ],
  imports: &#x5B;
    PoNotificationModule,PoDynamicModule,PoButtonModule  ,PoTemplatesModule,
    BrowserModule,
    AppRoutingModule,
    PoModule,
    RouterModule.forRoot(&#x5B;])
  ],
  providers: &#x5B;],
  bootstrap: &#x5B;AppComponent]
})
export class AppModule { }

</pre>
<p>&nbsp;</p>
<p>Após todas essas etapas, ao acessar o endereço <a href="http://localhost:4200/">http://localhost:4200/</a>, deve ser exibida a lista de Fornecedores que temos em nosso ERP.</p>
<p>*Obs.: caso tenha erro de CORS, veja mais <a href="https://tdn.totvs.com/display/framework/Exemplo+CORS">aqui</a>.</p>
<p>&nbsp;</p>
<p>O código fonte de outros exemplos podem ser encontrados em nosso <a href="https://github.com/llrafaell/SemPreju-Exemplos">git</a> oficial.</p>
<p><em>Post interessantes:</em></p>
<p>Aprenda a instalar o Protheus no Windows <a href="https://sempreju.com.br/tag/instalarprotheuswindows/">aqui</a>.</p>
<p>Aprenda a instalar o Protheus no Linux <a href="https://sempreju.com.br/tag/instalarprotheuslinux/">aqui</a>.</p>
<p>configurar serviço rest <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">aqui</a>.</p>
<p>Retornar datas por extenso <a href="https://sempreju.com.br/datas-por-extenso-no-protheus/">aqui</a>.</p>
<p>Barras de progresso <a href="https://sempreju.com.br/como-fazer-barras-de-progresso-no-advpl/">aqui</a>.</p>
<p>Dúvidas e sugestões, entre em contato.</p>
<p>Obrigado e até a próxima!</p>
<p>O post <a href="https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/">CRUD Fornecedor usando PO.UI(Angular) e ERP Protheus &#8211; part 1</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/crud-fornecedor-usando-po-uiangular-e-erp-protheus-part-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Alterando para o novo visual do Protheus com PO UI</title>
		<link>https://sempreju.com.br/novo-vizual-do-protheus/</link>
					<comments>https://sempreju.com.br/novo-vizual-do-protheus/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Tue, 15 Dec 2020 13:43:41 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<category><![CDATA[Configurador]]></category>
		<category><![CDATA[ADVPL]]></category>
		<category><![CDATA[Protheus]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=815</guid>

					<description><![CDATA[<p>Olá pessoal, já conferiram o novo visual do protheus? Com a evolução da tecnologia, o Protheus veio se adaptando e evoluindo conforme as necessidades do mercado, um avanço mesmo por exemplo, foi a utilização de CSS nos componentes gráficos, através das funcionalidades fornecidas com o usdo to TWebEngine e FWCallApp,<a class="moretag" href="https://sempreju.com.br/novo-vizual-do-protheus/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/novo-vizual-do-protheus/">Alterando para o novo visual do Protheus com PO UI</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Olá pessoal, já conferiram o novo visual do protheus?</p>
<p>Com a evolução da tecnologia, o Protheus veio se adaptando e evoluindo conforme as necessidades do mercado, um avanço mesmo por exemplo, foi a utilização de CSS nos componentes gráficos, através das funcionalidades fornecidas com o usdo to TWebEngine e FWCallApp, será possível criar aplicações com o visual e recursos usados na web, ou seja visualmente mais modernos, e através de REST integrá-las com o Protheus.</p>
<p>A documentação (inclusive em como ativar) você confere em<span> </span><a href="https://tdn.totvs.com/display/framework/Nova+interface+do+Protheus+com+PO+UI">https://tdn.totvs.com/display/framework/Nova+interface+do+Protheus+com+PO+UI</a></p>
<p><span>Nessa primeira fase, a novidade chega com a tela de login e a de seleção de ambiente, abaixo o print do novo visual.</span></p>
<p><img decoding="async" src="https://tdn.totvs.com/download/attachments/573183963/2020-11-18%2016_52_57-TOTVS%20Constru%C3%A7%C3%A3o%20e%20Projetos%20%28TOTVS%29%2002.9.0099.png?version=1&amp;modificationDate=1605901009927&amp;api=v2" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>O código fonte desse e outros exemplos podem ser encontrados em nosso <a href="https://github.com/llrafaell/SemPreju-Exemplos">git</a>.</p>
<p><em>Post interessantes:</em></p>
<p>Ponto de entrada ao acessar o sistema <a href="https://sempreju.com.br/executando-rotinas-ao-abrir-um-modulo-afterlogin-advpl/">aqui</a>.</p>
<p>Aprenda a instalar o Protheus no Windows <a href="https://sempreju.com.br/tag/instalarprotheuswindows/">aqui</a>.</p>
<p>Aprenda a instalar o Protheus no Linux <a href="https://sempreju.com.br/tag/instalarprotheuslinux/">aqui</a>.</p>
<p>Retornar datas por extenso <a href="https://sempreju.com.br/datas-por-extenso-no-protheus/">aqui</a>.</p>
<p>Barras de progresso <a href="https://sempreju.com.br/como-fazer-barras-de-progresso-no-advpl/">aqui</a>.</p>
<p>Dúvidas e sugestões, entre em contato.</p>
<p>Obrigado e até a próxima!</p>
<p>O post <a href="https://sempreju.com.br/novo-vizual-do-protheus/">Alterando para o novo visual do Protheus com PO UI</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/novo-vizual-do-protheus/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Autenticação com JWT + Protheus + Angular</title>
		<link>https://sempreju.com.br/autenticacao-com-jwt-protheus-angular/</link>
					<comments>https://sempreju.com.br/autenticacao-com-jwt-protheus-angular/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Tue, 13 Oct 2020 11:37:04 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=801</guid>

					<description><![CDATA[<p>Olá pessoal Essa dica vai para quem está iniciando no desenvolvimento Angular e quer realizar o login usando o protheus como backEnd! Nesse exemplo vamos usar a autenticação via JWT (usando os serviçoes já existentes no protheus), para saber mais sobre JWT no protheus, acesse a documentação aqui. A documentação<a class="moretag" href="https://sempreju.com.br/autenticacao-com-jwt-protheus-angular/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/autenticacao-com-jwt-protheus-angular/">Autenticação com JWT + Protheus + Angular</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Olá pessoal</p>
<p><span>Essa dica vai para quem está iniciando no desenvolvimento Angular e quer realizar o login usando o protheus como backEnd!</span></p>
<p>Nesse exemplo vamos usar a autenticação via JWT (usando os serviçoes já existentes no protheus), para saber mais sobre JWT no protheus, acesse a documentação <a href="https://tdn.totvs.com/pages/viewpage.action?pageId=465383509">aqui</a>.</p>
<p>A documentação oficial da rotina pode ser encontrada <a href="https://tdn.totvs.com/display/tec/GetPvProfString">aqui</a>.</p>
<p>O exemplo funcional pode ser baixado em nosso git, clique <a href="https://github.com/llrafaell/SemPreju-Exemplos/tree/master/PO-Angular/Angular_login%20-%20Usando%20REST%20Protheus">aqui</a> para ser direcionado.</p>
<p>&nbsp;</p>
<p><strong>Para executar esse projeto, temos que executar os passos abaixos:</strong></p>
<p>1-Configurar o serviço REST no protheus, <a href="http://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">aqui</a> tem um exemlo de como fazer isso.</p>
<p>2-Com o nosso serviço REST configurado e validado, conseguimos realizar a autentição de nosso usuário, então agora passamos para o angula, não itemos entrar em detalhes como criar um projeto angular com JWT, pois não é o foco desse post, mas um bom exemplo pode ser encontrado <a href="https://jasonwatmore.com/post/2020/04/19/angular-9-jwt-authentication-example-tutorial">aqui</a>. Nesse post vamos baixar o nosso projeto disponivel no GIT.</p>
<p>3-Assumiremos aqui que você tem o <a href="https://angular.io/guide/setup-local">Angular</a> e <a href="https://cli.angular.io/">Angular.Cli</a> ja instalado em seu computador.</p>
<p>4-Após baixar o projeto, no diretório raiz vamos instalar as dependencias com o comando:</p>
<p>npm install</p>
<p>5-Após a conclusão, vamos iniciar nosso projeto com o comando:</p>
<p>ng serve</p>
<p>6-Se tudo ocorreu bem até aqui, ao acessar a URL <a href="http://localhost:4200/">localhost:4200</a>, você se deparará com a tela abaixo para realizar o login usando usuario e senha do protheus.</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login.png" alt="" width="596" height="533" class="aligncenter size-full wp-image-803" srcset="https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login.png 596w, https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login-300x268.png 300w" sizes="(max-width: 596px) 100vw, 596px" /></p>
<p>7-Insira um usuário e senha e aguarde o carregamento, uma lista com todos os clientes do seu ERP protheus deverá ser exibida como o print abaixo.</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login_rest.png" alt="" width="1178" height="419" class="aligncenter size-full wp-image-804" srcset="https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login_rest.png 1178w, https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login_rest-300x107.png 300w, https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login_rest-1024x364.png 1024w, https://sempreju.com.br/wp-content/uploads/2020/10/jwt_advpl_login_rest-768x273.png 768w" sizes="(max-width: 1178px) 100vw, 1178px" /></p>
<p>&nbsp;</p>
<p>Nesse etapa o que conseguimos realizar:</p>
<p>-Autenticação de usuário usando o Protheus como BackEnd</p>
<p>-Usar JWT para verificar se nosso usuário ainda é válido na seção</p>
<p>-Consumir WebService REST para retornar a lista de clientes do ERP Protheus.</p>
<p>-Integrar Angular + Protheus</p>
<p>&nbsp;</p>
<p>Assim finalizamos nosso objetivo desse post, se você quiser mais conteudos de ADVPL + REST + Angular deixe nos comentários sugestões!</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>O código fonte desse e outros exemplos podem ser encontrados em nosso <a href="https://github.com/llrafaell/SemPreju-Exemplos">git</a>.</p>
<p><em>Post interessantes:</em></p>
<p>Aprenda a instalar o Protheus no Windows <a href="https://sempreju.com.br/tag/instalarprotheuswindows/">aqui</a>.</p>
<p>Aprenda a instalar o Protheus no Linux <a href="https://sempreju.com.br/tag/instalarprotheuslinux/">aqui</a>.</p>
<p>Retornar datas por extenso <a href="https://sempreju.com.br/datas-por-extenso-no-protheus/">aqui</a>.</p>
<p>Barras de progresso <a href="https://sempreju.com.br/como-fazer-barras-de-progresso-no-advpl/">aqui</a>.</p>
<p>Dúvidas e sugestões, entre em contato.</p>
<p>Obrigado e até a próxima!</p>
<p>O post <a href="https://sempreju.com.br/autenticacao-com-jwt-protheus-angular/">Autenticação com JWT + Protheus + Angular</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/autenticacao-com-jwt-protheus-angular/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Meu primeiro serviço REST no Protheus &#8211; parte 2</title>
		<link>https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/</link>
					<comments>https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Fri, 13 Mar 2020 13:36:53 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=570</guid>

					<description><![CDATA[<p>No post anterior sobre REST aprendemos a configurar o appserver para responder como servidor REST, se ainda nao viu esse post clique aqui. Nesse post vamos criar um WebService simples para retornar os dados dos clientes através de REST. Trataremos neste código sobre paginação, filtros e retorno JSON. O para<a class="moretag" href="https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/">Meu primeiro serviço REST no Protheus &#8211; parte 2</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>No post anterior sobre REST aprendemos a configurar o appserver para responder como servidor REST, se ainda nao viu esse post clique <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">aqui</a>.</p>
<p>Nesse post vamos criar um WebService simples para retornar os dados dos clientes através de REST.</p>
<p>Trataremos neste código sobre paginação, filtros e retorno JSON.</p>
<p>O para acessar o nosso WS, vamos usar {endereço WS configurado}/path definido no WS.</p>
<p>Abaixo o código usando:</p>
<pre class="brush: cpp; light: false; title: ; toolbar: true; notranslate">
#include &quot;TOTVS.CH&quot;
#Include &quot;RWMAKE.CH&quot;
#Include &quot;RESTFUL.CH&quot;

//Exemplo de WS para retorno do cliente
//Para mais informações acesse: www.sempreju.com.br e/ou nosso GIT https://github.com/llrafaell/SemPreju-Exemplos
WSRESTFUL SPCliente DESCRIPTION &quot;Clientes API&quot; FORMAT APPLICATION_JSON
	WSDATA page					AS INTEGER	OPTIONAL
	WSDATA pageSize 			AS INTEGER	OPTIONAL
	WSDATA searchKey 			AS STRING	OPTIONAL
	WSDATA branch				AS STRING 	OPTIONAL
	WSDATA byId					AS BOOLEAN	OPTIONAL

//Endereço para pegar os dados
//http://localhost:8082/rest/api/v1/spcliente
//WSMETHOD GET customers DESCRIPTION 'SP Lista de Clientes' WSSYNTAX '/api/v1/spcliente' PATH '/api/v1/spcliente' TTALK 'V1' PRODUCES APPLICATION_JSON  //-- Retorna lista de clientes, com possibilidade de paginaçao e filtros.
WSMETHOD GET customers DESCRIPTION 'SP Lista de Clientes' WSSYNTAX '/api/v1/spcliente' PATH '/api/v1/spcliente' PRODUCES APPLICATION_JSON  //-- Retorna lista de clientes, com possibilidade de paginaçao e filtros.

END WSRESTFUL




//-------------------------------------------------------------------
/*/{Protheus.doc} GET / cliente
Retorna a lista de clientes disponíveis.

@param	SearchKey		, caracter, chave de pesquisa utilizada em diversos campos
		Page			, numerico, numero da pagina
		PageSize		, numerico, quantidade de registros por pagina
		byId			, logico, indica se deve filtrar apenas pelo codigo

@return cResponse		, caracter, JSON contendo a lista de clientes

@author	rafael.goncalves
@since		Mar|2020
@version	12.1.27
/*/
//-------------------------------------------------------------------
WSMETHOD GET customers WSRECEIVE searchKey, page, pageSize, branch WSREST SPCliente
	Local lRet:= .T.
	lRet := Customers( self )
Return( lRet )

Static Function Customers( oSelf )
	Local aListCli	:= {}
	Local cJsonCli		:= ''
	Local oJsonCli	:= JsonObject():New()
	Local cSearch		:= ''
	Local cWhere		:= &quot;AND SA1.A1_FILIAL = '&quot;+xFilial('SA1')+&quot;'&quot;
	Local nCount		:= 0
	Local nStart 		:= 1
	Local nReg 			:= 0
	Local nAux			:= 0
	Local cAliasSA1		:= GetNextAlias()

	Default oself:searchKey 	:= ''
	Default oself:branch		:= ''
	Default oself:page		:= 1
	Default oself:pageSize	:= 20
	Default oself:byId		:=.F.

	// Tratativas para realizar os filtros
	If !Empty(oself:searchKey) //se tiver chave de busca no request
		cSearch := Upper( oself:SearchKey )
		If oself:byId //se filtra somente por ID
			cWhere += &quot; AND SA1.A1_COD = '&quot;	+ cSearch + &quot;'&quot;
		Else//busca chave nos campos abaixo
			cWhere += &quot; AND ( SA1.A1_COD LIKE 	'%&quot;	+ cSearch + &quot;%' OR &quot;
			cWhere	+= &quot; SA1.A1_LOJA LIKE 		'%&quot; + cSearch + &quot;%' OR &quot;
			cWhere	+= &quot; SA1.A1_NOME LIKE 		'%&quot; + FwNoAccent( cSearch ) + &quot;%' OR &quot;
			cWhere	+= &quot; SA1.A1_NREDUZ LIKE 	'%&quot; + FwNoAccent( cSearch ) + &quot;%' OR &quot;
			cWhere	+= &quot; SA1.A1_NREDUZ LIKE 	'%&quot; + cSearch  + &quot;%' OR &quot;
			cWhere	+= &quot; SA1.A1_NOME LIKE 		'%&quot; + cSearch + &quot;%' ) &quot;
		EndIf
	EndIf

	If !Empty(oself:branch) //se filtra a loja
		cWhere += &quot; AND SA1.A1_LOJA = '&quot;+oself:branch+&quot;'&quot;
	EndIf

	dbSelectArea('SA1')
	DbSetOrder(1)
	If SA1-&gt;( Columnpos('A1_MSBLQL') &gt; 0 ) //verifica se o campo de controle de bloqueio existe, se sim filtra esse caso
		cWhere += &quot; AND SA1.A1_MSBLQL &lt;&gt; '1'&quot;
	EndIf

	cWhere := '%'+cWhere+'%' //monta a expressao where

	// Realiza a query para selecionar clientes
	BEGINSQL Alias cAliasSA1
		SELECT SA1.A1_COD, SA1.A1_LOJA, SA1.A1_NOME, SA1.A1_END
		FROM 	%table:SA1% SA1
		WHERE 	SA1.%NotDel%
		%exp:cWhere%
		ORDER BY A1_COD
	ENDSQL

	If ( cAliasSA1 )-&gt;( ! Eof() )
		//-------------------------------------------------------------------
		// Identifica a quantidade de registro no alias temporário
		//-------------------------------------------------------------------
		COUNT TO nRecord
		//-------------------------------------------------------------------
		// nStart -&gt; primeiro registro da pagina
		// nReg -&gt; numero de registros do inicio da pagina ao fim do arquivo
		//-------------------------------------------------------------------
		If oself:page &gt; 1
			nStart := ( ( oself:page - 1 ) * oself:pageSize ) + 1
			nReg := nRecord - nStart + 1
		Else
			nReg := nRecord
		EndIf

		//-------------------------------------------------------------------
		// Posiciona no primeiro registro.
		//-------------------------------------------------------------------
		( cAliasSA1 )-&gt;( DBGoTop() )

		//-------------------------------------------------------------------
		// Valida a exitencia de mais paginas
		//-------------------------------------------------------------------
		If nReg  &gt; oself:pageSize
			oJsonCli&#x5B;'hasNext'] := .T.
		Else
			oJsonCli&#x5B;'hasNext'] := .F.
		EndIf
	Else
		//-------------------------------------------------------------------
		// Nao encontrou registros
		//-------------------------------------------------------------------
		oJsonCli&#x5B;'hasNext'] := .F.
	EndIf

	//-------------------------------------------------------------------
	// Alimenta array de clientes
	//-------------------------------------------------------------------
	While ( cAliasSA1 )-&gt;( ! Eof() )
		nCount++
		If nCount &gt;= nStart
			nAux++
		    aAdd( aListCli , JsonObject():New() )
			aListCli&#x5B;nAux]&#x5B;'id']	:= ( cAliasSA1 )-&gt;A1_COD
			aListCli&#x5B;nAux]&#x5B;'name']	:= Alltrim( EncodeUTF8( ( cAliasSA1 )-&gt;A1_NOME ) )
			aListCli&#x5B;nAux]&#x5B;'branch']	:= ( cAliasSA1 )-&gt;A1_LOJA
			aListCli&#x5B;nAux]&#x5B;'address']	:= ( cAliasSA1 )-&gt;A1_END
			If Len(aListCli) &gt;= oself:pageSize
				Exit
			EndIf
		EndIf
		( cAliasSA1 )-&gt;( DBSkip() )
	End
	( cAliasSA1 )-&gt;( DBCloseArea() )
	oJsonCli&#x5B;'clients'] := aListCli

	//-------------------------------------------------------------------
	// Serializa objeto Json
	//-------------------------------------------------------------------
	cJsonCli:= FwJsonSerialize( oJsonCli )

	//-------------------------------------------------------------------
	// Elimina objeto da memoria
	//-------------------------------------------------------------------
	FreeObj(oJsonCli)
	oself:SetResponse( cJsonCli ) //-- Seta resposta
Return .T.

</pre>
<p>O código fonte desse e outros exemplos podem ser encontrados em nosso <a href="https://github.com/llrafaell/SemPreju-Exemplos">git</a>.</p>
<p>&nbsp;</p>
<p>Para testar o nosso WS, vamos usar a ferramenta Postman.</p>
<p>1-Instale o postman através do link de download <a href="https://www.postman.com/downloads/">aqui</a>.</p>
<p>2-Execute o postman e informe a URL como no print abaixo:</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman-300x33.png" alt="" width="300" height="33" class="aligncenter wp-image-573 size-medium" srcset="https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman-300x33.png 300w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman-1024x114.png 1024w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman-768x85.png 768w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman-1536x171.png 1536w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman-2048x228.png 2048w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>3-Ao clicar em &#8220;SEND&#8221;, se tudo ocorreu bem, devemos ver a nossa lista de clientes como retorno.</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno-300x114.png" alt="" width="300" height="114" class="size-medium wp-image-574 aligncenter" srcset="https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno-300x114.png 300w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno-1024x390.png 1024w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno-768x292.png 768w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno-1536x584.png 1536w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno-2048x779.png 2048w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>4-Para usarmos o filtro ou paginação, devemos adicionar as &#8220;tag&#8221;no Header de nossa requisição, para isso no postman, vamos clicar em Header e por exemplo adicionar um filtro, no nosso WS o filtro foi definido com a tag <em>searchKey</em>, a requisição e retorno deve ficar como o print abaixo.</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno_filtro-300x140.png" alt="" width="300" height="140" class="size-medium wp-image-575 aligncenter" srcset="https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno_filtro-300x140.png 300w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno_filtro-1024x478.png 1024w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno_filtro-768x358.png 768w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno_filtro-1536x716.png 1536w, https://sempreju.com.br/wp-content/uploads/2020/03/sempreju_postman_retorno_filtro-2048x955.png 2048w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>Assim concluimos nosso primeiro WS.</p>
<p>&nbsp;</p>
<p><em>Post relacionados:</em></p>
<p>Aprenda a instalar o Protheus <a href="https://sempreju.com.br/como-instalar-o-protheus-appserver-e-smartclient-parte-5/">aqui</a>.</p>
<p>Aprenda a mudar o logo do sistema <a href="https://sempreju.com.br/como-mudar-o-logo-do-protheus/">aqui</a>.</p>
<p>Aprenda a diferença de path relativo e absoluto <a href="https://sempreju.com.br/path-relativo-x-path-absoluto/">aqui</a>.</p>
<p>&nbsp;</p>
<p>Dúdivas e sugestões, entre em contato.</p>
<p>Obrigado e até a próxima!</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>O post <a href="https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/">Meu primeiro serviço REST no Protheus &#8211; parte 2</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/meu-primeiro-servico-rest-no-protheus-parte-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Webservice REST no ERP Protheus &#8211; parte 1</title>
		<link>https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/</link>
					<comments>https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/#respond</comments>
		
		<dc:creator><![CDATA[Rafael Gonçalves]]></dc:creator>
		<pubDate>Mon, 17 Feb 2020 17:21:27 +0000</pubDate>
				<category><![CDATA[ADVPL - REST]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://sempreju.com.br/?p=506</guid>

					<description><![CDATA[<p>Introdução REST é um acrônimo para Representational State Transfer &#8211; uma descrição quase sem sentido da tecnologia de serviço da web mais usada! O REST é uma maneira de dois sistemas de computador se comunicarem via HTTP de maneira semelhante aos navegadores e servidores da Web. Compartilhar dados entre dois ou mais sistemas<a class="moretag" href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/"> Leia mais&#8230;</a></p>
<p>O post <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">Webservice REST no ERP Protheus &#8211; parte 1</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Introdução</h1>
<p><strong><span>REST é um acrônimo para </span><em><span>Representational State Transfer</span></em><span> &#8211; uma descrição quase sem sentido da tecnologia de serviço da web mais usada! O REST é uma maneira de dois sistemas de computador se comunicarem via HTTP de maneira semelhante aos navegadores e servidores da Web.</span></strong></p>
<p><span>Compartilhar dados entre dois ou mais sistemas sempre foi um requisito fundamental do desenvolvimento de software. Por exemplo, considere comprar um seguro automóvel. Sua seguradora deve obter informações sobre você e seu veículo para solicitar dados das autoridades de registro de automóveis, agências de crédito, bancos e outros sistemas. Tudo isso acontece de forma transparente em tempo real para determinar se uma política pode ser oferecida.</span></p>
<p>&nbsp;</p>
<p>O principal nesta arquitetura são as<span> </span><strong>URLs</strong><span> </span>do sistema e os resources (resource é um recurso, entidade). Ele aproveita os métodos<span> </span><strong>HTTP</strong><span> </span>para se comunicar, que são:</p>
<p><strong>GET</strong>: <span>Use solicitações GET </span><strong><span>para recuperar apenas informações / representação de recursos</span></strong><span> &#8211; e não modificá-las de nenhuma maneira. Como as solicitações GET não alteram o estado do recurso, esses </span><strong><span>métodos</span></strong><span> são considerados <strong>seguros</strong> . Além disso, as AP</span><span>Is GET devem ser </span><strong><span>idempotentes</span></strong><span> , o que significa que fazer várias solicitações idênticas deve produzir o mesmo resultado todas as vezes até que outra API (POST ou PUT) altere o estado do recurso no servidor.</span></p>
<p><strong>POST</strong>: <span>Use APIs do POST </span><strong><span>para criar novos recursos</span></strong><span>, por exemplo, um arquivo é subordinado a um diretório que o contém ou uma linha é subordinada a uma tabela de banco de dados. Falando estritamente em termos de REST, os métodos POST são usados ​​para criar um novo recurso na coleção de recursos.</span></p>
<p><strong>DELETE</strong>: <span>Conforme o nome se aplica, as APIs DELETE são usadas </span><strong><span>para excluir recursos</span></strong></p>
<p><strong>PUT</strong>: <span>Use APIs PUT principalmente </span><strong><span>para atualizar o recurso existente</span></strong><span> (se o recurso não existir, a API poderá decidir criar um novo recurso ou não)</span>. A principal diferença entre POST e PUT é que o primeiro pode lidar não somente com recursos, mas também pode fazer processamento de informações</p>
<p>&nbsp;</p>
<h2><span id="Configuracao_REST_no_Protheus">Configuração REST no Protheus</span></h2>
<p>O<span> </span><em>web service</em><span> </span><strong>REST</strong><span> </span>do AdvPL<span> </span><strong>não</strong><span> </span>utiliza as seções<span> </span><strong>HTTP</strong><span> </span>e<span> </span><strong>WebServices</strong><span> </span>utilizadas para o configurar o modelo SOAP.</p>
<p>Apesar disso o REST também utiliza<span> </span><em>working threads</em><span> </span>para atender as requisições recebidas também pelo protocolo HTTP.</p>
<p>O primeiro passo para criarmos um serviço REST é configurar o Protheus como um servidor HTTP REST. Para isso vamos manipular o arquivo<span> </span><strong>.ini</strong><span> </span>do AppServer, conforme exemplo abaixo:</p>
<p>A função <strong>HTTP_START</strong> que prepara o AppServer como servidor HTTP para REST, necessitando ser configurada na seção <strong>ONSTART</strong>:</p>
<p><code><br />
[GENERAL]<br />
MAXSTRINGSIZE=10</code></p>
<p><code><br />
[ONSTART]<br />
JOBS=HTTPJOB<br />
REFRESHRATE=120</code></p>
<p><code><br />
[HTTPJOB]<br />
MAIN=HTTP_START<br />
ENVIRONMENT=LOBO_12_25<br />
</code></p>
<blockquote><p><em>A chave <strong>MAXSTRINGSIZE</strong> é <strong>obrigatória </strong>na seção <strong>GENERAL</strong> com valor mínimo 10 para que o REST suporte requisições com mais de 1Mb </em></p></blockquote>
<p><span>Habilitando o servidor HTTP para REST:</span></p>
<p>&nbsp;</p>
<p><code>[HTTPV11]<br />
Enable=1<br />
Sockets=HTTPREST</code></p>
<p><code></code><br />
<strong>Obs:</strong><span></span><br />
<span>A chave Sockets referencia a(s) seção(ões) com a configuração de porta e URL que a mesma irá atender, permitindo que o </span><em>Application Server</em><span> seja configurado com mais de uma porta HTTP do REST:</span></p>
<p>&nbsp;</p>
<p><span>Configuração do(s) socket(s) definidos na seção HTTPV11:</span></p>
<p><code>[HTTPREST]<br />
Port=8084<br />
IPsBind=<br />
URIs=HTTPURI<br />
Security=0<br />
;Public=classe/path/get1,classe2/path/gety,classe3/path/post<br />
;Notenant=classe/path/get2,classe2/path/getv,classe3/path/post2</code></p>
<table>
<tbody>
<tr>
<td><strong>Parâmetro</strong></td>
<td><strong>Descrição</strong></td>
</tr>
<tr>
<td>Port</td>
<td>Porta HTTP</td>
</tr>
<tr>
<td>IPsBind</td>
<td>Indica os IPs que serão atendidos por essa porta, se não informado atenderá qualquer IP / DNS associado ao servidor</td>
</tr>
<tr>
<td>URIs</td>
<td>Seções com configuração de URL e ambiente (pelo menos uma seção)</td>
</tr>
<tr>
<td>Security</td>
<td>Indica se a autenticação de requisição esta habilitada</td>
</tr>
<tr>
<td>Public</td>
<td>Chave pública que contém listas de EndPoints que não possuem autenticação</td>
</tr>
<tr>
<td>NoTenant</td>
<td>Ao ser usada não será validada as empresas/filiais, apenas a autenticação do usuário.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>Observação:<br />
</strong>O HTTP do REST verifica existência do campo Authorization no HEADER da requisição, porém a autorização é realizada pelo framework do produto que está/ utilizando o protocolo</p>
<p>Para facilitar o desenvolvimento e testes pode-se configurar a chave Security com valor 0 (zero) para desabilitar a autenticação</p>
<p>A chave <em>URIs</em> referência a(s) seção(ões) com a configuração da URL que a porta irá atender, permite também que seja configurado com mais de uma URL como exemplo abaixo:</p>
<p><code>[HTTPREST]<br />
Port=8084<br />
IPsBind=<br />
URIs=HTTPURI,HTTPURI2<br />
Security=1<br />
</code></p>
<p>&nbsp;</p>
<p><span>Configuração da(s) seções URIs:</span></p>
<p><code><br />
[HTTPURI]<br />
URL=/rest<br />
PrepareIn=99,01<br />
<a href="https://tdn.totvs.com/display/tec/Instances">Instances</a>=1,1 </code></p>
<p><code>CORSEnable=1<br />
AllowOrigin=* </code></p>
<table>
<tbody>
<tr>
<td><strong>Parâmetro</strong></td>
<td><strong>Descrição</strong></td>
</tr>
<tr>
<td>URL</td>
<td>Indica o endereço que será atendido Nesse exemplo http://localhost:8012/rest</td>
</tr>
<tr>
<td>Preparein</td>
<td>Informações de empresa e filial para preparação do ambiente das working threads</td>
</tr>
<tr>
<td>Instances</td>
<td>Configuração de inicialização de working threads</td>
</tr>
<tr>
<td>CorsEnable</td>
<td>Indica se habilita o CORS</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<td colspan="2"><strong>Observaçoes</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2">A chave CORS é utilizada para permitir que páginas WEB de diferentes domínio do qual o servidor HTTP do Protheus está alocado, consigam realizar a requisição na nossa URI.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Essa parte configuração não temos muito como fugir do que está descrito no TDN, está bem documentado por parte da TOTVS.</p>
<p>Após a configuração, o appserver.ini deverá ficar da seguinte maneira:</p>
<p><code>[HTTPV11]<br />
Enable=1<br />
Sockets=HTTPREST</code></p>
<p><code><br />
[HTTPREST]<br />
Port=8084<br />
URIs=URIHTML<br />
SECURITY=1</code></p>
<p><code><br />
[URIHTML]<br />
URL=/rest<br />
PrepareIn=All<br />
Instances=2,2<br />
CORSEnable=1<br />
AllowOrigin=*</code></p>
<p><code><br />
[ONSTART]<br />
jobs=HTTPJOB<br />
RefreshRate=30</code></p>
<p><code><br />
[HTTPJOB]<br />
MAIN=HTTP_START<br />
ENVIRONMENT=LOBO_12_25<br />
</code></p>
<h2><span id="Iniciando_o_AppServer">Iniciando o AppServer</span></h2>
<p>Após a adição das seções no .ini, deve reiniciar o appserver e podemos ver no log que está no ar nosso servidor http/rest:</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/02/tdrfocus_rest-1024x594.png" alt="" width="750" height="435" class="aligncenter wp-image-517 size-large" srcset="https://sempreju.com.br/wp-content/uploads/2020/02/tdrfocus_rest-1024x594.png 1024w, https://sempreju.com.br/wp-content/uploads/2020/02/tdrfocus_rest-300x174.png 300w, https://sempreju.com.br/wp-content/uploads/2020/02/tdrfocus_rest-768x446.png 768w, https://sempreju.com.br/wp-content/uploads/2020/02/tdrfocus_rest.png 1108w" sizes="(max-width: 750px) 100vw, 750px" /></p>
<p>&nbsp;</p>
<h2><span id="Testando_a_Configuracao_REST">Testando a Configuração REST</span></h2>
<p>Com nosso servidor web no ar, vamos acessar via navegador a URI que configuramos no .ini, para ter 100% de certeza que esta tudo ok com o nosso servidor REST</p>
<p>Para acessar nossa URI, devemos acessar o caminho definido via navegador. Nesse caso, (exemplo acima) a URL que vamos acessar para testar nossa URI é a seguinte:</p>
<p><a href="http://localhost:8084/rest">http://localhost:8084/rest</a></p>
<p>Se tudo estiver ok, será exibido a seguinte tela:</p>
<p><img loading="lazy" decoding="async" src="https://sempreju.com.br/wp-content/uploads/2020/02/restfull_sempreju-1024x368.png" alt="" width="750" height="270" class="alignleft wp-image-518 size-large" srcset="https://sempreju.com.br/wp-content/uploads/2020/02/restfull_sempreju-1024x368.png 1024w, https://sempreju.com.br/wp-content/uploads/2020/02/restfull_sempreju-300x108.png 300w, https://sempreju.com.br/wp-content/uploads/2020/02/restfull_sempreju-768x276.png 768w, https://sempreju.com.br/wp-content/uploads/2020/02/restfull_sempreju.png 1534w" sizes="(max-width: 750px) 100vw, 750px" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Onde nada mais é que uma página WEB contendo todas as API’s Rest que está disponível no nosso ERP Protheus.</p>
<h2><span id="Conclusao">Conclusão</span></h2>
<p>Neste artigo vimos como configurar o servidor Protheus como HTTP REST, dessa forma podemos utiliza-lo para realizar integrações com outros aplicativos.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Referencias</strong>:</p>
<p>https://tdn.totvs.com/pages/viewpage.action?pageId=185747842</p>
<p>https://tdn.totvs.com/display/framework/REST+ADVPL</p>
<p>https://tdn.totvs.com/pages/viewpage.action?pageId=185757438</p>
<p>https://tdn.totvs.com/display/tec/Instances</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>No próximo post vamos criar o nosso promeiro WebServer REST.</p>
<p>Até lá</p>
<p>Abraços</p>
<p>O post <a href="https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/">Webservice REST no ERP Protheus &#8211; parte 1</a> apareceu primeiro em <a href="https://sempreju.com.br">Sem Preju</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sempreju.com.br/webservice-rest-no-erp-protheus-part-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
