La scelta della lista passa da un wizard a tre passi, con anteprima del conteggio e lista congelata solo dopo la conferma. Co-authored-by: Cursor <cursoragent@cursor.com>
410 lines
18 KiB
Ruby
Generated
410 lines
18 KiB
Ruby
Generated
# This file is auto-generated from the current state of the database. Instead
|
|
# of editing this file, please use the migrations feature of Active Record to
|
|
# incrementally modify your database, and then regenerate this schema definition.
|
|
#
|
|
# This file is the source Rails uses to define your schema when running `bin/rails
|
|
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
|
# be faster and is potentially less error prone than running all of your
|
|
# migrations from scratch. Old migrations may fail to apply correctly if those
|
|
# migrations use external dependencies or application code.
|
|
#
|
|
# It's strongly recommended that you check this file into your version control system.
|
|
|
|
ActiveRecord::Schema[8.1].define(version: 2026_08_24_190000) do
|
|
# These are extensions that must be enabled in order to support this database
|
|
enable_extension "pg_catalog.plpgsql"
|
|
|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
|
t.bigint "blob_id", null: false
|
|
t.datetime "created_at", null: false
|
|
t.string "name", null: false
|
|
t.bigint "record_id", null: false
|
|
t.string "record_type", null: false
|
|
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
|
|
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
|
|
end
|
|
|
|
create_table "active_storage_blobs", force: :cascade do |t|
|
|
t.bigint "byte_size", null: false
|
|
t.string "checksum"
|
|
t.string "content_type"
|
|
t.datetime "created_at", null: false
|
|
t.string "filename", null: false
|
|
t.string "key", null: false
|
|
t.text "metadata"
|
|
t.string "service_name", null: false
|
|
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
|
|
end
|
|
|
|
create_table "active_storage_variant_records", force: :cascade do |t|
|
|
t.bigint "blob_id", null: false
|
|
t.string "variation_digest", null: false
|
|
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
|
|
end
|
|
|
|
create_table "activities", force: :cascade do |t|
|
|
t.string "activity_type", null: false
|
|
t.bigint "contact_id"
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.text "description"
|
|
t.datetime "happened_at", null: false
|
|
t.bigint "opportunity_id"
|
|
t.bigint "organization_id", null: false
|
|
t.string "subject", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.bigint "user_id"
|
|
t.index ["activity_type"], name: "index_activities_on_activity_type"
|
|
t.index ["contact_id"], name: "index_activities_on_contact_id"
|
|
t.index ["happened_at"], name: "index_activities_on_happened_at"
|
|
t.index ["opportunity_id"], name: "index_activities_on_opportunity_id"
|
|
t.index ["organization_id", "happened_at"], name: "index_activities_on_organization_id_and_happened_at"
|
|
t.index ["organization_id"], name: "index_activities_on_organization_id"
|
|
t.index ["user_id"], name: "index_activities_on_user_id"
|
|
end
|
|
|
|
create_table "contacts", force: :cascade do |t|
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.string "email"
|
|
t.string "first_name", null: false
|
|
t.string "last_name", null: false
|
|
t.string "mobile"
|
|
t.text "notes"
|
|
t.bigint "organization_id", null: false
|
|
t.string "phone"
|
|
t.string "preferred_contact_method", default: "email"
|
|
t.boolean "primary_contact", default: false, null: false
|
|
t.string "role"
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["email"], name: "index_contacts_on_email"
|
|
t.index ["last_name", "first_name"], name: "index_contacts_on_last_name_and_first_name"
|
|
t.index ["organization_id"], name: "index_contacts_on_organization_id"
|
|
t.index ["phone"], name: "index_contacts_on_phone"
|
|
t.index ["primary_contact"], name: "index_contacts_on_primary_contact"
|
|
end
|
|
|
|
create_table "mail_identities", force: :cascade do |t|
|
|
t.boolean "active", default: true, null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.string "encryption", default: "starttls", null: false
|
|
t.string "from_email", null: false
|
|
t.string "from_name", null: false
|
|
t.string "name", null: false
|
|
t.string "reply_to"
|
|
t.string "smtp_authentication", default: "plain", null: false
|
|
t.string "smtp_host", null: false
|
|
t.text "smtp_password"
|
|
t.integer "smtp_port", default: 587, null: false
|
|
t.string "smtp_username"
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.boolean "verify_ssl", default: true, null: false
|
|
t.index ["active"], name: "index_mail_identities_on_active"
|
|
t.index ["from_email"], name: "index_mail_identities_on_from_email"
|
|
end
|
|
|
|
create_table "mail_templates", force: :cascade do |t|
|
|
t.text "body_html", null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.string "name", null: false
|
|
t.bigint "project_id"
|
|
t.string "subject", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["name"], name: "index_mail_templates_on_name"
|
|
t.index ["project_id"], name: "index_mail_templates_on_project_id"
|
|
end
|
|
|
|
create_table "mailing_recipients", force: :cascade do |t|
|
|
t.string "ab_variant"
|
|
t.bigint "contact_id"
|
|
t.datetime "created_at", null: false
|
|
t.string "email"
|
|
t.text "error_message"
|
|
t.datetime "last_opened_at"
|
|
t.bigint "mailing_id", null: false
|
|
t.integer "open_count", default: 0, null: false
|
|
t.datetime "opened_at"
|
|
t.bigint "organization_id", null: false
|
|
t.string "rendered_subject"
|
|
t.datetime "sent_at"
|
|
t.string "skip_reason"
|
|
t.string "status", default: "pending", null: false
|
|
t.string "tracking_token", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.index ["ab_variant"], name: "index_mailing_recipients_on_ab_variant"
|
|
t.index ["email"], name: "index_mailing_recipients_on_email"
|
|
t.index ["mailing_id", "organization_id"], name: "idx_mailing_recipients_unique", unique: true
|
|
t.index ["opened_at"], name: "index_mailing_recipients_on_opened_at"
|
|
t.index ["status"], name: "index_mailing_recipients_on_status"
|
|
t.index ["tracking_token"], name: "index_mailing_recipients_on_tracking_token", unique: true
|
|
end
|
|
|
|
create_table "mailings", force: :cascade do |t|
|
|
t.string "ab_assignment", default: "from_record", null: false
|
|
t.boolean "ab_test", default: false, null: false
|
|
t.string "audience", default: "to_send", null: false
|
|
t.jsonb "audience_filters", default: {}, null: false
|
|
t.datetime "authorized_at"
|
|
t.text "body_html", null: false
|
|
t.text "body_html_b"
|
|
t.datetime "completed_at"
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.integer "interval_seconds", default: 0, null: false
|
|
t.bigint "mail_identity_id", null: false
|
|
t.bigint "mail_template_b_id"
|
|
t.bigint "mail_template_id"
|
|
t.string "name", null: false
|
|
t.datetime "next_send_at"
|
|
t.bigint "project_id", null: false
|
|
t.datetime "queued_at"
|
|
t.boolean "send_window_enabled", default: false, null: false
|
|
t.integer "send_window_end_minutes"
|
|
t.integer "send_window_start_minutes"
|
|
t.string "status", default: "draft", null: false
|
|
t.string "subject", null: false
|
|
t.string "subject_b"
|
|
t.datetime "test_sent_at"
|
|
t.string "test_sent_to"
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["ab_test"], name: "index_mailings_on_ab_test"
|
|
t.index ["audience_filters"], name: "index_mailings_on_audience_filters", using: :gin
|
|
t.index ["mail_identity_id"], name: "index_mailings_on_mail_identity_id"
|
|
t.index ["project_id"], name: "index_mailings_on_project_id"
|
|
t.index ["status", "next_send_at"], name: "index_mailings_on_status_and_next_send_at"
|
|
t.index ["status"], name: "index_mailings_on_status"
|
|
end
|
|
|
|
create_table "opportunities", force: :cascade do |t|
|
|
t.string "ab_variant"
|
|
t.bigint "assigned_user_id"
|
|
t.boolean "converted", default: false, null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.boolean "demo_trial", default: false, null: false
|
|
t.decimal "estimated_value", precision: 12, scale: 2
|
|
t.date "expected_close_date"
|
|
t.datetime "first_contacted_at"
|
|
t.datetime "lost_at"
|
|
t.string "lost_reason"
|
|
t.string "name", null: false
|
|
t.text "notes"
|
|
t.bigint "organization_id", null: false
|
|
t.string "outcome"
|
|
t.string "pipeline_stage", default: "to_contact", null: false
|
|
t.integer "probability", default: 0
|
|
t.string "product"
|
|
t.bigint "project_id"
|
|
t.string "send_status"
|
|
t.date "sent_on"
|
|
t.datetime "stage_changed_at"
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.datetime "won_at"
|
|
t.index ["ab_variant"], name: "index_opportunities_on_ab_variant"
|
|
t.index ["assigned_user_id"], name: "index_opportunities_on_assigned_user_id"
|
|
t.index ["expected_close_date"], name: "index_opportunities_on_expected_close_date"
|
|
t.index ["lost_reason"], name: "index_opportunities_on_lost_reason"
|
|
t.index ["organization_id"], name: "index_opportunities_on_organization_id"
|
|
t.index ["pipeline_stage"], name: "index_opportunities_on_pipeline_stage"
|
|
t.index ["product"], name: "index_opportunities_on_product"
|
|
t.index ["project_id"], name: "index_opportunities_on_project_id"
|
|
t.index ["send_status"], name: "index_opportunities_on_send_status"
|
|
t.index ["stage_changed_at"], name: "index_opportunities_on_stage_changed_at"
|
|
end
|
|
|
|
create_table "organization_projects", force: :cascade do |t|
|
|
t.datetime "created_at", null: false
|
|
t.bigint "organization_id", null: false
|
|
t.bigint "project_id", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.index ["organization_id", "project_id"], name: "idx_org_projects_unique", unique: true
|
|
t.index ["organization_id"], name: "index_organization_projects_on_organization_id"
|
|
t.index ["project_id"], name: "index_organization_projects_on_project_id"
|
|
end
|
|
|
|
create_table "organizations", force: :cascade do |t|
|
|
t.string "address"
|
|
t.bigint "assigned_user_id"
|
|
t.string "city"
|
|
t.text "commercial_fit"
|
|
t.string "country", default: "Italia", null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.string "email"
|
|
t.string "lead_source"
|
|
t.string "legal_name"
|
|
t.integer "list_position"
|
|
t.string "name", null: false
|
|
t.text "notes"
|
|
t.string "organization_type", default: "altro", null: false
|
|
t.string "phone"
|
|
t.string "province"
|
|
t.string "region"
|
|
t.string "source_url"
|
|
t.string "sport"
|
|
t.string "status", default: "prospect", null: false
|
|
t.string "streaming_status"
|
|
t.string "team_gender"
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.string "vat_number"
|
|
t.date "verified_at"
|
|
t.string "website"
|
|
t.index ["assigned_user_id"], name: "index_organizations_on_assigned_user_id"
|
|
t.index ["city"], name: "index_organizations_on_city"
|
|
t.index ["country"], name: "index_organizations_on_country"
|
|
t.index ["email"], name: "index_organizations_on_email"
|
|
t.index ["lead_source"], name: "index_organizations_on_lead_source"
|
|
t.index ["list_position"], name: "index_organizations_on_list_position"
|
|
t.index ["name"], name: "index_organizations_on_name"
|
|
t.index ["organization_type"], name: "index_organizations_on_organization_type"
|
|
t.index ["region"], name: "index_organizations_on_region"
|
|
t.index ["sport"], name: "index_organizations_on_sport"
|
|
t.index ["status"], name: "index_organizations_on_status"
|
|
t.index ["streaming_status"], name: "index_organizations_on_streaming_status"
|
|
t.index ["team_gender"], name: "index_organizations_on_team_gender"
|
|
t.index ["website"], name: "index_organizations_on_website"
|
|
end
|
|
|
|
create_table "products", force: :cascade do |t|
|
|
t.boolean "active", default: true, null: false
|
|
t.string "code", null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.string "name", null: false
|
|
t.integer "position", default: 0, null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["code"], name: "index_products_on_code", unique: true
|
|
t.index ["position"], name: "index_products_on_position"
|
|
end
|
|
|
|
create_table "projects", force: :cascade do |t|
|
|
t.boolean "active", default: true, null: false
|
|
t.string "code", null: false
|
|
t.string "color", default: "#0f172a"
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.text "description"
|
|
t.string "name", null: false
|
|
t.integer "position", default: 0, null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["active"], name: "index_projects_on_active"
|
|
t.index ["code"], name: "index_projects_on_code", unique: true
|
|
t.index ["position"], name: "index_projects_on_position"
|
|
end
|
|
|
|
create_table "sales_goals", force: :cascade do |t|
|
|
t.boolean "active", default: true, null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.date "end_date", null: false
|
|
t.string "metric", null: false
|
|
t.string "name", null: false
|
|
t.bigint "project_id"
|
|
t.date "start_date", null: false
|
|
t.decimal "target_value", precision: 12, scale: 2, null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["active"], name: "index_sales_goals_on_active"
|
|
t.index ["metric"], name: "index_sales_goals_on_metric"
|
|
t.index ["project_id"], name: "index_sales_goals_on_project_id"
|
|
t.index ["start_date", "end_date"], name: "index_sales_goals_on_start_date_and_end_date"
|
|
end
|
|
|
|
create_table "tasks", force: :cascade do |t|
|
|
t.bigint "assigned_user_id"
|
|
t.datetime "completed_at"
|
|
t.bigint "contact_id"
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.text "description"
|
|
t.datetime "due_at", null: false
|
|
t.bigint "opportunity_id"
|
|
t.bigint "organization_id", null: false
|
|
t.string "priority", default: "normal", null: false
|
|
t.string "status", default: "pending", null: false
|
|
t.string "task_type", default: "generic", null: false
|
|
t.string "title", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["assigned_user_id"], name: "index_tasks_on_assigned_user_id"
|
|
t.index ["contact_id"], name: "index_tasks_on_contact_id"
|
|
t.index ["due_at"], name: "index_tasks_on_due_at"
|
|
t.index ["opportunity_id"], name: "index_tasks_on_opportunity_id"
|
|
t.index ["organization_id"], name: "index_tasks_on_organization_id"
|
|
t.index ["priority"], name: "index_tasks_on_priority"
|
|
t.index ["status", "due_at"], name: "index_tasks_on_status_and_due_at"
|
|
t.index ["status"], name: "index_tasks_on_status"
|
|
t.index ["task_type"], name: "index_tasks_on_task_type"
|
|
end
|
|
|
|
create_table "user_projects", force: :cascade do |t|
|
|
t.datetime "created_at", null: false
|
|
t.boolean "enabled", default: true, null: false
|
|
t.bigint "project_id", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "user_id", null: false
|
|
t.index ["enabled"], name: "index_user_projects_on_enabled"
|
|
t.index ["project_id"], name: "index_user_projects_on_project_id"
|
|
t.index ["user_id", "project_id"], name: "index_user_projects_on_user_id_and_project_id", unique: true
|
|
t.index ["user_id"], name: "index_user_projects_on_user_id"
|
|
end
|
|
|
|
create_table "users", force: :cascade do |t|
|
|
t.boolean "active", default: true, null: false
|
|
t.datetime "created_at", null: false
|
|
t.bigint "created_by_id"
|
|
t.string "email", null: false
|
|
t.string "first_name", null: false
|
|
t.string "last_name", null: false
|
|
t.string "password_digest", null: false
|
|
t.datetime "password_reset_sent_at"
|
|
t.string "password_reset_token"
|
|
t.string "role", default: "user", null: false
|
|
t.datetime "updated_at", null: false
|
|
t.bigint "updated_by_id"
|
|
t.index ["email"], name: "index_users_on_email", unique: true
|
|
t.index ["password_reset_token"], name: "index_users_on_password_reset_token", unique: true
|
|
t.index ["role"], name: "index_users_on_role"
|
|
end
|
|
|
|
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
|
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
|
add_foreign_key "activities", "contacts"
|
|
add_foreign_key "activities", "opportunities"
|
|
add_foreign_key "activities", "organizations"
|
|
add_foreign_key "activities", "users"
|
|
add_foreign_key "contacts", "organizations"
|
|
add_foreign_key "mail_templates", "projects"
|
|
add_foreign_key "mailing_recipients", "contacts"
|
|
add_foreign_key "mailing_recipients", "mailings"
|
|
add_foreign_key "mailing_recipients", "organizations"
|
|
add_foreign_key "mailings", "mail_identities"
|
|
add_foreign_key "mailings", "mail_templates"
|
|
add_foreign_key "mailings", "mail_templates", column: "mail_template_b_id"
|
|
add_foreign_key "mailings", "projects"
|
|
add_foreign_key "opportunities", "organizations"
|
|
add_foreign_key "opportunities", "projects"
|
|
add_foreign_key "opportunities", "users", column: "assigned_user_id"
|
|
add_foreign_key "organization_projects", "organizations"
|
|
add_foreign_key "organization_projects", "projects"
|
|
add_foreign_key "organizations", "users", column: "assigned_user_id"
|
|
add_foreign_key "sales_goals", "projects"
|
|
add_foreign_key "tasks", "contacts"
|
|
add_foreign_key "tasks", "opportunities"
|
|
add_foreign_key "tasks", "organizations"
|
|
add_foreign_key "tasks", "users", column: "assigned_user_id"
|
|
add_foreign_key "user_projects", "projects"
|
|
add_foreign_key "user_projects", "users"
|
|
end
|