first commit
Some checks failed
Validate, publish and deploy / validate (push) Successful in 2m2s
Validate, publish and deploy / publish-and-deploy (push) Failing after 8s

This commit is contained in:
Cauê Faleiros
2026-09-15 16:42:34 -03:00
commit 98c951d374
170 changed files with 95988 additions and 0 deletions

662
README.md Normal file
View File

@@ -0,0 +1,662 @@
# Sistema DTF 24h — Altus Group
> **Active local milestone (2026-09-11):** Read [CONTEXT.md](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 [LOCAL_SETUP.md](LOCAL_SETUP.md) for the complete test flow,
> local login, health checks, and troubleshooting. See
> [IMPLEMENTATION_REPORT.md](IMPLEMENTATION_REPORT.md) for scope and reuse decisions.
> Production delivery uses one Portainer stack; see [PORTAINER.md](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.
---
## 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 -r requirements.txt
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.