Files
PecHub/worker/scripts/fix_receipt_body.py
T
2026-03-27 13:54:07 +01:00

130 lines
4.0 KiB
Python

"""
Script one-shot: corregge il body_text/body_html delle ricevute PEC gia' in DB.
Problema: il parser EML sovrascriveva il body delle ricevute con il contenuto
di postacert.eml (messaggio originale inviato), invece di mostrare il testo
della ricevuta stessa.
Questo script:
1. Trova tutti i messaggi in DB con pec_type di tipo ricevuta
2. Scarica l'EML grezzo da MinIO (raw_eml_path)
3. Lo ri-parsa con is_receipt=True (parser corretto)
4. Aggiorna body_text e body_html nel DB
Uso:
cd /opt/pechub
docker compose exec pechub-worker-1 python /app/scripts/fix_receipt_body.py
"""
import asyncio
import logging
import sys
from datetime import UTC, datetime
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
# Aggiungi il path dell'app
sys.path.insert(0, "/app")
from app.config import get_settings
from app.models import Message
from app.parsers.eml_parser import parse_eml
from app.storage.minio_client import download_attachment
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
logger = logging.getLogger(__name__)
# Tipi di ricevuta che potrebbero avere il body sbagliato
RECEIPT_TYPES = {
"accettazione",
"non_accettazione",
"presa_in_carico",
"avvenuta_consegna",
"mancata_consegna",
"errore_consegna",
"preavviso_mancata_consegna",
"rilevazione_virus",
}
async def fix_receipt_bodies() -> None:
settings = get_settings()
engine = create_async_engine(settings.database_url, echo=False)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with async_session() as db:
# Trova tutti i messaggi ricevuta con raw_eml_path
result = await db.execute(
select(Message).where(
Message.pec_type.in_(RECEIPT_TYPES),
Message.raw_eml_path.is_not(None),
).order_by(Message.created_at)
)
messages = result.scalars().all()
logger.info(f"Trovate {len(messages)} ricevute da verificare")
fixed = 0
skipped = 0
errors = 0
for msg in messages:
try:
# Scarica EML grezzo da MinIO (download_attachment funziona per qualsiasi path)
raw_eml = await download_attachment(msg.raw_eml_path)
if not raw_eml:
logger.warning(f"EML non trovato su MinIO per messaggio {msg.id} (path={msg.raw_eml_path!r})")
skipped += 1
continue
# Re-parsing con is_receipt=True (parser corretto)
parsed = parse_eml(raw_eml, is_receipt=True)
# Controlla se il body e' cambiato
new_body_text = parsed.body_text
new_body_html = parsed.body_html
if new_body_text == msg.body_text and new_body_html == msg.body_html:
logger.debug(f"Messaggio {msg.id} ({msg.pec_type}): body invariato, skip")
skipped += 1
continue
# Aggiorna nel DB
msg.body_text = new_body_text
msg.body_html = new_body_html
msg.updated_at = datetime.now(UTC)
logger.info(
f"Fixato: id={msg.id} pec_type={msg.pec_type!r} subject={msg.subject!r} "
f"body_text_len={len(new_body_text or '')}"
)
fixed += 1
except Exception as e:
logger.error(f"Errore su messaggio {msg.id}: {e}", exc_info=True)
errors += 1
continue
if fixed > 0:
await db.commit()
logger.info(f"Commit eseguito: {fixed} messaggi aggiornati")
else:
logger.info("Nessun messaggio da aggiornare")
logger.info(
f"Completato: fixed={fixed} skipped={skipped} errors={errors} "
f"totale={len(messages)}"
)
await engine.dispose()
if __name__ == "__main__":
asyncio.run(fix_receipt_bodies())