223 lines
9.7 KiB
SQL
223 lines
9.7 KiB
SQL
-- =====================================================================
|
|
-- 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
|