Olá pessoal.

Nos post anterior vimos:

  • Parte 1 – Como configurar, testar API no Protheus e listar fornecedores no Angular (PO.UI) aqui.
  • Parte 2 – 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 de editar e excluir um fornecedor.

Vamos começar com a exclusão, para isso vamos usar a mesma API mas o verbo agora será DELETE ao invés de GET ou POST. 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, http://localhost:8084/rest/api/crm/v1/customerVendor/2/A2_COD+A2_LOJA(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)  como no print abaixo.

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.

 

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:

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: ['./supplier-list.component.css']
})
export class SupplierListComponent implements OnInit {

  supplierList: Array<any> = new Array();
  colunasTable: Array<any> = new Array();

  //Parte 3 
  //Adicionado ação deleter e editar
  actions: Array<PoTableAction> = [
    { 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([`/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(() => {
      this.updateSupplierList(); //atualiza a lista
      this.poNotification.success('o Fornecedor foi excluido com sucesso');
    }
    , err => 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 => {
      this.supplierList = response.items;
    });
  }
}

Foram incluídos:

  • Nova variável chamada actions com as ações que desejamos em nossa lista.
  • Novos métodos
    • updateSupplier, será responsável por atualizar um fornecedor (opção de editar).
    • deleteSupplier, será responsável por deletar um fornecedor.

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:

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<any> {
    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<PoTableColumn> {
    return [
      { property: 'code', label: 'Código'},
      { property: 'storeId', label: 'Loja' },
      { property: 'name', label: 'Nome' },
      { property: 'strategicCustomerType', label: 'Fisica/Juridica' ,
        type: 'label', //part3 add 
        labels: [
          { 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: [
        { 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' }
      ]  },
    ];
  }
}

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:

<po-page-default p-title="Lista de Fornecedores">
    <po-table
      p-container="light"
      [p-columns]="colunasTable"
      [p-items]="supplierList"
      [p-actions]="actions"><!--  adicionado part 3 -->
    </po-table>
  </po-page-default>

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:

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 = [
  { 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: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Alteraremos também o arquivo supplier-form.component.ts, nele vamos precisar:
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.
Vamos criar a ação no novo botão “atualizar” para confirmar alterações em um forncedor (esse botão será criado no HTML do form, logo abaixo).

O arquivo supplier-form.component.ts deve ficar como o código abaixo:

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: ['./supplier-form.component.css']
})
export class SupplierFormComponent implements OnInit {
//fields: Array<PoDynamicFormField> = []; //campos "dinamicos" para usar no formulário
supplier: Supplier = new Supplier();//model de um fornecedor
supplierValues = {    type: 2, code: "", storeId: "", shortName: "", name: "", strategicCustomerType: "J", entityType: "J",
number: "", address: "", zipCode: "", stateId: "", stateInternalId: "", registerSituation: "1",
stateDescription: "", complement: "", district: "", cityCode: "", cityDescription: ""}; //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: "", storeId: "", shortName: "", name: "", strategicCustomerType: "J", entityType: "J",
number: "", address: "", zipCode: "", stateId: "", stateInternalId: "",registerSituation: "1",
stateDescription: "", complement: "", district: "", cityCode: "", cityDescription: ""
}
this.route.paramMap.subscribe(parameters => {
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(() => {
this.poNotification.success('Fornecedor foi inserido com Sucesso');
this.router.navigate(['/supplier']); //redireciona para lista de fornecedor
}, err => {
//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(() => {
this.poNotification.success('Fornecedor alterado com Sucesso');
this.router.navigate(['/supplier']);//redireciona para lista de fornecedor
}, err => 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) => {
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<PoDynamicFormField> = [
{
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: [
{ 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: [
{ 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: [
{ label: 'Inativo', value: '1' },
{ label: 'Ativo', value: '2' }
]
},
{
property: 'type',
label: 'Tipo',
options: [
{ 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: [
{ 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: [
{ 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'
}*/
]
}

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:

<po-page-default [p-title]="title">
<po-dynamic-form #dynamicForm [p-fields]="fields" [p-value]="supplierValues">
</po-dynamic-form>
<div class="thf-row">
<po-button class="thf-md-3" 
*ngIf="!this.supplierId" 
p-label="Inserir" 
(p-click)="insertSupplier()">
</po-button>
</div>
<po-button 
*ngIf="this.supplierId" 
class="thf-md-3" 
p-label="Atualizar Fornecedor" 
(p-click)="updateSupplier()">
</po-button>
</po-page-default>

Após todas essas etapas, ao acessar o endereço http://localhost:4200/supplier, 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:

 

O código fonte desse e de outros exemplos podem ser encontrados em nosso git oficial.

Post interessantes:

Aprenda a instalar o Protheus no Windows aqui.

Aprenda a instalar o Protheus no Linux aqui.

configurar serviço rest aqui.

Retornar datas por extenso aqui.

Barras de progresso aqui.

Dúvidas e sugestões, entre em contato.

Obrigado e até a próxima!


0 comentário

Deixe um comentário