mirror of
https://github.com/idrainformatica/PecFlow.git
synced 2026-06-16 12:45:42 +02:00
vbox funzionanti
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
"""Virtual Boxes e Notifiche Multi-canale – Fase 2
|
||||
|
||||
Revision ID: 0003
|
||||
Revises: 0002
|
||||
Create Date: 2026-03-19 00:00:00.000000
|
||||
|
||||
Aggiunge le tabelle:
|
||||
- virtual_boxes
|
||||
- virtual_box_rules
|
||||
- virtual_box_assignments
|
||||
- notification_channels (+ ENUM notification_channel_type)
|
||||
- notification_rules
|
||||
- notification_log (+ ENUM notification_status)
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision = "0003"
|
||||
down_revision = "0002"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ── ENUM types ────────────────────────────────────────────────────────────
|
||||
op.execute(
|
||||
"CREATE TYPE notification_channel_type AS ENUM "
|
||||
"('webhook', 'email', 'telegram', 'whatsapp')"
|
||||
)
|
||||
op.execute(
|
||||
"CREATE TYPE notification_status AS ENUM "
|
||||
"('pending', 'sent', 'failed', 'skipped')"
|
||||
)
|
||||
|
||||
# ── VIRTUAL BOXES ─────────────────────────────────────────────────────────
|
||||
op.execute("""
|
||||
CREATE TABLE virtual_boxes (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
label VARCHAR(100),
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_vbox_name_tenant UNIQUE (tenant_id, name)
|
||||
)
|
||||
""")
|
||||
op.execute("CREATE INDEX idx_vbox_tenant ON virtual_boxes (tenant_id)")
|
||||
op.execute("""
|
||||
CREATE TRIGGER trg_virtual_boxes_updated_at
|
||||
BEFORE UPDATE ON virtual_boxes
|
||||
FOR EACH ROW EXECUTE FUNCTION set_updated_at()
|
||||
""")
|
||||
|
||||
op.execute("""
|
||||
CREATE TABLE virtual_box_rules (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
virtual_box_id UUID NOT NULL REFERENCES virtual_boxes(id) ON DELETE CASCADE,
|
||||
field VARCHAR(50) NOT NULL,
|
||||
operator VARCHAR(20) NOT NULL DEFAULT 'contains',
|
||||
value TEXT NOT NULL,
|
||||
date_from VARCHAR(20),
|
||||
date_to VARCHAR(20),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
""")
|
||||
op.execute("CREATE INDEX idx_vbox_rule_vbox ON virtual_box_rules (virtual_box_id)")
|
||||
|
||||
op.execute("""
|
||||
CREATE TABLE virtual_box_assignments (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
virtual_box_id UUID NOT NULL REFERENCES virtual_boxes(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
assigned_by UUID REFERENCES users(id),
|
||||
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT uq_vbox_assignment UNIQUE (virtual_box_id, user_id)
|
||||
)
|
||||
""")
|
||||
op.execute("CREATE INDEX idx_vbox_assign_user ON virtual_box_assignments (user_id)")
|
||||
op.execute("CREATE INDEX idx_vbox_assign_vbox ON virtual_box_assignments (virtual_box_id)")
|
||||
|
||||
# ── NOTIFICATION CHANNELS ─────────────────────────────────────────────────
|
||||
op.execute("""
|
||||
CREATE TABLE notification_channels (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
channel_type notification_channel_type NOT NULL,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
config JSONB,
|
||||
config_enc TEXT,
|
||||
consecutive_failures INT NOT NULL DEFAULT 0,
|
||||
circuit_open_until TIMESTAMPTZ,
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
""")
|
||||
op.execute("CREATE INDEX idx_notif_channel_tenant ON notification_channels (tenant_id)")
|
||||
op.execute("""
|
||||
CREATE TRIGGER trg_notification_channels_updated_at
|
||||
BEFORE UPDATE ON notification_channels
|
||||
FOR EACH ROW EXECUTE FUNCTION set_updated_at()
|
||||
""")
|
||||
|
||||
op.execute("""
|
||||
CREATE TABLE notification_rules (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
channel_id UUID NOT NULL REFERENCES notification_channels(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
event_type VARCHAR(100) NOT NULL,
|
||||
filter JSONB,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
""")
|
||||
op.execute("CREATE INDEX idx_notif_rule_tenant ON notification_rules (tenant_id)")
|
||||
op.execute("CREATE INDEX idx_notif_rule_channel ON notification_rules (channel_id)")
|
||||
op.execute("CREATE INDEX idx_notif_rule_event ON notification_rules (event_type)")
|
||||
|
||||
op.execute("""
|
||||
CREATE TABLE notification_log (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
channel_id UUID NOT NULL REFERENCES notification_channels(id) ON DELETE CASCADE,
|
||||
rule_id UUID REFERENCES notification_rules(id) ON DELETE SET NULL,
|
||||
event_type VARCHAR(100) NOT NULL,
|
||||
event_payload JSONB,
|
||||
status notification_status NOT NULL DEFAULT 'pending',
|
||||
attempt_count INT NOT NULL DEFAULT 0,
|
||||
max_attempts INT NOT NULL DEFAULT 3,
|
||||
next_retry_at TIMESTAMPTZ,
|
||||
last_error TEXT,
|
||||
http_status INT,
|
||||
sent_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
""")
|
||||
op.execute("CREATE INDEX idx_notif_log_tenant ON notification_log (tenant_id)")
|
||||
op.execute("CREATE INDEX idx_notif_log_channel ON notification_log (channel_id)")
|
||||
op.execute(
|
||||
"CREATE INDEX idx_notif_log_status ON notification_log (status, next_retry_at) "
|
||||
"WHERE status IN ('pending', 'failed')"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
for table in [
|
||||
"notification_log",
|
||||
"notification_rules",
|
||||
"notification_channels",
|
||||
"virtual_box_assignments",
|
||||
"virtual_box_rules",
|
||||
"virtual_boxes",
|
||||
]:
|
||||
op.execute(f"DROP TABLE IF EXISTS {table} CASCADE")
|
||||
|
||||
op.execute("DROP TYPE IF EXISTS notification_status")
|
||||
op.execute("DROP TYPE IF EXISTS notification_channel_type")
|
||||
Reference in New Issue
Block a user