alter table tabelaprecoexamesusuario alter teu_alteracao type varchar(300); --[lode] insert into atualizacoes(atu_nome) values ('v24020001_290524.sql'); --[lode] alter table examerequisicao alter exr_motivorecoleta type varchar(500); --[lode] insert into atualizacoes(atu_nome) values ('v24020002_100624.sql'); --[lode] alter table geladeiras alter usr_codigo type varchar(20); --[lode] create index xestornoloteexternoexamerequisicaofilial on loteexternoexamerequisicao(fil_kodigo, req_codigo, exa_codigo, mco_codigo, ler_datahoraestorno); --[lode] insert into atualizacoes(atu_nome) values ('v24020003_170624.sql'); --[lode] alter table examerequisicaosituacoes alter ers_motivorecoleta type varchar(500); --[lode] insert into atualizacoes(atu_nome) values ('v24020004_180624.sql'); --[lode] alter table loteexternorequisicao add leq_enviows text; --[lode] insert into atualizacoes(atu_nome) values ('v24020005_240624.sql'); --[lode] CREATE OR REPLACE FUNCTION calculaueps(integer, integer, integer, timestamp without time zone, numeric, numeric, character varying, integer, boolean) RETURNS void LANGUAGE plpgsql AS $function$ declare filial alias for $1; pcodigolancto alias for $2; codigomaterial alias FOR $3; datalancto alias FOR $4; pquantidade alias for $5; pvalorunitario alias for $6; tipolancto alias FOR $7; arredondamento alias FOR $8; cancelado alias FOR $9; TIPO_LANCTO_ENTRADA CHARACTER VARYING := upper('E'); TIPO_LANCTO_SAIDA CHARACTER VARYING := upper('S'); CASAS_ARREDONDAMENTO INTEGER := 4; valoraux numeric(15,4); quantidadeaux numeric(15,4); valorunitarioaux numeric(15,4); qtdeloopaux numeric(15,4); saldorestanteaux numeric(15,4); quantidade numeric(15,4); auxcursor refcursor; auxrecord RECORD; auxcursorcanc refcursor; auxrecordcanc RECORD; begin quantidade := pquantidade; if (cancelado and upper(tipolancto) = TIPO_LANCTO_SAIDA) then --se o lancamento de saida foi cancelado --busca os lancamentos de entrada com saldo restante menor que a quantidade (em ordem ascendente) OPEN auxcursor for select * from (select uep_codigo as codigo ,uep_quantidade as qtde ,uep_saldorestante as saldorestante ,SUM(uep.uep_quantidade - uep.uep_saldorestante) over (order by date_trunc('day', lce.lce_datahora), lce.lce_codigo) as somatotal ,SUM(uep.uep_quantidade - uep.uep_saldorestante) over (order by date_trunc('day', lce.lce_datahora), lce.lce_codigo) - (uep.uep_quantidade - uep.uep_saldorestante) + 1 as somaanterior from lanctoestoqueueps uep join lanctoestoque lce on uep.fil_codigo = lce.fil_codigo and uep.lce_codigo = lce.lce_codigo where uep.fil_codigo = filial and uep.lce_kodigo is null and lce.mat_codigo = codigomaterial and lce.lce_datahoracancelamento is null and uep.uep_saldorestante < uep.uep_quantidade and lce.lce_tipo = TIPO_LANCTO_ENTRADA order by date_trunc('day', lce_datahora) ,lce.lce_codigo) aux where quantidade >= somaanterior or quantidade between somaanterior and somatotal; loop fetch auxcursor into auxrecord; if (auxrecord is null OR quantidade <= 0) then close auxcursor; exit; end if; qtdeloopaux := CASE WHEN quantidade > (auxrecord.qtde - auxrecord.saldorestante) then (auxrecord.qtde - auxrecord.saldorestante) ELSE quantidade end; quantidade := quantidade - qtdeloopaux; --atualiza os saldo restante dos lancamentos update lanctoestoqueueps set uep_saldorestante = uep_saldorestante + qtdeloopaux WHERE fil_codigo = filial and uep_codigo = auxrecord.codigo; end loop; ELSIF (cancelado AND upper(tipolancto) = TIPO_LANCTO_ENTRADA) then --se o lancamento de entrada foi cancelado --busca os lancamentos de saida que utilizam a entrada que esta sendo cancelada (em ordem decrescente) OPEN auxcursorcanc for select uep.lce_codigo as codigolancto ,uep.uep_quantidade as qtde from lanctoestoqueueps uep join lanctoestoque lce on uep.fil_codigo = lce.fil_codigo and uep.lce_codigo = lce.lce_codigo where uep.fil_codigo = filial and uep.lce_kodigo = pcodigolancto and lce.lce_datahoracancelamento is null order by date_trunc('day', lce_datahora) desc ,lce.lce_codigo desc; --para cada lancamento de saida, deve-se gerar uma nova entrada utilizando os proximos lancamentos de entrada (em ordem decrescente) loop fetch auxcursorcanc into auxrecordcanc; if (auxrecordcanc is null) then close auxcursorcanc; exit; end if; --busca os lancamentos de entrada que serao usados para dar a saida (em ordem decrescente) OPEN auxcursor for select * from (select uep.uep_codigo as codigo ,uep.lce_codigo as codigolancto ,uep.uep_quantidade as qtde ,uep.uep_saldorestante as saldorestante ,uep.uep_valorunitario as valorunitario ,SUM(uep.uep_saldorestante) over (order by date_trunc('day', lce.lce_datahora), lce.lce_codigo) as somatotal ,SUM(uep.uep_saldorestante) over (order by date_trunc('day', lce.lce_datahora), lce.lce_codigo) - uep.uep_saldorestante + 1 as somaanterior from lanctoestoqueueps uep join lanctoestoque lce on uep.fil_codigo = lce.fil_codigo and uep.lce_codigo = lce.lce_codigo where uep.fil_codigo = filial and uep.lce_kodigo is null and lce.mat_codigo = codigomaterial and lce.lce_datahoracancelamento is null and uep.uep_saldorestante > 0 and lce.lce_tipo = TIPO_LANCTO_ENTRADA order by date_trunc('day', lce_datahora) desc ,lce.lce_codigo desc ) aux where saldorestante < quantidade or quantidade between somaanterior and somatotal; qtdeloopaux := auxrecordcanc.qtde; loop fetch auxcursor into auxrecord; if (auxrecord is null OR qtdeloopaux <= 0) then close auxcursor; exit; end if; if (auxrecord.saldorestante <= qtdeloopaux) then valoraux := round(auxrecord.valorunitario * auxrecord.saldorestante, CASAS_ARREDONDAMENTO, arredondamento); quantidadeaux := auxrecord.saldorestante; saldorestanteaux := 0; else valoraux := round(auxrecord.valorunitario * qtdeloopaux, CASAS_ARREDONDAMENTO, arredondamento); quantidadeaux := qtdeloopaux; saldorestanteaux := auxrecord.saldorestante - qtdeloopaux; end if; valorunitarioaux := auxrecord.valorunitario; qtdeloopaux := qtdeloopaux - quantidadeaux; --atualiza o lancamento de entrada de origem update lanctoestoqueueps set uep_saldorestante = saldorestanteaux where fil_codigo = filial and uep_codigo = auxrecord.codigo; --insere o novo lancamento ueps insert into lanctoestoqueueps (fil_codigo ,uep_codigo ,lce_codigo ,lce_kodigo ,uep_quantidade ,uep_saldorestante ,uep_valor ,uep_valorunitario) values(filial ,nextval('lanctoestoqueueps_' || filial || '_sequence') ,auxrecordcanc.codigolancto ,auxrecord.codigolancto ,quantidadeaux ,null ,valoraux ,valorunitarioaux); end loop; END LOOP; elsif (not cancelado AND upper(tipolancto) = TIPO_LANCTO_SAIDA) then --se o lancamento for de saida --busca os lancamentos de entrada que serao usados para dar a saida OPEN auxcursor for select * from (select uep.uep_codigo as codigo ,uep.lce_codigo as codigolancto ,uep.uep_quantidade as qtde ,uep.uep_saldorestante as saldorestante ,uep.uep_valorunitario as valorunitario ,SUM(uep.uep_saldorestante) over (order by date_trunc('day', lce.lce_datahora) desc, lce.lce_codigo desc) as somatotal ,SUM(uep.uep_saldorestante) over (order by date_trunc('day', lce.lce_datahora) desc, lce.lce_codigo desc) - uep.uep_saldorestante + 1 as somaanterior from lanctoestoqueueps uep join lanctoestoque lce on uep.fil_codigo = lce.fil_codigo and uep.lce_codigo = lce.lce_codigo where uep.fil_codigo = filial and uep.lce_kodigo is null and lce.mat_codigo = codigomaterial and lce.lce_datahoracancelamento is null and uep.uep_saldorestante > 0 and lce.lce_tipo = TIPO_LANCTO_ENTRADA order by date_trunc('day', lce_datahora) desc ,lce.lce_codigo desc ) aux where saldorestante < quantidade or quantidade between somaanterior and somatotal; qtdeloopaux := quantidade; loop fetch auxcursor into auxrecord; if (auxrecord is null OR qtdeloopaux <= 0) then close auxcursor; exit; end if; if (auxrecord.saldorestante <= qtdeloopaux) then valoraux := round(auxrecord.valorunitario * auxrecord.saldorestante, CASAS_ARREDONDAMENTO, arredondamento); quantidadeaux := auxrecord.saldorestante; saldorestanteaux := 0; else valoraux := round(auxrecord.valorunitario * qtdeloopaux, CASAS_ARREDONDAMENTO, arredondamento); quantidadeaux := qtdeloopaux; saldorestanteaux := auxrecord.saldorestante - qtdeloopaux; end if; valorunitarioaux := auxrecord.valorunitario; qtdeloopaux := qtdeloopaux - quantidadeaux; --atualiza o lancamento de entrada de origem update lanctoestoqueueps set uep_saldorestante = saldorestanteaux where fil_codigo = filial and uep_codigo = auxrecord.codigo; --insere o novo lancamento ueps insert into lanctoestoqueueps (fil_codigo ,uep_codigo ,lce_codigo ,lce_kodigo ,uep_quantidade ,uep_saldorestante ,uep_valor ,uep_valorunitario) values(filial ,nextval('lanctoestoqueueps_' || filial || '_sequence') ,pcodigolancto ,auxrecord.codigolancto ,quantidadeaux ,null ,valoraux ,valorunitarioaux); end loop; elsif (upper(tipolancto) = TIPO_LANCTO_ENTRADA) then --se o lancamento for de entrada --adiciona a entrada na tabela INSERT INTO lanctoestoqueueps (fil_codigo ,uep_codigo ,lce_codigo ,lce_kodigo ,uep_quantidade ,uep_saldorestante ,uep_valor ,uep_valorunitario) values (filial ,nextval('lanctoestoqueueps_' || filial || '_sequence') ,pcodigolancto ,null ,quantidade ,quantidade ,round(pvalorunitario * quantidade, CASAS_ARREDONDAMENTO, arredondamento) ,pvalorunitario); end if; end; $function$ ; --[lode] insert into atualizacoes(atu_nome) values ('v24020006_250624.sql'); --[lode]