Ir ao conteúdo
  • Cadastre-se

Registro sobrescrevendo outro no arquivo


Murilo Rocha

Posts recomendados

Olá pessoal, mais uma vez peço ajuda da galera aí com o meu projeto de final de semestre.

O esquema é o seguinte: Fazer um programa simples de cadastro de pedidos em uma cervejaria e constam os seguintes itens:

Cadastrar vendedor;

Cadastrar pedido;

Informar preços das cervejas;

etc.

Seguinte, fiz todas as etapas do projeto (ou quase), o problema é que, quando cadastro mais de um vendedor (opção 1) e vou para a opção 2 onde tem verifica se o nome do vendedor consta no arquivo ou não, ele só reconhece o nome dado no ultimo cadastro que fiz. Será que ele está gravando por cima do registro anterior?

Por favor, espero que alguém me de um help!

P.S.: Ainda não coloquei para os arquivos abrirem e fecharem nos locais certos (dica do Simon, conterrâneo ^_^) !

Segue o algoritmo:


program cervejaria;
uses crt;

// -------------------------------------------------------- Declarando Registros
//Registro [OPÇÃO 1]
type cadvendedor = record
codvendedor: string[15];
nomevendedor: string[30];
endereco: record
rua: string[20];
bairro: string[15];
cidade: string[20];
estado: string[2];
end;
telefone: integer;
admissao: string[10];
end;
arquivo1 = file of cadvendedor; //Arquivo [OPÇÃO 1]

//Registro [OPÇÃO 2]
type cadpedido = record
numpedido: string[5];
datapedido: string[10];
nomecliente: string[20];
nomevendedor: string[20];
qtdcerveja: record
qtdlatao: integer;
qtdlata: integer;
qtdlatinha: integer;
qtdlongneck: integer
end;
valortotal: real;
situacao: string[15];
end;
arquivo2 = file of cadpedido; //Arquivo [OPÇÃO 2]

//Registro [OPÇÃO 3]
type precocerveja = record
platao: real;
plata: real;
platinha: real;
plongneck: real;
end;
arquivo3 = file of precocerveja; //Arquivo [OPÇÃO 3]

// -------------------------------------------------------- Declarando variáveis
var
opcao: char;
arq1: arquivo1;
arq2: arquivo2;
arq3: arquivo3;
reg1: cadvendedor;
reg2: cadpedido;
reg3: precocerveja;
saida: boolean;
vtlatao, vtlata, vtlatinha, vtlneck, vtotal: real;
npedido: string;

// ----------------------------------------------------- Procedimentos e Funções
//Procedimento [Logotipo para Título]
procedure titulo;
begin
textcolor(7);
textbackground(4);
gotoxy(20,1);writeln(' Cervejaria Pasqual ');
gotoxy(18,1);textcolor(2);writeln(' ³³');
gotoxy(41,1);textcolor(2);writeln('³³ ');
writeln;
textbackground(8);
textcolor(7);
end;

//Procedimento [Tabela de preços]
procedure tabelapreco;
begin
reset(arq3);
while not eof(arq3) do
begin
read(arq3,reg3);
gotoxy(1,5);write(' ');
gotoxy(1,6);writeln('Tipo');
gotoxy(15,6);write('Preco');
gotoxy(1,8);write('Latao');
gotoxy(15,8);write('RS ',reg3.platao:2:2);
gotoxy(1,9);write('Lata');
gotoxy(15,9);write('RS ',reg3.plata:2:2);
gotoxy(1,10);write('Latinha');
gotoxy(15,10);write('RS ',reg3.platinha:2:2);
gotoxy(1,11);write('LongNeck');
gotoxy(15,11);write('RS ',reg3.plongneck:2:2);
writeln;
end;
end;

//Procedimento [Valor total do pedido]
procedure valortotal;
begin
vtlatao:=(reg3.platao*reg2.qtdcerveja.qtdlatao);
vtlata:=(reg3.plata*reg2.qtdcerveja.qtdlata);
vtlatinha:=(reg3.platinha*reg2.qtdcerveja.qtdlatinha);
vtlneck:=(reg3.plongneck*reg2.qtdcerveja.qtdlongneck);
vtotal:=(vtlatao+vtlata)+(vtlatinha+vtlneck);
reg2.valortotal:=vtotal;
writeln('RS ',vtotal:0:2);
end;

//Procedimento [Dados do vendedor]
procedure dadosvendedor;
begin
writeln('Digite o codigo identificador para o vendedor;');
readln(reg1.codvendedor);
writeln('Informe o nome do vendedor:');
readln(reg1.nomevendedor);
writeln;
writeln('Endereco:');
writeln;
writeln('Rua: ');
readln(reg1.endereco.rua);
writeln('Bairro: ');
readln(reg1.endereco.bairro);
writeln('Cidade: ');
readln(reg1.endereco.cidade);
writeln('Estado [ex.: BA]: ');
readln(reg1.endereco.estado);
writeln('Telefone (sem "-"):');
readln(reg1.telefone);
writeln('Data de admissao (dd/mm/aaa):');
readln(reg1.admissao);
clrscr;
end;

//Procedimento [OPÇÃO 1]
procedure cadastravendedor;
var
submenu: char;
begin
titulo;
writeln;
writeln('1 - Cadastrando vendedor;');
writeln;
writeln('Escolha uma das opções listadas abaixo:');
writeln;
writeln('1 - Estou cadastrando um vendedor pela primeira vez;');
writeln('2 - Quero cadastras outro um vendedor;');
readln(submenu);
case submenu of
'1': begin
rewrite(arq1);
reset(arq1);
writeln;
dadosvendedor;
write(arq1,reg1);
close(arq1);
end;
'2': begin
reset(arq1);
writeln;
dadosvendedor;
write(arq1,reg1);
close(arq1);
end;
end;
end;

//Procedimento [OPÇÃO 2]
procedure cadastrapedido;
begin
titulo;
writeln;
rewrite(arq2);
reset(arq2);
writeln('2 - Cadastrando pedidos;');
writeln;
writeln('Digite o numero do pedido:');
readln(reg2.numpedido);
writeln('Informe a data do pedido (dd/mm/aaaa):');
readln(reg2.datapedido);
writeln('Informe o nome do cliente:');
readln(reg2.nomecliente); writeln('Informe o nome do vendedor:');
readln(reg2.nomevendedor);
reset(arq1);
while not eof(arq1) do
begin
read(arq1,reg1);
while(reg2.nomevendedor)<>(reg1.nomevendedor) do
begin
writeln('Nome nao consta no sistema, insira um nome valido.');
readln(reg2.nomevendedor);
end;
end;
clrscr;
titulo;
writeln;
writeln('Informe a quantidade de cerveja por tipo: (Use a tabela abaixo)');
tabelapreco; //Procedimento para exibir a tabela de preço
writeln;
writeln('Informe a quantidade a ser vendida - latao:');
readln(reg2.qtdcerveja.qtdlatao);
writeln('Informe a quantidade a ser vendida - lata:');
readln(reg2.qtdcerveja.qtdlata);
writeln('Informe a quantidade a ser vendida - latinha:');
readln(reg2.qtdcerveja.qtdlatinha);
writeln('Informe a quantidade a ser vendida - Long Neck:');
readln(reg2.qtdcerveja.qtdlongneck);
writeln('Valor total do pedido:');
valortotal; //Procedimento para somar a quantidade de cervejas
writeln;
writeln('Informe a situacao do pedido: (Atendido = S ou N)');
readln(reg2.situacao);
write(arq2,reg2);
close(arq1);
close(arq2);
clrscr;
end;

//Procedimento [OPÇÃO 3]
procedure informapreco;
begin
titulo;
writeln;
rewrite(arq3);
reset(arq3);
writeln('3 - Informando precos das cervejas;');
writeln;
writeln('Tipos de cervejas disponiveis:');
writeln;
writeln('Latao;');
writeln('Lata;');
writeln('Latinha;');
writeln('Long Neck.');
writeln;
writeln('Informe o preco da cerveja tipo latao:');
write('R$ ');readln(reg3.platao);
writeln;
writeln('Informe o preco da cerveja tipo lata:');
write('R$ ');readln(reg3.plata);
writeln;
writeln('Informe o preco da cerveja tipo latinha:');
write('R$ ');readln(reg3.platinha);
writeln;
writeln('Informe o preco da cerveja tipo long neck:');
write('R$ ');readln(reg3.plongneck);
write(arq3,reg3);
close(arq3);
clrscr;
end;

//Procedimento [OPÇÃO 4]
procedure consultapedido;
begin
titulo;
writeln;
reset(arq2);
writeln('4 - Consultando situacao do pedido;');
writeln;
writeln('Digite o numero do pedido: (pressione 0 para sair)');
readln(npedido);
if (npedido='0') then
clrscr;
while not eof(arq2) do
begin
read(arq2,reg2);
end;
while (npedido<>reg2.numpedido) and (npedido<>'0') do
begin
writeln('Numero de pedido inexistente.');
writeln('Digite o numero do pedido: (pressione 0 para sair)');
readln(npedido);
end;
if (npedido=reg2.numpedido) then
begin
writeln;
writeln('Pedido n§: ',reg2.numpedido);
writeln('Data: ', reg2.datapedido);
writeln('Situacao (Atendido = S ou N): ',reg2.situacao);
readkey;
end;
close(arq2);
clrscr;
end;

//Procedimento [OPÇÃO 5]
procedure alterapedido;
var
sn: char;
situacaop, npedido1: string[15];
begin
titulo;
writeln;
writeln('5 - Alterando situacao de pedido;');
writeln;
writeln('Digite o numero do pedido que deseja alterar:');
readln(npedido1);
if (reg2.numpedido=npedido1) then
reset(arq2);
writeln('Deseja alterar a situacao? (S ou N)');
readln(sn);
if (sn='S') then
begin
writeln('Informe a atual situacao do pedido:');
readln(situacaop);
with reg2 do
begin
situacao:=situacaop;
write(arq2,reg2);
close(arq2);
end;
end;
clrscr;
end;

// ---------------------------------------------------------- Programa principal
begin
assign(arq1,'C:\Documents and Settings\Argelia\Desktop\vendedor.arq');
assign(arq2,'C:\Documents and Settings\Argelia\Desktop\pedidos.arq');
assign(arq3,'C:\Documents and Settings\Argelia\Desktop\pcerveja.arq');
saida := false;
repeat
begin
titulo;
gotoxy(24,3);writeln('Menu principal');
writeln;
writeln('Caro usuario, escolha uma das opções:');
writeln;
writeln('1 - Cadastrar vendedor;');
writeln('2 - Cadastrar pedidos;');
writeln('3 - Informar precos das cervejas;');
writeln('4 - Consultar situacao do pedido do cliente;');
writeln('5 - Alterar Situacao do pedido;');
writeln('6 - Gerar arquivos com pedidos do mes;');
writeln('7 - Sair;');
writeln;
readln(opcao);
clrscr;
case opcao of
'1': cadastravendedor;
'2': cadastrapedido;
'3': informapreco;
'4': consultapedido;
'5': alterapedido;
'7': begin
writeln('Saindo...');
gotoxy(1,3);write('System developed by Murilo Rocha.');
readln;
saida:=true;
end;
else
begin
gotoxy(1,20);writeln('Opcao invalida. Digite um numero valido!');
writeln;
end;
end;
end;
until(saida=true);
end.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Olá.

1) ESCREVER NOVOS REGISTROS

Seguinte, fiz todas as etapas do projeto (ou quase), o problema é que, quando cadastro mais de um vendedor (opção 1) e vou para a opção 2 onde tem verifica se o nome do vendedor consta no arquivo ou não, ele só reconhece o nome dado no ultimo cadastro que fiz. Será que ele está gravando por cima do registro anterior?

Sim, está gravando por cima, veja:

    '2':begin
reset(arq1);
writeln;
dadosvendedor;
write(arq1,reg1);
close(arq1);
end;

Então, para escrever no arquivo é necessário antes posicionar onde quer escrever... e isto está sendo feito pelo comando reset(), ou seja, além de tentar abrir o arquivo caso ele ainda não esteja aberto, ele posiciona o "ponteiro" no início do arquivo... logo na posição "0". Ao escreve neste arquivo, o registro será salvo nesta posição...

Logo, caso queira inserir um dado "novo", devem-se posicionar o "ponteiro" uma posição logo após a última posição cadastrada... uma boa alternativa seria usar o Seek(), que possibilita esse ponteiro onde desejar. E qual é a última posição do arquivo? Neste caso poderia usar o FileSize(), que retorna a quantidade de registros. Ex.:

Seek(arq1,FileSize(arq1));

Vamos supor que existam "10" vendedores cadastrados. Como as posições no arquivo começam com "0", logo a última posição seria "9". Ao dar esse Seek() acima ele vai posicionar na posição "10", que ainda não existe... logo criando uma posição nova, que estará uma posição após o último cadastrado. :)

Obs.1: CUIDADO. Ao dar um Seek() para uma posição que seja maior que a última existem (como no caso acima, uma a mais), o Pascal irá apontar para referida posição, ou seja, se apontar para 10 posições após o último, ao escrever, vai escrever a 10 posições a frente, criando 9 cadastros vazios no meio...

Obs.2: Usar reads sucessivos até o fim do arquivo também funcionaria para apontar para a posição após o último registro, já que o "ponteiro" estará apontando para lá, mas seria meio que trabalhoso e não sendo uma boa prática de programação (uma gambiarra). Mas vale frisar que o "ponteiro" sempre vai ficar apontando para uma posição logo após o último lido... ao ler novamente, vai apontar para o próximo.. etc... se continuar lendo, após o último, vai dar erro, já que a posição não existe.

Obs3: O reset() além de tentar abrir o arquivo, ele também funciona como um Seek() para posição "0" (apontando para a primeira posição).

2) BUSCA DE REGISTROS

     while not eof(arq1) do
begin
read(arq1,reg1);
while(reg2.nomevendedor)<>(reg1.nomevendedor) do
begin
writeln('Nome nao consta no sistema, insira um nome valido.');
readln(reg2.nomevendedor);
end;
end;

Você precisa corrigir esse trecho acima, lá na hora de cadastrar o pedido...

Para cada nome, comparar do primeiro até no máximo o último. Daí, se não encontrar, ler um próximo nome, e repetir o processo do primeiro até no máximo o último...

Obs.:

1) Se encontrar o vendedor, deve parar de procurar;

2) O mais coerente seria pesquisar pelo codVendedor, e não pelo nomeVendedor

PS: Sugiro que reajustar os nomes das variáveis. Por exemplo, em vez de reg1, usar regVendedor, daí mudaria de nomeVendedor para nome, já que ficaria regVendedor.nome (em vez de regVendedor.nomeVendedor). O mesmo vale para os arquivo, por exemplo de arquivo1 para arqVendedores.

3) CAMINHO DOS ARQUIVOS

Caso queira deixar os arquivo na mesma pasta onde está o executável, basta somente deixar o nome do arquivo, sem o caminho completo. Ex.:

Assign(arq1,'vendedor.arq');
Assign(arq2,'pedidos.arq');
Assign(arq3,'pcerveja.arq');

***

Por ai vai..

No aguardo.

Link para o comentário
Compartilhar em outros sites

Simon, consegui gravar mais de um registro, obrigado. Entretanto, estou "mordendo" nessa etapa aqui:

     while not eof(arq1) do
begin
read(arq1,reg1);
while(reg2.nomevendedor)<>(reg1.nomevendedor) do
begin
writeln('Nome nao consta no sistema, insira um nome valido.');
readln(reg2.nomevendedor);
end;
end;

Você precisa corrigir esse trecho acima, lá na hora de cadastrar o pedido...

Para cada nome, comparar do primeiro até no máximo o último. Daí, se não encontrar, ler um próximo nome, e repetir o processo do primeiro até no máximo o último...

Obs.:

1) Se encontrar o vendedor, deve parar de procurar;

Como assim cara? Poderia me mostrar como ficaria? Quando eu tentei aconteceu o seguinte:

Eu tentei fazer aqui e funciona quando o nome que dou é igual ao nome contido no registro. Quando eu coloco um nome diferente só pra teste ele mostra a mensagem de erro, certo? O problema é que em seguida, se eu colocar o nome correto, a mensagem de erro ainda persiste, ficando em loop infinito.


writeln('Informe o nome do vendedor:');
readln(nome);
reset(arq1);
while not eof(arq1) do
begin
read(arq1,reg1);
if(nome)=(reg1.nomevendedor) then
achou:=1;
end;
while achou <> 1 do
begin
writeln('Nome nao consta no sistema, insira um nome valido.');
readln(nome);
end;
if achou = 1 then
begin
reg2.nomevendedor:=nome;
{aí vem o restante do programa}

--------------------------------------------------------------------------

2) O mais coerente seria pesquisar pelo codVendedor, e não pelo nomeVendedor

Na especificação do trabalho pede para que, no registro, contenha o nome do vendedor.

No aguardo!

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Olá...

Simon, consegui gravar mais de um registro, obrigado.

Então beleza..

Entretanto, estou "mordendo" nessa etapa aqui:

Como assim cara? Poderia me mostrar como ficaria? Quando eu tentei aconteceu o seguinte:

Eu tentei fazer aqui e funciona quando o nome que dou é igual ao nome contido no registro. Quando eu coloco um nome diferente só pra teste ele mostra a mensagem de erro, certo? O problema é que em seguida, se eu colocar o nome correto, a mensagem de erro ainda persiste, ficando em loop infinito.

     writeln('Informe o nome do vendedor:');
readln(nome);
reset(arq1);
while not eof(arq1) do
begin
read(arq1,reg1);
if(nome)=(reg1.nomevendedor) then
achou:=1;
end;
while achou <> 1 do
begin
writeln('Nome nao consta no sistema, insira um nome valido.');
readln(nome);
end;
if achou = 1 then
begin
reg2.nomevendedor:=nome;
{aí vem o restante do programa}

Creio que faltou (re)inicializar a variável achou.

achou:=0;
while not eof(arq1) do

E o que deve se repetir é todo o trecho de pesquisa, e não só a leitura do nome a ser pesquisado, ou seja, após ler o novo nome, tem que pesquisar novamente no arquivo.

Obs.: Não é para repetir o trecho de pesquisa no arquivo, mas sim ajustar o loop do trecho.

Na especificação do trabalho pede para que, no registro, contenha o nome do vendedor.

Conter «o nome do vendedor», é diferente de "ter que pesquisar pelo nome".

Se estiver se referindo que tem que pesquisar pelo nome, OK. Se não, poderia pesquisar pelo código (ou deixar assim mesmo).

No aguardo

Link para o comentário
Compartilhar em outros sites

Valeu Simon, funcionou beleza. Obrigado, de novo.

Seguinte cara, agora me deparei com esse problema, é o último do projeto. :(


//Rotina [OPÇÃO 5 - Alterando pedido]
procedure alterapedido;
var
sn: char;
achou: integer;
situacaop, npedido1: string[15];
begin
titulo;
writeln;
writeln('5 - Alterando situacao de pedido;');
writeln;
writeln('Digite o numero do pedido que deseja alterar:');
readln(npedido1);
reset(arq2);
achou:=0;
while not eof(arq2) do
begin
read(arq2,reg2);
if (reg2.numpedido=npedido1) and (npedido1<>'0') then
begin
achou:=1;
writeln('Numero de pedido encontrado!');
writeln('Deseja alterar a situacao? (S ou N)');
readln(sn);
if (sn='S') then
begin
writeln('Informe a atual situacao do pedido:');
readln(situacaop);
reg2.situacao:=situacaop;
write(arq2,reg2);
close(arq2);
end
else
if (sn='N') then
clrscr;
end;
end;
while achou = 0 do
begin
writeln('Numero de pedido inexistente.');
writeln('Digite o numero do pedido: (pressione 0 para sair)');
readln(npedido1);
reset(arq2);
achou:=0;
while not eof(arq2) do
begin
read(arq2,reg2);
if (reg2.numpedido=npedido1) and (npedido1<>'0') then
begin
achou:=1;
writeln('Numero de pedido encontrado!');
writeln('Deseja alterar a situacao? (S ou N)');
readln(sn);
if (sn='S') then
begin
writeln('Informe a atual situacao do pedido:');
readln(situacaop);
reg2.situacao:=situacaop;
seek(arq2,filepos(arq2)-1);
write(arq2,reg2);
readln;
clrscr;
end
else
if (sn='N') then
clrscr;
end;
end;
end;
clrscr;
end;

Essa rotina é a de alterar os dados, quando eu coloco o numero do pedido errado ele mostra a mensagem... tudo certinho. O problema é que, depois que eu altero o valor, quando vou na opção de consultar situação do pedido, o programa apaga o registro que vem depois do que eu alterei e mostra o registro alterado "antes e depois" ao invés de mostrar só ele atualizado.

Ou seja, o registro que vem depois ele diz que não existe nada e o que alterei, mostra os dados de antes e depois.

To ficando maluco, o projeto é para amanhã (terça) e só falta isso. :D

Abraço, cara!

No aguardo.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Valeu Simon, funcionou beleza. Obrigado, de novo.

Seguinte cara, agora me deparei com esse problema, é o último do projeto. :(


//Rotina [OPÇÃO 5 - Alterando pedido]
procedure alterapedido;
var
sn: char;
achou: integer;
situacaop, npedido1: string[15];
begin
titulo;
writeln;
writeln('5 - Alterando situacao de pedido;');
writeln;
writeln('Digite o numero do pedido que deseja alterar:');
readln(npedido1);
reset(arq2);
achou:=0;
while not eof(arq2) do
begin
read(arq2,reg2);
if (reg2.numpedido=npedido1) and (npedido1<>'0') then
begin
achou:=1;
writeln('Numero de pedido encontrado!');
writeln('Deseja alterar a situacao? (S ou N)');
readln(sn);
if (sn='S') then
begin
writeln('Informe a atual situacao do pedido:');
readln(situacaop);
reg2.situacao:=situacaop;
write(arq2,reg2);
close(arq2);
end
else
if (sn='N') then
clrscr;
end;
end;
while achou = 0 do
begin
writeln('Numero de pedido inexistente.');
writeln('Digite o numero do pedido: (pressione 0 para sair)');
readln(npedido1);
reset(arq2);
achou:=0;
while not eof(arq2) do
begin
read(arq2,reg2);
if (reg2.numpedido=npedido1) and (npedido1<>'0') then
begin
achou:=1;
writeln('Numero de pedido encontrado!');
writeln('Deseja alterar a situacao? (S ou N)');
readln(sn);
if (sn='S') then
begin
writeln('Informe a atual situacao do pedido:');
readln(situacaop);
reg2.situacao:=situacaop;
seek(arq2,filepos(arq2)-1);
write(arq2,reg2);
readln;
clrscr;
end
else
if (sn='N') then
clrscr;
end;
end;
end;
clrscr;
end;

Essa rotina é a de alterar os dados, quando eu coloco o numero do pedido errado ele mostra a mensagem... tudo certinho. O problema é que, depois que eu altero o valor, quando vou na opção de consultar situação do pedido, o programa apaga o registro que vem depois do que eu alterei e mostra o registro alterado "antes e depois" ao invés de mostrar só ele atualizado.

Ou seja, o registro que vem depois ele diz que não existe nada e o que alterei, mostra os dados de antes e depois.

To ficando maluco, o projeto é para amanhã (terça) e só falta isso. :D

Abraço, cara!

No aguardo.

Na primeira parte, faltou dar um Seek() antes de cadastrar...

        if (sn='S') then //Só vai aceita o "S" maiúsculo [SimonViegas]
begin
writeln('Informe a atual situacao do pedido:');
readln(situacaop);
reg2.situacao:=situacaop;
Seek(arq2,filepos(arq2)-1); //FALTOU - posiciona uma "casa" antes [SV]
write(arq2,reg2);
close(arq2);
end

Caso não encontre, você não deve repetir o código, mas sim refazer a pesquisa. Ex.:

  begin
repetir:='S';
while (repetir='S') do
begin

...


if (achou=0 then
begin
//writeln('Numero de pedido inexistente.');
writeln('Numero de pedido não encontrado.');
writeln('Deseja fazer uma nova pesquisa?');
readln(repetir);
end;
end;
end;

No aguardo.

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!