dodil/erp-brick-fixed-assets

DODIL ERP brick: fixed assets

scripts/gen_schema.py

"""Writes schema.sql and migrations/NNNNN_<name>/{up,down}.sql from infrastructure/tables.py (one column model).
Usage: python scripts/gen_schema.py [name]   (rewrites 00001_init; later releases append a new migration by hand)."""
import pathlib
import sys

from sqlalchemy.dialects import postgresql

sys.path.insert(0, "src")
from brick_fixed_assets.infrastructure.tables import ASSET, CA, COUNT, DEP_RUN, MIGRATION_RUN, TRANSACTION, md  # noqa: E402

HEAD = ("-- Tables of the fixed-assets brick (module `fixed-assets`). Every table prefixed `fa_`, a natural primary key each (never\n"
        "-- SERIAL), money NUMERIC(18,2), units and rates NUMERIC(19,4), creation columns last. Additive only.\n\n")
VERSIONED = {a.root.name: a for a in (ASSET, TRANSACTION, DEP_RUN, CA, COUNT, MIGRATION_RUN)}


def ddl(t) -> str:
    d = postgresql.dialect()
    cols = [f"    {c.name} {c.type.compile(dialect=d).replace(', ', ',')}{' NOT NULL' if c.primary_key else ''}," for c in t.columns]
    pk = ", ".join(c.name for c in t.primary_key.columns)
    return f"CREATE TABLE IF NOT EXISTS {t.name} (\n" + "\n".join(cols) + f"\n    PRIMARY KEY ({pk})\n);\n"


def body() -> str:
    out, done = [], set()
    for t in md.sorted_tables:
        if t.name.endswith("_versions"):
            continue
        out.append(ddl(t))
        if t.name in VERSIONED:
            v = VERSIONED[t.name].versions
            done.add(v.name)
            out.append(VERSIONED[t.name].version_ddl().replace("NUMERIC(18, 2)", "NUMERIC(18,2)"))
    return "\n".join(out).replace("TIMESTAMP WITHOUT TIME ZONE", "TIMESTAMP")


root = pathlib.Path("src/brick_fixed_assets")
text = HEAD + body()
(root / "schema.sql").write_text(text)
mig = root / "migrations" / "00001_init"
mig.mkdir(parents=True, exist_ok=True)
(mig / "up.sql").write_text("-- 00001_init: the brick's first schema. The versioned layout (migrations/NNNNN_<name>/{up,down}.sql) with a\n"
                            "-- per-brick journal; `erp-migrate --schema schema.sql` applies the same tables today.\n\n" + body())
drops = [t.name for t in reversed(md.sorted_tables)]
(mig / "down.sql").write_text("-- 00001_init down: drops every table the brick made. Destroys the brick's data: a rollback of a first install only.\n"
                              + "".join(f"DROP TABLE IF EXISTS {n};\n" for n in drops))
print(len(drops), "tables")