- Updated Dockerfile to set permissions for the entrypoint script and defined the entrypoint for the container. - Consolidated Alembic migration history into a single initial migration file and removed obsolete revision files. - Added a new script to run Alembic migrations before starting the application. - Updated changelog to reflect changes in migration handling and Docker setup. - Enhanced pytest configuration for coverage reporting and excluded specific files from coverage calculations.
719 lines
22 KiB
Python
719 lines
22 KiB
Python
"""Combined initial schema"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from passlib.context import CryptContext
|
|
from sqlalchemy.sql import column, table
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = "20251111_00"
|
|
down_revision = None
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
password_context = CryptContext(schemes=["argon2"], deprecated="auto")
|
|
|
|
mining_operation_type = sa.Enum(
|
|
"open_pit",
|
|
"underground",
|
|
"in_situ_leach",
|
|
"placer",
|
|
"quarry",
|
|
"mountaintop_removal",
|
|
"other",
|
|
name="miningoperationtype",
|
|
)
|
|
|
|
scenario_status = sa.Enum(
|
|
"draft",
|
|
"active",
|
|
"archived",
|
|
name="scenariostatus",
|
|
)
|
|
|
|
financial_category = sa.Enum(
|
|
"capex",
|
|
"opex",
|
|
"revenue",
|
|
"contingency",
|
|
"other",
|
|
name="financialcategory",
|
|
)
|
|
|
|
cost_bucket = sa.Enum(
|
|
"capital_initial",
|
|
"capital_sustaining",
|
|
"operating_fixed",
|
|
"operating_variable",
|
|
"maintenance",
|
|
"reclamation",
|
|
"royalties",
|
|
"general_admin",
|
|
name="costbucket",
|
|
)
|
|
|
|
distribution_type = sa.Enum(
|
|
"normal",
|
|
"triangular",
|
|
"uniform",
|
|
"lognormal",
|
|
"custom",
|
|
name="distributiontype",
|
|
)
|
|
|
|
stochastic_variable = sa.Enum(
|
|
"ore_grade",
|
|
"recovery_rate",
|
|
"metal_price",
|
|
"operating_cost",
|
|
"capital_cost",
|
|
"discount_rate",
|
|
"throughput",
|
|
name="stochasticvariable",
|
|
)
|
|
|
|
resource_type = sa.Enum(
|
|
"diesel",
|
|
"electricity",
|
|
"water",
|
|
"explosives",
|
|
"reagents",
|
|
"labor",
|
|
"equipment_hours",
|
|
"tailings_capacity",
|
|
name="resourcetype",
|
|
)
|
|
|
|
|
|
DEFAULT_PRICING_SLUG = "default"
|
|
|
|
|
|
def _ensure_default_pricing_settings(connection) -> int:
|
|
settings_table = table(
|
|
"pricing_settings",
|
|
column("id", sa.Integer()),
|
|
column("slug", sa.String()),
|
|
column("name", sa.String()),
|
|
column("description", sa.Text()),
|
|
column("default_currency", sa.String()),
|
|
column("default_payable_pct", sa.Numeric()),
|
|
column("moisture_threshold_pct", sa.Numeric()),
|
|
column("moisture_penalty_per_pct", sa.Numeric()),
|
|
column("created_at", sa.DateTime(timezone=True)),
|
|
column("updated_at", sa.DateTime(timezone=True)),
|
|
)
|
|
|
|
existing = connection.execute(
|
|
sa.select(settings_table.c.id).where(
|
|
settings_table.c.slug == DEFAULT_PRICING_SLUG
|
|
)
|
|
).scalar_one_or_none()
|
|
if existing is not None:
|
|
return existing
|
|
|
|
now = datetime.now(timezone.utc)
|
|
insert_stmt = settings_table.insert().values(
|
|
slug=DEFAULT_PRICING_SLUG,
|
|
name="Default Pricing",
|
|
description="Automatically generated default pricing settings.",
|
|
default_currency="USD",
|
|
default_payable_pct=100.0,
|
|
moisture_threshold_pct=8.0,
|
|
moisture_penalty_per_pct=0.0,
|
|
created_at=now,
|
|
updated_at=now,
|
|
)
|
|
result = connection.execute(insert_stmt)
|
|
default_id = result.inserted_primary_key[0]
|
|
if default_id is None:
|
|
default_id = connection.execute(
|
|
sa.select(settings_table.c.id).where(
|
|
settings_table.c.slug == DEFAULT_PRICING_SLUG
|
|
)
|
|
).scalar_one()
|
|
return default_id
|
|
|
|
|
|
def upgrade() -> None:
|
|
bind = op.get_bind()
|
|
|
|
# Enumerations
|
|
mining_operation_type.create(bind, checkfirst=True)
|
|
scenario_status.create(bind, checkfirst=True)
|
|
financial_category.create(bind, checkfirst=True)
|
|
cost_bucket.create(bind, checkfirst=True)
|
|
distribution_type.create(bind, checkfirst=True)
|
|
stochastic_variable.create(bind, checkfirst=True)
|
|
resource_type.create(bind, checkfirst=True)
|
|
|
|
# Pricing settings core tables
|
|
op.create_table(
|
|
"pricing_settings",
|
|
sa.Column("id", sa.Integer(), primary_key=True),
|
|
sa.Column("name", sa.String(length=128), nullable=False),
|
|
sa.Column("slug", sa.String(length=64), nullable=False),
|
|
sa.Column("description", sa.Text(), nullable=True),
|
|
sa.Column("default_currency", sa.String(length=3), nullable=True),
|
|
sa.Column(
|
|
"default_payable_pct",
|
|
sa.Numeric(precision=5, scale=2),
|
|
nullable=False,
|
|
server_default=sa.text("100.00"),
|
|
),
|
|
sa.Column(
|
|
"moisture_threshold_pct",
|
|
sa.Numeric(precision=5, scale=2),
|
|
nullable=False,
|
|
server_default=sa.text("8.00"),
|
|
),
|
|
sa.Column(
|
|
"moisture_penalty_per_pct",
|
|
sa.Numeric(precision=14, scale=4),
|
|
nullable=False,
|
|
server_default=sa.text("0.0000"),
|
|
),
|
|
sa.Column("metadata", sa.JSON(), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.UniqueConstraint("name", name="uq_pricing_settings_name"),
|
|
sa.UniqueConstraint("slug", name="uq_pricing_settings_slug"),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_pricing_settings_id"),
|
|
"pricing_settings",
|
|
["id"],
|
|
unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"pricing_metal_settings",
|
|
sa.Column("id", sa.Integer(), primary_key=True),
|
|
sa.Column(
|
|
"pricing_settings_id",
|
|
sa.Integer(),
|
|
sa.ForeignKey("pricing_settings.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
),
|
|
sa.Column("metal_code", sa.String(length=32), nullable=False),
|
|
sa.Column("payable_pct", sa.Numeric(
|
|
precision=5, scale=2), nullable=True),
|
|
sa.Column(
|
|
"moisture_threshold_pct",
|
|
sa.Numeric(precision=5, scale=2),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"moisture_penalty_per_pct",
|
|
sa.Numeric(precision=14, scale=4),
|
|
nullable=True,
|
|
),
|
|
sa.Column("data", sa.JSON(), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.UniqueConstraint(
|
|
"pricing_settings_id",
|
|
"metal_code",
|
|
name="uq_pricing_metal_settings_code",
|
|
),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_pricing_metal_settings_id"),
|
|
"pricing_metal_settings",
|
|
["id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_pricing_metal_settings_pricing_settings_id"),
|
|
"pricing_metal_settings",
|
|
["pricing_settings_id"],
|
|
unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"pricing_impurity_settings",
|
|
sa.Column("id", sa.Integer(), primary_key=True),
|
|
sa.Column(
|
|
"pricing_settings_id",
|
|
sa.Integer(),
|
|
sa.ForeignKey("pricing_settings.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
),
|
|
sa.Column("impurity_code", sa.String(length=32), nullable=False),
|
|
sa.Column(
|
|
"threshold_ppm",
|
|
sa.Numeric(precision=14, scale=4),
|
|
nullable=False,
|
|
server_default=sa.text("0.0000"),
|
|
),
|
|
sa.Column(
|
|
"penalty_per_ppm",
|
|
sa.Numeric(precision=14, scale=4),
|
|
nullable=False,
|
|
server_default=sa.text("0.0000"),
|
|
),
|
|
sa.Column("notes", sa.Text(), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.UniqueConstraint(
|
|
"pricing_settings_id",
|
|
"impurity_code",
|
|
name="uq_pricing_impurity_settings_code",
|
|
),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_pricing_impurity_settings_id"),
|
|
"pricing_impurity_settings",
|
|
["id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_pricing_impurity_settings_pricing_settings_id"),
|
|
"pricing_impurity_settings",
|
|
["pricing_settings_id"],
|
|
unique=False,
|
|
)
|
|
|
|
# Core domain tables
|
|
op.create_table(
|
|
"projects",
|
|
sa.Column("id", sa.Integer(), nullable=False),
|
|
sa.Column("name", sa.String(length=255), nullable=False),
|
|
sa.Column("location", sa.String(length=255), nullable=True),
|
|
sa.Column("operation_type", mining_operation_type, nullable=False),
|
|
sa.Column("description", sa.Text(), nullable=True),
|
|
sa.Column(
|
|
"pricing_settings_id",
|
|
sa.Integer(),
|
|
sa.ForeignKey("pricing_settings.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
sa.UniqueConstraint("name"),
|
|
)
|
|
op.create_index(op.f("ix_projects_id"), "projects", ["id"], unique=False)
|
|
op.create_index(
|
|
"ix_projects_pricing_settings_id",
|
|
"projects",
|
|
["pricing_settings_id"],
|
|
unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"scenarios",
|
|
sa.Column("id", sa.Integer(), nullable=False),
|
|
sa.Column("project_id", sa.Integer(), nullable=False),
|
|
sa.Column("name", sa.String(length=255), nullable=False),
|
|
sa.Column("description", sa.Text(), nullable=True),
|
|
sa.Column("status", scenario_status, nullable=False),
|
|
sa.Column("start_date", sa.Date(), nullable=True),
|
|
sa.Column("end_date", sa.Date(), nullable=True),
|
|
sa.Column("discount_rate", sa.Numeric(
|
|
precision=5, scale=2), nullable=True),
|
|
sa.Column("currency", sa.String(length=3), nullable=True),
|
|
sa.Column("primary_resource", resource_type, nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["project_id"], ["projects.id"], ondelete="CASCADE"),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(op.f("ix_scenarios_id"), "scenarios", ["id"], unique=False)
|
|
op.create_index(
|
|
op.f("ix_scenarios_project_id"),
|
|
"scenarios",
|
|
["project_id"],
|
|
unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"financial_inputs",
|
|
sa.Column("id", sa.Integer(), nullable=False),
|
|
sa.Column("scenario_id", sa.Integer(), nullable=False),
|
|
sa.Column("name", sa.String(length=255), nullable=False),
|
|
sa.Column("category", financial_category, nullable=False),
|
|
sa.Column("cost_bucket", cost_bucket, nullable=True),
|
|
sa.Column("amount", sa.Numeric(precision=18, scale=2), nullable=False),
|
|
sa.Column("currency", sa.String(length=3), nullable=True),
|
|
sa.Column("effective_date", sa.Date(), nullable=True),
|
|
sa.Column("notes", sa.Text(), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["scenario_id"], ["scenarios.id"], ondelete="CASCADE"),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_financial_inputs_id"),
|
|
"financial_inputs",
|
|
["id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_financial_inputs_scenario_id"),
|
|
"financial_inputs",
|
|
["scenario_id"],
|
|
unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"simulation_parameters",
|
|
sa.Column("id", sa.Integer(), nullable=False),
|
|
sa.Column("scenario_id", sa.Integer(), nullable=False),
|
|
sa.Column("name", sa.String(length=255), nullable=False),
|
|
sa.Column("distribution", distribution_type, nullable=False),
|
|
sa.Column("variable", stochastic_variable, nullable=True),
|
|
sa.Column("resource_type", resource_type, nullable=True),
|
|
sa.Column("mean_value", sa.Numeric(
|
|
precision=18, scale=4), nullable=True),
|
|
sa.Column(
|
|
"standard_deviation",
|
|
sa.Numeric(precision=18, scale=4),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"minimum_value",
|
|
sa.Numeric(precision=18, scale=4),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"maximum_value",
|
|
sa.Numeric(precision=18, scale=4),
|
|
nullable=True,
|
|
),
|
|
sa.Column("unit", sa.String(length=32), nullable=True),
|
|
sa.Column("configuration", sa.JSON(), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(),
|
|
nullable=False,
|
|
),
|
|
sa.ForeignKeyConstraint(
|
|
["scenario_id"], ["scenarios.id"], ondelete="CASCADE"),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
op.f("ix_simulation_parameters_id"),
|
|
"simulation_parameters",
|
|
["id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
op.f("ix_simulation_parameters_scenario_id"),
|
|
"simulation_parameters",
|
|
["scenario_id"],
|
|
unique=False,
|
|
)
|
|
|
|
# Authentication and RBAC tables
|
|
op.create_table(
|
|
"users",
|
|
sa.Column("id", sa.Integer(), primary_key=True),
|
|
sa.Column("email", sa.String(length=255), nullable=False),
|
|
sa.Column("username", sa.String(length=128), nullable=False),
|
|
sa.Column("password_hash", sa.String(length=255), nullable=False),
|
|
sa.Column("is_active", sa.Boolean(),
|
|
nullable=False, server_default=sa.true()),
|
|
sa.Column(
|
|
"is_superuser",
|
|
sa.Boolean(),
|
|
nullable=False,
|
|
server_default=sa.false(),
|
|
),
|
|
sa.Column("last_login_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.UniqueConstraint("email", name="uq_users_email"),
|
|
sa.UniqueConstraint("username", name="uq_users_username"),
|
|
)
|
|
op.create_index(
|
|
"ix_users_active_superuser",
|
|
"users",
|
|
["is_active", "is_superuser"],
|
|
unique=False,
|
|
)
|
|
|
|
op.create_table(
|
|
"roles",
|
|
sa.Column("id", sa.Integer(), primary_key=True),
|
|
sa.Column("name", sa.String(length=64), nullable=False),
|
|
sa.Column("display_name", sa.String(length=128), nullable=False),
|
|
sa.Column("description", sa.Text(), nullable=True),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.UniqueConstraint("name", name="uq_roles_name"),
|
|
)
|
|
|
|
op.create_table(
|
|
"user_roles",
|
|
sa.Column("user_id", sa.Integer(), nullable=False),
|
|
sa.Column("role_id", sa.Integer(), nullable=False),
|
|
sa.Column(
|
|
"granted_at",
|
|
sa.DateTime(timezone=True),
|
|
nullable=False,
|
|
server_default=sa.func.now(),
|
|
),
|
|
sa.Column("granted_by", sa.Integer(), nullable=True),
|
|
sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
|
|
sa.ForeignKeyConstraint(["role_id"], ["roles.id"], ondelete="CASCADE"),
|
|
sa.ForeignKeyConstraint(
|
|
["granted_by"], ["users.id"], ondelete="SET NULL"),
|
|
sa.PrimaryKeyConstraint("user_id", "role_id"),
|
|
sa.UniqueConstraint("user_id", "role_id",
|
|
name="uq_user_roles_user_role"),
|
|
)
|
|
op.create_index(
|
|
"ix_user_roles_role_id",
|
|
"user_roles",
|
|
["role_id"],
|
|
unique=False,
|
|
)
|
|
|
|
# Seed roles and default admin
|
|
roles_table = table(
|
|
"roles",
|
|
column("id", sa.Integer()),
|
|
column("name", sa.String()),
|
|
column("display_name", sa.String()),
|
|
column("description", sa.Text()),
|
|
)
|
|
|
|
op.bulk_insert(
|
|
roles_table,
|
|
[
|
|
{
|
|
"id": 1,
|
|
"name": "admin",
|
|
"display_name": "Administrator",
|
|
"description": "Full platform access with user management rights.",
|
|
},
|
|
{
|
|
"id": 2,
|
|
"name": "project_manager",
|
|
"display_name": "Project Manager",
|
|
"description": "Manage projects, scenarios, and associated data.",
|
|
},
|
|
{
|
|
"id": 3,
|
|
"name": "analyst",
|
|
"display_name": "Analyst",
|
|
"description": "Review dashboards and scenario outputs.",
|
|
},
|
|
{
|
|
"id": 4,
|
|
"name": "viewer",
|
|
"display_name": "Viewer",
|
|
"description": "Read-only access to assigned projects and reports.",
|
|
},
|
|
],
|
|
)
|
|
|
|
admin_password_hash = password_context.hash("ChangeMe123!")
|
|
|
|
users_table = table(
|
|
"users",
|
|
column("id", sa.Integer()),
|
|
column("email", sa.String()),
|
|
column("username", sa.String()),
|
|
column("password_hash", sa.String()),
|
|
column("is_active", sa.Boolean()),
|
|
column("is_superuser", sa.Boolean()),
|
|
)
|
|
|
|
op.bulk_insert(
|
|
users_table,
|
|
[
|
|
{
|
|
"id": 1,
|
|
"email": "admin@calminer.local",
|
|
"username": "admin",
|
|
"password_hash": admin_password_hash,
|
|
"is_active": True,
|
|
"is_superuser": True,
|
|
}
|
|
],
|
|
)
|
|
|
|
user_roles_table = table(
|
|
"user_roles",
|
|
column("user_id", sa.Integer()),
|
|
column("role_id", sa.Integer()),
|
|
column("granted_by", sa.Integer()),
|
|
)
|
|
|
|
op.bulk_insert(
|
|
user_roles_table,
|
|
[
|
|
{
|
|
"user_id": 1,
|
|
"role_id": 1,
|
|
"granted_by": 1,
|
|
}
|
|
],
|
|
)
|
|
|
|
# Ensure a default pricing settings record exists for future project linkage
|
|
_ensure_default_pricing_settings(bind)
|
|
|
|
|
|
def downgrade() -> None:
|
|
# Drop RBAC
|
|
op.drop_index("ix_user_roles_role_id", table_name="user_roles")
|
|
op.drop_table("user_roles")
|
|
|
|
op.drop_table("roles")
|
|
|
|
op.drop_index("ix_users_active_superuser", table_name="users")
|
|
op.drop_table("users")
|
|
|
|
# Drop domain tables
|
|
op.drop_index(
|
|
op.f("ix_simulation_parameters_scenario_id"),
|
|
table_name="simulation_parameters",
|
|
)
|
|
op.drop_index(op.f("ix_simulation_parameters_id"),
|
|
table_name="simulation_parameters")
|
|
op.drop_table("simulation_parameters")
|
|
|
|
op.drop_index(
|
|
op.f("ix_financial_inputs_scenario_id"), table_name="financial_inputs"
|
|
)
|
|
op.drop_index(op.f("ix_financial_inputs_id"),
|
|
table_name="financial_inputs")
|
|
op.drop_table("financial_inputs")
|
|
|
|
op.drop_index(op.f("ix_scenarios_project_id"), table_name="scenarios")
|
|
op.drop_index(op.f("ix_scenarios_id"), table_name="scenarios")
|
|
op.drop_table("scenarios")
|
|
|
|
op.drop_index("ix_projects_pricing_settings_id", table_name="projects")
|
|
op.drop_index(op.f("ix_projects_id"), table_name="projects")
|
|
op.drop_table("projects")
|
|
|
|
# Drop pricing settings ancillary tables
|
|
op.drop_index(
|
|
op.f("ix_pricing_impurity_settings_pricing_settings_id"),
|
|
table_name="pricing_impurity_settings",
|
|
)
|
|
op.drop_index(
|
|
op.f("ix_pricing_impurity_settings_id"),
|
|
table_name="pricing_impurity_settings",
|
|
)
|
|
op.drop_table("pricing_impurity_settings")
|
|
|
|
op.drop_index(
|
|
op.f("ix_pricing_metal_settings_pricing_settings_id"),
|
|
table_name="pricing_metal_settings",
|
|
)
|
|
op.drop_index(
|
|
op.f("ix_pricing_metal_settings_id"),
|
|
table_name="pricing_metal_settings",
|
|
)
|
|
op.drop_table("pricing_metal_settings")
|
|
|
|
op.drop_index(op.f("ix_pricing_settings_id"),
|
|
table_name="pricing_settings")
|
|
op.drop_table("pricing_settings")
|
|
|
|
# Drop enumerations
|
|
resource_type.drop(op.get_bind(), checkfirst=True)
|
|
stochastic_variable.drop(op.get_bind(), checkfirst=True)
|
|
distribution_type.drop(op.get_bind(), checkfirst=True)
|
|
cost_bucket.drop(op.get_bind(), checkfirst=True)
|
|
financial_category.drop(op.get_bind(), checkfirst=True)
|
|
scenario_status.drop(op.get_bind(), checkfirst=True)
|
|
mining_operation_type.drop(op.get_bind(), checkfirst=True)
|