first commit
329
tmp/pdfs/current-roadmap.txt
Normal file
@@ -0,0 +1,329 @@
|
||||
PLANO DE ENTREGA
|
||||
|
||||
|
||||
|
||||
Sistema DTF
|
||||
Plano de entrega
|
||||
Uma operação em que o cliente envia a arte, recebe análise, paga e
|
||||
acompanha a produção sem depender de WhatsApp, pastas ou repasse
|
||||
manual.
|
||||
|
||||
|
||||
|
||||
OBJETIVO DECISÃO DE ARQUITETURA
|
||||
|
||||
|
||||
Portal e Kanban online +
|
||||
Transformar capacidade ociosa Cloudflare R2 + VPS existente. A
|
||||
em atendimento e produção 24 impressão continua manual na
|
||||
horas. fábrica.
|
||||
|
||||
|
||||
|
||||
Consolidação das discussões técnicas e comerciais - setembro de 2026
|
||||
DTF Dropstar - plano de entrega
|
||||
|
||||
|
||||
|
||||
CONTEXTO
|
||||
|
||||
|
||||
O problema que vamos resolver
|
||||
A sala de DTF tem capacidade instalada muito maior que a produção atual. O gargalo não é a máquina:
|
||||
é o fluxo entre o pedido, a arte, o designer e a sala. Hoje o cliente envia arquivo no WhatsApp, o
|
||||
atendimento repassa, o designer descobre problemas tarde e o status fica escondido em pastas de rede.
|
||||
|
||||
O projeto resolve quatro falhas do processo:
|
||||
• Recebimento limitado pelo horário: um cliente que chega no fim do dia espera até o turno seguinte.
|
||||
• Arquivo sem rastreabilidade: WhatsApp e nomes digitados manualmente facilitam perda e erro.
|
||||
• Arquivo ruim chega tarde ao designer: qualidade, dimensão e transparência são verificadas depois de
|
||||
consumir tempo humano.
|
||||
• Produção sem números: não há registro confiável de espera, velocidade real, fila ou retrabalho.
|
||||
|
||||
|
||||
ANTES DEPOIS
|
||||
|
||||
|
||||
Pedido e arte circulam por WhatsApp e pastas. Site DTF recebe a arte, analisa, precifica e registra o
|
||||
fluxo.
|
||||
|
||||
|
||||
Designer corrige indiscriminadamente. Arte pronta segue rápido; exceções vão para atendimento
|
||||
humano.
|
||||
|
||||
|
||||
Sala não enxerga fila real nem tempos. Kanban online organiza a fila e registra cada movimento
|
||||
manualmente.
|
||||
|
||||
|
||||
|
||||
|
||||
Página 2
|
||||
DTF Dropstar - plano de entrega
|
||||
|
||||
|
||||
|
||||
MODELO OPERACIONAL
|
||||
|
||||
|
||||
Como será a jornada do pedido
|
||||
|
||||
Escolhe o produto, envia a arte e vê o valor conforme as regras comerciais
|
||||
Cliente entra no site DTF
|
||||
1 já configuradas.
|
||||
|
||||
|
||||
Calcula a metragem e prepara o pedido. O pré-flight automático será
|
||||
Sistema registra a arte
|
||||
2 validado depois da entrega, com arquivos reais.
|
||||
|
||||
|
||||
O checkout é do Mercado Pago; os dados do cartão não passam pelo nosso
|
||||
Cliente paga
|
||||
3 servidor.
|
||||
|
||||
|
||||
Depois da confirmação do pagamento, o pedido é criado no Tiny e aparece
|
||||
Pedido entra no sistema
|
||||
4 no Kanban.
|
||||
|
||||
|
||||
O operador baixa o arquivo final no Kanban, importa no FlexiPRINT e
|
||||
Equipe baixa e imprime
|
||||
5 atualiza o card.
|
||||
|
||||
|
||||
|
||||
|
||||
Onde o WhatsApp entra
|
||||
O WhatsApp deixa de ser o lugar onde a arte é enviada. Ele serve para avisar o cliente: pagamento
|
||||
aprovado, pedido em produção, pedido pronto ou necessidade de correção. Quando houver problema, a
|
||||
mensagem leva o cliente de volta para o site.
|
||||
|
||||
Cuidados na automação: se Mercado Pago, Tiny ou WhatsApp reenviar um aviso por falha, o sistema confere antes de
|
||||
agir. Assim, não cria dois pedidos nem manda a mesma mensagem duas vezes.
|
||||
|
||||
|
||||
|
||||
|
||||
Página 3
|
||||
DTF Dropstar - plano de entrega
|
||||
|
||||
|
||||
|
||||
PRODUÇÃO
|
||||
|
||||
|
||||
Arquitetura de software e infraestrutura
|
||||
Todo o sistema roda na nuvem: recebe, processa, integra e disponibiliza o arquivo final. A fábrica acessa
|
||||
o Kanban pelo navegador e baixa o arquivo quando for produzir; não há componente instalado na rede
|
||||
interna.
|
||||
|
||||
CLIENTE E INTEGRAÇÕES NUVEM / VPS EQUIPE DA FÁBRICA
|
||||
|
||||
|
||||
|
||||
|
||||
Site DTF API FastAPI R2 Kanban online
|
||||
arte, preço e checkout pedido, upload originais e fila, status e
|
||||
acompanhamento do pedido e integrações arte final privada download seguro
|
||||
|
||||
|
||||
|
||||
|
||||
Integrações externas Worker PostgreSQL Operador
|
||||
Mercado Pago · Tiny/Olist antivírus e pedidos, jobs baixa e importa
|
||||
WhatsApp Business pré-flight e histórico no FlexiPRINT
|
||||
|
||||
|
||||
|
||||
|
||||
NUVEM Site DTF, Kanban online, API FastAPI, worker, ClamAV, PostgreSQL e Cloudflare R2.
|
||||
|
||||
|
||||
FÁBRICA Navegador, operador e FlexiPRINT atual. O arquivo é baixado e importado manualmente.
|
||||
|
||||
|
||||
TERCEIROS Mercado Pago, Tiny/Olist e WhatsApp Business API.
|
||||
|
||||
|
||||
• Upload grande: o navegador manda o arquivo direto para o R2, em partes. O VPS não precisa receber 5
|
||||
GB de uma vez.
|
||||
• Fila: o banco guarda o que precisa ser analisado, enviado ao Tiny, avisado no WhatsApp ou apagado no
|
||||
prazo certo.
|
||||
• Segurança: o arquivo entra em quarentena, passa pelo antivírus e só depois é analisado e liberado no
|
||||
Kanban.
|
||||
• Se a fábrica ficar sem internet: o site continua no ar. A equipe apenas não consegue baixar arquivo
|
||||
novo ou atualizar o Kanban até a conexão voltar.
|
||||
|
||||
|
||||
|
||||
|
||||
Página 4
|
||||
DTF Dropstar - plano de entrega
|
||||
|
||||
|
||||
|
||||
CLOUDFLARE
|
||||
|
||||
|
||||
R2: custos e retenção
|
||||
O R2 é onde os arquivos ficam guardados. Ele é privado: o operador só baixa pelo Kanban, com link
|
||||
temporário. O custo vem principalmente da média de GB guardados no mês; leitura e gravação
|
||||
costumam pesar bem menos. O download não tem cobrança de saída de dados.
|
||||
|
||||
|
||||
MÉDIA ARMAZENADA R2 / MÊS APROX. EM R$*
|
||||
|
||||
|
||||
100 GB US$ 1,35 R$ 7
|
||||
|
||||
|
||||
500 GB US$ 7,35 R$ 38
|
||||
|
||||
|
||||
1 TB US$ 14,85 R$ 76
|
||||
|
||||
|
||||
3 TB US$ 44,85 R$ 230
|
||||
|
||||
* Referência de US$ 1 = R$ 5,13; câmbio, impostos e tarifas do meio de pagamento podem variar.
|
||||
|
||||
|
||||
ARTEFATO PRAZO REGRA
|
||||
|
||||
|
||||
Upload multipart incompleto 1 dia Abortado automaticamente.
|
||||
|
||||
|
||||
Recusado ou infectado 3 dias Suporte pode conferir; depois apaga.
|
||||
|
||||
|
||||
Original do cliente até 7 dias Após aprovação, não fica guardado sem necessidade.
|
||||
|
||||
|
||||
Arte pronta para impressão máx. 30 dias Prazo conta do primeiro upload; permite correção ou
|
||||
reimpressão recente.
|
||||
|
||||
|
||||
Histórico e métricas banco Sem manter a imagem.
|
||||
|
||||
|
||||
Decisão: não haverá biblioteca infinita de artes. Após o prazo, o cliente reenvia o arquivo; o pedido e sua
|
||||
rastreabilidade permanecem registrados.
|
||||
|
||||
|
||||
|
||||
|
||||
Página 5
|
||||
DTF Dropstar - plano de entrega
|
||||
|
||||
|
||||
|
||||
OPERAÇÃO, PUBLICAÇÃO E CONTINUIDADE
|
||||
|
||||
|
||||
Como fica em produção
|
||||
A primeira entrega será operada como uma única aplicação na VPS. Portal, Kanban, processamento e
|
||||
banco seguem o mesmo ciclo de publicação, com acesso da fábrica exclusivamente pelo navegador.
|
||||
Isso reduz pontos de manutenção e mantém a operação independente da rede interna.
|
||||
|
||||
|
||||
AMBIENTE COMPONENTES OPERAÇÃO
|
||||
|
||||
|
||||
Sistema DTF site DTF, Kanban online, API, processamento, antivírus, banco VPS com armazenamento
|
||||
de dados e cópia diária de segurança persistente; operação e
|
||||
acompanhamento
|
||||
centralizados
|
||||
|
||||
|
||||
|
||||
|
||||
Publicação com controle
|
||||
• Toda alteração passa por testes automáticos antes de poder chegar ao ambiente de produção.
|
||||
• Cada publicação fica identificada pela versão do código, permitindo restaurar rapidamente a versão
|
||||
anterior se houver qualquer problema.
|
||||
• As mudanças são conferidas primeiro em ambiente de validação e só então liberadas para a operação.
|
||||
• Ao final da publicação, uma verificação confirma que os serviços essenciais voltaram a responder antes
|
||||
de encerrar o processo.
|
||||
• Credenciais de storage, pagamentos, integrações e banco permanecem fora do código e são tratadas
|
||||
como dados restritos do ambiente.
|
||||
|
||||
|
||||
Acompanhamento operacional
|
||||
A rotina de operação acompanha disponibilidade do site e do Kanban, andamento da fila de processamento, falhas de
|
||||
integração e resultado das cópias de segurança. Assim, qualquer desvio é identificado antes de interromper o
|
||||
atendimento ou a produção.
|
||||
|
||||
|
||||
|
||||
|
||||
Página 6
|
||||
DTF Dropstar - plano de entrega
|
||||
|
||||
|
||||
|
||||
MVP EM ATÉ 3 SEMANAS
|
||||
|
||||
|
||||
Roadmap de implementação
|
||||
O cronograma considera a base de código existente e dedicação integral. A prioridade é concluir o fluxo
|
||||
completo - envio, pagamento, frete, pedido e acompanhamento - antes de qualquer integração com as
|
||||
máquinas. As regras comerciais seguem exatamente o que já está configurado no Site DTF.
|
||||
|
||||
|
||||
QUANDO ENTREGA RESULTADO
|
||||
|
||||
|
||||
Sem. 1 Infraestrutura e upload VPS, domínio, banco, R2, upload multipart, antivírus e base do
|
||||
serviço.
|
||||
|
||||
|
||||
Sem. 2 Pagamento, frete e pedido Mercado Pago, cotação de frete, criação idempotente no Tiny,
|
||||
geração do arquivo final e estados principais do Kanban.
|
||||
|
||||
|
||||
Sem. 3 Kanban e entrega Kanban online, download seguro, mensagens de status no WhatsApp,
|
||||
retenção de 30 dias e orientação à operação.
|
||||
|
||||
|
||||
|
||||
|
||||
Fora da primeira entrega
|
||||
A primeira entrega termina no download do arquivo final pelo Kanban e na orientação de uso à operação. Integração
|
||||
direta com FlexiPRINT, agente dentro da fábrica, pasta monitorada, painel de sala e relatórios avançados não fazem
|
||||
parte deste prazo. O pré-flight automático será validado depois da entrega, com arquivos e impressão reais. A fábrica
|
||||
mantém esses recursos no ambiente atual; após a entrega, damos suporte e avaliamos mudanças conforme a
|
||||
necessidade.
|
||||
|
||||
|
||||
O que fica com a operação
|
||||
• Acessar o Kanban, baixar o arquivo final e importá-lo manualmente no FlexiPRINT atual.
|
||||
• Realizar os testes de impressão e informar qualquer diferença encontrada no arquivo ou no resultado
|
||||
impresso.
|
||||
• Manter computadores, FlexiPRINT, perfis de impressão, impressoras e eventuais pastas internas
|
||||
funcionando.
|
||||
• A conexão local é necessária apenas para a equipe acessar o Kanban e baixar o arquivo na fábrica. Se
|
||||
ela cair, portal, pagamentos, uploads e fila continuam ativos na nuvem; a produção retoma quando o
|
||||
acesso local voltar.
|
||||
• Comunicar mudanças de preços, frete ou regras operacionais que precisem ser refletidas no sistema.
|
||||
|
||||
|
||||
O que precisamos para começar
|
||||
• Credenciais do Mercado Pago, incluindo a configuração do webhook para confirmação de pagamento.
|
||||
• Dados da integração de frete: plataforma(s) já utilizada(s), acesso à API, CEP de origem, serviços
|
||||
oferecidos, regra de cobrança e referência de peso e dimensões por pacote.
|
||||
|
||||
|
||||
Antes de começar
|
||||
Com esses acessos e dados liberados, a primeira semana pode começar. A tabela, os descontos e as regras comerciais
|
||||
já existentes no Site DTF serão mantidos. Tiny/Olist e WhatsApp já estão disponíveis; durante o desenvolvimento será
|
||||
definida a ligação técnica dessas integrações com os eventos do pedido. A fábrica valida a impressão depois, baixando
|
||||
o arquivo final pelo Kanban.
|
||||
|
||||
|
||||
|
||||
|
||||
Página 7
|
||||
|
||||
438
tmp/pdfs/generate_dtf_report.py
Normal file
@@ -0,0 +1,438 @@
|
||||
from pathlib import Path
|
||||
import math
|
||||
|
||||
from reportlab.lib import colors
|
||||
from reportlab.lib.enums import TA_CENTER, TA_LEFT
|
||||
from reportlab.lib.pagesizes import A4
|
||||
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
from reportlab.platypus import (
|
||||
BaseDocTemplate, Frame, PageBreak, PageTemplate, Paragraph, Spacer,
|
||||
Table, TableStyle, KeepTogether, Flowable,
|
||||
)
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
OUT = ROOT / "output/pdf/dtf-plano-producao-e-roadmap.pdf"
|
||||
FONT = "/usr/share/fonts/TTF/DejaVuSans.ttf"
|
||||
FONT_BOLD = "/usr/share/fonts/TTF/DejaVuSans-Bold.ttf"
|
||||
|
||||
pdfmetrics.registerFont(TTFont("DejaVu", FONT))
|
||||
pdfmetrics.registerFont(TTFont("DejaVu-Bold", FONT_BOLD))
|
||||
|
||||
NAVY = colors.HexColor("#071426")
|
||||
BLUE = colors.HexColor("#1463D8")
|
||||
SKY = colors.HexColor("#EAF2FF")
|
||||
ORANGE = colors.HexColor("#FF8A1F")
|
||||
GREEN = colors.HexColor("#16825B")
|
||||
RED = colors.HexColor("#B83737")
|
||||
INK = colors.HexColor("#162235")
|
||||
MUTED = colors.HexColor("#607085")
|
||||
LINE = colors.HexColor("#D9E1EA")
|
||||
PALE = colors.HexColor("#F6F8FB")
|
||||
WHITE = colors.white
|
||||
|
||||
|
||||
class Rule(Flowable):
|
||||
def __init__(self, color=ORANGE, width=4.0, length=54):
|
||||
Flowable.__init__(self)
|
||||
self.color, self.thickness, self.length = color, width, length
|
||||
self.width, self.height = length, width
|
||||
|
||||
def draw(self):
|
||||
self.canv.setStrokeColor(self.color)
|
||||
self.canv.setLineWidth(self.thickness)
|
||||
self.canv.line(0, self.thickness / 2, self.length, self.thickness / 2)
|
||||
|
||||
|
||||
class ArchitectureDiagram(Flowable):
|
||||
"""Small three-zone diagram drawn in vector primitives."""
|
||||
def __init__(self):
|
||||
Flowable.__init__(self)
|
||||
self.width, self.height = 17.0 * cm, 7.2 * cm
|
||||
|
||||
def box(self, x, y, w, h, title, sub, fill, accent):
|
||||
c = self.canv
|
||||
c.setFillColor(fill)
|
||||
c.setStrokeColor(accent)
|
||||
c.setLineWidth(1)
|
||||
c.roundRect(x, y, w, h, 7, fill=1, stroke=1)
|
||||
c.setFillColor(INK)
|
||||
c.setFont("DejaVu-Bold", 8.3)
|
||||
c.drawString(x + 8, y + h - 16, title)
|
||||
c.setFillColor(MUTED)
|
||||
c.setFont("DejaVu", 6.6)
|
||||
for i, line in enumerate(sub.split("\n")):
|
||||
c.drawString(x + 8, y + h - 29 - 9 * i, line)
|
||||
|
||||
def _arrowhead(self, tip_x, tip_y, from_x, from_y):
|
||||
c = self.canv
|
||||
dx, dy = from_x - tip_x, from_y - tip_y
|
||||
distance = math.hypot(dx, dy)
|
||||
if not distance:
|
||||
return
|
||||
ux, uy = dx / distance, dy / distance
|
||||
angle = math.radians(28)
|
||||
arm = 5
|
||||
for sign in (-1, 1):
|
||||
vx = ux * math.cos(angle) - sign * uy * math.sin(angle)
|
||||
vy = uy * math.cos(angle) + sign * ux * math.sin(angle)
|
||||
c.line(tip_x, tip_y, tip_x + arm * vx, tip_y + arm * vy)
|
||||
|
||||
def arrow(self, x1, y1, x2, y2, label=None):
|
||||
c = self.canv
|
||||
c.setStrokeColor(colors.HexColor("#8BA0B8"))
|
||||
c.setFillColor(colors.HexColor("#8BA0B8"))
|
||||
c.setLineWidth(1.1)
|
||||
c.line(x1, y1, x2, y2)
|
||||
self._arrowhead(x2, y2, x1, y1)
|
||||
if label:
|
||||
c.setFillColor(MUTED)
|
||||
c.setFont("DejaVu", 5.9)
|
||||
c.drawCentredString((x1 + x2) / 2, (y1 + y2) / 2 + 4, label)
|
||||
|
||||
def double_arrow(self, x1, y1, x2, y2, label=None):
|
||||
c = self.canv
|
||||
c.setStrokeColor(colors.HexColor("#8BA0B8"))
|
||||
c.setFillColor(colors.HexColor("#8BA0B8"))
|
||||
c.setLineWidth(1.1)
|
||||
c.line(x1, y1, x2, y2)
|
||||
self._arrowhead(x1, y1, x2, y2)
|
||||
self._arrowhead(x2, y2, x1, y1)
|
||||
if label:
|
||||
c.setFillColor(MUTED)
|
||||
c.setFont("DejaVu", 5.9)
|
||||
c.drawCentredString((x1 + x2) / 2, (y1 + y2) / 2 + 4, label)
|
||||
|
||||
def draw(self):
|
||||
c = self.canv
|
||||
zones = [(0, 0, 142, "CLIENTE E INTEGRAÇÕES"), (152, 0, 214, "NUVEM / VPS"),
|
||||
(376, 0, 106, "EQUIPE DA FÁBRICA")]
|
||||
for x, y, w, name in zones:
|
||||
c.setFillColor(PALE)
|
||||
c.setStrokeColor(LINE)
|
||||
c.roundRect(x, 0, w, self.height, 8, fill=1, stroke=1)
|
||||
c.setFillColor(MUTED)
|
||||
c.setFont("DejaVu-Bold", 6.4)
|
||||
c.drawString(x + 9, self.height - 13, name)
|
||||
self.box(12, 117, 120, 40, "Site DTF", "arte, preço e checkout\nacompanhamento do pedido", WHITE, ORANGE)
|
||||
self.box(12, 48, 120, 40, "Integrações externas", "Mercado Pago · Tiny/Olist\nWhatsApp Business", WHITE, BLUE)
|
||||
self.box(162, 117, 88, 40, "API FastAPI", "pedido, upload\ne integrações", SKY, BLUE)
|
||||
self.box(258, 117, 92, 40, "R2", "originais e\narte final privada", SKY, BLUE)
|
||||
self.box(162, 48, 88, 40, "Worker", "antivírus e\npré-flight", SKY, GREEN)
|
||||
self.box(258, 48, 92, 40, "PostgreSQL", "pedidos, jobs\ne histórico", SKY, BLUE)
|
||||
self.box(388, 117, 82, 40, "Kanban online", "fila, status e\ndownload seguro", WHITE, colors.HexColor("#7650B8"))
|
||||
self.box(388, 48, 82, 40, "Operador", "baixa e importa\nno FlexiPRINT", WHITE, colors.HexColor("#7650B8"))
|
||||
self.arrow(132, 137, 162, 137)
|
||||
self.double_arrow(132, 88, 162, 117)
|
||||
self.arrow(250, 137, 258, 137)
|
||||
self.arrow(206, 117, 206, 88)
|
||||
self.double_arrow(250, 117, 258, 88)
|
||||
self.double_arrow(250, 68, 258, 68)
|
||||
self.arrow(350, 137, 388, 137)
|
||||
self.arrow(429, 117, 429, 88)
|
||||
|
||||
|
||||
def paragraph(text, style):
|
||||
return Paragraph(text, style)
|
||||
|
||||
|
||||
def bullet(text, styles):
|
||||
return Paragraph(f"<font color='#FF8A1F'>•</font> {text}", styles["bullet"])
|
||||
|
||||
|
||||
def section_title(text, styles, kicker=None):
|
||||
blocks = []
|
||||
if kicker:
|
||||
blocks.append(Paragraph(kicker.upper(), styles["kicker"]))
|
||||
blocks.append(Spacer(1, 3))
|
||||
blocks += [Paragraph(text, styles["dtf_h1"]), Spacer(1, 7), Rule(), Spacer(1, 12)]
|
||||
return blocks
|
||||
|
||||
|
||||
def on_page(canvas, doc):
|
||||
if doc.page == 1:
|
||||
return
|
||||
canvas.saveState()
|
||||
canvas.setStrokeColor(LINE)
|
||||
canvas.line(doc.leftMargin, A4[1] - 1.25 * cm, A4[0] - doc.rightMargin, A4[1] - 1.25 * cm)
|
||||
canvas.setFont("DejaVu", 7.4)
|
||||
canvas.setFillColor(MUTED)
|
||||
canvas.drawString(doc.leftMargin, A4[1] - 1.05 * cm, "DTF Dropstar - plano de entrega")
|
||||
canvas.drawRightString(A4[0] - doc.rightMargin, 0.82 * cm, f"Página {doc.page}")
|
||||
canvas.restoreState()
|
||||
|
||||
|
||||
def build_pdf():
|
||||
styles = getSampleStyleSheet()
|
||||
styles.add(ParagraphStyle(name="cover_kicker", fontName="DejaVu-Bold", fontSize=10,
|
||||
leading=13, textColor=ORANGE, spaceAfter=10, letterSpacing=0.6))
|
||||
styles.add(ParagraphStyle(name="cover_title", fontName="DejaVu-Bold", fontSize=30,
|
||||
leading=35, textColor=WHITE, spaceAfter=11))
|
||||
styles.add(ParagraphStyle(name="cover_text", fontName="DejaVu", fontSize=12,
|
||||
leading=17, textColor=colors.HexColor("#D6E0EF")))
|
||||
styles.add(ParagraphStyle(name="kicker", fontName="DejaVu-Bold", fontSize=8,
|
||||
leading=10, textColor=ORANGE, letterSpacing=0.7))
|
||||
styles.add(ParagraphStyle(name="dtf_h1", fontName="DejaVu-Bold", fontSize=20,
|
||||
leading=24, textColor=NAVY, spaceAfter=0))
|
||||
styles.add(ParagraphStyle(name="dtf_h2", fontName="DejaVu-Bold", fontSize=12,
|
||||
leading=15, textColor=INK, spaceBefore=6, spaceAfter=5))
|
||||
styles.add(ParagraphStyle(name="body", fontName="DejaVu", fontSize=9.3,
|
||||
leading=14, textColor=INK, spaceAfter=8))
|
||||
styles.add(ParagraphStyle(name="bullet", fontName="DejaVu", fontSize=9.1,
|
||||
leading=13, textColor=INK, leftIndent=2, spaceAfter=4))
|
||||
styles.add(ParagraphStyle(name="small", fontName="DejaVu", fontSize=7.6,
|
||||
leading=10.5, textColor=MUTED))
|
||||
styles.add(ParagraphStyle(name="cell", fontName="DejaVu", fontSize=7.7,
|
||||
leading=10, textColor=INK))
|
||||
styles.add(ParagraphStyle(name="cell_bold", fontName="DejaVu-Bold", fontSize=7.7,
|
||||
leading=10, textColor=INK))
|
||||
styles.add(ParagraphStyle(name="cell_white", fontName="DejaVu-Bold", fontSize=7.7,
|
||||
leading=10, textColor=WHITE))
|
||||
styles.add(ParagraphStyle(name="note", fontName="DejaVu", fontSize=8.2,
|
||||
leading=12, textColor=INK, backColor=colors.HexColor("#FFF4E7"),
|
||||
borderColor=colors.HexColor("#F7D2A5"), borderWidth=0.5,
|
||||
borderPadding=8, borderRadius=4))
|
||||
|
||||
doc = BaseDocTemplate(str(OUT), pagesize=A4, leftMargin=1.65 * cm, rightMargin=1.65 * cm,
|
||||
topMargin=1.7 * cm, bottomMargin=1.45 * cm)
|
||||
frame = Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id="main")
|
||||
doc.addPageTemplates([PageTemplate(id="main", frames=[frame], onPage=on_page)])
|
||||
story = []
|
||||
|
||||
# Cover
|
||||
story.append(Spacer(1, 2.4 * cm))
|
||||
cover = [
|
||||
Paragraph("PLANO DE ENTREGA", styles["cover_kicker"]),
|
||||
Paragraph("Sistema DTF<br/>Plano de entrega", styles["cover_title"]),
|
||||
Paragraph("Uma operação em que o cliente envia a arte, recebe análise, paga e acompanha a produção sem depender de WhatsApp, pastas ou repasse manual.", styles["cover_text"]),
|
||||
Spacer(1, 28),
|
||||
Table([[paragraph("OBJETIVO", styles["cover_kicker"]), paragraph("DECISÃO DE ARQUITETURA", styles["cover_kicker"])],
|
||||
[paragraph("Transformar capacidade ociosa em atendimento e produção 24 horas.", styles["cover_text"]),
|
||||
paragraph("Portal e Kanban online + Cloudflare R2 + VPS existente. A impressão continua manual na fábrica.", styles["cover_text"])]],
|
||||
colWidths=[8.1 * cm, 8.1 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, -1), NAVY),
|
||||
("BOX", (0, 0), (-1, -1), 0.6, colors.HexColor("#40516B")),
|
||||
("INNERGRID", (0, 0), (-1, -1), 0.4, colors.HexColor("#40516B")),
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 13), ("RIGHTPADDING", (0, 0), (-1, -1), 13),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 11), ("BOTTOMPADDING", (0, 0), (-1, -1), 12),
|
||||
])),
|
||||
Spacer(1, 0.7 * cm),
|
||||
Paragraph("Consolidação das discussões técnicas e comerciais - setembro de 2026", styles["cover_text"]),
|
||||
]
|
||||
cover_table = Table([[cover]], colWidths=[17.7 * cm], rowHeights=[23.6 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, -1), NAVY),
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 1.15 * cm),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 1.15 * cm),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 1.05 * cm),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 1.05 * cm),
|
||||
]))
|
||||
story.append(cover_table)
|
||||
story.append(PageBreak())
|
||||
|
||||
# Context
|
||||
story += section_title("O problema que vamos resolver", styles, "Contexto")
|
||||
story.append(paragraph(
|
||||
"A sala de DTF tem capacidade instalada muito maior que a produção atual. O gargalo não é a máquina: é o fluxo entre o pedido, a arte, o designer e a sala. Hoje o cliente envia arquivo no WhatsApp, o atendimento repassa, o designer descobre problemas tarde e o status fica escondido em pastas de rede.",
|
||||
styles["body"]))
|
||||
story.append(paragraph("O projeto resolve quatro falhas do processo:", styles["dtf_h2"]))
|
||||
for item in [
|
||||
"<b>Recebimento limitado pelo horário:</b> um cliente que chega no fim do dia espera até o turno seguinte.",
|
||||
"<b>Arquivo sem rastreabilidade:</b> WhatsApp e nomes digitados manualmente facilitam perda e erro.",
|
||||
"<b>Arquivo ruim chega tarde ao designer:</b> qualidade, dimensão e transparência são verificadas depois de consumir tempo humano.",
|
||||
"<b>Produção sem números:</b> não há registro confiável de espera, velocidade real, fila ou retrabalho.",
|
||||
]:
|
||||
story.append(bullet(item, styles))
|
||||
story.append(Spacer(1, 7))
|
||||
decision = Table([
|
||||
[paragraph("ANTES", styles["cell_bold"]), paragraph("DEPOIS", styles["cell_bold"])],
|
||||
[paragraph("Pedido e arte circulam por WhatsApp e pastas.", styles["cell"]), paragraph("Site DTF recebe a arte, analisa, precifica e registra o fluxo.", styles["cell"])],
|
||||
[paragraph("Designer corrige indiscriminadamente.", styles["cell"]), paragraph("Arte pronta segue rápido; exceções vão para atendimento humano.", styles["cell"])],
|
||||
[paragraph("Sala não enxerga fila real nem tempos.", styles["cell"]), paragraph("Kanban online organiza a fila e registra cada movimento manualmente.", styles["cell"])],
|
||||
], colWidths=[8.6 * cm, 8.6 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, 0), SKY), ("GRID", (0, 0), (-1, -1), 0.45, LINE),
|
||||
("VALIGN", (0, 0), (-1, -1), "TOP"), ("LEFTPADDING", (0, 0), (-1, -1), 9),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 9), ("TOPPADDING", (0, 0), (-1, -1), 8),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
|
||||
]))
|
||||
story.append(decision)
|
||||
story.append(PageBreak())
|
||||
|
||||
# Flow
|
||||
story += section_title("Como será a jornada do pedido", styles, "Modelo operacional")
|
||||
steps = [
|
||||
("1", "Cliente entra no site DTF", "Escolhe o produto, envia a arte e vê o valor conforme as regras comerciais já configuradas."),
|
||||
("2", "Sistema registra a arte", "Calcula a metragem e prepara o pedido. O pré-flight automático será validado depois da entrega, com arquivos reais."),
|
||||
("3", "Cliente paga", "O checkout é do Mercado Pago; os dados do cartão não passam pelo nosso servidor."),
|
||||
("4", "Pedido entra no sistema", "Depois da confirmação do pagamento, o pedido é criado no Tiny e aparece no Kanban."),
|
||||
("5", "Equipe baixa e imprime", "O operador baixa o arquivo final no Kanban, importa no FlexiPRINT e atualiza o card."),
|
||||
]
|
||||
rows = []
|
||||
for n, title, text in steps:
|
||||
rows.append([
|
||||
paragraph(n, ParagraphStyle("num" + n, parent=styles["cell_bold"], fontSize=13, textColor=ORANGE, alignment=TA_CENTER)),
|
||||
paragraph(title, styles["cell_bold"]),
|
||||
paragraph(text, styles["cell"]),
|
||||
])
|
||||
story.append(Table(rows, colWidths=[1.0 * cm, 5.3 * cm, 10.9 * cm], style=TableStyle([
|
||||
("GRID", (0, 0), (-1, -1), 0.45, LINE), ("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
|
||||
("BACKGROUND", (0, 0), (0, -1), PALE), ("LEFTPADDING", (0, 0), (-1, -1), 9),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 9), ("TOPPADDING", (0, 0), (-1, -1), 10),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 10),
|
||||
])))
|
||||
story.append(Spacer(1, 15))
|
||||
story.append(paragraph("Onde o WhatsApp entra", styles["dtf_h2"]))
|
||||
story.append(paragraph(
|
||||
"O WhatsApp deixa de ser o lugar onde a arte é enviada. Ele serve para avisar o cliente: pagamento aprovado, pedido em produção, pedido pronto ou necessidade de correção. Quando houver problema, a mensagem leva o cliente de volta para o site.", styles["body"]))
|
||||
story.append(paragraph(
|
||||
"<b>Cuidados na automação:</b> se Mercado Pago, Tiny ou WhatsApp reenviar um aviso por falha, o sistema confere antes de agir. Assim, não cria dois pedidos nem manda a mesma mensagem duas vezes.", styles["note"]))
|
||||
story.append(PageBreak())
|
||||
|
||||
# Architecture
|
||||
story += section_title("Arquitetura de software e infraestrutura", styles, "Produção")
|
||||
story.append(paragraph(
|
||||
"Todo o sistema roda na nuvem: recebe, processa, integra e disponibiliza o arquivo final. A fábrica acessa o Kanban pelo navegador e baixa o arquivo quando for produzir; não há componente instalado na rede interna.", styles["body"]))
|
||||
story.append(ArchitectureDiagram())
|
||||
story.append(Spacer(1, 12))
|
||||
columns = [
|
||||
[paragraph("NUVEM", styles["cell_bold"]), paragraph("Site DTF, Kanban online, API FastAPI, worker, ClamAV, PostgreSQL e Cloudflare R2.", styles["cell"])],
|
||||
[paragraph("FÁBRICA", styles["cell_bold"]), paragraph("Navegador, operador e FlexiPRINT atual. O arquivo é baixado e importado manualmente.", styles["cell"])],
|
||||
[paragraph("TERCEIROS", styles["cell_bold"]), paragraph("Mercado Pago, Tiny/Olist e WhatsApp Business API.", styles["cell"])],
|
||||
]
|
||||
story.append(Table(columns, colWidths=[3.0 * cm, 14.2 * cm], style=TableStyle([
|
||||
("GRID", (0, 0), (-1, -1), 0.45, LINE), ("VALIGN", (0, 0), (-1, -1), "TOP"),
|
||||
("BACKGROUND", (0, 0), (0, -1), SKY), ("LEFTPADDING", (0, 0), (-1, -1), 8),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 8), ("TOPPADDING", (0, 0), (-1, -1), 8),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
|
||||
])))
|
||||
story.append(Spacer(1, 10))
|
||||
for item in [
|
||||
"<b>Upload grande:</b> o navegador manda o arquivo direto para o R2, em partes. O VPS não precisa receber 5 GB de uma vez.",
|
||||
"<b>Fila:</b> o banco guarda o que precisa ser analisado, enviado ao Tiny, avisado no WhatsApp ou apagado no prazo certo.",
|
||||
"<b>Segurança:</b> o arquivo entra em quarentena, passa pelo antivírus e só depois é analisado e liberado no Kanban.",
|
||||
"<b>Se a fábrica ficar sem internet:</b> o site continua no ar. A equipe apenas não consegue baixar arquivo novo ou atualizar o Kanban até a conexão voltar.",
|
||||
]:
|
||||
story.append(bullet(item, styles))
|
||||
story.append(PageBreak())
|
||||
|
||||
# Storage/costs
|
||||
story += section_title("R2: custos e retenção", styles, "Cloudflare")
|
||||
story.append(paragraph(
|
||||
"O R2 é onde os arquivos ficam guardados. Ele é privado: o operador só baixa pelo Kanban, com link temporário. O custo vem principalmente da média de GB guardados no mês; leitura e gravação costumam pesar bem menos. O download não tem cobrança de saída de dados.", styles["body"]))
|
||||
cost = [
|
||||
[paragraph("MÉDIA ARMAZENADA", styles["cell_white"]), paragraph("R2 / MÊS", styles["cell_white"]), paragraph("APROX. EM R$*", styles["cell_white"])],
|
||||
[paragraph("100 GB", styles["cell"]), paragraph("US$ 1,35", styles["cell"]), paragraph("R$ 7", styles["cell"])],
|
||||
[paragraph("500 GB", styles["cell"]), paragraph("US$ 7,35", styles["cell"]), paragraph("R$ 38", styles["cell"])],
|
||||
[paragraph("1 TB", styles["cell"]), paragraph("US$ 14,85", styles["cell"]), paragraph("R$ 76", styles["cell"])],
|
||||
[paragraph("3 TB", styles["cell"]), paragraph("US$ 44,85", styles["cell"]), paragraph("R$ 230", styles["cell"])],
|
||||
]
|
||||
story.append(Table(cost, colWidths=[6.0 * cm, 5.2 * cm, 6.0 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, 0), NAVY), ("TEXTCOLOR", (0, 0), (-1, 0), WHITE),
|
||||
("GRID", (0, 0), (-1, -1), 0.45, LINE), ("ALIGN", (1, 0), (-1, -1), "RIGHT"),
|
||||
("VALIGN", (0, 0), (-1, -1), "MIDDLE"), ("LEFTPADDING", (0, 0), (-1, -1), 9),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 9), ("TOPPADDING", (0, 0), (-1, -1), 8),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
|
||||
])))
|
||||
story.append(Spacer(1, 5))
|
||||
story.append(paragraph("* Referência de US$ 1 = R$ 5,13; câmbio, impostos e tarifas do meio de pagamento podem variar.", styles["small"]))
|
||||
story.append(Spacer(1, 10))
|
||||
retention = [
|
||||
[paragraph("ARTEFATO", styles["cell_bold"]), paragraph("PRAZO", styles["cell_bold"]), paragraph("REGRA", styles["cell_bold"])],
|
||||
[paragraph("Upload multipart incompleto", styles["cell"]), paragraph("1 dia", styles["cell"]), paragraph("Abortado automaticamente.", styles["cell"])],
|
||||
[paragraph("Recusado ou infectado", styles["cell"]), paragraph("3 dias", styles["cell"]), paragraph("Suporte pode conferir; depois apaga.", styles["cell"])],
|
||||
[paragraph("Original do cliente", styles["cell"]), paragraph("até 7 dias", styles["cell"]), paragraph("Após aprovação, não fica guardado sem necessidade.", styles["cell"])],
|
||||
[paragraph("Arte pronta para impressão", styles["cell"]), paragraph("máx. 30 dias", styles["cell"]), paragraph("Prazo conta do primeiro upload; permite correção ou reimpressão recente.", styles["cell"])],
|
||||
[paragraph("Histórico e métricas", styles["cell"]), paragraph("banco", styles["cell"]), paragraph("Sem manter a imagem.", styles["cell"])],
|
||||
]
|
||||
story.append(Table(retention, colWidths=[5.2 * cm, 2.8 * cm, 9.2 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, 0), SKY), ("GRID", (0, 0), (-1, -1), 0.45, LINE),
|
||||
("VALIGN", (0, 0), (-1, -1), "TOP"), ("LEFTPADDING", (0, 0), (-1, -1), 8),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 8), ("TOPPADDING", (0, 0), (-1, -1), 7),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 7),
|
||||
])))
|
||||
story.append(Spacer(1, 9))
|
||||
story.append(paragraph("Decisão: não haverá biblioteca infinita de artes. Após o prazo, o cliente reenvia o arquivo; o pedido e sua rastreabilidade permanecem registrados.", styles["note"]))
|
||||
story.append(PageBreak())
|
||||
|
||||
# Production / CI CD
|
||||
story += section_title("Como fica em produção", styles, "Operação, publicação e continuidade")
|
||||
story.append(paragraph(
|
||||
"A primeira entrega será operada como uma única aplicação na VPS. Portal, Kanban, processamento e banco seguem o mesmo ciclo de publicação, com acesso da fábrica exclusivamente pelo navegador. Isso reduz pontos de manutenção e mantém a operação independente da rede interna.", styles["body"]))
|
||||
stacks = [
|
||||
[paragraph("AMBIENTE", styles["cell_white"]), paragraph("COMPONENTES", styles["cell_white"]), paragraph("OPERAÇÃO", styles["cell_white"])],
|
||||
[paragraph("Sistema DTF", styles["cell_bold"]), paragraph("site DTF, Kanban online, API, processamento, antivírus, banco de dados e cópia diária de segurança", styles["cell"]), paragraph("VPS com armazenamento persistente; operação e acompanhamento centralizados", styles["cell"])],
|
||||
]
|
||||
story.append(Table(stacks, colWidths=[3.7 * cm, 9.1 * cm, 4.4 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, 0), NAVY), ("TEXTCOLOR", (0, 0), (-1, 0), WHITE),
|
||||
("GRID", (0, 0), (-1, -1), 0.45, LINE), ("VALIGN", (0, 0), (-1, -1), "TOP"),
|
||||
("LEFTPADDING", (0, 0), (-1, -1), 8), ("RIGHTPADDING", (0, 0), (-1, -1), 8),
|
||||
("TOPPADDING", (0, 0), (-1, -1), 8), ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
|
||||
])))
|
||||
story.append(Spacer(1, 13))
|
||||
story.append(paragraph("Publicação com controle", styles["dtf_h2"]))
|
||||
for item in [
|
||||
"Toda alteração passa por testes automáticos antes de poder chegar ao ambiente de produção.",
|
||||
"Cada publicação fica identificada pela versão do código, permitindo restaurar rapidamente a versão anterior se houver qualquer problema.",
|
||||
"As mudanças são conferidas primeiro em ambiente de validação e só então liberadas para a operação.",
|
||||
"Ao final da publicação, uma verificação confirma que os serviços essenciais voltaram a responder antes de encerrar o processo.",
|
||||
"Credenciais de storage, pagamentos, integrações e banco permanecem fora do código e são tratadas como dados restritos do ambiente.",
|
||||
]:
|
||||
story.append(bullet(item, styles))
|
||||
story.append(Spacer(1, 9))
|
||||
story.append(paragraph("Acompanhamento operacional", styles["dtf_h2"]))
|
||||
story.append(Spacer(1, 5))
|
||||
story.append(paragraph(
|
||||
"A rotina de operação acompanha disponibilidade do site e do Kanban, andamento da fila de processamento, falhas de integração e resultado das cópias de segurança. Assim, qualquer desvio é identificado antes de interromper o atendimento ou a produção.", styles["note"]))
|
||||
story.append(PageBreak())
|
||||
|
||||
# Roadmap
|
||||
story += section_title("Roadmap de implementação", styles, "MVP em até 3 semanas")
|
||||
story.append(paragraph("O cronograma considera a base de código existente e dedicação integral. A prioridade é concluir o fluxo completo - envio, pagamento, frete, pedido e acompanhamento - antes de qualquer integração com as máquinas. As regras comerciais seguem exatamente o que já está configurado no Site DTF.", styles["body"]))
|
||||
roadmap = [
|
||||
[paragraph("QUANDO", styles["cell_white"]), paragraph("ENTREGA", styles["cell_white"]), paragraph("RESULTADO", styles["cell_white"])],
|
||||
[paragraph("Sem. 1", styles["cell_bold"]), paragraph("Infraestrutura e upload", styles["cell"]), paragraph("VPS, domínio, banco, R2, upload multipart, antivírus e base do serviço.", styles["cell"])],
|
||||
[paragraph("Sem. 2", styles["cell_bold"]), paragraph("Pagamento, frete e pedido", styles["cell"]), paragraph("Mercado Pago, cotação de frete, criação idempotente no Tiny, geração do arquivo final e estados principais do Kanban.", styles["cell"])],
|
||||
[paragraph("Sem. 3", styles["cell_bold"]), paragraph("Kanban e entrega", styles["cell"]), paragraph("Kanban online, download seguro, mensagens de status no WhatsApp, retenção de 30 dias e orientação à operação.", styles["cell"])],
|
||||
]
|
||||
story.append(Table(roadmap, colWidths=[2.1 * cm, 5.0 * cm, 10.1 * cm], style=TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, 0), NAVY), ("TEXTCOLOR", (0, 0), (-1, 0), WHITE),
|
||||
("GRID", (0, 0), (-1, -1), 0.45, LINE), ("VALIGN", (0, 0), (-1, -1), "TOP"),
|
||||
("BACKGROUND", (0, 1), (0, -1), PALE), ("LEFTPADDING", (0, 0), (-1, -1), 8),
|
||||
("RIGHTPADDING", (0, 0), (-1, -1), 8), ("TOPPADDING", (0, 0), (-1, -1), 8),
|
||||
("BOTTOMPADDING", (0, 0), (-1, -1), 8),
|
||||
])))
|
||||
story.append(Spacer(1, 14))
|
||||
story.append(paragraph("Fora da primeira entrega", styles["dtf_h2"]))
|
||||
story.append(Spacer(1, 5))
|
||||
story.append(paragraph("A primeira entrega termina no download do arquivo final pelo Kanban e na orientação de uso à operação. Integração direta com FlexiPRINT, agente dentro da fábrica, pasta monitorada, painel de sala e relatórios avançados não fazem parte deste prazo. O pré-flight automático será validado depois da entrega, com arquivos e impressão reais. A fábrica mantém esses recursos no ambiente atual; após a entrega, damos suporte e avaliamos mudanças conforme a necessidade.", styles["note"]))
|
||||
story.append(Spacer(1, 10))
|
||||
story.append(paragraph("O que fica com a operação", styles["dtf_h2"]))
|
||||
for item in [
|
||||
"Acessar o Kanban, baixar o arquivo final e importá-lo manualmente no FlexiPRINT atual.",
|
||||
"Realizar os testes de impressão e informar qualquer diferença encontrada no arquivo ou no resultado impresso.",
|
||||
"Manter computadores, FlexiPRINT, perfis de impressão, impressoras e eventuais pastas internas funcionando.",
|
||||
"A conexão local é necessária apenas para a equipe acessar o Kanban e baixar o arquivo na fábrica. Se ela cair, portal, pagamentos, uploads e fila continuam ativos na nuvem; a produção retoma quando o acesso local voltar.",
|
||||
"Comunicar mudanças de preços, frete ou regras operacionais que precisem ser refletidas no sistema.",
|
||||
]:
|
||||
story.append(bullet(item, styles))
|
||||
story.append(Spacer(1, 7))
|
||||
story.append(paragraph("O que precisamos para começar", styles["dtf_h2"]))
|
||||
for item in [
|
||||
"Credenciais do Mercado Pago, incluindo a configuração do webhook para confirmação de pagamento.",
|
||||
"Dados da integração de frete: plataforma(s) já utilizada(s), acesso à API, CEP de origem, serviços oferecidos, regra de cobrança e referência de peso e dimensões por pacote.",
|
||||
]:
|
||||
story.append(bullet(item, styles))
|
||||
story.append(Spacer(1, 7))
|
||||
story.append(paragraph("Antes de começar", styles["dtf_h2"]))
|
||||
story.append(Spacer(1, 5))
|
||||
story.append(paragraph("Com esses acessos e dados liberados, a primeira semana pode começar. A tabela, os descontos e as regras comerciais já existentes no Site DTF serão mantidos. Tiny/Olist e WhatsApp já estão disponíveis; durante o desenvolvimento será definida a ligação técnica dessas integrações com os eventos do pedido. A fábrica valida a impressão depois, baixando o arquivo final pelo Kanban.", styles["note"]))
|
||||
|
||||
doc.build(story)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
build_pdf()
|
||||
print(OUT)
|
||||
BIN
tmp/pdfs/rendered-arrowfix/page-4.png
Normal file
|
After Width: | Height: | Size: 191 KiB |
BIN
tmp/pdfs/rendered-arrowfix/page-7.png
Normal file
|
After Width: | Height: | Size: 201 KiB |
BIN
tmp/pdfs/rendered-dbfix/page-4.png
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
tmp/pdfs/rendered-final/page-4.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
tmp/pdfs/rendered-human/page-1.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
tmp/pdfs/rendered-human/page-2.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
tmp/pdfs/rendered-human/page-3.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
tmp/pdfs/rendered-human/page-4.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
tmp/pdfs/rendered-human/page-5.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
tmp/pdfs/rendered-human/page-6.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
tmp/pdfs/rendered-human/page-7.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
BIN
tmp/pdfs/rendered-human2/page-1.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
tmp/pdfs/rendered-human2/page-2.png
Normal file
|
After Width: | Height: | Size: 139 KiB |
BIN
tmp/pdfs/rendered-human2/page-3.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
tmp/pdfs/rendered-human2/page-4.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
tmp/pdfs/rendered-human2/page-5.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
tmp/pdfs/rendered-human2/page-6.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
tmp/pdfs/rendered-human2/page-7.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
BIN
tmp/pdfs/rendered-level1/page-1.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
tmp/pdfs/rendered-level1/page-2.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
tmp/pdfs/rendered-level1/page-3.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
tmp/pdfs/rendered-level1/page-4.png
Normal file
|
After Width: | Height: | Size: 191 KiB |
BIN
tmp/pdfs/rendered-level1/page-5.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
tmp/pdfs/rendered-level1/page-6.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
tmp/pdfs/rendered-level1/page-7.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
tmp/pdfs/rendered-professional-final/page-5.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
tmp/pdfs/rendered-professional-final/page-6.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
tmp/pdfs/rendered-professional-final/page-7.png
Normal file
|
After Width: | Height: | Size: 217 KiB |
BIN
tmp/pdfs/rendered-professional/page-1.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
tmp/pdfs/rendered-professional/page-2.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
tmp/pdfs/rendered-professional/page-3.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
tmp/pdfs/rendered-professional/page-4.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
tmp/pdfs/rendered-professional/page-5.png
Normal file
|
After Width: | Height: | Size: 143 KiB |
BIN
tmp/pdfs/rendered-professional/page-6.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
tmp/pdfs/rendered-professional/page-7.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
tmp/pdfs/rendered-targeted/page-4.png
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
tmp/pdfs/rendered-targeted/page-7.png
Normal file
|
After Width: | Height: | Size: 201 KiB |
BIN
tmp/pdfs/rendered/freight-prereqs-7.png
Normal file
|
After Width: | Height: | Size: 299 KiB |
BIN
tmp/pdfs/rendered/journey-after-preflight-3.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
tmp/pdfs/rendered/local-internet-clarified-7.png
Normal file
|
After Width: | Height: | Size: 278 KiB |
BIN
tmp/pdfs/rendered/operation-responsibilities-7.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
tmp/pdfs/rendered/page-1.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
tmp/pdfs/rendered/page-2.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
tmp/pdfs/rendered/page-3.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
tmp/pdfs/rendered/page-4.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
tmp/pdfs/rendered/page-5.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
tmp/pdfs/rendered/page-6.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
tmp/pdfs/rendered/page-7.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
tmp/pdfs/rendered/problem-title-2.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
tmp/pdfs/rendered/production-6.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
tmp/pdfs/rendered/production-final-6.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
tmp/pdfs/rendered/production-spacing-6.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
tmp/pdfs/rendered/start-dependencies-7.png
Normal file
|
After Width: | Height: | Size: 194 KiB |
BIN
tmp/pdfs/rendered/three-week-final-7.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
tmp/pdfs/rendered/whatsapp-available-7.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
141
tmp/pdfs/reuniao.txt
Normal file
@@ -0,0 +1,141 @@
|
||||
set. 9, 2026
|
||||
|
||||
|
||||
|
||||
Reunião em 9 de set. de 2026
|
||||
às 09:39 GMT-03:00
|
||||
Registros da reunião Gravação
|
||||
|
||||
|
||||
|
||||
|
||||
Resumo
|
||||
Reunião de planejamento com foco na automação de processos via portal
|
||||
dedicado e melhoria produtiva.
|
||||
|
||||
Automacao do DTF e Checkout
|
||||
Portal automatizado reconhece arquivos e valida parâmetros. Checkout via
|
||||
Mercado Pago aprova pedidos automaticamente.
|
||||
|
||||
Gestao de Pedidos e Precos
|
||||
Sistema Kanban organiza fluxo de trabalho e rastreabilidade. Clientes com arquivos
|
||||
prontos recebem 20 porcento de desconto.
|
||||
|
||||
Priorizacao e Viabilidade Tecnica
|
||||
Projeto DTF ganha prioridade sobre o PCP para ganhos rápidos. Servidor externo e
|
||||
FTP suportam uploads pesados.
|
||||
|
||||
|
||||
|
||||
|
||||
Decisões
|
||||
Precisa de mais conversa
|
||||
● Definição de solução para arquivos pesados Ficou pendente de estudo
|
||||
técnico a viabilidade de envio de arquivos grandes para evitar problemas no
|
||||
navegador.
|
||||
Alinhada
|
||||
● Estruturação de portal e subdomínio DTF Ficou alinhada a criação de um
|
||||
novo subdomínio dedicado ao DTF com checkout transparente e fila de
|
||||
impressão.
|
||||
|
||||
● Priorização do projeto DTF sobre PCP Ficou acordado pausar o PCP e
|
||||
definir o desenvolvimento do módulo DTF como prioridade máxima.
|
||||
|
||||
|
||||
|
||||
|
||||
Próximas etapas
|
||||
[Marcus Fernandes] Enviar referencias: Enviar para Jorge e Cauê os links de
|
||||
referência do site para o novo módulo DTF.
|
||||
[Jorge Faleiros, Cauê Faleiros] Criar roadmap: Estruturar o plano de
|
||||
desenvolvimento do sistema após analisar os requisitos e gargalos técnicos.
|
||||
[Jorge Faleiros, Cauê Faleiros] Estudar infraestrutura: Avaliar custos de
|
||||
hospedagem e soluções técnicas para viabilizar o upload de arquivos
|
||||
grandes no servidor externo.
|
||||
|
||||
|
||||
|
||||
|
||||
Detalhes
|
||||
● Problema de Processo no DTF e Solução Proposta: Marcus Fernandes
|
||||
identifica um gargalo na produção de DTF (Direct to Film), onde designers
|
||||
perdem tempo corrigindo arquivos mal formatados ou despadronizados
|
||||
enviados pelos clientes. A solução proposta consiste em criar um portal
|
||||
automatizado que reconhece os arquivos, verifica parâmetros de qualidade
|
||||
e metragem, e cria filas de impressão automaticamente, evitando a
|
||||
dependência constante do atendimento manual e permitindo a
|
||||
escalabilidade do negócio.
|
||||
|
||||
● Arquitetura do Sistema e Servidor Externo: Para garantir a continuidade
|
||||
da operação mesmo em casos de falhas de energia ou conexão local, a
|
||||
equipe planeja utilizar um servidor externo para o recebimento inicial dos
|
||||
arquivos. O sistema deve conectar-se tanto a servidores internos quanto
|
||||
externos, com um painel de identificação para monitorar a movimentação
|
||||
dos arquivos, integrando-se aos processos já existentes.
|
||||
● Automação do Pagamento e Checkout: O processo atual de aprovação
|
||||
manual de pagamentos impede que a sala de impressão opere 24 horas por
|
||||
dia. Marcus Fernandes propõe a criação de um novo domínio exclusivo para
|
||||
o módulo DTF, utilizando um sistema de checkout transparente via Mercado
|
||||
Pago, o que permitirá a aprovação automática dos pedidos e a liberação
|
||||
imediata para a fila de produção.
|
||||
|
||||
● Gestão de Pedidos e Integração com Kanban: O fluxo de trabalho será
|
||||
gerido por meio de um sistema Kanban para evitar a perda de arquivos e
|
||||
garantir uma ordem de chegada linear, resolvendo o problema de pedidos
|
||||
esquecidos. Este sistema deve se integrar com o Tine para gerar tags nos
|
||||
pedidos, utilizar o número do pedido para rastreabilidade na expedição e
|
||||
calcular correios ou transportadoras para o cliente.
|
||||
|
||||
● Interface do Site e Estrutura de Preços: O site contará com uma interface
|
||||
intuitiva onde os clientes poderão fazer upload de arquivos e receber
|
||||
feedback imediato sobre a qualidade. Será implementado um modelo de
|
||||
precificação diferenciado: clientes que enviarem arquivos prontos e dentro
|
||||
dos parâmetros ideais receberão um desconto de 20%, enquanto aqueles
|
||||
que exigirem suporte de design pagarão um valor maior, incentivando o
|
||||
envio de arquivos de qualidade.
|
||||
|
||||
● Fluxo de Trabalho do Design: Mesmo com a automação, os designers
|
||||
continuarão a realizar um trabalho ativo, ajudando clientes que possuem
|
||||
dificuldades, mas com uma carga de trabalho mais otimizada. Os designers
|
||||
utilizarão pastas específicas no servidor interno para tratar os arquivos,
|
||||
garantindo que o fluxo de conversão (por exemplo, para PDF) seja
|
||||
padronizado antes da impressão.
|
||||
|
||||
● Segmentação de Clientes e Proposta de Valor: Marcus Fernandes
|
||||
enfatiza a necessidade de distinguir entre clientes que enviam artes prontas
|
||||
e clientes que precisam de auxílio, evitando que a empresa perca margem ou
|
||||
produtividade ao misturar ambos os perfis. A automação visa permitir que a
|
||||
equipe foque o trabalho de design onde ele é realmente necessário,
|
||||
aumentando a capacidade produtiva de 10.000 para 25.000 metros
|
||||
mensais.
|
||||
|
||||
● Viabilidade Técnica e Dashboard de Produção: A equipe discute a
|
||||
viabilidade técnica de criar um painel (dashboard) para a sala de impressão,
|
||||
que exibirá dados das máquinas, metragem produzida e retrabalhos,
|
||||
conectando-se ao software de impressão (Flexprint). Cauê Faleiros e Jorge
|
||||
Faleiros validam que o projeto é executável, dependendo apenas da
|
||||
verificação das capacidades da API do sistema Tine.
|
||||
● Priorização do Projeto DTF sobre o PCP: Marcus Fernandes propõe pausar
|
||||
parcialmente o projeto de PCP (Planejamento e Controle da Produção) para
|
||||
priorizar a implementação do módulo DTF, visto que este último possui um
|
||||
escopo mais definido, um ciclo de entrega claro e promete ganhos
|
||||
imediatos de produtividade e redução de pessoal.
|
||||
|
||||
● Desafios Técnicos e Próximos Passos: Jorge Faleiros levanta
|
||||
preocupações sobre o upload de arquivos pesados (que podem chegar a 5
|
||||
GB) via navegador, sugerindo a necessidade de estudar soluções
|
||||
alternativas como FTP. Como próximos passos, Jorge Faleiros e Cauê
|
||||
Faleiros definirão um roadmap, avaliarão custos de hospedagem e a
|
||||
infraestrutura necessária para suportar os uploads, enquanto Marcus
|
||||
Fernandes enviará sites de referência para análise da lógica de
|
||||
funcionamento.
|
||||
|
||||
|
||||
|
||||
|
||||
Revise as anotações do Gemini para checar se estão corretas. Confira dicas e saiba
|
||||
como o Gemini faz anotações
|
||||
Como está a qualidade de destas observações? Responda a uma breve pesquisa
|
||||
para nos dar seu feedback, incluindo o quanto as observações foram úteis para o
|
||||
que você precisa.
|
||||
|
||||
BIN
tmp/pdfs/roadmap-review-1.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
tmp/pdfs/roadmap-review-2.png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
tmp/pdfs/roadmap-review-3.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
tmp/pdfs/roadmap-review-4.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
tmp/pdfs/roadmap-review-5.png
Normal file
|
After Width: | Height: | Size: 99 KiB |
BIN
tmp/pdfs/roadmap-review-6.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
tmp/pdfs/roadmap-review-7.png
Normal file
|
After Width: | Height: | Size: 206 KiB |