[verified] Implement account valuation history for issue 12
This commit is contained in:
@@ -98,10 +98,28 @@ def migrate_db(conn: sqlite3.Connection) -> None:
|
||||
"correction_reason": "TEXT NOT NULL DEFAULT ''",
|
||||
"is_correction": "INTEGER NOT NULL DEFAULT 0",
|
||||
"closed_at": "TEXT NOT NULL DEFAULT ''",
|
||||
"valuation_id": "TEXT NOT NULL DEFAULT ''",
|
||||
"selection_policy": "TEXT NOT NULL DEFAULT 'exact'",
|
||||
"verification_status": "TEXT NOT NULL DEFAULT 'unverified'",
|
||||
"evidence_kind": "TEXT NOT NULL DEFAULT 'applied'",
|
||||
"exclusion_reason": "TEXT NOT NULL DEFAULT ''",
|
||||
})
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_asset_snapshots_basis_date ON asset_snapshots(basis_date)")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_asset_snapshots_source ON asset_snapshots(source_type, source_id)")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_asset_snapshots_run ON asset_snapshots(basis_date, snapshot_run_id, created_at)")
|
||||
conn.execute("""CREATE TABLE IF NOT EXISTS asset_snapshot_runs (
|
||||
id TEXT PRIMARY KEY, basis_date TEXT NOT NULL, close_status TEXT NOT NULL,
|
||||
selection_policy TEXT NOT NULL DEFAULT 'exact', idempotency_key TEXT NOT NULL DEFAULT '',
|
||||
approved_by TEXT NOT NULL DEFAULT '', approved_at TEXT NOT NULL DEFAULT '',
|
||||
approval_reason TEXT NOT NULL DEFAULT '', approval_reference TEXT NOT NULL DEFAULT '',
|
||||
correction_of_run_id TEXT NOT NULL DEFAULT '', correction_reason TEXT NOT NULL DEFAULT '',
|
||||
applied_evidence TEXT NOT NULL DEFAULT '[]', excluded_evidence TEXT NOT NULL DEFAULT '[]',
|
||||
carried_evidence TEXT NOT NULL DEFAULT '[]', request_fingerprint TEXT NOT NULL DEFAULT '', created_at TEXT NOT NULL
|
||||
)""")
|
||||
_add_missing_columns(conn, "asset_snapshot_runs", {"request_fingerprint": "TEXT NOT NULL DEFAULT ''"})
|
||||
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_snapshot_runs_idempotency ON asset_snapshot_runs(idempotency_key) WHERE idempotency_key <> ''")
|
||||
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_snapshot_runs_initial_basis ON asset_snapshot_runs(basis_date) WHERE correction_of_run_id = ''")
|
||||
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_snapshot_runs_correction_parent ON asset_snapshot_runs(correction_of_run_id) WHERE correction_of_run_id <> ''")
|
||||
conn.execute("""CREATE TABLE IF NOT EXISTS review_decisions (
|
||||
id TEXT PRIMARY KEY,
|
||||
target_type TEXT NOT NULL,
|
||||
@@ -136,6 +154,22 @@ def migrate_db(conn: sqlite3.Connection) -> None:
|
||||
)""")
|
||||
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_reconciliation_sessions_account_basis ON reconciliation_sessions(account_id, basis_date)")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_reconciliation_sessions_status ON reconciliation_sessions(status, closed_at)")
|
||||
conn.execute("""CREATE TABLE IF NOT EXISTS account_valuations (
|
||||
id TEXT PRIMARY KEY, account_id TEXT NOT NULL REFERENCES accounts(id), basis_date TEXT NOT NULL,
|
||||
amount INTEGER NOT NULL, currency TEXT NOT NULL DEFAULT 'KRW', valuation_kind TEXT NOT NULL DEFAULT 'balance',
|
||||
source_type TEXT NOT NULL DEFAULT 'manual', source_ref TEXT NOT NULL DEFAULT '',
|
||||
verification_status TEXT NOT NULL DEFAULT 'unverified', recorded_at TEXT NOT NULL,
|
||||
memo TEXT NOT NULL DEFAULT '', idempotency_key TEXT NOT NULL DEFAULT '',
|
||||
supersedes_id TEXT REFERENCES account_valuations(id), correction_reason TEXT NOT NULL DEFAULT '',
|
||||
as_of_at TEXT, timezone TEXT, cost_basis INTEGER, net_contributed INTEGER,
|
||||
reported_principal_kind TEXT, reported_principal_label TEXT, profit INTEGER,
|
||||
return_rate REAL, return_basis TEXT, principal INTEGER, interest INTEGER, fee INTEGER,
|
||||
representative_liability_definition TEXT
|
||||
)""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_account_valuations_account_date ON account_valuations(account_id, basis_date, recorded_at)")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_account_valuations_status_date ON account_valuations(verification_status, basis_date)")
|
||||
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_account_valuations_idempotency ON account_valuations(account_id, idempotency_key) WHERE idempotency_key <> ''")
|
||||
conn.execute("CREATE UNIQUE INDEX IF NOT EXISTS idx_account_valuations_single_correction ON account_valuations(supersedes_id) WHERE supersedes_id IS NOT NULL")
|
||||
conn.execute("INSERT OR REPLACE INTO schema_meta(key, value) VALUES ('schema_version', ?)", (SCHEMA_VERSION,))
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
SCHEMA_VERSION = "11"
|
||||
SCHEMA_VERSION = "12"
|
||||
|
||||
SCHEMA_SQL = """
|
||||
PRAGMA journal_mode=WAL;
|
||||
@@ -163,11 +163,38 @@ CREATE TABLE IF NOT EXISTS asset_snapshots (
|
||||
correction_reason TEXT NOT NULL DEFAULT '',
|
||||
is_correction INTEGER NOT NULL DEFAULT 0,
|
||||
closed_at TEXT NOT NULL DEFAULT '',
|
||||
valuation_id TEXT NOT NULL DEFAULT '',
|
||||
selection_policy TEXT NOT NULL DEFAULT 'exact',
|
||||
verification_status TEXT NOT NULL DEFAULT 'unverified',
|
||||
evidence_kind TEXT NOT NULL DEFAULT 'applied',
|
||||
exclusion_reason TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_asset_snapshots_basis_date ON asset_snapshots(basis_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_asset_snapshots_source ON asset_snapshots(source_type, source_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS asset_snapshot_runs (
|
||||
id TEXT PRIMARY KEY,
|
||||
basis_date TEXT NOT NULL,
|
||||
close_status TEXT NOT NULL,
|
||||
selection_policy TEXT NOT NULL DEFAULT 'exact',
|
||||
idempotency_key TEXT NOT NULL DEFAULT '',
|
||||
approved_by TEXT NOT NULL DEFAULT '',
|
||||
approved_at TEXT NOT NULL DEFAULT '',
|
||||
approval_reason TEXT NOT NULL DEFAULT '',
|
||||
approval_reference TEXT NOT NULL DEFAULT '',
|
||||
correction_of_run_id TEXT NOT NULL DEFAULT '',
|
||||
correction_reason TEXT NOT NULL DEFAULT '',
|
||||
applied_evidence TEXT NOT NULL DEFAULT '[]',
|
||||
excluded_evidence TEXT NOT NULL DEFAULT '[]',
|
||||
carried_evidence TEXT NOT NULL DEFAULT '[]',
|
||||
request_fingerprint TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_snapshot_runs_idempotency ON asset_snapshot_runs(idempotency_key) WHERE idempotency_key <> '';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_snapshot_runs_initial_basis ON asset_snapshot_runs(basis_date) WHERE correction_of_run_id = '';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_asset_snapshot_runs_correction_parent ON asset_snapshot_runs(correction_of_run_id) WHERE correction_of_run_id <> '';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS review_decisions (
|
||||
id TEXT PRIMARY KEY,
|
||||
target_type TEXT NOT NULL,
|
||||
@@ -204,7 +231,41 @@ CREATE TABLE IF NOT EXISTS reconciliation_sessions (
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_reconciliation_sessions_account_basis ON reconciliation_sessions(account_id, basis_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_reconciliation_sessions_status ON reconciliation_sessions(status, closed_at);
|
||||
|
||||
INSERT OR REPLACE INTO schema_meta(key, value) VALUES ('schema_version', '11');
|
||||
CREATE TABLE IF NOT EXISTS account_valuations (
|
||||
id TEXT PRIMARY KEY,
|
||||
account_id TEXT NOT NULL REFERENCES accounts(id),
|
||||
basis_date TEXT NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
currency TEXT NOT NULL DEFAULT 'KRW',
|
||||
valuation_kind TEXT NOT NULL DEFAULT 'balance',
|
||||
source_type TEXT NOT NULL DEFAULT 'manual',
|
||||
source_ref TEXT NOT NULL DEFAULT '',
|
||||
verification_status TEXT NOT NULL DEFAULT 'unverified',
|
||||
recorded_at TEXT NOT NULL,
|
||||
memo TEXT NOT NULL DEFAULT '',
|
||||
idempotency_key TEXT NOT NULL DEFAULT '',
|
||||
supersedes_id TEXT REFERENCES account_valuations(id),
|
||||
correction_reason TEXT NOT NULL DEFAULT '',
|
||||
as_of_at TEXT,
|
||||
timezone TEXT,
|
||||
cost_basis INTEGER,
|
||||
net_contributed INTEGER,
|
||||
reported_principal_kind TEXT,
|
||||
reported_principal_label TEXT,
|
||||
profit INTEGER,
|
||||
return_rate REAL,
|
||||
return_basis TEXT,
|
||||
principal INTEGER,
|
||||
interest INTEGER,
|
||||
fee INTEGER,
|
||||
representative_liability_definition TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_account_valuations_account_date ON account_valuations(account_id, basis_date, recorded_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_account_valuations_status_date ON account_valuations(verification_status, basis_date);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_account_valuations_idempotency ON account_valuations(account_id, idempotency_key) WHERE idempotency_key <> '';
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_account_valuations_single_correction ON account_valuations(supersedes_id) WHERE supersedes_id IS NOT NULL;
|
||||
|
||||
INSERT OR REPLACE INTO schema_meta(key, value) VALUES ('schema_version', '12');
|
||||
"""
|
||||
|
||||
ACCOUNT_ADDITIVE_COLUMNS: dict[str, str] = {
|
||||
|
||||
Reference in New Issue
Block a user