Triggers SAR→ERP (scripts/sar-triggers.sql): - trg_pedido_aprovado: ao aprovar (situa 1→2) em sar.pedidos, replica automaticamente em sig.pedidos + sig.peditens e grava erp_id_pedido - trg_cliente_novo: INSERT em sar.clientes_novos replica em sig.corrent com todos os campos obrigatórios; grava id_corrent_erp e flag sincronizado - Corrige trigger tsvectorupdate do ERP para PG 18 (bpchar→text cast) - Adiciona coluna erp_id_pedido em sar.pedidos e tabela sar.clientes_novos Migrations Prisma: - Remove 5 migrations obsoletas com nomes PascalCase (Order, Client, etc.) que não batiam com os @@map snake_case do schema atual - Cria baseline 20260624000000_init_baseline apontando para estado correto Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
456 lines
14 KiB
PL/PgSQL
456 lines
14 KiB
PL/PgSQL
-- =============================================================================
|
|
-- sar-triggers.sql
|
|
-- Triggers de integração SAR → ERP (schema sig/gestao no banco libreplast)
|
|
--
|
|
-- Execução: psql -U postgres -d libreplast -f scripts/sar-triggers.sql
|
|
--
|
|
-- CONTEÚDO:
|
|
-- 1. ALTER TABLE sar.pedidos — adiciona erp_id_pedido para rastrear ref ERP
|
|
-- 2. fn_sync_pedido_aprovado_to_erp — replica pedido aprovado em sig.pedidos
|
|
-- 3. trg_pedido_aprovado — dispara fn acima ao aprovar (situa 1→2)
|
|
-- 4. sar.clientes_novos — tabela staging de clientes criados pelo rep
|
|
-- 5. fn_sync_cliente_to_erp — replica cliente em sig.corrent
|
|
-- 6. trg_cliente_novo — dispara fn acima no INSERT em clientes_novos
|
|
-- =============================================================================
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- 1. Coluna de referência ERP no pedido SAR
|
|
-- ---------------------------------------------------------------------------
|
|
ALTER TABLE sar.pedidos
|
|
ADD COLUMN IF NOT EXISTS erp_id_pedido INTEGER;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sar_ped_erp_id ON sar.pedidos(erp_id_pedido)
|
|
WHERE erp_id_pedido IS NOT NULL;
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- 2. Função: replicar pedido aprovado → sig.pedidos + sig.peditens
|
|
--
|
|
-- Dispara quando sar.pedidos.situa muda de qualquer valor para 2 (Aprovado).
|
|
-- Insere em sig.pedidos com situa=1 (Pendente ERP) para que o operador
|
|
-- da fábrica finalize o lançamento. Grava o id_pedido ERP de volta em
|
|
-- sar.pedidos.erp_id_pedido.
|
|
--
|
|
-- id_tes=48 (Venda de Produção) — padrão SAR. Mudar para 53 se for bonificação.
|
|
-- numero: MAX+1 por empresa — mesmo padrão usado pelo SIG Desktop.
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE OR REPLACE FUNCTION sar.fn_sync_pedido_aprovado_to_erp()
|
|
RETURNS TRIGGER LANGUAGE plpgsql AS $$
|
|
DECLARE
|
|
v_numero INTEGER;
|
|
v_id_pedido_erp INTEGER;
|
|
v_cod_pauta INTEGER;
|
|
v_item RECORD;
|
|
v_id_st INTEGER;
|
|
v_endereco TEXT;
|
|
v_bairro TEXT;
|
|
v_municipio TEXT;
|
|
v_estado TEXT;
|
|
v_cep TEXT;
|
|
BEGIN
|
|
-- Só dispara na transição → 2 (Aprovado) e se ainda não sincronizado
|
|
IF NEW.situa <> 2 OR OLD.situa = 2 OR NEW.erp_id_pedido IS NOT NULL THEN
|
|
RETURN NEW;
|
|
END IF;
|
|
|
|
-- Próximo número disponível para a empresa (com lock)
|
|
SELECT COALESCE(MAX(numero), 0) + 1
|
|
INTO v_numero
|
|
FROM sig.pedidos
|
|
WHERE id_empresa = NEW.id_empresa
|
|
FOR UPDATE;
|
|
|
|
-- Código da pauta (sig usa codigo, SAR armazena id_pauta)
|
|
SELECT codigo INTO v_cod_pauta
|
|
FROM gestao.pauta
|
|
WHERE id_pauta = NEW.id_pauta
|
|
LIMIT 1;
|
|
|
|
-- Endereço de entrega do cliente (do ERP)
|
|
SELECT
|
|
COALESCE(c.endereco, ''),
|
|
COALESCE(c.bairr, ''),
|
|
COALESCE(m.nome, ''),
|
|
COALESCE(m.estado, ''),
|
|
COALESCE(c.cep, '')
|
|
INTO v_endereco, v_bairro, v_municipio, v_estado, v_cep
|
|
FROM sig.corrent c
|
|
LEFT JOIN gestao.municipio m ON m.id_municipio = c.id_municipio
|
|
WHERE c.id_corrent = NEW.id_cliente
|
|
LIMIT 1;
|
|
|
|
-- Inserir cabeçalho do pedido no ERP
|
|
INSERT INTO sig.pedidos (
|
|
id_empresa,
|
|
tipo,
|
|
numero,
|
|
data,
|
|
data_emissao,
|
|
num_ped_vendedor,
|
|
id_tes,
|
|
situa,
|
|
id_local,
|
|
clien,
|
|
cod_vendedor,
|
|
cod_pauta,
|
|
cod_formapag,
|
|
e_ender,
|
|
e_bairr,
|
|
e_munic,
|
|
e_estad,
|
|
e_cep,
|
|
conta,
|
|
totpr,
|
|
ipi,
|
|
vl_icms_subst,
|
|
total,
|
|
descp,
|
|
descv,
|
|
com_fat,
|
|
com_rec,
|
|
obs,
|
|
prz_con,
|
|
tx_acrescimo,
|
|
num_ped_sar,
|
|
inf_usuario,
|
|
fconta,
|
|
frete,
|
|
cliente_retira,
|
|
pesob,
|
|
pesol,
|
|
ordem,
|
|
finalidade,
|
|
vol_qtd,
|
|
vol_especie,
|
|
vol_marca,
|
|
vol_numero,
|
|
obs_nf1,
|
|
obs_nf2,
|
|
num_oc,
|
|
usuario_credito,
|
|
num_lacre,
|
|
etiqueta_emitida,
|
|
canc_saldo,
|
|
rec_antecipado,
|
|
guid_sarped,
|
|
redesp_frete,
|
|
prioridade,
|
|
classificacao,
|
|
enviar_email,
|
|
tp_moeda,
|
|
vl_cotacao
|
|
) VALUES (
|
|
NEW.id_empresa,
|
|
'P',
|
|
v_numero,
|
|
NEW.dt_pedido,
|
|
NEW.dt_pedido,
|
|
NEW.num_ped_sar, -- num_ped_vendedor = SAR ref
|
|
48, -- id_tes: Venda de Produção
|
|
1, -- situa ERP: Pendente (operador finaliza)
|
|
0,
|
|
NEW.id_cliente,
|
|
NEW.cod_vendedor,
|
|
COALESCE(v_cod_pauta, 0),
|
|
COALESCE(NEW.cod_formapag, 0),
|
|
COALESCE(v_endereco, ''),
|
|
COALESCE(v_bairro, ''),
|
|
COALESCE(v_municipio, ''),
|
|
COALESCE(v_estado, ''),
|
|
COALESCE(v_cep, ''),
|
|
'',
|
|
NEW.total_produtos,
|
|
NEW.total_ipi,
|
|
NEW.total_icmsst,
|
|
NEW.total,
|
|
NEW.desconto_perc,
|
|
NEW.desconto_valor,
|
|
NEW.comissao,
|
|
0,
|
|
COALESCE(LEFT(NEW.obs, 1024), ''),
|
|
0,
|
|
COALESCE(NEW.acrescimo, 0),
|
|
NEW.num_ped_sar,
|
|
1, -- inf_usuario=1: criado pelo SAR
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
' ',
|
|
'',
|
|
'',
|
|
'',
|
|
'',
|
|
'',
|
|
'',
|
|
' ',
|
|
'',
|
|
'',
|
|
0,
|
|
0,
|
|
0,
|
|
'',
|
|
0,
|
|
2,
|
|
' ',
|
|
0,
|
|
0,
|
|
0
|
|
)
|
|
RETURNING id_pedido INTO v_id_pedido_erp;
|
|
|
|
-- Inserir itens no ERP
|
|
FOR v_item IN
|
|
SELECT pi.*
|
|
FROM sar.pedido_itens pi
|
|
WHERE pi.id_pedido = NEW.id
|
|
ORDER BY pi.ordem
|
|
LOOP
|
|
-- Situação tributária do produto
|
|
SELECT s.id_st INTO v_id_st
|
|
FROM gestao.produto p
|
|
JOIN gestao.st s ON s.codigo = p.cod_st
|
|
WHERE p.id_erp = v_item.id_produto
|
|
AND p.id_empresa = CASE
|
|
WHEN NEW.id_empresa > 9000
|
|
THEN NEW.id_empresa - 9000
|
|
ELSE NEW.id_empresa
|
|
END
|
|
LIMIT 1;
|
|
|
|
INSERT INTO sig.peditens (
|
|
id_pedido,
|
|
ordem,
|
|
produ,
|
|
id_grade,
|
|
qtd,
|
|
pruni,
|
|
descp,
|
|
descv,
|
|
ipi,
|
|
total,
|
|
comis,
|
|
obs,
|
|
id_st,
|
|
preco_pauta,
|
|
qtd_vasilhame_dev,
|
|
id_integrado,
|
|
qtd_bonificacao,
|
|
num_entrega,
|
|
vl_comissao_und,
|
|
id_acabamento,
|
|
id_vidro,
|
|
largura,
|
|
altura,
|
|
l1, l2, l3, l4,
|
|
h1, h2, h3, h4,
|
|
id_varprod,
|
|
id_vista,
|
|
num_op,
|
|
status,
|
|
vl_icmsst,
|
|
tp_operacao,
|
|
vl_acrescimo,
|
|
tempo_prod_prev,
|
|
preco_ipi,
|
|
vl_flex
|
|
) VALUES (
|
|
v_id_pedido_erp,
|
|
v_item.ordem,
|
|
v_item.id_produto,
|
|
NULL,
|
|
v_item.qtd,
|
|
v_item.preco_unitario,
|
|
v_item.desconto_perc,
|
|
v_item.desconto_valor,
|
|
v_item.vl_ipi,
|
|
v_item.total,
|
|
v_item.comissao,
|
|
'',
|
|
COALESCE(v_id_st, 0),
|
|
v_item.preco_pauta,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0,
|
|
0,
|
|
0,
|
|
1, -- status=1: item ativo/normal
|
|
v_item.vl_icmsst,
|
|
0,
|
|
0,
|
|
0,
|
|
v_item.preco_com_ipi,
|
|
v_item.vl_flex
|
|
);
|
|
END LOOP;
|
|
|
|
-- Gravar referência ERP de volta no pedido SAR
|
|
UPDATE sar.pedidos
|
|
SET erp_id_pedido = v_id_pedido_erp
|
|
WHERE id = NEW.id;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
-- Criar (ou recriar) o trigger
|
|
DROP TRIGGER IF EXISTS trg_pedido_aprovado ON sar.pedidos;
|
|
|
|
CREATE TRIGGER trg_pedido_aprovado
|
|
AFTER UPDATE OF situa ON sar.pedidos
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION sar.fn_sync_pedido_aprovado_to_erp();
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- 4. Tabela staging de clientes novos criados pelo SAR
|
|
--
|
|
-- O rep preenche os campos obrigatórios e o trigger replica em sig.corrent.
|
|
-- Após a replicação, id_corrent_erp é preenchido com o id gerado pelo ERP.
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE TABLE IF NOT EXISTS sar.clientes_novos (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
id_empresa INTEGER NOT NULL,
|
|
cod_vendedor INTEGER NOT NULL,
|
|
|
|
-- Dados principais
|
|
nome VARCHAR(40) NOT NULL,
|
|
razao VARCHAR(65) NOT NULL,
|
|
pesso SMALLINT NOT NULL DEFAULT 1, -- 0=PJ 1=PF
|
|
consfinal SMALLINT NOT NULL DEFAULT 0,
|
|
cgcpf VARCHAR(18),
|
|
suf_cgcpf VARCHAR(3) NOT NULL DEFAULT '',
|
|
inscr VARCHAR(18) NOT NULL DEFAULT '',
|
|
indicador_ie SMALLINT, -- 1=contribuinte 2=isento 9=não contribuinte
|
|
|
|
-- Endereço
|
|
endereco VARCHAR(60) NOT NULL DEFAULT '',
|
|
num_endereco VARCHAR(10) NOT NULL DEFAULT '',
|
|
bairro VARCHAR(60) NOT NULL DEFAULT '',
|
|
id_municipio INTEGER NOT NULL,
|
|
cep VARCHAR(9) NOT NULL DEFAULT '',
|
|
|
|
-- Contato
|
|
ddd VARCHAR(4) NOT NULL DEFAULT '',
|
|
telefone VARCHAR(35) NOT NULL DEFAULT '',
|
|
email VARCHAR(80) NOT NULL DEFAULT '',
|
|
|
|
-- Comercial
|
|
limite_credito NUMERIC(15,2) NOT NULL DEFAULT 0,
|
|
cod_formapag INTEGER,
|
|
cod_pauta INTEGER,
|
|
|
|
-- Resultado após sync
|
|
id_corrent_erp INTEGER,
|
|
sincronizado BOOLEAN NOT NULL DEFAULT FALSE,
|
|
erro_sync TEXT,
|
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_sar_clinovos_empresa ON sar.clientes_novos(id_empresa);
|
|
CREATE INDEX IF NOT EXISTS idx_sar_clinovos_vend ON sar.clientes_novos(cod_vendedor);
|
|
CREATE INDEX IF NOT EXISTS idx_sar_clinovos_sync ON sar.clientes_novos(sincronizado);
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- 5. Função: replicar cliente novo → sig.corrent
|
|
--
|
|
-- Campos obrigatórios NOT NULL sem default em sig.corrent recebem '' (char)
|
|
-- ou 0 (int). O ERP aceita esses defaults — é o mesmo padrão do SIG Desktop
|
|
-- ao cadastrar cliente mínimo.
|
|
-- ---------------------------------------------------------------------------
|
|
CREATE OR REPLACE FUNCTION sar.fn_sync_cliente_to_erp()
|
|
RETURNS TRIGGER LANGUAGE plpgsql AS $$
|
|
DECLARE
|
|
v_id_corrent INTEGER;
|
|
BEGIN
|
|
BEGIN
|
|
INSERT INTO sig.corrent (
|
|
ativo, pesso, consfinal, cgcpf, suf_cgcpf, inscr, nome, razao,
|
|
endereco, cxpostal, compl, bairr, id_municipio, cep,
|
|
e_ender, e_bairr, e_cep, c_ender, c_bairr, c_cep,
|
|
e_mail, grupo_eco, no_reg, hor_descarga,
|
|
fat_anul, cap_social, cap_realiz, cap_aberto, con_ac_privado, con_ac_nacional,
|
|
ramo_ativ, cod_ativ_ir, no_empregados,
|
|
importa, p_importa, exporta, p_exporta,
|
|
princ_produ1, princ_produ2, princ_produ3, perc_vendas1, perc_vendas2, perc_vendas3,
|
|
www, banc1, banc2, banc3, agen1, agen2, agen3, nagen1, nagen2, nagen3,
|
|
ct_nu, ct_se, ci1, ci2, orgex, uf,
|
|
ddd, telef, fax, data, cod_vendedor, conta,
|
|
c_dm_nascto, c_fone, con_f, f_dm_nascto, f_fone, c_ctb, c_ctb_consig,
|
|
-- campos pessoais (obrigatórios sem default)
|
|
sexo, e_civ, pai, mae, conju, ocupa, c_spc, natur,
|
|
t_ser, l_tra, t_end, inscr_pro, classe,
|
|
tolatr, inscr_suframa, lei_livre, codigo,
|
|
aviso_protesto, codigo_vend_prep, id_tipo,
|
|
i_ban, i_com, obs,
|
|
-- comercial
|
|
limcred, indicador_ie, cod_formapag, cod_pauta
|
|
) VALUES (
|
|
1, NEW.pesso, NEW.consfinal,
|
|
COALESCE(NEW.cgcpf, ''), COALESCE(NEW.suf_cgcpf, ''), COALESCE(NEW.inscr, ''),
|
|
COALESCE(LEFT(NEW.nome, 40), ''), LEFT(NEW.razao, 65),
|
|
COALESCE(LEFT(NEW.endereco, 60), ''), 0, '',
|
|
COALESCE(LEFT(NEW.bairro, 60), ''), NEW.id_municipio, COALESCE(NEW.cep, ''),
|
|
COALESCE(LEFT(NEW.endereco, 60), ''), COALESCE(LEFT(NEW.bairro, 60), ''), COALESCE(NEW.cep, ''),
|
|
COALESCE(LEFT(NEW.endereco, 60), ''), COALESCE(LEFT(NEW.bairro, 60), ''), COALESCE(NEW.cep, ''),
|
|
COALESCE(LEFT(NEW.email, 80), ''), '', '', '',
|
|
0, 0, 0, 0, 0, 0,
|
|
'', 0, 0,
|
|
0, 0, 0, 0,
|
|
'', '', '', 0, 0, 0,
|
|
'', 0, 0, 0, '', '', '', '', '', '',
|
|
0, 0, '', 0, '', '',
|
|
COALESCE(NEW.ddd, ''), COALESCE(LEFT(NEW.telefone, 35), ''), '', CURRENT_DATE,
|
|
NEW.cod_vendedor, '',
|
|
NULL, '', '', NULL, '', 0, 0,
|
|
-- campos pessoais com defaults neutros
|
|
0, 0, '', '', '', '', '', '',
|
|
0, '', 0, '', '',
|
|
0, '', '', '',
|
|
0, 0, 0,
|
|
'', '', '',
|
|
-- comercial
|
|
COALESCE(NEW.limite_credito, 0), NEW.indicador_ie, NEW.cod_formapag, NEW.cod_pauta
|
|
)
|
|
RETURNING id_corrent INTO v_id_corrent;
|
|
|
|
UPDATE sar.clientes_novos
|
|
SET id_corrent_erp = v_id_corrent,
|
|
sincronizado = TRUE,
|
|
erro_sync = NULL
|
|
WHERE id = NEW.id;
|
|
|
|
EXCEPTION WHEN OTHERS THEN
|
|
-- Registra o erro sem abortar — rep vê o status na UI
|
|
UPDATE sar.clientes_novos
|
|
SET sincronizado = FALSE,
|
|
erro_sync = SQLERRM
|
|
WHERE id = NEW.id;
|
|
END;
|
|
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
-- Criar (ou recriar) o trigger
|
|
DROP TRIGGER IF EXISTS trg_cliente_novo ON sar.clientes_novos;
|
|
|
|
CREATE TRIGGER trg_cliente_novo
|
|
AFTER INSERT ON sar.clientes_novos
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION sar.fn_sync_cliente_to_erp();
|
|
|
|
-- ---------------------------------------------------------------------------
|
|
-- Verificação final
|
|
-- ---------------------------------------------------------------------------
|
|
SELECT
|
|
trigger_name,
|
|
event_object_schema || '.' || event_object_table AS tabela,
|
|
event_manipulation AS evento,
|
|
action_timing AS timing
|
|
FROM information_schema.triggers
|
|
WHERE trigger_schema = 'sar'
|
|
ORDER BY tabela, trigger_name;
|