refactor(infra)!: schema sar no banco ERP substitui banco-por-workspace
Revoga o ADR 0006. O isolamento multi-tenant deixa de ser um banco por workspace e passa a ser o schema `sar` dentro do proprio banco ERP do cliente, com `id_empresa` discriminando o tenant em todas as tabelas. Provisionamento: - `provision-client.ts` substitui `provision-workspace.ts`. Nao cria mais banco: aplica schema + views + triggers num banco ERP ja existente. Trata o encoding LATIN1 dos bancos ERP via `toLatinSafe()`. - `sar-erp-schema.sql` vira a fonte unica: absorve as views que estavam em `sarweb_views.sql` e passa a conter tambem `sar.chamados` / `sar.chamado_mensagens`, que so existiam via migration. Correcoes necessarias para o provisionamento rodar ponta a ponta: - `migrate deploy` abortava com P3005, porque o schema SQL roda antes do Prisma e o schema `sar` nunca esta vazio. O script agora detecta banco pre-existente e faz o baseline sozinho. - `_prisma_migrations` ia parar no schema `public` do ERP do cliente; a URL de migracao agora leva `?schema=sar`. - `sar.pedidos` nao tinha `end_entrega`, coluna que o schema.prisma ja declarava desde a feature de endereco de entrega, e que derrubava GET /orders com 500. Migration adicionada. - `vw_sitpedido` se perdeu junto com `sarweb_views.sql` e e usada pela consulta de pedidos ERP. Restaurada. Remove o seed de dados demo e os fallbacks de DATABASE_URL hardcoded: sem a variavel configurada a API agora falha explicitamente, em vez de apontar silenciosamente para um banco de desenvolvimento inexistente. Verificado ponta a ponta contra um banco ERP real: schema aplicado, 13 tabelas + 20 views, migrations registradas, e segunda execucao idempotente. BREAKING CHANGE: DATABASE_URL passa a ser obrigatoria. O comando de provisionamento muda para `pnpm client:provision --host <host> --db <banco>` (rename efetivado no commit de dependencias). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -82,9 +82,20 @@ SELECT
|
||||
e.nome,
|
||||
e.razao_social,
|
||||
e.cnpj,
|
||||
e.estado AS uf,
|
||||
e.estado AS uf,
|
||||
e.id_matriz,
|
||||
e.id_portador_padrao,
|
||||
-- Endereço e contato
|
||||
e.inscr_estadual,
|
||||
e.endereco,
|
||||
NULLIF(e.numero, 0) AS num_endereco,
|
||||
NULLIF(TRIM(e.complemento), '.') AS complemento,
|
||||
e.bairro,
|
||||
e.id_municipio,
|
||||
e.cep::text AS cep,
|
||||
e.telefone::text AS telefone,
|
||||
e.email,
|
||||
-- Configurações SAR (gestao.sarcfg)
|
||||
s.origem_descmax,
|
||||
s.tp_estoque,
|
||||
s.bloq_preco_pedido,
|
||||
@@ -381,6 +392,15 @@ SELECT
|
||||
NULL::integer AS tp_pauta
|
||||
FROM gestao.pauxpro pp;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 12b. Situações de pedido do ERP (sig.sitpedido — somente leitura)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE OR REPLACE VIEW sar.vw_sitpedido AS
|
||||
SELECT
|
||||
s.id_sitpedido,
|
||||
TRIM(s.descricao) AS descricao
|
||||
FROM sig.sitpedido s;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 13. Pedidos históricos do ERP (sig.pedidos — somente leitura)
|
||||
-- -----------------------------------------------------------------------------
|
||||
@@ -418,7 +438,10 @@ SELECT
|
||||
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
|
||||
p.tx_com_vend2 AS taxa_com_super,
|
||||
-- Campos usados internamente pelas views de consulta composta
|
||||
p.dtprevent AS dt_prevent,
|
||||
p.numer_ped_vinc
|
||||
FROM sig.pedidos p
|
||||
LEFT JOIN gestao.formapag fp ON fp.codigo = p.cod_formapag
|
||||
AND fp.id_empresa = CASE
|
||||
@@ -542,6 +565,22 @@ LEFT JOIN sig.corrent cr ON cr.id_corrent = CASE
|
||||
WHERE TRIM(c.id_entidade) ~ '^\d+$'
|
||||
OR TRIM(c.id_entidade) ~ '^COR#\d+$';
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 18. Notas Fiscais emitidas (gestao.nf — somente leitura)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE OR REPLACE VIEW sar.vw_nf AS
|
||||
SELECT
|
||||
nf.id_nf,
|
||||
nf.id_empresa,
|
||||
nf.numero,
|
||||
TRIM(nf.serie) AS serie,
|
||||
nf.dt_emissao,
|
||||
nf.vl_nf,
|
||||
nf.num_entrega,
|
||||
TRIM(nf.chave_acesso_nfe) AS chave_acesso_nfe,
|
||||
nf.status
|
||||
FROM gestao.nf nf;
|
||||
|
||||
-- =============================================================================
|
||||
-- PARTE 2 — TABELAS DE ESCRITA DO SAR
|
||||
-- Dados gerados pelo SAR — não existem no ERP.
|
||||
@@ -571,6 +610,7 @@ CREATE TABLE IF NOT EXISTS sar.pedidos (
|
||||
comissao NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
ped_flex NUMERIC(15,2) NOT NULL DEFAULT 0,
|
||||
obs TEXT,
|
||||
end_entrega TEXT, -- endereco de entrega alternativo
|
||||
aprovado_por INTEGER, -- cod_vendedor do supervisor
|
||||
aprovado_em TIMESTAMP,
|
||||
motivo_recusa TEXT,
|
||||
@@ -658,6 +698,74 @@ CREATE TABLE IF NOT EXISTS sar.push_subscription (
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- Promoções comerciais (C8 — criadas pelo Gerente)
|
||||
-- descPct em % (ex.: 5.00 = 5%). Pode ser por produto ou grupo de produto.
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS sar.promocoes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id_empresa INTEGER NOT NULL,
|
||||
descricao VARCHAR(200) NOT NULL,
|
||||
cod_produto VARCHAR(30),
|
||||
grp_prod VARCHAR(30),
|
||||
desc_pct NUMERIC(5,2) NOT NULL,
|
||||
data_inicio DATE NOT NULL,
|
||||
data_fim DATE NOT NULL,
|
||||
ativa BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_by VARCHAR(100) NOT NULL
|
||||
);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- Oportunidades (Funil de Vendas)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS sar.oportunidades (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id_empresa INTEGER NOT NULL,
|
||||
cod_vendedor INTEGER NOT NULL,
|
||||
id_cliente INTEGER,
|
||||
nome_prospect VARCHAR(200),
|
||||
empresa_prospect VARCHAR(200),
|
||||
titulo VARCHAR(200) NOT NULL,
|
||||
etapa VARCHAR(20) NOT NULL DEFAULT 'lead',
|
||||
valor_estimado NUMERIC(15,2),
|
||||
observacoes TEXT,
|
||||
id_pedido UUID REFERENCES sar.pedidos(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- Chamados (SAC) — pedido pode ser SAR (id_pedido/num_ped_sar) ou ERP (num_ped_erp)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS sar.chamados (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id_empresa INTEGER NOT NULL,
|
||||
cod_vendedor INTEGER NOT NULL,
|
||||
id_pedido UUID REFERENCES sar.pedidos(id) ON DELETE SET NULL,
|
||||
num_ped_sar INTEGER,
|
||||
num_ped_erp INTEGER,
|
||||
id_cliente INTEGER NOT NULL,
|
||||
nome_cliente VARCHAR(200),
|
||||
tipo VARCHAR(50) NOT NULL,
|
||||
assunto VARCHAR(200) NOT NULL,
|
||||
descricao TEXT NOT NULL,
|
||||
status VARCHAR(30) NOT NULL DEFAULT 'aberto',
|
||||
resolucao VARCHAR(50),
|
||||
nota_resolucao TEXT,
|
||||
itens_afetados JSONB,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sar.chamado_mensagens (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id_chamado INTEGER NOT NULL REFERENCES sar.chamados(id) ON DELETE CASCADE,
|
||||
autor VARCHAR(10) NOT NULL,
|
||||
texto TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- ÍNDICES
|
||||
-- =============================================================================
|
||||
@@ -673,17 +781,23 @@ CREATE INDEX IF NOT EXISTS idx_sar_push_empresa ON sar.push_subscription(id_emp
|
||||
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);
|
||||
CREATE INDEX IF NOT EXISTS idx_sar_promo_empresa ON sar.promocoes(id_empresa);
|
||||
CREATE INDEX IF NOT EXISTS idx_sar_promo_vigente ON sar.promocoes(id_empresa, data_fim) WHERE ativa;
|
||||
CREATE INDEX IF NOT EXISTS idx_sar_oport_vend ON sar.oportunidades(id_empresa, cod_vendedor);
|
||||
CREATE INDEX IF NOT EXISTS idx_sar_oport_etapa ON sar.oportunidades(etapa);
|
||||
CREATE INDEX IF NOT EXISTS idx_chamados_empresa_vendedor ON sar.chamados(id_empresa, cod_vendedor);
|
||||
CREATE INDEX IF NOT EXISTS idx_chamados_empresa_status ON sar.chamados(id_empresa, status);
|
||||
CREATE INDEX IF NOT EXISTS idx_chamado_mensagens_chamado ON sar.chamado_mensagens(id_chamado);
|
||||
|
||||
-- =============================================================================
|
||||
-- GRANTS (descomentar e ajustar o role conforme o ambiente)
|
||||
-- GRANTS
|
||||
-- Executado pelo provision-client.ts quando --role <nome> é informado.
|
||||
-- Referência manual:
|
||||
-- GRANT USAGE ON SCHEMA sar TO <role>;
|
||||
-- GRANT SELECT ON ALL TABLES IN SCHEMA sar TO <role>;
|
||||
-- GRANT INSERT, UPDATE, DELETE ON
|
||||
-- sar.pedidos, sar.pedido_itens, sar.historico_pedido,
|
||||
-- sar.alcada_desconto, sar.meta_representante, sar.push_subscription,
|
||||
-- sar.promocoes, sar.clientes_novos, sar.contatos_novos
|
||||
-- TO <role>;
|
||||
-- =============================================================================
|
||||
-- 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;
|
||||
|
||||
Reference in New Issue
Block a user