205 lines
8.0 KiB
Python
205 lines
8.0 KiB
Python
from pathlib import Path
|
|
|
|
from reportlab.lib.colors import HexColor
|
|
from reportlab.lib.enums import TA_LEFT
|
|
from reportlab.lib.pagesizes import LETTER
|
|
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
|
|
from reportlab.lib.units import inch
|
|
from reportlab.platypus import (
|
|
BaseDocTemplate,
|
|
Frame,
|
|
PageBreak,
|
|
PageTemplate,
|
|
Paragraph,
|
|
Spacer,
|
|
)
|
|
|
|
|
|
OUTPUT = Path("output/pdf/resumo-alteracoes-ultimas-duas-semanas.pdf")
|
|
|
|
BLUE = HexColor("#2E75B6")
|
|
NAVY = HexColor("#1F4E79")
|
|
BLACK = HexColor("#000000")
|
|
GRAY = HexColor("#666666")
|
|
|
|
|
|
def footer(canvas, doc):
|
|
canvas.saveState()
|
|
canvas.setFont("Helvetica", 9)
|
|
canvas.setFillColor(GRAY)
|
|
canvas.drawRightString(7.45 * inch, 0.47 * inch, "Nexstar Graphs")
|
|
canvas.restoreState()
|
|
|
|
|
|
def make_styles():
|
|
styles = getSampleStyleSheet()
|
|
return {
|
|
"title": ParagraphStyle(
|
|
"SummaryTitle",
|
|
parent=styles["Normal"],
|
|
fontName="Helvetica-Bold",
|
|
fontSize=18,
|
|
leading=22,
|
|
textColor=BLACK,
|
|
spaceAfter=13,
|
|
alignment=TA_LEFT,
|
|
),
|
|
"overview": ParagraphStyle(
|
|
"Overview",
|
|
parent=styles["Normal"],
|
|
fontName="Helvetica-Bold",
|
|
fontSize=10,
|
|
leading=13.5,
|
|
textColor=NAVY,
|
|
spaceAfter=16,
|
|
),
|
|
"section": ParagraphStyle(
|
|
"Section",
|
|
parent=styles["Normal"],
|
|
fontName="Helvetica-Bold",
|
|
fontSize=14.2,
|
|
leading=17.4,
|
|
textColor=BLUE,
|
|
spaceBefore=1,
|
|
spaceAfter=7,
|
|
),
|
|
"bullet": ParagraphStyle(
|
|
"Bullet",
|
|
parent=styles["Normal"],
|
|
fontName="Helvetica",
|
|
fontSize=9.8,
|
|
leading=13.1,
|
|
textColor=BLACK,
|
|
leftIndent=19,
|
|
firstLineIndent=-12,
|
|
spaceAfter=1.8,
|
|
),
|
|
}
|
|
|
|
|
|
def bullet(text, styles):
|
|
return Paragraph(f"• {text}", styles["bullet"])
|
|
|
|
|
|
def section(title, items, styles):
|
|
flowables = [Paragraph(title, styles["section"])]
|
|
flowables.extend(bullet(item, styles) for item in items)
|
|
flowables.append(Spacer(1, 8))
|
|
return flowables
|
|
|
|
|
|
def main():
|
|
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
|
|
document = BaseDocTemplate(
|
|
str(OUTPUT),
|
|
pagesize=LETTER,
|
|
leftMargin=0.96 * inch,
|
|
rightMargin=0.84 * inch,
|
|
topMargin=1.08 * inch,
|
|
bottomMargin=0.75 * inch,
|
|
title="Resumo de Alterações - Nexstar Graphs",
|
|
author="Nexstar Graphs",
|
|
)
|
|
frame = Frame(
|
|
document.leftMargin,
|
|
document.bottomMargin,
|
|
document.width,
|
|
document.height,
|
|
id="content",
|
|
)
|
|
document.addPageTemplates([PageTemplate(id="main", frames=[frame], onPage=footer)])
|
|
|
|
styles = make_styles()
|
|
story = [
|
|
Paragraph("RESUMO DE ALTERAÇÕES", styles["title"]),
|
|
Paragraph(
|
|
"Visão geral: nas últimas duas semanas, o Graphs evoluiu a integração com a Olist, "
|
|
"o planejamento de corte, a gestão de ordens de produção, suprimentos e a experiência operacional.",
|
|
styles["overview"],
|
|
),
|
|
]
|
|
|
|
story.extend(
|
|
section(
|
|
"Integração Olist e dados de produção",
|
|
[
|
|
"Implementada conexão OAuth nativa com a API V3 da Olist, com armazenamento seguro de token, renovação automática e reconexão pela tela de monitoramento.",
|
|
"Criada sincronização de produtos fabricados e composições, com atualização incremental, retomada após reinício e limite de requisições compatível com a operação.",
|
|
"Adicionado agendamento diário às 11h, com exibição da próxima execução, progresso, duração, histórico, logs por produto e falhas na tela Olist.",
|
|
"Incluídos controles para parar e continuar a sincronização e importação de OPs finalizadas por CSV, com deduplicação em reimportações.",
|
|
"As observações das OPs agora fornecem fornecedor, lote, bobinas, quilos de malha e ribana e rendimento; as pendências podem ser exportadas pela tela Olist.",
|
|
],
|
|
styles,
|
|
)
|
|
)
|
|
story.extend(
|
|
section(
|
|
"Plano de corte e rendimentos",
|
|
[
|
|
"Reorganizada a tela de Plano de Corte para priorizar produto, necessidade de corte, demanda, disponível e situação operacional, sem repetir indicadores.",
|
|
"Incluídas edição contextual por SKU, visualização de produto e paginação no plano e na prévia de OPs.",
|
|
"Centralizada a configuração de corte e simplificado o preenchimento de rendimentos por família.",
|
|
"Corrigida a taxonomia: BLCS, BLOS, BLMC, BLPM e BLRM representam camiseta regular, oversize, moletom, pima e regata.",
|
|
"Importado histórico de OPs finalizadas para sugerir rendimento por família e, quando disponível, por fornecedor de tecido.",
|
|
],
|
|
styles,
|
|
)
|
|
)
|
|
story.extend(
|
|
section(
|
|
"Ordens de produção",
|
|
[
|
|
"Melhorada a prévia das OPs com paginação e seleção de itens individuais, página atual, todos os elegíveis ou somente itens com dados completos.",
|
|
"Reestruturada a página de Ordens de Produção para usar detalhes expansíveis na tabela, evitando painel lateral e duplicidade de controles.",
|
|
"Transformado o status em um menu compacto com opções claras para Em aberto, Em andamento, Finalizada e Cancelada.",
|
|
"Adicionada ação para devolver uma OP local em aberto ao Plano de Corte, preservando o histórico e devolvendo a necessidade ao planejamento.",
|
|
],
|
|
styles,
|
|
)
|
|
)
|
|
|
|
story.append(PageBreak())
|
|
story.extend(
|
|
section(
|
|
"Suprimentos, compras e estoque",
|
|
[
|
|
"Redesenhado o hub de Suprimentos para seguir o fluxo Necessidade de Compra, Plano de Corte e Ordens de Produção, com foco nas próximas ações.",
|
|
"Simplificado o fluxo de Necessidade de Compra: removida a área de mapeamento separada e incluída edição direta dos materiais por ícone.",
|
|
"Materiais sem saldo, com saldo negativo ou com necessidade de serviço passaram a usar filtros e estados visuais consistentes entre abas.",
|
|
"Criado centro de exceções para saldos negativos, SKUs sem composição e cadastro para corte, mantendo essas filas informativas e auditáveis.",
|
|
"Aplicada regra de estoque disponível: saldo negativo vale zero para compras e corte, sem esconder o saldo original para auditoria.",
|
|
],
|
|
styles,
|
|
)
|
|
)
|
|
story.extend(
|
|
section(
|
|
"Cadastros e produtos",
|
|
[
|
|
"Adicionada paginação com 10 itens por padrão nas listas de Produtos, Categorias e Referências de Consumo.",
|
|
"Incluídas ações de edição para Categorias, Produtos e Referências de Consumo, aproximando Cadastros da página de Produtos.",
|
|
"Melhorados os detalhes de composição e a navegação entre variações de produto para tornar a consulta mais direta.",
|
|
"Criadas ações compactas por ícone para materiais, preservando a leitura das tabelas.",
|
|
],
|
|
styles,
|
|
)
|
|
)
|
|
story.extend(
|
|
section(
|
|
"Experiência e navegação",
|
|
[
|
|
"Padronizado o visual de Suprimentos, Corte e Produção com as tabelas, filtros, badges e paginação já usados em Produtos.",
|
|
"Ajustada a cor da família BLCS no Plano de Corte e removidos cartões-resumo redundantes de Vendedores.",
|
|
"Aprimorada a navegação para dispositivos menores e refinados os estados de carregamento nas páginas comerciais.",
|
|
],
|
|
styles,
|
|
)
|
|
)
|
|
|
|
document.build(story)
|
|
print(OUTPUT)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|