-- ============================================================================= -- sar-erp-schema.sql -- Schema SAR — criado no banco PostgreSQL do ERP (módulo SIG + gestao) -- -- Conteúdo: -- PARTE 1 — Views de leitura (espelham dados do ERP, sem modificar nada) -- PARTE 2 — Tabelas de escrita do SAR (pedidos, histórico, configurações) -- -- Pré-requisito: schemas gestao e sig já existem no banco do ERP. -- Execução: psql -U -d -f sar-erp-schema.sql -- ============================================================================= CREATE SCHEMA IF NOT EXISTS sar; -- ============================================================================= -- PARTE 1 — VIEWS DE LEITURA -- Lêem dos schemas do ERP (gestao, sig). Somente SELECT — nunca escrevem. -- ============================================================================= -- ----------------------------------------------------------------------------- -- 1. Empresas / configuração SAR por empresa -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_empresas AS SELECT e.id_empresa, e.nome, e.razao_social, e.cnpj, e.estado AS uf, e.id_matriz, e.id_portador_padrao, s.origem_descmax, s.tp_estoque, s.bloq_preco_pedido, s.ativar_prod_pauta, s.preco_padrao, s.preco_com_ipi FROM gestao.empresa e LEFT JOIN gestao.sarcfg s ON s.id_empresa = e.id_empresa; -- ----------------------------------------------------------------------------- -- 2. Representantes / vendedores habilitados no SAR -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_representantes AS SELECT v.id_vendedor, v.id_empresa, v.codigo, v.nome, v.exp_sar AS habilitado_sar, v.taxa_com, v.forma_pag AS forma_pag_comissao, v.cod_supervisor, v.taxa_com_super, v.forma_pag_super, v.desconto_max, v.permitir_flex, COALESCE(f.saldo_flex, 0) AS saldo_flex, v.vl_ped_minimo, v.desc_rateio_com, v.origem_com, v.cod_pauta1, v.cod_pauta2, v.cod_pauta3, v.cod_pauta4, v.cod_pauta5, v.cod_pauta6 FROM gestao.vendedor v LEFT JOIN gestao.flex f ON f.id_vendedor = v.id_vendedor; -- ----------------------------------------------------------------------------- -- 3. Clientes (sig.corrent) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_clientes AS SELECT c.id_empresa, c.id_corrent AS id_cliente, c.ativo, c.nome, c.razao, c.pesso AS pessoa, -- 0=PJ 1=PF c.consfinal, c.cgcpf, c.suf_cgcpf, c.inscr AS inscricao_estadual, c.endereco, COALESCE(c.num_endereco, '') AS num_endereco, c.bairr AS bairro, c.id_municipio, c.cep, c.ddd, c.telef AS telefone, c.e_mail AS email, c.data AS dt_cadastro, c.obs, c.cod_formapag, ( SELECT fp.id_formapag FROM gestao.formapag fp LEFT JOIN gestao.empresa e ON e.id_empresa = c.id_empresa WHERE fp.id_empresa = COALESCE(e.id_matriz, c.id_empresa) AND fp.codigo = c.cod_formapag LIMIT 1 ) AS id_formapag, c.indicador_ie, c.cod_pauta, c.st_especifica, COALESCE(c.limcred, 0) AS limite_credito, c.cod_vendedor, c.dt_atual FROM sig.corrent c; -- ----------------------------------------------------------------------------- -- 4. Municípios -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_municipios AS SELECT id_municipio, nome, estado AS uf, codigo_ibge FROM gestao.municipio; -- ----------------------------------------------------------------------------- -- 5. Formas de Pagamento -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_formas_pagamento AS SELECT id_formapag, id_empresa, codigo, descr AS descricao, ativa, numparc AS num_parcelas, desco AS desconto_perc, COALESCE(vl_ped_minimo, 0) AS vl_ped_minimo, COALESCE(libera_credito, 0) AS libera_credito, COALESCE(acresc, 0) AS tx_acrescimo, integrar_sar, dt_atual FROM gestao.formapag; -- ----------------------------------------------------------------------------- -- 6. Produtos (catálogo com grupo, subgrupo, marca, tributação) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_produtos AS SELECT p.id_empresa, p.id_erp, p.codigo, p.referencia, p.descricao, p.descr_det, p.ativo, p.cod_barra, p.unidade, p.tipo, p.vl_preco1, COALESCE(p.vl_preco2, 0) AS vl_preco2, COALESCE(p.vl_preco3, 0) AS vl_preco3, p.cod_grupo, grp.descricao AS grupo, p.cod_subgrupo, sub.descricao AS subgrupo, sub.desc_max, COALESCE(p.grupo_st, '') AS grupo_st, p.cod_marca, COALESCE(mrc.nome, 'Sem Marca') AS marca, p.classe_abc, p.taxa_comissao, p.cod_st, st.aliq_ipi, COALESCE(st.desc_ipi_bc, 0) AS desc_ipi_bc, p.peso_liquido, p.qtd_volume, COALESCE(p.lote_mul_venda, 1) AS lote_mul_venda, COALESCE(p.permitir_dif_lote, 0) AS permitir_dif_lote, COALESCE(p.id_prodvinc, 0) AS id_prodvinc, COALESCE(p.preco_promocional, 0) AS preco_promocional, COALESCE(p.tx_desc_lote, 0) AS tx_desc_lote, p.lista_pauta, CASE WHEN p.dt_atual > sub.da THEN p.dt_atual ELSE sub.da END AS dt_atual FROM gestao.produto p LEFT JOIN gestao.grupo grp ON grp.codigo = p.cod_grupo AND grp.id_empresa = p.id_empresa LEFT JOIN gestao.grupo sub ON sub.codigo = p.cod_subgrupo AND sub.id_empresa = p.id_empresa LEFT JOIN gestao.marca mrc ON mrc.codigo = p.cod_marca AND mrc.id_empresa = p.id_empresa LEFT JOIN gestao.st st ON st.codigo = p.cod_st WHERE p.id_erp IS NOT NULL; -- ----------------------------------------------------------------------------- -- 7. Estoque calculado (respeita tp_estoque da configuração SAR) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_estoque AS SELECT p.id_empresa, p.id_erp, cfg.tp_estoque, CASE cfg.tp_estoque WHEN 'E' THEN COALESCE(e.qtdade, 0) - COALESCE(e.qtd_empenhada, 0) WHEN 'P' THEN COALESCE(e.qtdade, 0) - COALESCE(e.qtd_empenhada, 0) - COALESCE(e.qtd_pedidos, 0) WHEN 'Z' THEN 0 ELSE COALESCE(e.qtdade, 0) END AS qtd_estoque, COALESCE(e.qtdade, 0) AS qtd_fisico, COALESCE(e.qtd_empenhada, 0) AS qtd_empenhada, COALESCE(e.qtd_pedidos, 0) AS qtd_pedidos FROM gestao.produto p LEFT JOIN gestao.grupo grp ON grp.codigo = p.cod_grupo AND grp.id_empresa = p.id_empresa LEFT JOIN gestao.grupo sub ON sub.codigo = p.cod_subgrupo AND sub.id_empresa = p.id_empresa LEFT JOIN gestao.sarcfg cfg ON cfg.id_empresa = p.id_empresa LEFT JOIN gestao.estsaldo e ON e.id_produto = p.id_erp AND e.id_empresa = p.id_empresa AND e.id_estlocal = p.cod_estlocal WHERE p.id_erp IS NOT NULL AND p.ativo = 1 AND p.lista_pauta = 1 AND grp.int_sar = 1 AND sub.int_sar = 1 AND (sub.produto_variacao = 0 OR p.id_prodvinc > 0); -- ----------------------------------------------------------------------------- -- 8. Situação Tributária ICMS-ST -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_sticms AS SELECT st.id_empresa AS id_empresa_matriz, si.id_sticms, st.codigo AS cod_st, si.uf, si.st_especifica, si.perc_bc_icms, si.aliq_icms, si.modal_bc_icmsst, si.aliq_icmsst, si.somar_icmsst_nf, si.perc_marg_vl_icmsst, si.contribuinte_icms FROM gestao.sticms si JOIN gestao.st st ON st.id_st = si.id_st; -- ----------------------------------------------------------------------------- -- 9. Pautas de Preço -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_pautas AS SELECT p.id_pauta, p.id_empresa, p.codigo, p.ativo, p.num_pauta, COALESCE(p.dt_cadast, '1900-01-01'::date) AS dt_cadastro, p.descricao, p.obs, COALESCE(p.dt_ini, '1900-01-01'::date) AS dt_inicio, COALESCE(p.dt_fim, '2100-01-01'::date) AS dt_fim, p.pauta_exclusiva_cliente, COALESCE(p.vl_pedido1, 0) AS vl_pedido1, COALESCE(p.vl_pedido2, 0) AS vl_pedido2, COALESCE(p.vl_pedido3, 0) AS vl_pedido3, COALESCE(p.vl_pedido4, 0) AS vl_pedido4, COALESCE(p.vl_pedido5, 0) AS vl_pedido5, COALESCE(p.tx_desconto1, 0) AS tx_desconto1, COALESCE(p.tx_desconto2, 0) AS tx_desconto2, COALESCE(p.tx_desconto3, 0) AS tx_desconto3, COALESCE(p.tx_desconto4, 0) AS tx_desconto4, COALESCE(p.tx_desconto5, 0) AS tx_desconto5, COALESCE(p.tp_desconto, 0) AS tp_desconto FROM gestao.pauta p; -- ----------------------------------------------------------------------------- -- 10. Produtos por Pauta (preços específicos por pauta) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_pauta_produtos AS SELECT pp.id_pauta, COALESCE(pp.id_varprod, 0) AS id_varprod, pp.id_prod AS id_produto, pp.preco1, COALESCE(pp.preco2, 0) AS preco2, COALESCE(pp.preco3, 0) AS preco3, COALESCE(pp.valor_pauta_icms_st, 0) AS valor_pauta_icms_st, pp.tp_pauta FROM gestao.pauxpro pp; -- ----------------------------------------------------------------------------- -- 11. Pedidos históricos do ERP (sig.pedidos — somente leitura) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_pedidos_erp AS SELECT p.id_empresa, p.id_pedido, p.num_ped_sar, p.numero, p.tipo, p.situa, CASE p.situa WHEN 1 THEN 'Pendente' WHEN 2 THEN 'Liberado' WHEN 4 THEN 'Faturado' WHEN 5 THEN 'Cancelado' ELSE 'Enviado' END AS status_descr, p.data AS dt_pedido, p.data_emissao AS dt_emissao, p.clien AS id_cliente, p.cod_vendedor, p.cod_formapag, fp.id_formapag, fp.descr AS forma_pagamento, pau.id_pauta, COALESCE(p.obs, '') AS obs, p.totpr AS total_produtos, COALESCE(p.ipi, 0) AS total_ipi, 0 AS total_icmsst, COALESCE(p.total, 0) AS total, COALESCE(p.descp, 0) AS desconto_perc, COALESCE(p.descv, 0) AS desconto_valor, COALESCE(p.tx_acrescimo, 0) AS acrescimo, COALESCE(p.com_fat, 0) AS comissao, COALESCE(p.ped_flex, 0) AS ped_flex, p.cod_vend2 AS cod_supervisor, p.tx_com_vend2 AS taxa_com_super FROM sig.pedidos p LEFT JOIN gestao.formapag fp ON fp.codigo = p.cod_formapag AND fp.id_empresa = CASE WHEN p.id_empresa > 9000 THEN p.id_empresa - 9000 ELSE p.id_empresa END LEFT JOIN gestao.pauta pau ON pau.codigo = p.cod_pauta AND pau.id_empresa = CASE WHEN p.id_empresa > 9000 THEN p.id_empresa - 9000 ELSE p.id_empresa END; -- ----------------------------------------------------------------------------- -- 12. Itens dos Pedidos ERP (sig.peditens — somente leitura) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_peditens_erp AS SELECT i.id_pedido, i.ordem, i.produ AS id_produto, i.qtd, i.pruni AS preco_unitario, COALESCE(i.descp, 0) AS desconto_perc, COALESCE(i.descv, 0) AS desconto_valor, COALESCE(i.obs, '') AS obs, COALESCE(i.preco_pauta, 0) AS preco_pauta, COALESCE(i.vl_flex, 0) AS vl_flex, COALESCE(i.comis, 0) AS comissao, COALESCE(i.preco_ipi, 0) AS preco_com_ipi, 0 AS bc_ipi, COALESCE(i.ipi, 0) AS vl_ipi, 0 AS bc_icmsst, 0 AS vl_icmsst, COALESCE(i.total, 0) AS total FROM sig.peditens i; -- ----------------------------------------------------------------------------- -- 13. Contas a Receber (sig.ctr — situação financeira do cliente) -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_ctr AS SELECT c.id_empresa, c.id_ctr, c.prefixo, c.numero, c.docto AS documento, c.deved AS id_cliente, c.id_entrega AS id_pedido_erp, c.emiss AS dt_emissao, c.vecto AS dt_vencimento, c.valor, 0 AS despesa_cartorio, c.saldo, c.situacao, c.data_baixa AS dt_baixa, c.cod_vendedor FROM sig.ctr c; -- ----------------------------------------------------------------------------- -- 14. Grupos de Produtos -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_grupos AS SELECT id_empresa, codigo, descricao, int_sar, produto_variacao, desc_max, da AS dt_atualizacao FROM gestao.grupo; -- ----------------------------------------------------------------------------- -- 15. Marcas -- ----------------------------------------------------------------------------- CREATE OR REPLACE VIEW sar.vw_marcas AS SELECT id_empresa, codigo, nome FROM gestao.marca; -- ============================================================================= -- PARTE 2 — TABELAS DE ESCRITA DO SAR -- Dados gerados pelo SAR — não existem no ERP. -- ============================================================================= -- ----------------------------------------------------------------------------- -- Pedidos criados pelo SAR -- situa: 1=Pendente aprovação 2=Aprovado 3=Cancelado 4=Faturado pelo ERP -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS sar.pedidos ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), id_empresa INTEGER NOT NULL, num_ped_sar VARCHAR(20) NOT NULL UNIQUE, id_cliente INTEGER NOT NULL, -- sig.corrent.id_corrent cod_vendedor INTEGER NOT NULL, -- gestao.vendedor.codigo situa SMALLINT NOT NULL DEFAULT 1, dt_pedido DATE NOT NULL DEFAULT CURRENT_DATE, id_pauta INTEGER, cod_formapag INTEGER, total_produtos NUMERIC(15,2) NOT NULL DEFAULT 0, total_ipi NUMERIC(15,2) NOT NULL DEFAULT 0, total_icmsst NUMERIC(15,2) NOT NULL DEFAULT 0, total NUMERIC(15,2) NOT NULL DEFAULT 0, desconto_perc NUMERIC(5,2) NOT NULL DEFAULT 0, desconto_valor NUMERIC(15,2) NOT NULL DEFAULT 0, acrescimo NUMERIC(15,2) NOT NULL DEFAULT 0, comissao NUMERIC(15,2) NOT NULL DEFAULT 0, ped_flex NUMERIC(15,2) NOT NULL DEFAULT 0, obs TEXT, aprovado_por INTEGER, -- cod_vendedor do supervisor aprovado_em TIMESTAMP, motivo_recusa TEXT, idempotency_key VARCHAR(100) UNIQUE, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- ----------------------------------------------------------------------------- -- Itens dos Pedidos SAR -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS sar.pedido_itens ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), id_pedido UUID NOT NULL REFERENCES sar.pedidos(id) ON DELETE CASCADE, ordem SMALLINT NOT NULL, id_produto INTEGER NOT NULL, -- gestao.produto.id_erp cod_produto VARCHAR(30), desc_produto VARCHAR(200), qtd NUMERIC(10,3) NOT NULL, preco_unitario NUMERIC(15,2) NOT NULL, desconto_perc NUMERIC(5,2) NOT NULL DEFAULT 0, desconto_valor NUMERIC(15,2) NOT NULL DEFAULT 0, preco_pauta NUMERIC(15,2) NOT NULL DEFAULT 0, comissao NUMERIC(15,2) NOT NULL DEFAULT 0, vl_flex NUMERIC(15,2) NOT NULL DEFAULT 0, preco_com_ipi NUMERIC(15,2) NOT NULL DEFAULT 0, vl_ipi NUMERIC(15,2) NOT NULL DEFAULT 0, vl_icmsst NUMERIC(15,2) NOT NULL DEFAULT 0, total NUMERIC(15,2) NOT NULL ); -- ----------------------------------------------------------------------------- -- Histórico de transições de status dos Pedidos SAR -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS sar.historico_pedido ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), id_pedido UUID NOT NULL REFERENCES sar.pedidos(id) ON DELETE CASCADE, situa_anterior SMALLINT, situa_nova SMALLINT NOT NULL, changed_by INTEGER NOT NULL, -- cod_vendedor nota TEXT, changed_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- ----------------------------------------------------------------------------- -- Alçadas de desconto por vendedor / empresa / grupo de produto -- cod_grupo = 0 → limite global do vendedor -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS sar.alcada_desconto ( cod_vendedor INTEGER NOT NULL, id_empresa INTEGER NOT NULL, cod_grupo INTEGER NOT NULL DEFAULT 0, limite_perc NUMERIC(5,2) NOT NULL DEFAULT 5, updated_at TIMESTAMP NOT NULL DEFAULT NOW(), PRIMARY KEY (cod_vendedor, id_empresa, cod_grupo) ); -- ----------------------------------------------------------------------------- -- Metas mensais por representante -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS sar.meta_representante ( cod_vendedor INTEGER NOT NULL, id_empresa INTEGER NOT NULL, ano SMALLINT NOT NULL, mes SMALLINT NOT NULL, meta_valor NUMERIC(15,2) NOT NULL, taxa_comissao NUMERIC(5,2) NOT NULL DEFAULT 3, taxa_flex NUMERIC(5,2) NOT NULL DEFAULT 1, updated_at TIMESTAMP NOT NULL DEFAULT NOW(), PRIMARY KEY (cod_vendedor, id_empresa, ano, mes) ); -- ----------------------------------------------------------------------------- -- Web Push Subscriptions (C6 — VAPID) -- ----------------------------------------------------------------------------- CREATE TABLE IF NOT EXISTS sar.push_subscription ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), cod_vendedor INTEGER, -- NULL se for admin não-vendedor id_empresa INTEGER NOT NULL, role VARCHAR(20) NOT NULL, -- rep | supervisor | admin endpoint TEXT NOT NULL UNIQUE, p256dh TEXT NOT NULL, auth TEXT NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); -- ============================================================================= -- ÍNDICES -- ============================================================================= CREATE INDEX IF NOT EXISTS idx_sar_ped_empresa ON sar.pedidos(id_empresa); CREATE INDEX IF NOT EXISTS idx_sar_ped_vendedor ON sar.pedidos(cod_vendedor); CREATE INDEX IF NOT EXISTS idx_sar_ped_cliente ON sar.pedidos(id_cliente); CREATE INDEX IF NOT EXISTS idx_sar_ped_situa ON sar.pedidos(situa); CREATE INDEX IF NOT EXISTS idx_sar_ped_dt ON sar.pedidos(dt_pedido); CREATE INDEX IF NOT EXISTS idx_sar_itens_pedido ON sar.pedido_itens(id_pedido); CREATE INDEX IF NOT EXISTS idx_sar_hist_pedido ON sar.historico_pedido(id_pedido); CREATE INDEX IF NOT EXISTS idx_sar_push_empresa ON sar.push_subscription(id_empresa); CREATE INDEX IF NOT EXISTS idx_sar_push_vend ON sar.push_subscription(cod_vendedor); CREATE INDEX IF NOT EXISTS idx_sar_meta_vend ON sar.meta_representante(cod_vendedor, id_empresa); CREATE INDEX IF NOT EXISTS idx_sar_alcada_vend ON sar.alcada_desconto(cod_vendedor, id_empresa); -- ============================================================================= -- GRANTS (descomentar e ajustar o role conforme o ambiente) -- ============================================================================= -- GRANT USAGE ON SCHEMA sar TO sar_app; -- GRANT SELECT ON ALL TABLES IN SCHEMA sar TO sar_app; -- GRANT INSERT, UPDATE, DELETE ON -- sar.pedidos, -- sar.pedido_itens, -- sar.historico_pedido, -- sar.alcada_desconto, -- sar.meta_representante, -- sar.push_subscription -- TO sar_app;