Aplicação: Esse recurso tem a função de substituir o PDV Sync para clientes que possuem sistema Lyncis PDV. O método de sincronismo de venda é via webservice.
Pré Requisito:
- Maquina que possui sistema Lyncis PDV, deve possuir IP fixo, bem como o servidor;
- Firewall do windows deve estar liberado para as portas: 8084 e 4848 para TCP e UDP;
- Banco de dados PostgreSQL deve estar obrigatoriamente na versão 9.3;
Instalação:
1. Na maquina do Lyncis PDV bem como na maquina do servidor, execute a instalação do WebService Tomcat.
OBS: Obrigatoriamente deve ser o webservice Tomcat, caso a maquina já possua outro webservice, como o Glassfish, faca a nova instalação e altere a porta de comunicação para 8080, clique aqui.
Configurações:
1. Faca o Deploy no servidor e no caixa do arquivo, LyncisWeb_PDV.war localizado na rede Lyncis em:
\\172.16.7.45\Release\Lyncis - pdvsync\PDV Sync - WebService
2. No servidor, acesse o properties do webservice, LyncisWeb_PDV, pela URL: http://127.0.0.1:8084/LyncisWeb_PDV/Properties, autenticando com o usuário: lyncis / senha: lyncis@si, verifique, caso não tenha a conexão crie a conexão com o banco de dados lyncis, conforme ilustrado abaixo;

3. No caixa, acesse o properties do webservice, LyncisWeb_PDV, pela URL: http://127.0.0.1:8084/LyncisWeb_PDV/Properties, autenticando com o usuário: lyncis / senha: lyncis@si, verifique, caso não tenha a conexão crie a conexão com o banco de dados lyncis_pdv, conforme ilustrado abaixo;

Importante: Caso na maquina possui 2 bases de dados PDV, crie suas devidas conexões conforme exemplo acima.
4. Ainda na maquina do caixa, execute as scrips abaixo em todas as bases PDV;
SCRIP 1
|
--drop function fn_buscamov(date, date);
--drop function fn_buscamov();
create or replace function fn_buscamov(
_DataInicial date,
_DataFinal date,
out registro integer,
out linha text
) returns setof record as $$
declare rRec record;
begin
for rRec in (select sqltext.registro, sqltext.linha from get_registros_movimento('cupom', _DataInicial, _DataFinal) sqltext ) loop
registro := rRec.registro;
linha := rRec.linha;
return next;
end loop;
for rRec in (select sqltext.registro, sqltext.linha from get_registros_movimento('recebimento', _DataInicial, _DataFinal) sqltext ) loop
registro := rRec.registro;
linha := rRec.linha;
return next;
end loop;
for rRec in (select sqltext.registro, sqltext.linha from get_registros_movimento('operacao', _DataInicial, _DataFinal) sqltext ) loop
registro := rRec.registro;
linha := rRec.linha;
return next;
end loop;
for rRec in (select sqltext.registro, sqltext.linha from get_registros_movimento('mapa_resumo', _DataInicial, _DataFinal) sqltext ) loop
registro := rRec.registro;
linha := rRec.linha;
return next;
end loop;
-- devolucao não tem proteção de indice unico
for rRec in (select sqltext.registro, sqltext.linha from get_registros_movimento('devolucao', null, null) sqltext ) loop
registro := rRec.registro;
linha := rRec.linha;
return next;
end loop;
end;
$$
language 'plpgsql';
create or replace function fn_buscamov(
out registro integer,
out linha text
) returns setof record as $$
declare rRec record;
begin
for rRec in (select sqltext.registro, sqltext.linha from fn_buscamov(null, null) sqltext) loop
registro := rRec.registro;
linha := rRec.linha;
return next;
end loop;
end;
$$
language 'plpgsql';
|
SCRIP 2
-- exemplo select get_insert_sql(tableoid, cupom) from cupom limit 10
create or replace function get_insert_sql(regclass, anyelement)
returns text as $$
declare
_schemaname text;
_tablename text;
_key text;
_value text;
_columns text[];
_values text[];
begin
select pg_namespace.nspname, pg_class.relname
into strict _schemaname, _tablename
from pg_class
join pg_namespace on (pg_namespace.oid = pg_class.relnamespace)
where pg_class.oid = $1;
for _key in
select columns.column_name
from information_schema.COLUMNS
where columns.table_schema = _schemaname
and columns.table_name = _tablename
order by columns.ordinal_position
loop
execute format($s$select format('%%L', ((($1)::%s).%I))$s$, $1, _key) using $2 into strict _value;
_columns := _columns || _key;
_values := _values || _value;
end loop;
return format('insert into %s (%s) values (%s);', $1, array_to_string(_columns, ','), array_to_string(_values, ','));
end;
$$
language 'plpgsql'; |
SCRIP 3
--drop function get_registros_movimento(varchar, date, date);
create or replace function get_registros_movimento(
_TipoMovimento varchar,
_DataInicial date,
_DataFinal date,
out registro integer,
out linha text
) returns setof record as $$
declare
rCab record;
rCab_Item record;
rCab_Finaliz record;
rCab_Docs record;
tSQL text;
begin
registro := 0;
if _TipoMovimento not in ('cupom', 'recebimento', 'operacao', 'mapa_resumo', 'devolucao') then
raise exception 'Tipo de movimento não implementado. Ligue LYNCIS. [%]', _TipoMovimento;
end if;
if _DataInicial is not null and _DataFinal is null then
raise exception 'Faixa de datas inválido. Necessário uma data inicial e final válida.';
elsif _DataInicial is null and _DataFinal is not null then
raise exception 'Faixa de datas inválido. Necessário uma data inicial e final válida.';
elsif _DataFinal < _DataInicial then
raise exception 'Faixa de datas inválido. Necessário uma data inicial e final válida.';
end if;
if _TipoMovimento = 'devolucao' then
-- gerando devolucao
-- como foi verificado acima, se a data incial view significa que a final
-- tbm vai ser preenchida
--if _DataInicial is not null then
-- update devolucao set enviado_erp = null where cast(datahorac as date) between _DataInicial and _DataFinal;
--end if;
-- DEVOLUÇÃO NÃO TEM PROTEÇÃO DE INDICE UNICO
for rCab in (
select id, empresa, checkout, datahorac, cadid, observacao, datamov, ecf, coo
from devolucao
where enviado_erp is null and finalizado is not null
) loop
-- apaga o registro caso o mesmo foi enviado anteriormente mas não processado
-- a trigger no ERP já apaga os itens caso o mesmo exista
tSQL := 'delete from venda_devolucao ';
tSQL := tSQL || 'where pdv_id = ' || rCab.id;
tSQL := tSQL || ' and pdv_empresa =' || rCab.empresa;
tSQL := tSQL || ' and pdv_checkout = ' || rCab.checkout;
tSQL := tSQL || ' and pdv_datahorac = cast(' || quote_literal(rCab.datahorac) || 'as timestamp)';
tSQL := tSQL || ' and pdv_enviado is null';
registro := registro + 1;
linha := tSQL;
return next;
tSQL := 'insert into venda_devolucao(id, status, cadid, observacao, idnota, idempresa, idestoque,';
tSQL := tSQL || 'datahoraa, datahorac, datamov, pdv, cupom, pedido,';
tSQL := tSQL || 'pdv_id, pdv_empresa, pdv_checkout, pdv_datahorac, pdv_processado) values(';
/* ID */ tSQL := tSQL || 'null';
/* STATUS */ tSQL := tSQL || ',0';
/* CADID */ tSQL := tSQL || ',' || coalesce(cast(rCab.cadid as varchar), 'null');
/* OBSERVACAO */ tSQL := tSQL || ',' || coalesce(quote_literal(rCab.observacao), 'null');
/* IDNOTA */ tSQL := tSQL || ',null';
/* IDEMPRESA */ tSQL := tSQL || ',' || rCab.empresa;
/* IDESTOQUE */ tSQL := tSQL || ',null';
/* DATAHORAA */ tSQL := tSQL || ',current_timestamp';
/* DATAHORAC */ tSQL := tSQL || ',current_timestamp';
/* DATAMOV */ tSQL := tSQL || ',cast(' || quote_literal(rCab.datamov) || 'as date)';
/* PDV */ tSQL := tSQL || ',null';
/* CUPOM */ tSQL := tSQL || ',null';
/* PEDIDO */ tSQL := tSQL || ',null';
/* PDV_ID */ tSQL := tSQL || ',' || rCab.id;
/* PDV_EMPRESA */ tSQL := tSQL || ',' || rCab.empresa;
/* PDV_CHECKOUT */ tSQL := tSQL || ',' || rCab.checkout;
/* PDV_DATAHORAC */ tSQL := tSQL || ',cast(' || quote_literal(rCab.datahorac) || 'as timestamp)';
/* PDV_PROCESSADO */ tSQL := tSQL || ',null);';
registro := registro + 1;
linha := tSQL;
return next;
for rCab_Item in (
select id, iddevolucao, empresa, checkout, datahorac, produto, qtde,
qtdeemb, qtdedev, valor, atendente, tipo_venda
from devolucao_item
where iddevolucao = rCab.id
and empresa = rCab.empresa
and checkout = rCab.checkout
and datahorac = rCab.datahorac
) loop
tSQL := 'insert into venda_item_devolucao (id, iddevolucao, idproduto, qtde, qtdeemb, qtdedev, ';
tSQL := tSQL || 'valor, atendente, tipo_venda, pdv_id, pdv_iddevolucao, pdv_empresa, pdv_checkout,';
tSQL := tSQL || 'pdv_datahorac) values(';
/* ID */ tSQL := tSQL || 'null';
/* IDDEVOLUCAO */ tSQL := tSQL || ',null';
/* IDPRODUTO */ tSQL := tSQL || ',' || rCab_Item.produto;
/* QTDE */ tSQL := tSQL || ',' || rCab_Item.qtde;
/* QTDEEMB */ tSQL := tSQL || ',' || rCab_Item.qtdeemb;
/* QTDEDEV */ tSQL := tSQL || ',' || rCab_Item.qtdedev;
/* VALOR */ tSQL := tSQL || ',' || rCab_Item.valor;
/* ATENDENTE */ tSQL := tSQL || ',' || coalesce(cast(rCab_Item.atendente as varchar), 'null');
/* TIPO_VENDA */ tSQL := tSQL || ',' || rCab_Item.tipo_venda;
/* PDV_ID */ tSQL := tSQL || ',' || rCab_Item.id;
/* PDV_IDDEVOLUCAO */ tSQL := tSQL || ',' || rCab_Item.iddevolucao;
/* PDV_EMPRESA */ tSQL := tSQL || ',' || rCab_Item.empresa;
/* PDV_CHECKOUT */ tSQL := tSQL || ',' || rCab_Item.checkout;
/* PDV_DATAHORAC */ tSQL := tSQL || ',cast(' || quote_literal(rCab_Item.datahorac) || ' as timestamp));';
registro := registro + 1;
linha := tSQL;
return next;
end loop;
tSQL := 'update venda_devolucao set pdv_enviado = current_timestamp';
tSQL := tSQL || ' where pdv_id = ' || rCab.id;
tSQL := tSQL || ' and pdv_empresa =' || rCab.empresa;
tSQL := tSQL || ' and pdv_checkout = ' || rCab.checkout;
tSQL := tSQL || ' and pdv_datahorac = cast(' || quote_literal(rCab.datahorac)||' as timestamp);';
registro := registro + 1;
linha := tSQL;
return next;
-- faz update no registro para marcar como enviado
update devolucao set enviado_erp = current_timestamp where finalizado is not null and id = rCab.id;
end loop;
elsif _TipoMovimento = 'cupom' then
-- gerando cupom
-- como foi verificado acima, se a data incial view significa que a final
-- tbm vai ser preenchida
if _DataInicial is not null then
update cupom set processado = null where cast(datahorac as date) between _DataInicial and _DataFinal;
end if;
for rCab in (
select id, get_insert_sql(tableoid, cupom) as sqltext from cupom
where datahoraf is not null and processado is null
and id <> coalesce(idcancelado, 0)
order by id limit 10 ) loop
registro := registro + 1;
linha := rCab.sqltext;
return next;
-- gerando cupom_item
for rCab_Item in (
select id, get_insert_sql(tableoid, cupom_item) as sqltext from cupom_item
where idcupom = rCab.id ) loop
registro := registro + 1;
linha := rCab_Item.sqltext;
return next;
end loop;
-- gerando cupom_finaliz
for rCab_Finaliz in (
select id, get_insert_sql(tableoid, cupom_finaliz) as sqltext from cupom_finaliz
where idcupom = rCab.id ) loop
registro := registro + 1;
linha := rCab_Finaliz.sqltext;
return next;
-- gerando cupom_docs
for rCab_Docs in (
select id, get_insert_sql(tableoid, cupom_docs) as sqltext from cupom_docs
where idcupom_finaliz = rCab_Finaliz.id) loop
registro := registro + 1;
linha := rCab_Docs.sqltext;
return next;
end loop;
end loop;
-- faz update no registro para marcar como enviado
update cupom set processado = current_timestamp where processado is null and id = rCab.id;
end loop;
elsif _TipoMovimento = 'recebimento' then
-- gerando recebimento
-- como foi verificado acima, se a data incial view significa que a final
-- tbm vai ser preenchida
if _DataInicial is not null then
update recebimento set processado = null where cast(datahorac as date) between _DataInicial and _DataFinal;
end if;
for rCab in (
select id, get_insert_sql(tableoid, recebimento) as sqltext from recebimento
where datahoraf is not null and processado is null
order by id limit 10 ) loop
registro := registro + 1;
linha := rCab.sqltext;
return next;
-- gerando recebimento_itens
for rCab_Item in (
select id, get_insert_sql(tableoid, recebimento_itens) as sqltext from recebimento_itens
where idrecebimento = rCab.id ) loop
registro := registro + 1;
linha := rCab_Item.sqltext;
return next;
end loop;
-- gerando cupom_finaliz
for rCab_Finaliz in (
select id, get_insert_sql(tableoid, recebimento_finaliz) as sqltext from recebimento_finaliz
where idrecebimento = rCab.id ) loop
registro := registro + 1;
linha := rCab_Finaliz.sqltext;
return next;
-- gerando cupom_docs
for rCab_Docs in (
select id, get_insert_sql(tableoid, recebimento_docs) as sqltext from recebimento_docs
where idrecebimento_finaliz = rCab_Finaliz.id) loop
registro := registro + 1;
linha := rCab_Docs.sqltext;
return next;
end loop;
end loop;
-- faz update no registro para marcar como enviado
update recebimento set processado = current_timestamp where processado is null and id = rCab.id;
end loop;
elsif _TipoMovimento = 'operacao' then
-- gerando operacao
-- como foi verificado acima, se a data incial view significa que a final
-- tbm vai ser preenchida
if _DataInicial is not null then
update operacao set processado = null where cast(datahora as date) between _DataInicial and _DataFinal;
end if;
for rCab in (
select id, get_insert_sql(tableoid, operacao) as sqltext from operacao
where processado is null
order by id limit 100 ) loop
registro := registro + 1;
linha := rCab.sqltext;
return next;
-- faz update no registro para marcar como enviado
update operacao set processado = current_timestamp where processado is null and id = rCab.id;
end loop;
elseif _TipoMovimento = 'mapa_resumo' then
-- gerando mapa resumo
-- como foi verificado acima, se a data incial view significa que a final
-- tbm vai ser preenchida
if _DataInicial is not null then
update mapa_resumo set processado = null where data between _DataInicial and _DataFinal;
end if;
for rCab in (
select pdv, empresa, data, get_insert_sql(tableoid, mapa_resumo) as sqltext from mapa_resumo
where processado is null
order by pdv, empresa, data limit 10) loop
registro := registro + 1;
linha := rCab.sqltext;
return next;
-- gerando recebimento_itens
for rCab_Item in (
select pdv, empresa, data, get_insert_sql(tableoid, mapa_resumo_trib) as sqltext from mapa_resumo_trib
where pdv = rCab.pdv and empresa = rCab.empresa and data = rCab.data) loop
registro := registro + 1;
linha := rCab_Item.sqltext;
return next;
end loop;
-- faz update no registro para marcar como enviado
update mapa_resumo set processado = current_timestamp where pdv = rCab.pdv and empresa = rCab.empresa and data = rCab.data and processado is null;
end loop;
end if;
end;
$$
language 'plpgsql'; |
|
5. Dentro da pasta Lyncis, unidade L:, crie uma pasta com a nomenclatura ”PDV_sync” e copie executável wget64.exe, localizado na rede Lyncis em:
\\172.16.7.45\Release\Lyncis - pdvsync\PDV Sync - WebService
6. Configurando as URLs que irão fazer o disparo no PDV.
a. Identifique o IP do servidor e PDV.
b. Identifique o nome da conexão criada no PROPERTIES do PDV.
6.1 Criando a URL
"http://IP_SERVIDOR:PORTA/LyncisWeb_PDV/Controller?opcao=executaMovimento&nomeConexao=lyncis&httpLyncisWebPDV=IP_PDV PORTA&nomeConexaoPDV=NOME_CONEXAO_PROPERTIES_PDV&nomeWebService=LyncisWeb_PDV" |
URL exemplo:
"http://127.0.0.1:8080/LyncisWeb_PDV/Controller?opcao=executaMovimento&nomeConexao=lyncis&httpLyncisWebPDV=192.168.20.146:8084&nomeConexaoPDV=lyncis_pdv&nomeWebService=LyncisWeb_PDV" |
6.2 Com a URL definida, abra o navegador no servidor e a digite, sem aspas duplas, o retorno obrigatoriamente deve ser ”Sem Dados Retornados”, com isso obtivemos exito na captura dos cupons no PDV.
IMPORTANTE: Para cada PDV(banco de dados diferente), deve possuir uma URL, apontando para NOME DE CONEXAO DO PROPERTIES, bem como o IP, caso seja em maquinas diferentes.
7. Crie um arquivo .bat com a nomenclatura buscamov, dentro desse arquivo preencha o comando WGET e a URL do PDV.
wget64.exe -N -t 1 -O pdv1.txt "URL_DO_PDV" |
No comando acima, o pdv.txt, é um LOG de execucao da URL que sera criado na raiz da pasta, que pode ser consultado em caso de problemas.
Exemplo:
wget64.exe -N -t 1 -O pdv1.txt "http://127.0.0.1:8080/LyncisWeb_PDV/Controller?opcao=executaMovimento&nomeConexao=lyncis&httpLyncisWebPDV=192.168.20.146:8084&nomeConexaoPDV=lyncis_pdv&nomeWebService=LyncisWeb_PDV" |
Para cada PDV(banco de dados diferente), deve possuir uma URL, apontando para NOME DE CONEXÃO DO PROPERTIES, bem como o IP, caso seja em maquinas diferentes, tudo no mesmo arquivo buscamov.bat
Exemplo:
wget64.exe -N -t 1 -O pdv1.txt "http://127.0.0.1:8080/LyncisWeb_PDV/Controller?opcao=executaMovimento&nomeConexao=lyncis&httpLyncisWebPDV=192.168.20.146:8084&nomeConexaoPDV=lyncis_pdv&nomeWebService=LyncisWeb_PDV"
wget64.exe -N -t 1 -O pdv2.txt "http://127.0.0.1:8080/LyncisWeb_PDV/Controller?opcao=executaMovimento&nomeConexao=lyncis&httpLyncisWebPDV=192.168.20.146:8084&nomeConexaoPDV=lyncis_treinamento&nomeWebService=LyncisWeb_PDV" |
|
8. Execute o arquivo buscamov.bat, onde brevemente a tela do CMD ira abrir e fechar. Para verificar o comando criado bem como a comunicação com os PDVs. Abra o arquivo pdv1.txt, localizado na raiz e o mesmo deve estar como na imagem abaixo:

9. Agora sera necessario criar um Agendador de Tarefas no Windows do servidor para que o buscamov.bet seja executado de tempo em tempo para processamento das vendas.
a. Abra o Agendador de Tarefas do windows, localizado em Ferramentas do Sistema (em inglês System Tools > Task Scheduler).
b. Clique com o botão direto e Crie uma nova tarefa.

c. Em Geral preencha, conforme imagem abaixo:

d. Em Disparadores preencha, conforme imagem abaixo:

e. Em ação preencha, conforme imagem abaixo, e aponte o arquivo buscamov.bat (sempre pela unidade local) – Opção 1

Ou utilize como configuração abaixo: – Opção 2

f. Em configurações, desmarque a opção, Interromper a tarefa se ela for executada por mais de X dias

g. Conclua a criação da tarefa, e verifique a data da próxima execução.

h. Agora, aguarde a próxima execução e caso tenha vendas a processar, verifique se a mesma foi processada pelo ProcVenda.