first commit
This commit is contained in:
222
schema.sql
Normal file
222
schema.sql
Normal file
@@ -0,0 +1,222 @@
|
||||
-- =====================================================================
|
||||
-- Módulo DTF — schema completo
|
||||
-- =====================================================================
|
||||
-- Duas bases:
|
||||
-- NUVEM (PostgreSQL, no VPS) → pedido, arte, parte, job, agente
|
||||
-- LOCAL (SQLite, na fábrica) → card, movimento, retrabalho, job_local
|
||||
--
|
||||
-- A separação é proposital: o kanban precisa funcionar com a internet fora.
|
||||
-- =====================================================================
|
||||
|
||||
|
||||
-- =====================================================================
|
||||
-- NUVEM · PostgreSQL
|
||||
-- =====================================================================
|
||||
|
||||
CREATE TABLE pedido (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
numero_tiny TEXT NOT NULL UNIQUE, -- chave de tudo
|
||||
cliente TEXT NOT NULL,
|
||||
telefone TEXT NOT NULL,
|
||||
metros NUMERIC(10,2) NOT NULL, -- metros comprados por arte
|
||||
cliente_novo BOOLEAN NOT NULL DEFAULT false,-- dispara prova de cor
|
||||
token TEXT NOT NULL UNIQUE, -- UUID v4 do link
|
||||
token_expira TIMESTAMPTZ NOT NULL, -- 7 dias
|
||||
lembrete_em TIMESTAMPTZ, -- 1h sem arte → cobra
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX ix_pedido_token ON pedido(token);
|
||||
CREATE INDEX ix_pedido_semarte ON pedido(criado_em)
|
||||
WHERE NOT EXISTS (SELECT 1 FROM arte WHERE arte.pedido_id = pedido.id);
|
||||
|
||||
|
||||
CREATE TABLE arte (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
pedido_id BIGINT NOT NULL REFERENCES pedido(id),
|
||||
arquivo TEXT NOT NULL, -- chave no storage
|
||||
arquivo_orig TEXT, -- original preservado
|
||||
bytes BIGINT NOT NULL DEFAULT 0,
|
||||
formato_orig TEXT, -- png, pdf, psd, cdr...
|
||||
natureza TEXT, -- vetor | raster | conferir
|
||||
repeticoes INT NOT NULL DEFAULT 1,
|
||||
status TEXT NOT NULL DEFAULT 'recebida',
|
||||
-- recebida | processando | aprovada | recusada
|
||||
conferir_manual BOOLEAN NOT NULL DEFAULT false,-- CDR
|
||||
motivo TEXT, -- por que foi recusada
|
||||
avisos TEXT, -- aceitou mas com ressalva
|
||||
dpi_efetivo NUMERIC(8,2),
|
||||
largura_cm NUMERIC(8,2),
|
||||
metros_totais NUMERIC(10,2),
|
||||
minutos_maquina INT, -- estimativa; vira campo no card
|
||||
cores_tensas TEXT, -- fora do gamut, se houver
|
||||
virus_ok BOOLEAN NOT NULL DEFAULT false,-- ClamAV liberou
|
||||
baixada BOOLEAN NOT NULL DEFAULT false,-- o agente já trouxe
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX ix_arte_pedido ON arte(pedido_id);
|
||||
CREATE INDEX ix_arte_baixar ON arte(status, baixada, virus_ok);
|
||||
|
||||
|
||||
CREATE TABLE parte (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
arte_id BIGINT NOT NULL REFERENCES arte(id),
|
||||
ordem INT NOT NULL,
|
||||
metros NUMERIC(10,2) NOT NULL,
|
||||
arquivo TEXT NOT NULL,
|
||||
carimbada BOOLEAN NOT NULL DEFAULT false,-- só a última leva carimbo
|
||||
UNIQUE (arte_id, ordem)
|
||||
);
|
||||
|
||||
|
||||
-- Fila de jobs. Tabela, não broker: no volume da Altus (algumas centenas de
|
||||
-- pedidos/dia) Redis e Celery são complexidade sem retorno.
|
||||
-- Consumir com: SELECT ... FOR UPDATE SKIP LOCKED
|
||||
CREATE TABLE job (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
tipo TEXT NOT NULL, -- preflight | whats | tiny | limpeza
|
||||
payload JSONB NOT NULL,
|
||||
tentativas INT NOT NULL DEFAULT 0,
|
||||
proxima_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
erro TEXT,
|
||||
feito BOOLEAN NOT NULL DEFAULT false,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX ix_job_fila ON job(feito, proxima_em) WHERE NOT feito;
|
||||
|
||||
|
||||
CREATE TABLE agente_heartbeat (
|
||||
id SERIAL PRIMARY KEY,
|
||||
visto_em TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
-- sem sinal por 15 min → alertar o TI
|
||||
|
||||
|
||||
-- Artes guardadas para recompra. Prefixo separado no storage, retenção 12 meses.
|
||||
CREATE TABLE arte_cliente (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
numero_cliente TEXT NOT NULL,
|
||||
token_cliente TEXT NOT NULL, -- link permanente
|
||||
arte_id BIGINT REFERENCES arte(id),
|
||||
arquivo TEXT NOT NULL, -- só a arte tratada
|
||||
descricao TEXT,
|
||||
criado_em TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
expira_em TIMESTAMPTZ NOT NULL
|
||||
);
|
||||
CREATE INDEX ix_arte_cliente ON arte_cliente(numero_cliente, token_cliente);
|
||||
|
||||
|
||||
-- =====================================================================
|
||||
-- LOCAL · SQLite (na fábrica)
|
||||
-- =====================================================================
|
||||
|
||||
CREATE TABLE card (
|
||||
arte_id INTEGER PRIMARY KEY,
|
||||
pedido TEXT NOT NULL,
|
||||
cliente TEXT NOT NULL,
|
||||
metros REAL NOT NULL,
|
||||
minutos_maquina INTEGER, -- estimativa. Herda os marcadores 30min/1h/3h
|
||||
-- do Tiny. Sugerida por metros/20*60; quem
|
||||
-- trata a arte ajusta só quando foge do normal
|
||||
partes INTEGER NOT NULL DEFAULT 1,
|
||||
coluna TEXT NOT NULL DEFAULT 'rec',
|
||||
-- rec | tra | apc | fil | imp | cor | fin
|
||||
-- NÃO existe coluna de aplicação: a sala só imprime o filme
|
||||
desde TEXT NOT NULL, -- entrada na coluna atual (ISO)
|
||||
maquina TEXT, -- 'Maq 1' … 'Maq 6'
|
||||
reservado_por TEXT, -- máquina que puxou
|
||||
reservado_em TEXT, -- expira em 3 min (ajuste da sala)
|
||||
conferir_manual INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE INDEX ix_card_coluna ON card(coluna, desde);
|
||||
|
||||
|
||||
-- A tabela mais importante do sistema. Dela saem TODOS os números que hoje
|
||||
-- não existem: tempo por etapa, fila por máquina, retrabalho, ocupação real.
|
||||
CREATE TABLE movimento (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
arte_id INTEGER NOT NULL,
|
||||
pedido TEXT NOT NULL,
|
||||
de TEXT NOT NULL,
|
||||
para TEXT NOT NULL,
|
||||
entrou_em TEXT NOT NULL,
|
||||
saiu_em TEXT NOT NULL,
|
||||
segundos INTEGER NOT NULL,
|
||||
usuario TEXT NOT NULL, -- login do PCP. Se o PC tiver login
|
||||
-- compartilhado, o indicador de retrabalho
|
||||
-- por pessoa fica sem dono
|
||||
maquina TEXT
|
||||
);
|
||||
CREATE INDEX ix_mov_arte ON movimento(arte_id);
|
||||
CREATE INDEX ix_mov_saiu ON movimento(saiu_em);
|
||||
CREATE INDEX ix_mov_etapa ON movimento(de, saiu_em);
|
||||
|
||||
|
||||
CREATE TABLE retrabalho (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
pedido_origem TEXT NOT NULL,
|
||||
pedido_novo TEXT,
|
||||
metros REAL NOT NULL,
|
||||
causa TEXT NOT NULL,
|
||||
-- arte_cliente | tratamento | impressao | perfil_cor | pedido
|
||||
-- TRAVADA depois de aberta: com o indicador atrelado a bônus,
|
||||
-- haveria incentivo para reclassificar falha de máquina como
|
||||
-- culpa do cliente
|
||||
aberto_por TEXT NOT NULL, -- Mayana: conhece o cliente e a reclamação
|
||||
aberto_em TEXT NOT NULL,
|
||||
vez INTEGER NOT NULL DEFAULT 1, -- 2ª sobe alçada, 3ª trava
|
||||
alcada TEXT NOT NULL, -- sala | financeiro | diretoria
|
||||
autorizado_por TEXT, -- Thales ou Alexandre: entra na meta deles
|
||||
autorizado_em TEXT,
|
||||
contestado_por TEXT, -- discorda da causa mas não pode mudá-la
|
||||
contestado_em TEXT,
|
||||
contestacao TEXT,
|
||||
evidencia TEXT -- foto ou print da reclamação
|
||||
);
|
||||
CREATE INDEX ix_retra_data ON retrabalho(aberto_em);
|
||||
CREATE INDEX ix_retra_causa ON retrabalho(causa, aberto_em);
|
||||
|
||||
|
||||
CREATE TABLE job_local (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tipo TEXT NOT NULL, -- tiny_marcador | whats
|
||||
payload TEXT NOT NULL,
|
||||
tentativas INTEGER NOT NULL DEFAULT 0,
|
||||
proxima_em REAL NOT NULL, -- 1, 5 e 30 min
|
||||
erro TEXT,
|
||||
feito INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE INDEX ix_joblocal ON job_local(feito, proxima_em);
|
||||
|
||||
|
||||
-- Consumo de filme, para o aproveitamento. NÃO exige apontamento novo:
|
||||
-- lê as transferências para o depósito de impressão no Tiny.
|
||||
CREATE TABLE consumo_filme (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
em TEXT NOT NULL,
|
||||
metros REAL NOT NULL,
|
||||
origem TEXT NOT NULL DEFAULT 'tiny' -- transferência de depósito
|
||||
);
|
||||
|
||||
|
||||
-- =====================================================================
|
||||
-- Consultas que o painel usa
|
||||
-- =====================================================================
|
||||
|
||||
-- Tempo médio por etapa nos últimos N dias
|
||||
-- SELECT de, COUNT(*) n, AVG(segundos)/60 media_min, MAX(segundos)/60 pior_min
|
||||
-- FROM movimento WHERE saiu_em >= date('now','-7 days') GROUP BY de;
|
||||
|
||||
-- Velocidade real por máquina — é o número que valida ou derruba os 20 m/h
|
||||
-- SELECT m.maquina, SUM(c.metros) metros, SUM(m.segundos)/3600.0 horas,
|
||||
-- SUM(c.metros)/(SUM(m.segundos)/3600.0) m_por_hora
|
||||
-- FROM movimento m JOIN card c ON c.arte_id = m.arte_id
|
||||
-- WHERE m.de='imp' AND m.saiu_em >= date('now','-7 days') GROUP BY m.maquina;
|
||||
|
||||
-- Retrabalho por causa, com responsável
|
||||
-- SELECT causa, COUNT(*) n, SUM(metros) m FROM retrabalho
|
||||
-- WHERE aberto_em >= date('now','-30 days') GROUP BY causa;
|
||||
|
||||
-- Aproveitamento do filme
|
||||
-- faturado = SELECT SUM(metros) FROM card WHERE coluna='fin' AND desde >= ...
|
||||
-- consumido = SELECT SUM(metros) FROM consumo_filme WHERE em >= ...
|
||||
-- aproveitamento = faturado / consumido
|
||||
Reference in New Issue
Block a user