fix parsing ricevute
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Migrazione 0023: aggiunge colonna riferimento_message_id alla tabella messages.
|
||||
|
||||
La colonna memorizza il valore di X-Riferimento-Message-ID presente nelle
|
||||
ricevute PEC inbound (accettazione, avvenuta_consegna, ecc.). Serve per:
|
||||
|
||||
1. Binding retroattivo: se il binding fallisce durante la sync (race condition
|
||||
con send_pec che non ha ancora committato message_id_header), il job di
|
||||
rebinding puo' usare questa colonna per ricollegare le ricevute orfane
|
||||
al messaggio outbound originale senza dover ri-leggere l'EML da MinIO.
|
||||
|
||||
2. Diagnostica: permette di verificare rapidamente quali ricevute hanno un
|
||||
X-Riferimento valorizzato ma non hanno trovato il corrispondente outbound.
|
||||
|
||||
Revision ID: 0023_add_riferimento_message_id
|
||||
Revises: 0022_partial_unique_mailbox_email
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# ── Identificatori migrazione ─────────────────────────────────────────────────
|
||||
revision = "0023"
|
||||
down_revision = "0022"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Colonna nullable: solo le ricevute inbound la hanno valorizzata.
|
||||
# I messaggi posta_certificata (inbound e outbound) la lasciano NULL.
|
||||
op.add_column(
|
||||
"messages",
|
||||
sa.Column("riferimento_message_id", sa.Text(), nullable=True),
|
||||
)
|
||||
|
||||
# Indice parziale per le query di binding retroattivo:
|
||||
# cerca ricevute orfane (parent_message_id IS NULL) con riferimento valorizzato.
|
||||
op.create_index(
|
||||
"idx_messages_riferimento",
|
||||
"messages",
|
||||
["riferimento_message_id"],
|
||||
postgresql_where=sa.text("riferimento_message_id IS NOT NULL"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_index("idx_messages_riferimento", table_name="messages")
|
||||
op.drop_column("messages", "riferimento_message_id")
|
||||
@@ -244,6 +244,24 @@ async def list_messages(
|
||||
Message.parent_message_id.is_(None),
|
||||
)
|
||||
|
||||
# ── Auto-filtro ricevute ───────────────────────────────────────────────────
|
||||
# Esclude automaticamente i messaggi inbound di tipo ricevuta (accettazione,
|
||||
# avvenuta_consegna, ecc.) quando pec_type non e' specificato esplicitamente.
|
||||
# Le ricevute correttamente bindate hanno parent_message_id != NULL e sono
|
||||
# gia' escluse dal filtro sopra. Quelle non bindato (race condition o invii
|
||||
# da client esterni) verrebbero mostrate in inbox come messaggi normali senza
|
||||
# questo filtro aggiuntivo.
|
||||
# I messaggi outbound hanno sempre pec_type='posta_certificata' in questo
|
||||
# sistema (non creiamo mai record outbound di tipo ricevuta) quindi il filtro
|
||||
# e' trasparente per la vista posta inviata.
|
||||
if pec_type is None:
|
||||
q = q.where(
|
||||
or_(
|
||||
Message.direction == "outbound",
|
||||
Message.pec_type == "posta_certificata",
|
||||
)
|
||||
)
|
||||
|
||||
if visible_mailbox_ids is not None:
|
||||
if not visible_mailbox_ids:
|
||||
return MessageListResponse(items=[], total=0, page=page, page_size=page_size)
|
||||
|
||||
@@ -92,6 +92,12 @@ class Message(Base):
|
||||
parent_message_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True), ForeignKey("messages.id"), nullable=True
|
||||
)
|
||||
# X-Riferimento-Message-ID estratto dalle ricevute inbound PEC.
|
||||
# Permette il binding retroattivo se la race condition ha impedito il binding
|
||||
# live (send_pec non aveva ancora committato message_id_header quando la
|
||||
# ricevuta e' stata processata dalla sync IMAP).
|
||||
# Solo le ricevute (pec_type != posta_certificata) la hanno valorizzata.
|
||||
riferimento_message_id: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
|
||||
# Flag operativi
|
||||
is_read: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
||||
|
||||
Reference in New Issue
Block a user