Files
dtf-system/README.md
Cauê Faleiros 7386469404
All checks were successful
Build and deploy / Validate source (push) Successful in 5s
Build and deploy / Integration suite on a real stack (push) Successful in 1m18s
Build and deploy / Secret scan and release gate (push) Successful in 6s
Build and deploy / Publish images and notify Portainer (push) Successful in 1m26s
docs: move the engineering documents into docs/
Thirteen files at the repository root, seven of them documents. Only README.md
earns a place there; the rest are now in docs/ beside the meeting notes, the
client roadmap and the historical material.

The compose files stay. docker-compose.yml is the path the dtf-cloud Portainer
stack reads, so moving it would break deployment, and Docker resolves a compose
file's relative build contexts against its own directory, so moving the other
two would silently break every build. Both reasons are now written down where
someone would otherwise try it.

Correcting references turned up a live fault: the Portainer stack creation
instructions still named deploy/stack.yaml as the compose path. That file was
removed, so anyone recreating the stack from these instructions would have
failed. It names docker-compose.yml now, with the reason it stays at the root.

ROADMAP.md keeps the paths its closed findings were written with, and says so at
the top. Those entries record where a fault was when it was found; rewriting
them to match a later layout would make the record less true, not more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 17:52:20 -03:00

673 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sistema DTF 24h — Altus Group
> **Active local milestone (2026-09-11):** Read [docs/CONTEXT.md](docs/CONTEXT.md) first.
> Start with `docker compose up --build`, then open the [Site](http://localhost:8080)
> and [Kanban](http://localhost:8081). Optional configuration: copy `.env.example`
> to `.env`. Follow [docs/LOCAL_SETUP.md](docs/LOCAL_SETUP.md) for the complete test flow,
> local login, health checks, and troubleshooting. See
> [IMPLEMENTATION_REPORT.md](docs/historico/IMPLEMENTATION_REPORT.md) for scope and reuse decisions.
> Production delivery uses one Portainer stack; see [docs/PORTAINER.md](docs/PORTAINER.md).
> Everything below is preserved historical prototype documentation, not the active
> setup or delivery specification. Do not run its production integrations or agent.
> Documentação para o TI. Reúne o contexto do projeto, as decisões já tomadas,
> a arquitetura, o código e o que ainda depende de resposta.
> Base: conversas de 29 e 30/08/2026 com Marcus.
> **2026-09-21.** Everything below this line is the original prototype
> documentation. The code it describes (`portal/`, `kanban/`, `agente/`, the root
> `schema.sql`, `.env.exemplo`) no longer exists, and the model it describes is
> not the one implemented. Kept for the business reasoning in it — the capacity
> figures, the cost argument, the meeting decisions. For how the system actually
> works read [docs/CONTEXT.md](docs/CONTEXT.md); for what is outstanding read
> [docs/ROADMAP.md](docs/ROADMAP.md); for the original documents see
> [docs/historico/](docs/historico/README.md).
---
## Por que este projeto existe
A sala de DTF tem 6 máquinas a 20 m/h. Em dois turnos, das 5h às 20h, isso dá
**37.800 metros/mês de capacidade**. A produção real de maio a agosto de 2026
ficou em **11.605 metros/mês** — 31% de ocupação. O pico foi junho, com 12.373 m.
**Não falta máquina. Falta a porta ficar aberta.**
O que limita a venda é o horário em que conseguimos receber e responder. O
pedido que chega às 17h30 espera até as 5h da manhã, porque não há ninguém para
receber o arquivo, tratar e mandar imprimir. O cliente de DTF compra por
rapidez, e a rapidez tem duas metades: receber e produzir. Hoje as duas param
juntas às 20h.
### O que muda com o projeto
| | Hoje · 18k m | Com 24h · 36k m |
|---|---|---|
| Custo por metro | R$ 9,43 | R$ 7,46 |
| Receita | R$ 268.200 | R$ 536.400 |
| **Resultado** | R$ 77.011 | **R$ 225.032** |
| Margem | 28,7% | 42,0% |
**Ganho de R$ 148 mil/mês, R$ 1,78 milhão/ano**, com a folha subindo 20%
(R$ 6.333). Cada metro acima de 18 mil rende R$ 8,76 de margem de contribuição —
insumo e manutenção custam R$ 4,94 e não mudam; folha, fixo e administrativo já
estão pagos.
Contra isso, a infraestrutura do projeto custa **R$ 160 a 450 por mês**.
### Os quatro furos do fluxo atual
1. **A arte entra por WhatsApp** — canal que não registra nada auditável
2. **O número do pedido é digitado à mão** no nome do arquivo; se errar, a arte
some no servidor e ninguém descobre até o cliente cobrar
3. **O status vive numa pasta de rede** — o Tiny sabe do pedido no começo e no
fim, no meio ninguém sabe
4. **Ninguém mede o tempo de espera** entre etapas
O item 4 é o que mais importa. Sem ele, não dá para saber se o gargalo é máquina
ou designer — e essa resposta decide se vale montar o terceiro turno.
---
Três componentes que fazem a sala de DTF receber arte 24 horas e medir o próprio tempo.
> **Comece pelo `TAREFAS.md`** — ordem de execução com critério de aceite.
> Depois `ESPECIFICACAO.md` — ele traz as fases de implementação, as
> funcionalidades uma a uma, e o que mudou depois das reuniões com os designers e
> a sala em 02/09/2026. Este README cobre a arquitetura.
```
TAREFAS.md o que fazer, em ordem, com critério de aceite
ESPECIFICACAO.md as funcionalidades uma a uma e o que mudou nas reuniões
API.md contratos de todos os endpoints
schema.sql banco completo, nuvem e local
README.md arquitetura e decisões (este arquivo)
portal/ FastAPI na nuvem · recebe a arte, valida, repete, fatia, carimba
agente/ script na fábrica · traz o arquivo aprovado para o servidor
kanban/ FastAPI local · a sala move o card, o Tiny recebe o marcador
static/kanban.html front já conectado à API
```
---
## O que cada um faz
**portal** — aberto na internet, roda em VPS. O Tiny avisa por webhook que
nasceu um pedido; o portal cria um link com token e manda no WhatsApp. O cliente
sobe o arquivo direto para o storage, sem passar pelo servidor. O robô valida,
empilha as repetições, fatia em partes de no máximo 15 m e carimba a última.
**agente** — roda como serviço no servidor da fábrica. Busca o que foi aprovado
e grava na pasta `00_ARTE_RECEBIDA`. Se a internet cair, ele para e o portal
continua recebendo; quando voltar, baixa o acumulado.
**kanban** — tela da sala, só na rede interna. Mover o card grava o movimento,
move o arquivo entre as pastas e enfileira o marcador no Tiny e o WhatsApp.
---
## Regras do processo, em código
| Regra | Onde está |
|---|---|
| Área útil 57 × 97 cm (30 mm de rodapé) | `preflight.AREA_UTIL_CM` |
| DPI efetivo mínimo 150, ideal 300 | `preflight.validar()` |
| Largura máxima 57 cm | `preflight.validar()` |
| Repetição da arte | `preflight.empilhar()` |
| Montagem empilhada de vários arquivos | `preflight.montar_folha()` |
| Normalização por natureza do arquivo | `preflight.normalizar()` |
| CDR entra sem validar, etiqueta "conferir" | `preflight.FORMATOS_SEM_VALIDACAO` |
| Máximo 20 m por arquivo | `preflight.fatiar()` |
| Carimbo: QR 20 mm + texto, só preto | `preflight.carimbar()` |
| Um carimbo por pedido, na última parte | `preflight.processar()` |
**A regra que mais pega arquivo ruim é o DPI efetivo.** O valor gravado no
cabeçalho mente com frequência — o cliente escala a imagem e o programa mantém
"300". O que vale é `pixels ÷ (centímetros comprados ÷ 2,54)`.
---
## Decisões já tomadas
Não precisam ser rediscutidas. Estão implementadas no código.
| Assunto | Decisão | Por quê |
|---|---|---|
| Chave do pedido | **número do Tiny** | é o que a empresa inteira já usa |
| Gatilho do link | **webhook do Tiny**, não polling | o link sai no segundo em que o pedido nasce |
| Hospedagem do portal | **fora da fábrica** | se a internet cair às 3h, o cliente sobe do mesmo jeito |
| Hospedagem do kanban | **rede interna** | é tela de operação, funciona sem internet |
| Upload | **direto para o storage**, URL pré-assinada | 200 MB passando pelo VPS derrubaria o processo |
| Limite do site | VNDA não aceita 200 MB | por isso o portal é externo |
| Faixa do rodapé | **30 mm** → área útil 57 × 97 cm | cabe o QR de 20 mm com folga |
| QR | **20 mm**, leitura por **celular** | não haverá coletor; celular lê com folga |
| Conteúdo do QR | **URL do card no kanban** | a revisão bipa e cai na tela do pedido |
| Carimbo | **um por pedido**, na última parte | é ela que fecha o pedido |
| Cor do carimbo | **só canal preto** | sem branco de apoio: economiza a tinta mais cara |
| Repetição | **campo no portal**, robô empilha | tira do designer o trabalho mais braçal |
| Limite por arquivo | **20 metros** | 100 m viram 5 arquivos |
| Tamanho do upload | **5 GB** | é o que os PCs da sala aguentam abrir |
| Retenção | **30 dias** | depois apaga do storage |
| Montagem | **empilhada**, sem encaixe lado a lado | são artes de 1 m em sequência |
| CDR | entra com etiqueta **conferir** | a licença do Corel é de estação, não de servidor |
| Movimento | **no kanban**, pasta espelha | sem watchdog: uma peça a menos para manter |
| Qualidade na mensagem | **% e DPI** juntos | um para leigo, outro para quem é do ramo |
| Marcadores no Tiny | **3, não 7** | o kanban é a fonte de verdade |
| Avisos ao cliente | **3 + correção** | sete viraria spam e ele para de ler |
| Designer de madrugada | **não haverá** | a noite imprime o que já estava tratado |
### O que o robô NÃO faz
Tratar arte continua sendo trabalho do designer: remover fundo quando o cliente
não removeu, corrigir cor para o perfil da impressora, e julgar o que não presta
mesmo passando na validação técnica — degradê que vira mancha branca, traço fino
que some na aplicação.
O robô filtra o que **nem deveria chegar** ao designer: DPI baixo, fundo não
removido, largura acima de 57 cm, arquivo corrompido. Isso volta ao cliente
automaticamente e não consome minuto de arte nenhum.
**Isso gera o número que decide o terceiro turno:** quanto do tempo do designer é
retrabalho de arquivo ruim, e quanto é trabalho de verdade. O kanban mede isso na
primeira semana, olhando o tempo entre `Arte recebida` e `Arte tratada`.
### Referência de mercado
O **dtflexprint.com.br**, de Salvador, já opera este modelo: upload no próprio
produto, pré-flight automático, sem receber arquivo por WhatsApp. **Cobram
R$ 55,00 pela mesma unidade de 57 × 100 cm que vendemos a R$ 14,90.**
A guerra de preço é local; o mercado não é. Depois de resolver a dinâmica de
horário, o passo seguinte é logística nacional.
---
## Fase 1 — limpeza dos marcadores do Tiny
Primeira entrega do projeto. Não depende de nada e pode começar hoje.
### Regra que não pode ser violada
**Limpar a lista de sugestão, não o histórico dos pedidos.** Apagar marcador de
pedido já fechado destrói o pouco de dado que existe sobre o passado. O que
atrapalha é a lista de opções aparecer poluída na hora de marcar um pedido novo.
### O que sai da lista
Todas as variações de horário e duração digitadas à mão. Existem dezenas, quase
todas com um ou dois pedidos:
```
inicio 14:45 inicio13:34 inicio 12:38hr inicio 930 INICIO 15:09
11:10 15:30hr 1hrs 3h 3hr
2hrs 1h30min +20m +30min de correcao
+1hr (correcao)
```
Alguém na sala está tentando registrar tempo de máquina há meses, à mão, sem
padrão nenhum. **O kanban passa a fazer isso sozinho e melhor**, com carimbo
automático de entrada e saída em cada etapa. Esse trabalho manual deixa de
existir — e é bom dizer isso à sala, porque é esforço real que estava sendo
desperdiçado.
### O que fica
| Marcador | Pedidos | Para quê |
|---|---|---|
| `fila de impressao` | 2.004 | coluna do kanban |
| `CORRECAO DTF` | 116 | coluna do kanban |
| `Maq 1` … `Maq 6` | 3.406 | histórico de máquina |
| `multiempresa`, `VALE`, `Troca`, `BOLETO NEXSTAR SICCOB` | — | outra natureza, não mexer |
### O que nasce
`DTF-PRODUCAO` e `DTF-PRONTO`. Só dois — ver a seção de marcadores acima.
### Atenção: os marcadores de duração NÃO são poluição
```
30 min → 2.430 pedidos
1 hora → 833 pedidos
3 horas → 40 pedidos
```
Estes são padronizados e parecem ser a **estimativa de minutos de máquina do
pedido** — exatamente o dado que o kanban precisa para calcular fila contra
capacidade.
Hoje o código estima esse tempo pelos metros, a 20 m/h
(`kanban/main.py`, campo `minutos_maquina`). Mas arte complexa pode demorar mais
que arte simples do mesmo tamanho.
**Confirmar com o Thales antes de apagar:** esses marcadores são estimativa de
tempo de máquina ou outra coisa? Se forem estimativa e refletirem algo que a
sala sabe e o metro não captura, viram **campo no card**, não marcador — e o
cálculo de capacidade fica mais preciso que a conta por metragem.
---
## Como o arquivo chega na máquina
**Desenho novo, decidido em 30/08/2026.** O PC central deixa de ser passagem
obrigatória e vira posto de validação e exceção.
### Antes
```
PC central → abre o arquivo, aplica o SPOT à mão, salva de novo na pasta
↓
PC da máquina → alguém pega o arquivo e toca no software
```
Todos os arquivos passavam por uma máquina e uma pessoa. Se ela saía, a fila
parava. Às 3h da manhã, não havia ninguém.
### Agora
```
portal → robô (valida · monta · SPOT · carimba) → fila única
↓
operador clica "puxar próximo" na máquina
↓
arquivo cai na hot folder 30_MAQ1 … 30_MAQ6
↓
FlexiPRINT processa sozinho de lá
```
O operador abre no Flexi, roda, e arrasta o card para Finalizado. **Um clique no
começo, um arraste no fim.** Nunca escolhe pedido, nunca procura arquivo, nunca
decide ordem.
### Por que puxada e não empurro
Empurrar exigiria adivinhar qual máquina estará livre daqui a duas horas. Se uma
travar, a fila dela para enquanto outra fica ociosa, e alguém remaneja na mão.
**Por puxada nunca desbalanceia.**
Três regras que sustentam isso:
| Regra | Por quê |
|---|---|
| Reserva expira em **3 min** | ajustado pela sala: 15 era demais |
| Devolver põe no **topo**, não no fim | o pedido já esperou uma vez |
| **Um pedido por vez** | a sala preferiu assim a puxar lote de trabalho |
Ver `/api/puxar` e `/api/devolver` em `kanban/main.py`.
### O que sobra para o PC central
Validação, exceções e o SPOT manual dos casos que a regra automática não cobre.
Deixa de estar no caminho crítico de todo pedido.
---
## A validar com os designers e a sala — SPOT
O canal branco passa a ser gerado pelo robô. A regra base é medível e cabe em
poucas linhas, mas existem variações que **precisam ser confirmadas antes de
codificar**.
### O que já é regra, não julgamento
**Choke** (contração do branco) evita que o branco apareça na borda quando o
registro sai levemente fora. O problema é que em traço fino ele come a linha:
um filete de 0,4 mm a 300 DPI tem ~5 px; tirando 2 de cada lado sobra 1, e o
branco quase some.
Isso é medível. O robô mede a espessura de cada elemento e aplica choke
proporcional — **na mesma arte, texto grosso encolhe e filete fino não**:
| Espessura do elemento | Choke |
|---|---|
| acima de 2 mm | 2 px |
| 1 a 2 mm | 1 px |
| abaixo de 1 mm | nenhum |
### O que precisa ser validado
| Ponto | Pergunta para a sala |
|---|---|
| **Valores do choke** | 2 px acima de 2 mm está certo, ou vocês usam outro número? |
| **Limite do traço fino** | abaixo de quanto vocês nunca aplicam contração? |
| **Branco em degradê** | onde a arte tem transparência parcial, o branco fica meio transparente. Vocês ajustam? Como? |
| **Densidade do branco** | arte escura pede mais branco que arte clara? Isso é ajustado hoje? |
| **Tipo de tecido** | o branco muda conforme o cliente vai aplicar em algodão ou poliéster? |
| **Casos que nunca dão certo no automático** | quais? |
### Como conduzir a conversa
Não perguntar "o que vocês fazem". Pedir **cinco arquivos**:
- dois que sempre saem bem no automático
- dois que sempre precisam de ajuste
- um que já deu errado
Com esses cinco dá para descobrir se a regra cabe em três linhas de código ou se
há julgamento de verdade envolvido.
**Aposta:** 80% dos casos cabem na regra de espessura. Os 20% restantes viram
uma etiqueta `spot manual` no card e vão para o PC central como **exceção, não
como padrão**.
**Isso decide a madrugada:** se o SPOT manual for exceção, o turno da noite roda
no automático e deixa as exceções para o dia. Não precisa de designer de plantão.
---
## Insumos: tudo que passa pelo depósito já está medido
O aproveitamento do filme sai das transferências para o depósito de impressão no
Tiny. O mesmo caminho serve para todo o resto:
| Insumo | Consumo teórico por 100 m | O que o desvio revela |
|---|---|---|
| Filme | 100 m comprados → 90 úteis | acerto, prova de cor, refile, ponta |
| Tinta | 1,5 L | purga excessiva, vazamento, apontamento errado |
| Poliamida | 2,5 kg | idem |
| Peças de máquina | — | custo por metro, sem teórico |
O sistema sabe quantos metros imprimiu, então calcula o teórico e compara com o
transferido. Tinta a 1,8 L por 100 m significa 20% de desvio — hoje ninguém
saberia.
---
## FlexiPRINT · hot folder confirmado, arquitetura a definir
A documentação oficial da SAi confirma: **o Flexi tem hot folder**, uma pasta
por dispositivo de saída, monitorada continuamente. Arquivo copiado ou movido
para dentro entra na fila automaticamente. Por padrão fica em
`C:\Program Files\[Software]\Jobs`.
A versão 21 traz dois recursos relevantes:
- **"RIP only" ao receber na hot folder** — processa o arquivo sem esperar a
máquina ficar livre
- **Opções melhoradas de branco para DTF** e ferramenta de fundo transparente
### O problema de memória
Relato da sala: **o PC que roda a máquina não aguenta preparar outro arquivo ao
mesmo tempo** — o RIP consome memória demais. É por isso que existe o PC
central hoje.
Duas arquiteturas possíveis, e a escolha depende do que a licença de vocês
permite:
**A · Production Manager centralizado.** Se o Flexi permitir gerenciar a fila de
várias impressoras a partir de um PC só, o **PC central vira servidor de RIP** e
os PCs das máquinas ficam leves — só transmitem dados para a impressora.
Resolve o problema sem trocar computador.
**B · RIP distribuído.** Cada PC ripa o próprio trabalho. Aí o "RIP only" ajuda,
porque o arquivo é processado enquanto a máquina ainda roda o anterior — mas o
PC precisa aguentar as duas coisas.
**Levantamento pendente com Thales e Alexandre** (ver `dtf-roteiro-reuniao.md`,
bloco E2):
- edição e versão do Flexi **em cada máquina** — se forem diferentes, o
comportamento da hot folder varia entre elas
- a hot folder aceita pasta de rede ou só local?
- existe "RIP only" na versão instalada?
- o Production Manager centraliza várias impressoras?
- o Flexi gera o canal branco a partir da transparência?
- as licenças são por PC ou flutuantes?
**Enquanto isso não fecha, não programe a fase 4.** O desenho da hot folder
depende de a pasta de rede funcionar.
---
## Instalação
### Portal (VPS Ubuntu)
```bash
apt install -y python3.12-venv libvips-tools postgresql nginx certbot
python3 -m venv /opt/dtf/venv && source /opt/dtf/venv/bin/activate
pip install fastapi uvicorn sqlmodel 'psycopg[binary]' boto3 httpx # prototype only; no longer tracked
cp .env.exemplo .env # preencher
cd portal && uvicorn main:app --host 0.0.0.0 --port 8000
```
Nginx faz proxy para a 8000 e o certbot cuida do TLS em
`arte.dropstaratacado.com.br`.
### Agente (servidor da fábrica)
Windows, como serviço:
```
nssm install DtfAgente "C:\Python312\python.exe" "C:\dtf\agente.py"
nssm set DtfAgente AppEnvironmentExtra BASE_PORTAL=... AGENTE_TOKEN=...
nssm start DtfAgente
```
Linux: usar `agente/dtf-agente.service`.
### Kanban (servidor da fábrica)
```bash
cd kanban && uvicorn main:app --host 0.0.0.0 --port 8080
```
O front é o protótipo `dtf-portal-kanban.html`, apontando para `/api/quadro`
e `/api/mover`. Colocar em `kanban/static/kanban.html`.
---
## Estrutura de pastas no servidor
```
\\servidor\DTF\
00_ARTE_RECEBIDA 10_ARTE_TRATADA 20_FILA_IMPRESSAO
30_IMPRIMINDO 40_CORRECAO 50_APLICACAO
60_FINALIZADO _ERRO _log
```
O banco é a fonte de verdade e a pasta é espelho. Se divergirem, o banco ganha.
---
## Tabelas
| Tabela | Onde | Para quê |
|---|---|---|
| `pedido` | nuvem | número do Tiny, cliente, token e validade |
| `arte` | nuvem | arquivo, DPI, status, motivo da recusa |
| `parte` | nuvem + local | cada arquivo gerado pelo fatiamento |
| `card` | local | posição atual no kanban |
| **`movimento`** | local | **de onde saem todos os números** |
| `job` | local | fila de marcador e WhatsApp, com retentativa |
### Normalização: o cliente manda o que quiser
Não existe "formato certo" único — normalizar tudo para um só jogaria fora o
melhor de cada tipo. A regra é por **natureza do conteúdo**:
| Chega como | Sai como | Por quê |
|---|---|---|
| PDF, AI, SVG, EPS | **PDF**, mantendo vetor | rasterizar aqui é perder qualidade |
| PNG, TIF, PSD, PSB | **TIF** com alfa, LZW | é o que a sala já usa |
| CDR | não converte | sem Corel no servidor |
**O original é sempre preservado.** Pedido dos designers: se a conversão sair
ruim num caso, eles voltam ao arquivo do cliente.
**Resolve o limite dos 5 metros.** Os designers relatam abrir PDF no Corel para
não rasterizar, exportar, abrir no Photoshop — e esbarrar em 5 metros. O limite
não é do Photoshop: é do formato **PSD**, que trava em 30.000 px por dimensão,
o que a 150 DPI dá 5,08 m. PSB vai a 300.000 px, ou 50 metros. Em PDF vetorial
não há esse limite.
**Melhor ainda:** PDF vetorial pode ir do portal direto para a hot folder. O
FlexiPRINT rasteriza na resolução exata da máquina, na hora de imprimir —
qualidade melhor que qualquer caminho manual, e uma etapa a menos.
**CMYK vira RGB na normalização.** Arquivo em CMYK é uma das causas de cor
errada no DTF: o cliente monta em CMYK, a máquina trabalha em RGB, e a cor muda.
### Retrabalho: meta por causa, não meta única
SKU `CRRMP.TX.100CM`. A Mayana abre e classifica a causa; Thales ou Alexandre
autorizam, porque o retrabalho da casa entra na meta e na remuneração deles.
**A causa fica travada depois de aberta** — com indicador atrelado a bônus,
haveria incentivo para reclassificar falha de máquina como culpa do cliente.
Quem discorda contesta, e a contestação fica registrada.
| Causa | Responsável | Hoje | Meta |
|---|---|---|---|
| Falha de impressão | Thales e Alexandre | 1,8% | 0,4% |
| Perfil de cor | Thales e Alexandre | — | 0,4% |
| Erro de tratamento | designers | 1,1% | 0,4% |
| Erro de pedido | comercial | — | 0,4% |
| Arte do cliente | — | 0,9% | fora da meta |
| **Total da casa** | | **2,9%** | **1,6%** |
**Perfil de cor virou causa própria.** Cor errada é o retrabalho mais comum de
DTF e quase nunca é defeito de máquina. Separando de "falha de impressão", dá
para saber quanto é arte em CMYK, quanto é monitor do cliente e quanto é perfil
da impressora desatualizado — só o último é da casa.
**Coluna nova: aprovação de cor.** Antes de imprimir o pedido inteiro, sai uma
amostra, foto pelo WhatsApp e o cliente aprova. Dispara sozinho em arquivo acima
de 10 m, primeiro pedido do cliente, ou cor fora do gamut CMYK. Custa
centímetros de filme e evita metros de reposição.
**Não existe coluna de aplicação.** A sala só imprime o filme — quem aplica na
peça é o cliente.
Meta única de 1,5% penalizaria o designer por falha de máquina e exigiria
derrubar 64% do retrabalho de uma vez. Meta inatingível empurra para
reclassificar causa, não para reduzir defeito. Ver `META_POR_CAUSA` e
`/api/relatorio/retrabalho`.
### Os marcadores de duração são estimativa de máquina
Confirmado pela sala em 02/09/2026. `30 min` (2.430 pedidos), `1 hora` (833) e
`3 horas` (40) **não são lixo de cadastro** — são a estimativa de quanto tempo o
trabalho leva na máquina.
**Não somem: viram o campo `minutos_maquina` no card.** É esse número que o
kanban usa para calcular fila contra capacidade do dia. Sem ele, a estimativa
sai dos metros a 20 m/h — mas arte complexa demora mais que arte simples do
mesmo tamanho, e a sala sabe qual é qual.
**Quem preenche:** o sistema sugere pelo tamanho; quem trata a arte ajusta só
quando foge do normal.
| Marcador | Destino |
|---|---|
| `inicio 14:45` e variações | **some** — o sistema carimba a hora do movimento real |
| `Maq 1` … `Maq 6` | vira etiqueta no card, sai do Tiny |
| `fila de impressao` | vira coluna do kanban |
| `CORRECAO DTF` | continua no Tiny — o comercial precisa ver |
| **`30 min` · `1 hora` · `3 horas`** | **vira campo `minutos_maquina`** |
### Marcadores no Tiny: três, não sete
O kanban é a fonte de verdade da operação. O Tiny recebe só o estágio grosso,
para quem não abre o kanban — comercial no telefone, expedição, celular:
| Movimento no kanban | Marcador no Tiny |
|---|---|
| recebida · tratada · fila · aplicação | nenhum |
| entra em **Imprimindo** | `DTF-PRODUCAO` |
| vai para **Correção** | `CORRECAO DTF` |
| **Finalizado** | `DTF-PRONTO` |
Três chamadas por pedido em vez de sete. A 213 pedidos/dia, 640 requisições
em vez de 1.500 — folga no limite da API e menos job para monitorar.
A máquina que imprimiu fica só no kanban.
### Artes guardadas para recompra
Prefixo separado no storage: `artes-cliente/{numero_cliente}/`, retenção de
**12 meses** — contra os 30 dias do arquivo de trabalho. Guarda-se só a **arte
tratada**, não o original: é menor e é a que vai para a máquina.
O cliente acessa por um link permanente dele (token de cliente, não de pedido),
numa página "minhas artes", e pede reimpressão com um clique — que abre pedido
novo no Tiny. Resolve o caso de quem quer a mesma arte de dois meses atrás.
### Abrir o arquivo pelo kanban · sem instalar nada
**Decisão de 30/08/2026: nada instalado nos PCs da sala. Só a tela.**
Navegador não lança programa externo — é bloqueio de segurança, sem contorno.
Então o desenho é:
1. **Miniatura no card** — o operador confere a arte sem sair da tela
2. **Botão copia o caminho** — cola no FlexiPRINT
3. **File System Access API** — Chrome ou Edge pede permissão à pasta de rede
uma vez; a partir daí o kanban lê e move arquivo direto do navegador
O item 3 tem uma consequência boa: **a movimentação de arquivo sai do backend.**
O `mover_arquivos()` em `kanban/main.py` vira opcional — quem move é a própria
tela. Menos código no servidor e menos chance de o estado divergir.
O que continua manual: colar o caminho no Flexi. Uma tecla a mais que o ideal.
Handler local resolveria, mas exige instalação em cada máquina — descartado.
### Aproveitamento do filme: sai do Tiny, sem apontamento novo
A Altus transfere o insumo para um depósito de impressão antes de rodar, porque
também **revende insumo** — o depósito separa consumo interno de revenda.
Isso significa que o consumo de filme **já é registrado hoje**. O painel só lê a
movimentação desse depósito e divide os metros faturados pelos metros
transferidos. Nenhum gesto novo para a sala.
Ver `DEPOSITO_IMPRESSAO` e `tiny.transferido_para_deposito()`.
`movimento` é a mais importante. Dela saem tempo por etapa, fila por máquina,
taxa de retrabalho e ocupação real — os números que hoje não existem em lugar
nenhum. Ver `/api/relatorio/etapas`.
---
## Decisões que dependem de você, Wagner
1. **Servidor da fábrica é Windows ou Linux?** Muda como o agente vira serviço.
2. **A conta do Tiny já tem aplicação na API v3?** Precisamos de client id e secret.
3. **Confirmar na documentação do Tiny** o endpoint de marcadores e o limite de
requisições por minuto. `tiny.py` isola isso — se mudar, muda só ali.
4. **O número do WhatsApp do DTF migra para a API oficial da Meta**, ou fica com
provedor tipo Z-API? A oficial exige template aprovado para mensagem iniciada
por nós, mas não corre risco de bloqueio.
5. **Latência da integração VNDA → Tiny.** É ela que define quanto tempo passa
entre a compra e o link chegar no cliente. Se for alta, o argumento de
rapidez do projeto perde força.
6. **Retenção dos arquivos: 90 dias.** Configurar regra de ciclo de vida no
bucket. A arte é propriedade do cliente.
---
## Segurança
- Token do link: UUID v4, 7 dias, um por pedido
- HTTPS obrigatório no portal, Let's Encrypt com renovação automática
- Kanban **sem porta aberta para fora** — se precisar de acesso remoto, VPN
- ClamAV no arquivo recebido antes de liberar para o agente
- Dump diário do Postgres para o storage
- Heartbeat do agente a cada 5 min; sem sinal por 15 min, alertar o TI
Serviço silencioso parado é pior que erro barulhento — ninguém percebe até o
cliente cobrar.
---
## Ordem de entrega
| Fase | Entrega | Já dá valor sozinha? |
|---|---|---|
| 1 | Limpar marcadores — ver seção própria | **sim**: destrava o kanban e some com trabalho manual da sala |
| 2 | Portal + robô + storage no ar | **sim**: recebimento 24h e recusa automática |
| 3 | Agente rodando como serviço | **sim**: arquivo cai na pasta sozinho |
| 4 | Kanban + Tiny + WhatsApp | é o que transforma movimento em número |
As fases 2 e 3 entregam sozinhas. A fase 4 é onde a medição começa.