update conf set confrelease = '13408'; ------------------------------------------------------------------------------------------------ -- f_processar_fv -- DROP FUNCTION public.f_processar_fv(int4, int4); CREATE OR REPLACE FUNCTION public.f_processar_fv(integer, integer) RETURNS TABLE(frprocpvcod integer, frpropedcod integer, frpropednum integer, frpromens text) LANGUAGE plpgsql AS $function$ DECLARE /* 23/11/22 - David: Criação da função f_processar_fv 11/02/26 - Atualização: Adição de campos de geolocalização 17/03/26 - Atualização: Validações de cabeçalho e itens (bloqueio, horário, cliente, boleto/opnf, estoque, desconto, limite de crédito, corte, promoção, desconto por quantidade, formatação de valores, duplicidade, RCA, produto ativo/fora de linha, data programada, divergência de valor total, itens duplicados) 26/03/26 - Alteração do campo ped_referenciaerp para v_pvcod */ p_pedcod ALIAS FOR $1; p_empresa ALIAS FOR $2; rec_ped RECORD; rec_item RECORD; v_pvcod INTEGER; v_agora DATE; v_valido BOOLEAN; v_resposta TEXT; v_bloq TEXT; v_bloqusuparcod INTEGER; v_bloqhorario DATE; v_bloqobs TEXT; v_qtdedisp NUMERIC(14,4); v_qtdeate NUMERIC(14,4); v_qtdeatecar NUMERIC(14,4); v_vltab NUMERIC(14,4); v_vlven NUMERIC(14,4); v_custocompra NUMERIC(14,4); v_custoreal NUMERIC(14,4); v_basedebcred NUMERIC(14,4); v_calcDebCred TEXT; v_sit TEXT; -- Configurações da empresa v_conf_sempre_bloqueado TEXT; v_conf_sempre_pendente TEXT; v_conf_recusa_lim_cred TEXT; v_conf_recusa_item_sem_est TEXT; v_conf_vende_bo_n_contab TEXT; v_conf_pv_clibloq TEXT; v_conf_perc_min NUMERIC(14,4); v_conf_perc_max NUMERIC(14,4); v_conf_corte TEXT; v_conf_hora_ini VARCHAR(10); v_conf_hora_fim VARCHAR(10); -- Controle de corte/itens v_item_aceito BOOLEAN; v_tratou_corte BOOLEAN; v_item_ate INTEGER; v_soma_pedido NUMERIC(14,4); v_soma_pedido_ate NUMERIC(14,4); v_perc_dif NUMERIC(14,4); -- Desconto por quantidade v_dq_vlven NUMERIC(14,4); v_dq_qtde INTEGER; v_dq_qtate INTEGER; v_dq_taxa NUMERIC(14,4); v_dq_vl NUMERIC(14,4); -- Dados do cliente/operação v_clibloq TEXT; v_clilimdisp NUMERIC(14,4); v_opnfsta TEXT; v_tctdoc TEXT; -- Duplicidade v_pvcod_existente INTEGER; v_ped_dup_clicod INTEGER; v_ped_dup_rcacod INTEGER; v_ped_dup_vltotal NUMERIC(14,4); -- RCA v_parsit TEXT; v_rcaav TEXT; -- Produto v_estdispfv TEXT; v_estforalinha TEXT; -- Promoção v_promsta TEXT; v_promdtini DATE; v_promdtfim DATE; -- Divergência de valor v_soma_itens NUMERIC(14,4); BEGIN SELECT now()::date INTO v_agora; FOR rec_ped IN SELECT ped_codigo, ped_referenciaerp, ped_rcacod AS pvcadusuparcod, ped_dtlan AS pvcadhorario, 'IMPORTADO PELO DEMANDER' AS pvacao, ped_filcod AS pvempparcod, 'FV' AS pvcanal, 'AA' AS pvsta, ped_clicod AS pvcliparcod, pardes, ped_tvcod AS pvopnfcod, ped_plpgcod AS pvplpgcod, ped_cobcod AS pvtccod, ped_vltotal AS pvvltotal, ped_vltotal AS pvvltotalate, ped_vltotal AS pvvltotalatecar, ped_indice AS pvindice, ped_rcacod AS pvrcaparcod, ped_obs AS pvobsped, ped_obsnota AS pvobsnf, ped_numpedcli AS pvpedcli, ped_dtprog AS pvdtprog, ped_latitude AS pvlatitude, ped_longitude AS pvlongitude, ped_accuracy AS pvaccuracy, ped_timestamp_geo AS pvtimestamp_geo, (SELECT lpcod FROM lp WHERE lpcod = (SELECT f_livro_do_cliente FROM f_livro_do_cliente(ped_clicod, ped_filcod))) AS lpcod, (SELECT lpdes FROM lp WHERE lpcod = (SELECT f_livro_do_cliente FROM f_livro_do_cliente(ped_clicod, ped_filcod))) AS lpdes, 'ENVIADO' || chr(10) || 'Dt.Lancamento.....: ' || to_char(ped_dtlan, 'DD/MM/YYYY') || chr(10) || 'Dt.Processamento..: ' || to_char(now(), 'DD/MM/YYYY HH24:MI:SS') || chr(10) || '** Pedido enviado com sucesso' || chr(10) || 'Cod.Cliente.......: ' || ped_clicod || chr(10) || 'Cliente...........: ' || pardes || chr(10) || 'Livro.............: ' || (SELECT lpcod FROM lp WHERE lpcod = (SELECT f_livro_do_cliente FROM f_livro_do_cliente(ped_clicod, ped_filcod))) || ' - ' || (SELECT lpdes FROM lp WHERE lpcod = (SELECT f_livro_do_cliente FROM f_livro_do_cliente(ped_clicod, ped_filcod))) || chr(10) || 'Pedido no Palm....: ' || ped_codigo || chr(10) || 'Valor Pedido......: ' || TO_CHAR(ped_vltotal, 'FM999999990.00') AS pedresposta FROM ipedi.ped JOIN par ON ped_clicod = parcod WHERE ped_importado = 1 AND ped_codigo = p_pedcod AND ped_filcod = p_empresa LOOP -- Carregar configurações SELECT conf_fv_sempre_bloqueado, conf_fv_sempre_pendente, conf_fv_recusa_lim_cred, conf_fv_recusa_item_sem_est, conf_fv_vende_bo_opnf_n_contab, conf_fv_pv_clibloq, COALESCE(conf_fv_perc_min, 0), COALESCE(conf_fv_perc_max, 0), confcondicaocortepvfv, confhorarioinireceberfv, confhorariofimreceberfv INTO v_conf_sempre_bloqueado, v_conf_sempre_pendente, v_conf_recusa_lim_cred, v_conf_recusa_item_sem_est, v_conf_vende_bo_n_contab, v_conf_pv_clibloq, v_conf_perc_min, v_conf_perc_max, v_conf_corte, v_conf_hora_ini, v_conf_hora_fim FROM conf WHERE confempparcod = rec_ped.pvempparcod; -- Inicializar controles v_valido := TRUE; v_sit := 'AA'; v_bloq := NULL; v_bloqusuparcod := NULL; v_bloqhorario := NULL; v_bloqobs := NULL; v_tratou_corte := FALSE; v_item_ate := 0; v_soma_pedido := 0; v_soma_pedido_ate := 0; v_soma_itens := 0; v_pvcod := 0; v_resposta := rec_ped.pedresposta; -- ---------------------------------------------- -- VALIDAÇÃO 1: DUPLICIDADE -- ---------------------------------------------- SELECT pvcod, pvcliparcod, pvrcaparcod, pvvltotal INTO v_pvcod_existente, v_ped_dup_clicod, v_ped_dup_rcacod, v_ped_dup_vltotal FROM pv WHERE pvrefpvcod = rec_ped.ped_referenciaerp LIMIT 1; IF FOUND THEN -- Verifica se é realmente o mesmo pedido (cliente + rca + valor) IF v_ped_dup_clicod = rec_ped.pvcliparcod AND v_ped_dup_rcacod = rec_ped.pvcadusuparcod AND ABS(v_ped_dup_vltotal - rec_ped.pvvltotal) <= 0.05 THEN v_resposta := v_resposta || chr(10) || '** PEDIDO JA PROCESSADO ANTERIORMENTE **' || chr(10) || 'Pedido ERP existente: ' || v_pvcod_existente || chr(10) || 'Referencia: ' || rec_ped.ped_referenciaerp; UPDATE ipedi.ped SET ped_importado = 2, ped_obsretorno = v_resposta WHERE ped_codigo = p_pedcod; RETURN QUERY SELECT p_pedcod, v_pvcod_existente::integer, v_pvcod_existente::integer, v_resposta::text; RETURN; ELSE -- Mesma referência mas dados divergentes — recusa v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Referencia duplicada com dados divergentes' || chr(10) || 'Referencia: ' || rec_ped.ped_referenciaerp; END IF; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 2: RCA ATIVO E USA FV -- ---------------------------------------------- IF v_valido THEN SELECT parsit INTO v_parsit FROM par WHERE parcod = rec_ped.pvcadusuparcod; SELECT rcaav INTO v_rcaav FROM rca WHERE rcaparcod = rec_ped.pvcadusuparcod; IF v_parsit = 'I' THEN v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Vendedor inativo (RCA: ' || rec_ped.pvcadusuparcod || ')'; ELSIF v_rcaav = 'N' THEN v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Vendedor nao habilitado para o Forca de Vendas (RCA: ' || rec_ped.pvcadusuparcod || ')'; END IF; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 3: SEMPRE BLOQUEADO -- ---------------------------------------------- IF v_valido AND v_conf_sempre_bloqueado = 'S' THEN v_bloq := 'S'; v_bloqusuparcod := 100; v_bloqhorario := date(now()); v_bloqobs := 'BLOQUEADO PELA CONFIGURACAO PADRAO'; v_sit := 'BLOQUEADO'; v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO BLOQUEADO **' || chr(10) || 'Motivo: Bloqueado pela configuracao padrao'; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 4: HORÁRIO DE RECEPÇÃO -- ---------------------------------------------- IF v_valido AND v_conf_hora_ini IS NOT NULL AND v_conf_hora_fim IS NOT NULL THEN IF now()::time < v_conf_hora_ini::time OR now()::time > v_conf_hora_fim::time THEN v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Fora do horario de recepcao de pedidos' || chr(10) || 'Horario permitido: ' || v_conf_hora_ini || ' ate ' || v_conf_hora_fim; END IF; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 5: CLIENTE BLOQUEADO -- ---------------------------------------------- IF v_valido THEN SELECT clibloq INTO v_clibloq FROM cli WHERE cliparcod = rec_ped.pvcliparcod; IF v_clibloq = 'S' THEN IF v_conf_pv_clibloq = 'S' THEN v_sit := 'AP'; v_bloq := 'S'; v_bloqusuparcod := rec_ped.pvcadusuparcod; v_bloqhorario := date(now()); v_bloqobs := 'CLIENTE BLOQUEADO'; v_resposta := v_resposta || chr(10) || '** Pedido sujeito a aprovacao, cliente bloqueado.'; ELSE v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Cliente BLOQUEADO'; END IF; END IF; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 6: OPERAÇÃO NÃO CONTÁBIL COM BOLETO -- ---------------------------------------------- IF v_valido THEN SELECT opnfsta INTO v_opnfsta FROM opnf WHERE opnfcod = rec_ped.pvopnfcod; SELECT tctdoc INTO v_tctdoc FROM tc WHERE tccod = rec_ped.pvtccod; IF v_conf_vende_bo_n_contab = 'N' AND v_tctdoc = 'BO' AND v_opnfsta = 'G' THEN v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Venda com operacao nao contabil (' || v_opnfsta || ') nao permitida para BOLETO'; END IF; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 7: DATA PROGRAMADA NO PASSADO -- ---------------------------------------------- IF v_valido AND rec_ped.pvdtprog < date(now()) THEN IF v_sit = 'AA' THEN v_sit := 'AP'; END IF; v_resposta := v_resposta || chr(10) || '** Pedido sujeito a aprovacao: data programada no passado' || chr(10) || 'Data informada: ' || to_char(rec_ped.pvdtprog, 'DD/MM/YYYY') || chr(10) || 'Data atual.....: ' || to_char(now(), 'DD/MM/YYYY'); END IF; -- ---------------------------------------------- -- VALIDAÇÃO 8: SEMPRE PENDENTE -- ---------------------------------------------- IF v_valido AND v_conf_sempre_pendente = 'S' AND v_sit = 'AA' THEN v_sit := 'AP'; v_resposta := v_resposta || chr(10) || '** Pedido sujeito a aprovacao conforme configuracao padrao.'; END IF; -- ---------------------------------------------- -- VALIDAÇÃO 9: DIVERGÊNCIA VALOR TOTAL -- Calcula soma real dos itens para comparar com cabeçalho -- ---------------------------------------------- IF v_valido THEN SELECT COALESCE(SUM(pedi_vltotal), 0) INTO v_soma_itens FROM ipedi.pedi WHERE pedi_ped_codigo = rec_ped.ped_codigo; IF ABS(v_soma_itens - rec_ped.pvvltotal) > 0.05 THEN v_resposta := v_resposta || chr(10) || 'AVISO: Valor do cabecalho diverge da soma dos itens' || chr(10) || 'Cabecalho: ' || TO_CHAR(rec_ped.pvvltotal, 'FM999999990.00') || chr(10) || 'Soma itens: ' || TO_CHAR(v_soma_itens, 'FM999999990.00') || chr(10) || 'Valor corrigido para soma dos itens.'; END IF; END IF; -- ---------------------------------------------- -- PROCESSAMENTO DOS ITENS -- ---------------------------------------------- IF v_valido THEN SELECT nextval('pv_pvcod_seq') INTO v_pvcod; INSERT INTO pv( pvcod, pvcadusuparcod, pvcadhorario, pvacao, pvnumped, pvempparcod, pvcanal, pvsta, pvcliparcod, pvopnfcod, pvplpgcod, pvtccod, pvvltotal, pvvltotalate, pvvltotalatecar, pvindice, pvrcaparcod, pvobsped, pvobsnf, pvpedcli, pvdtprog, pvfvresposta, pvbloq, pvbloqusuparcod, pvbloqhorario, pvbloqobs, pvsit, pv_latitude, pv_longitude, pv_accuracy, pv_timestamp_geo, pvrefpvcod ) VALUES ( v_pvcod, rec_ped.pvcadusuparcod, rec_ped.pvcadhorario, rec_ped.pvacao, v_pvcod, rec_ped.pvempparcod, rec_ped.pvcanal, v_sit, rec_ped.pvcliparcod, rec_ped.pvopnfcod, rec_ped.pvplpgcod, rec_ped.pvtccod, -- Usa soma real dos itens como valor correto v_soma_itens, v_soma_itens, v_soma_itens, rec_ped.pvindice, rec_ped.pvrcaparcod, rec_ped.pvobsped, rec_ped.pvobsnf, rec_ped.pvpedcli, rec_ped.pvdtprog, v_resposta, v_bloq, v_bloqusuparcod, v_bloqhorario, v_bloqobs, v_sit, rec_ped.pvlatitude, rec_ped.pvlongitude, rec_ped.pvaccuracy, rec_ped.pvtimestamp_geo, v_pvcod ); FOR rec_item IN SELECT 'IMPORTADO PELO DEMANDER' AS pviacao, 'FV' AS pvicanal, pedi_procod AS pviprocod, pedi_embcod AS pviuvecod, uvedes AS pviuvedes, uveun AS pviuveun, uvemult AS pviuvemult, pedi_qt AS pviqtde, (pedi_vltotal / NULLIF(pedi_qt, 0)) AS pvivlven, pedi_vltotal AS pvivltotal, COALESCE(pedi_promcod, 0) AS pvipromcod, COALESCE(pedi_descqtdecod, 0) AS pvidescqtdecod, pedi_vlst AS pvivlst, pedi_vlipi AS pvivlipi, ROW_NUMBER() OVER (ORDER BY pedi_codigo) AS pviseq FROM ipedi.pedi JOIN uve ON pedi_procod = uveprocod AND pedi_embcod = uvecod WHERE pedi_ped_codigo = rec_ped.ped_codigo LOOP v_item_aceito := TRUE; v_dq_vlven := NULL; -- -- VALIDAÇÃO: PRODUTO ATIVO E DISPONÍVEL NO FV -- SELECT estdispfv, estforalinha INTO v_estdispfv, v_estforalinha FROM est WHERE estprocod = rec_item.pviprocod AND estempparcod = rec_ped.pvempparcod; IF v_estforalinha = 'S' THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Produto fora de linha'; ELSIF v_estdispfv = 'N' THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Produto nao disponivel para Forca de Vendas'; END IF; IF v_item_aceito THEN -- -- ESTOQUE E PREÇO -- SELECT COALESCE(TRUNC((estqtde - estqtderes - estqtdebloq - estqtdepend - estqtdediverg) / rec_item.pviuvemult), 0), COALESCE(estcustocompra, 0), COALESCE(estcustoreal, 0), estcalcdebcred INTO v_qtdedisp, v_custocompra, v_custoreal, v_calcDebCred FROM est WHERE estprocod = rec_item.pviprocod AND estempparcod = rec_ped.pvempparcod; SELECT fprvltab, fprvlven INTO v_vltab, v_vlven FROM f_preco( rec_ped.lpcod, rec_ped.pvrcaparcod, rec_ped.pvcliparcod, rec_ped.pvplpgcod, rec_ped.pvtccod, rec_item.pviprocod::text, 1 ) WHERE fprembcod = rec_item.pviuvecod; IF v_vltab IS NULL THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM SEM PRECO: ' || rec_item.pviprocod || ' (livro ' || rec_ped.lpcod || ') - Item cortado'; ELSE -- ---------------------------------------------- -- VALIDAÇÃO DE PREÇO -- Precedência: desconto por qtde > promoção > mín/máx -- ---------------------------------------------- IF rec_item.pvidescqtdecod > 0 THEN SELECT dqiqtde, dqiqtate, dqitaxa, dqivl INTO v_dq_qtde, v_dq_qtate, v_dq_taxa, v_dq_vl FROM descqtdei JOIN descqtde ON dqidqcod = dqcod WHERE dqcod = rec_item.pvidescqtdecod AND dqsta = 'A' AND dqfv = 'S' AND date(now()) BETWEEN dqDtIni AND dqDtFim AND dqiqtde <= rec_item.pviqtde AND dqiqtate >= rec_item.pviqtde LIMIT 1; IF NOT FOUND THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Politica de desconto por qtde nao encontrada ou fora da faixa' || ' (cod: ' || rec_item.pvidescqtdecod || ' qtde: ' || TO_CHAR(rec_item.pviqtde, 'FM999999990.00') || ')'; ELSE IF v_dq_vl > 0 THEN v_dq_vlven := v_dq_vl; ELSE v_dq_vlven := v_vltab - (v_vltab * v_dq_taxa / 100); END IF; IF ABS(rec_item.pvivlven - v_dq_vlven) > 0.01 THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Preco diverge da politica de desconto por qtde' || ' Enviado: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' Esperado: ' || TO_CHAR(v_dq_vlven, 'FM999999990.00'); END IF; END IF; ELSIF rec_item.pvipromcod > 0 THEN -- -- VALIDA SE PROMOÇÃO ESTÁ VIGENTE NO BANCO -- SELECT promsta, promdtini, promdtfim INTO v_promsta, v_promdtini, v_promdtfim FROM promocao WHERE promcod = rec_item.pvipromcod LIMIT 1; IF NOT FOUND OR v_promsta <> 'A' THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Promocao inexistente ou inativa' || ' (promcod: ' || rec_item.pvipromcod || ')'; ELSIF date(now()) NOT BETWEEN v_promdtini AND v_promdtfim THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Promocao fora do periodo de vigencia' || ' (de: ' || to_char(v_promdtini, 'DD/MM/YYYY') || ' ate: ' || to_char(v_promdtfim, 'DD/MM/YYYY') || ')'; ELSIF ABS(rec_item.pvivlven - v_vlven) > 0.01 THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Preco diverge da promocao' || ' Enviado: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' Preco promo: ' || TO_CHAR(v_vlven, 'FM999999990.00') || ' (prom: ' || rec_item.pvipromcod || ')'; END IF; ELSE -- -- SEM PROMOÇÃO E SEM DESCONTO QTDE: VALIDA MÍN/MÁX -- IF v_vltab > 0 THEN IF rec_item.pvivlven < v_vltab THEN v_perc_dif := (v_vltab / rec_item.pvivlven - 1) * 100; IF v_perc_dif > v_conf_perc_min THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Preco ABAIXO do permitido' || ' Venda: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' Min: ' || TO_CHAR(ROUND(v_vltab * (1 - v_conf_perc_min / 100), 2), 'FM999999990.00'); ELSE IF v_sit = 'AA' THEN v_sit := 'AP'; END IF; v_resposta := v_resposta || chr(10) || 'AVISO ITEM: ' || rec_item.pviprocod || ' - Preco abaixo, dentro da margem permitida' || ' Venda: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' Min: ' || TO_CHAR(ROUND(v_vltab * (1 - v_conf_perc_min / 100), 2), 'FM999999990.00'); END IF; ELSIF rec_item.pvivlven > v_vltab THEN v_perc_dif := (rec_item.pvivlven / v_vltab - 1) * 100; IF v_perc_dif > v_conf_perc_max THEN v_item_aceito := FALSE; v_resposta := v_resposta || chr(10) || 'ITEM CORTADO: ' || rec_item.pviprocod || ' - Preco ACIMA do permitido' || ' Venda: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' Max: ' || TO_CHAR(ROUND(v_vltab * (1 + v_conf_perc_max / 100), 2), 'FM999999990.00'); ELSE IF v_sit = 'AA' THEN v_sit := 'AP'; END IF; v_resposta := v_resposta || chr(10) || 'AVISO ITEM: ' || rec_item.pviprocod || ' - Preco acima, dentro da margem permitida' || ' Venda: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' Max: ' || TO_CHAR(ROUND(v_vltab * (1 + v_conf_perc_max / 100), 2), 'FM999999990.00'); END IF; END IF; END IF; END IF; -- bloco validação de preço -- -- VALIDAÇÃO DE ESTOQUE -- IF v_item_aceito THEN IF v_qtdedisp >= rec_item.pviqtde THEN v_qtdeate := rec_item.pviqtde; v_qtdeatecar := rec_item.pviqtde; ELSIF v_qtdedisp > 0 THEN v_resposta := v_resposta || chr(10) || 'CORTE: ' || rec_item.pviprocod || ' Q.Ven: ' || TO_CHAR(rec_item.pviqtde, 'FM999999990.00') || ' Q.Ate: ' || TO_CHAR(v_qtdedisp, 'FM999999990.00'); IF NOT v_tratou_corte THEN IF v_conf_corte = 'P' THEN IF v_sit = 'AA' THEN v_sit := 'AP'; END IF; v_resposta := v_resposta || chr(10) || '** Pedido sujeito a aprovacao por ocorrencia de cortes.'; ELSIF v_conf_corte = 'R' THEN v_item_aceito := FALSE; v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO por ocorrencia de cortes.'; EXIT; END IF; v_tratou_corte := TRUE; END IF; v_qtdeate := v_qtdedisp; v_qtdeatecar := v_qtdedisp; ELSE v_resposta := v_resposta || chr(10) || 'SEM ESTOQUE: ' || rec_item.pviprocod || ' Q.Ven: ' || TO_CHAR(rec_item.pviqtde, 'FM999999990.00') || ' Q.Ate: 0.00'; IF v_conf_recusa_item_sem_est = 'S' THEN v_item_aceito := FALSE; v_qtdeate := 0; v_qtdeatecar := 0; v_resposta := v_resposta || ' - Item recusado'; ELSE v_qtdeate := rec_item.pviqtde; v_qtdeatecar := rec_item.pviqtde; v_resposta := v_resposta || ' - Aceito sem estoque (config desmarcada)'; END IF; IF v_item_aceito AND NOT v_tratou_corte THEN IF v_conf_corte = 'P' THEN IF v_sit = 'AA' THEN v_sit := 'AP'; END IF; v_resposta := v_resposta || chr(10) || '** Pedido sujeito a aprovacao por ocorrencia de cortes.'; ELSIF v_conf_corte = 'R' THEN v_item_aceito := FALSE; v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO por ocorrencia de cortes.'; EXIT; END IF; v_tratou_corte := TRUE; END IF; END IF; END IF; -- v_item_aceito após preço END IF; -- v_vltab IS NULL END IF; -- v_item_aceito após produto ativo/dispfv -- Base deb/cred e acúmulo IF v_calcDebCred = 'S' THEN v_basedebcred := v_vltab; ELSE v_basedebcred := rec_item.pvivlven; END IF; v_soma_pedido := v_soma_pedido + rec_item.pvivltotal; v_soma_pedido_ate := v_soma_pedido_ate + CASE WHEN v_item_aceito THEN (v_qtdeate * rec_item.pvivlven) + rec_item.pvivlst + rec_item.pvivlipi ELSE 0 END; IF v_item_aceito THEN v_item_ate := v_item_ate + 1; INSERT INTO pvi( pvicadusuparcod, pvicadhorario, pviacao, pvicanal, pvipvempparcod, pvipvcod, pviprocod, pviuvecod, pviuvedes, pviuveun, pviuvemult, pviqtde, pviqtdeate, pviqtdeatecar, pvivltab, pvivlven, pvivltotal, pvicustocompra, pvicustoreal, pvipromcod, pvidescqtdecod, pvivlst, pvivlipi, pviseq, pvibasedebcred ) VALUES ( rec_ped.pvcadusuparcod, rec_ped.pvcadhorario, rec_item.pviacao, rec_item.pvicanal, rec_ped.pvempparcod, v_pvcod, rec_item.pviprocod, rec_item.pviuvecod, rec_item.pviuvedes, rec_item.pviuveun, rec_item.pviuvemult, rec_item.pviqtde, v_qtdeate, v_qtdeatecar, v_vltab, rec_item.pvivlven, rec_item.pvivltotal, v_custocompra, v_custoreal, NULLIF(rec_item.pvipromcod, 0), NULLIF(rec_item.pvidescqtdecod, 0), rec_item.pvivlst, rec_item.pvivlipi, rec_item.pviseq, v_basedebcred ); -- -- LINHA DE RESUMO DO ITEM NA MENSAGEM -- v_resposta := v_resposta || chr(10) || 'ITEM: ' || LPAD(rec_item.pviprocod::text, 6) || ' | Qt: ' || TO_CHAR(rec_item.pviqtde, 'FM999999990.00') || ' | Vl.Unit: ' || TO_CHAR(rec_item.pvivlven, 'FM999999990.00') || ' | Total: ' || TO_CHAR(rec_item.pvivltotal, 'FM999999990.00') || CASE WHEN rec_item.pvipromcod > 0 THEN ' | PROMO: ' || rec_item.pvipromcod::text ELSE '' END || CASE WHEN rec_item.pvidescqtdecod > 0 THEN ' | DESC.QT: ' || rec_item.pvidescqtdecod::text ELSE '' END; END IF; END LOOP; -- FOR rec_item -- -- TOTALIZADOR -- v_resposta := v_resposta || chr(10) || '---' || chr(10) || 'Itens atendidos..: ' || v_item_ate || chr(10) || 'Valor atendido...: ' || TO_CHAR(v_soma_pedido_ate, 'FM999999990.00'); -- -- NENHUM ITEM ATENDIDO -- IF v_item_ate = 0 THEN v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Nenhum item atendido'; END IF; -- -- LIMITE DE CRÉDITO -- IF v_valido THEN SELECT f_calc_clilimdisp INTO v_clilimdisp FROM f_calc_clilimdisp(rec_ped.pvempparcod, rec_ped.pvcliparcod); IF v_soma_pedido_ate > v_clilimdisp THEN IF v_conf_recusa_lim_cred = 'S' THEN v_valido := FALSE; v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || chr(10) || 'Motivo: Limite de credito excedido' || chr(10) || 'Valor atendido...: ' || TO_CHAR(v_soma_pedido_ate, 'FM999999990.00') || chr(10) || 'Limite disponivel: ' || TO_CHAR(v_clilimdisp, 'FM999999990.00'); ELSE IF v_sit = 'AA' THEN v_sit := 'AP'; END IF; v_resposta := v_resposta || chr(10) || '** Pedido sujeito a aprovacao, limite de credito excedido.' || chr(10) || 'Valor atendido...: ' || TO_CHAR(v_soma_pedido_ate, 'FM999999990.00') || chr(10) || 'Limite disponivel: ' || TO_CHAR(v_clilimdisp, 'FM999999990.00'); END IF; END IF; END IF; -- Atualiza PV com resposta e status finais UPDATE pv SET pvfvresposta = v_resposta, pvsta = v_sit, pvvltotal = v_soma_pedido_ate, pvvltotalate = v_soma_pedido_ate, pvvltotalatecar = v_soma_pedido_ate WHERE pvcod = v_pvcod; END IF; -- v_valido cabeçalho END LOOP; -- FOR rec_ped -- ---------------------------------------------- -- RETORNO FINAL -- ---------------------------------------------- IF (v_pvcod > 0) AND ((SELECT COUNT(pviprocod) FROM pvi WHERE pvipvcod = v_pvcod) > 0) THEN UPDATE ipedi.ped SET ped_importado = 2, ped_obsretorno = v_resposta WHERE ped_codigo = p_pedcod; RETURN QUERY SELECT p_pedcod, v_pvcod::integer, v_pvcod::integer, v_resposta::text; ELSE v_resposta := v_resposta || chr(10) || '** PEDIDO RECUSADO **' || CASE WHEN v_bloqobs IS NOT NULL THEN chr(10) || 'Detalhe: ' || v_bloqobs ELSE '' END || chr(10) || 'Pedido Palm: ' || p_pedcod || chr(10) || 'Empresa: ' || p_empresa; UPDATE ipedi.ped SET ped_importado = 1, ped_obsretorno = v_resposta WHERE ped_codigo = p_pedcod; RETURN QUERY SELECT 0, 0::integer, 0::integer, v_resposta::text; END IF; RETURN; EXCEPTION WHEN OTHERS THEN RETURN QUERY SELECT 0, 0::integer, 0::integer, ('ERRO INTERNO: ' || SQLERRM)::text; END; $function$ ; -- Permissions ALTER FUNCTION public.f_processar_fv(int4, int4) OWNER TO postgres; GRANT ALL ON FUNCTION public.f_processar_fv(int4, int4) TO public; GRANT ALL ON FUNCTION public.f_processar_fv(int4, int4) TO postgres;