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
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>
673 lines
28 KiB
Markdown
673 lines
28 KiB
Markdown
# 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.
|