Ruptura_Projetada/relatório_cobertura/relatório_cobertura.py
2025-08-26 13:57:11 -03:00

213 lines
6.5 KiB
Python

# enviar_email_excel.py
import smtplib
import ssl
import pyodbc
import configparser
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mtick
import seaborn as sns
from email.message import EmailMessage
from email.utils import make_msgid
from email.mime.image import MIMEImage
from pathlib import Path
from datetime import datetime, time
config = configparser.ConfigParser()
config.read(r"credenciais.ini")
excel_path = Path("relatorio.xlsx")
print(config['banco']['host'],config['banco']['user'],config['banco']['password'])
# Conexão com o banco
conn = pyodbc.connect(
f"DRIVER={{SQL Server}};"
f"SERVER={config['banco']['host']},1433;"
f"DATABASE=GINSENG;"
f"UID={config['banco']['user']};"
f"PWD={config['banco']['password']}")
# 1. Criar dados fictícios e gerar Excel
query = '''
WITH CTE_Estoque AS (
SELECT
em.ORIGEM,
em.PDV,
CONCAT(em.PDV, em.ORIGEM) AS PDV_Origem, -- Coluna unificada
CASE
WHEN em.SKU_PARA IS NULL THEN em.SKU
ELSE em.SKU_PARA
END AS SKU_FINAL,
em.DESCRICAO,
em.CATEGORIA,
em.CLASSE,
CAST(REPLACE(em.[ESTOQUE ATUAL], ',', '.') AS FLOAT) AS [ESTOQUE ATUAL],
CAST(REPLACE(em.[ESTOQUE EM TRANSITO], ',', '.') AS FLOAT) AS [ESTOQUE EM TRANSITO],
CAST(REPLACE(em.[PEDIDO PENDENTE], ',', '.') AS FLOAT) AS [PEDIDO PENDENTE],
CAST(REPLACE(em.[DDV PREVISTO], ',', '.') AS FLOAT) AS [DDV PREVISTO],
ROUND(
CAST(REPLACE(em.[ESTOQUE ATUAL], ',', '.') AS FLOAT)
/ NULLIF(CAST(REPLACE(em.[DDV PREVISTO], ',', '.') AS FLOAT), 0), 0
) AS [Cobertura Atual],
ROUND(
(CAST(REPLACE(em.[ESTOQUE ATUAL], ',', '.') AS FLOAT)
+ CAST(REPLACE(em.[ESTOQUE EM TRANSITO], ',', '.') AS FLOAT)
+ CAST(REPLACE(em.[PEDIDO PENDENTE], ',', '.') AS FLOAT))
/ NULLIF(CAST(REPLACE(em.[DDV PREVISTO], ',', '.') AS FLOAT), 0), 0
) AS [Cobertura Projetada],
d.preco_Compra,
d.Dias_sem_Vendas,
pr.ATUAL_PROMO ,
pr.PROX_PROMO
FROM estoque_mar em
LEFT JOIN (
SELECT
d.loja_id AS PDV,
d.code AS SKU,
d.description AS Descricao,
d.pricesellin AS preco_Compra,
d.dayswithoutsales as Dias_sem_Vendas
FROM draft d) d ON em.PDV = d.PDV
AND (CASE WHEN em.SKU_PARA IS NULL THEN em.SKU ELSE em.SKU_PARA END) = CAST( d.SKU AS INT)
LEFT JOIN (
SELECT
p.loja_id AS PDV,
p.code AS SKU,
CASE
WHEN STRING_AGG(p.currentCycle_description, ', ') IS NULL OR LTRIM(RTRIM( STRING_AGG(p.currentCycle_description, ', '))) = ''
THEN 'Regular'
ELSE 'Promocao'
END AS ATUAL_PROMO,
CASE
WHEN STRING_AGG(p.nextCycle_description, ', ') IS NULL OR LTRIM(RTRIM(STRING_AGG(p.nextCycle_description, ', '))) = ''
THEN 'Regular'
ELSE 'Promocao'
END AS PROX_PROMO
FROM promo p
WHERE P.created_at >= CAST(GETDATE() AS DATE)
AND P.created_at < DATEADD(DAY, 1, CAST(GETDATE() AS DATE))
GROUP BY
p.loja_id,
p.code
) pr ON em.PDV = pr.PDV
AND (CASE WHEN em.SKU_PARA IS NULL THEN em.SKU ELSE em.SKU_PARA END) = CAST(pr.SKU AS INT)
WHERE em.CATEGORIA NOT IN ('SUPORTE À VENDA', 'EMBALAGENS')
)
SELECT
bpm.DESCRICAO AS DESCRICAO_PDV,
bpm.UF,
bpm.ANALISTA,
cte.*
FROM CTE_Estoque cte
LEFT JOIN base_pdvs_marca bpm
ON cte.PDV_Origem = bpm.PDV_MARCA -- agora join pelo unificado
WHERE [Cobertura Atual] > 60;
'''
df = pd.read_sql(query, conn)
df.to_excel(excel_path,index=False)
conn.close()
print(df.columns)
remetente = config['credenciais']['remetente']
senha = config['credenciais']['senha']
destinatarios = [email.strip() for email in config['email_cobertura']['destinatarios'].split(',')]
assunto = config['email_cobertura']['assunto']
print(remetente,senha,destinatarios,assunto)
# Obtém a hora atual
agora = datetime.now().time()
hoje = datetime.today().strftime("%d/%m/%Y")
# Define os intervalos de tempo
manhã_inicio = time(5, 0)
manhã_fim = time(12, 0)
tarde_inicio = time(12, 1)
tarde_fim = time(18, 0)
# noite é dividida em dois intervalos por causa da virada do dia
noite_inicio = time(18, 1)
noite_fim = time(4, 59)
# Verifica em qual intervalo a hora atual está
if manhã_inicio <= agora <= manhã_fim:
boa = "Bom dia!"
elif tarde_inicio <= agora <= tarde_fim:
boa = "Boa tarde!"
else:
boa = "Boa noite!"
# 3. Criar e-mail com imagem embutida
msg = EmailMessage()
msg['From'] = remetente
msg['To'] = ', '.join(destinatarios)
msg['Subject'] = assunto
# 4. Conteúdo do e-mail
html_email = f"""
<html>
<body>
<p>{boa}</p>
<p>
Segue o relatório semanal de Cobertura referente às regiões de
Alagoas (AL), Bahia (BA), Sergipe (SE), Conquista (VDC), Bahia3(BA3).
</p>
<p>
Este relatório contempla exclusivamente os itens com cobertura superior à 60 dias.
</p>
<p>
O objetivo é trazer visibilidade para os produtos parados e reforçar a importância
de ações para estimular a sua saída, contribuindo assim para a redução da cobertura
de estoque e otimização dos recursos.
</p>
<p>
Contamos com o apoio de todos para análise e tratativa dos itens listados.
Sugestões de ações como campanhas, transferências ou ajustes de sortimento são
bem-vindas para acelerar a movimentação dos produtos.
</p>
<p>
Importante destacar que este relatório ainda não contempla as transferências realizadas internamente, uma vez que estamos trabalhando para viabilizar a inclusão dessas informações no banco de dados.
</p>
<p>
Para mais informações, favor consultar a planilha em anexo.
</p>
</body>
</html>
"""
msg.set_content("Seu e-mail precisa de um visualizador HTML.")
msg.add_alternative(html_email, subtype='html')
# 5. Anexar o arquivo Excel
with open(excel_path, 'rb') as f:
msg.add_attachment(
f.read(),
maintype='application',
subtype='vnd.openxmlformats-officedocument.spreadsheetml.sheet',
filename=excel_path.name
)
# 6. Enviar o e-mail via SMTP Outlook com configurações fornecidas
with smtplib.SMTP('smtp-mail.outlook.com', 587) as smtp:
smtp.ehlo()
smtp.starttls(context=ssl.create_default_context())
smtp.login(remetente, senha)
smtp.send_message(msg)
print("E-mail enviado com sucesso.")