Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/soa_builder/web/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
_migrate_rollback_add_elements_restored,
_migrate_add_epoch_type,
_migrate_visit_columns,
_migrate_timing_add_member_of_timeline,
)
from .routers import activities as activities_router
from .routers import arms as arms_router
Expand All @@ -72,6 +73,7 @@
from .routers import audits as audits_router

from .routers import timings as timings_router
from .routers import schedule_timelines as schedule_timelines_router
from .routers import instances as instances_router
from .routers.arms import create_arm # re-export for backward compatibility
from .routers.arms import delete_arm
Expand Down Expand Up @@ -159,6 +161,7 @@ def _configure_logging():


# Database migration steps
_migrate_timing_add_member_of_timeline()
_migrate_visit_columns()
_migrate_add_epoch_type()
_migrate_add_arm_uid()
Expand Down Expand Up @@ -193,6 +196,7 @@ def _configure_logging():
app.include_router(timings_router.router)
app.include_router(instances_router.router)
app.include_router(audits_router.router)
app.include_router(schedule_timelines_router.router)


# Create Audit record functions
Expand Down
27 changes: 27 additions & 0 deletions src/soa_builder/web/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,33 @@ def _record_timing_audit(
logger.warning("Failed recording timing audit: %s", e)


def _record_schedule_timeline_audit(
soa_id: int,
action: str,
schedule_timeline_id: int | None,
before: Optional[Dict[str, Any]] = None,
after: Optional[Dict[str, Any]] = None,
):
try:
conn = _connect()
cur = conn.cursor()
cur.execute(
"INSERT into schedule_timelines_audit (soa_id,schedule_timeline_id,action,before_json,after_json,performed_at) VALUES (?,?,?,?,?,?)",
(
soa_id,
schedule_timeline_id,
action,
json.dumps(before) if before else None,
json.dumps(after) if after else None,
datetime.now(timezone.utc).isoformat(),
),
)
conn.commit()
conn.close()
except Exception as e:
logger.warning("Failed recording schedule timeline audit: %s", e)


def _record_instance_audit(
soa_id: int,
action: str,
Expand Down
13 changes: 13 additions & 0 deletions src/soa_builder/web/initialize_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,19 @@ def _init_db():
)"""
)

# create schedule_timelines_audit table
cur.execute(
"""CREATE TABLE IF NOT EXISTS schedule_timelines_audit (
id INTEGER PRIMARY KEY AUTOINCREMENT,
soa_id INTEGER NOT NULL,
instance_id INTEGER,
action TEXT NOT NULL,
before_json TEXT,
after_json TEXT,
performed_at TEXT NOT NULL
)"""
)

# create instance_audit table
cur.execute(
"""CREATE TABLE IF NOT EXISTS instance_audit (
Expand Down
24 changes: 24 additions & 0 deletions src/soa_builder/web/migrate_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,27 @@ def _migrate_visit_columns():
conn.close()
except Exception as e: # pragma: no cover
logger.warning("visit table migration failed: %s", e)


def _migrate_timing_add_member_of_timeline():
"""Add optional member_of_timeline column to timing table if missing."""
try:
conn = _connect()
cur = conn.cursor()
# Ensure timing table exists
cur.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name='timing'"
)
if not cur.fetchone():
conn.close()
return
# Check column presence
cur.execute("PRAGMA table_info(timing)")
cols = {r[1] for r in cur.fetchall()}
if "member_of_timeline" not in cols:
cur.execute("ALTER TABLE timing ADD COLUMN member_of_timeline TEXT")
conn.commit()
logger.info("Added member_of_timeline column to timing table")
conn.close()
except Exception as e: # pragma: no cover
logger.warning("timing member_of_timeline migration failed: %s", e)
6 changes: 3 additions & 3 deletions src/soa_builder/web/routers/instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,16 @@ def create_instance(soa_id: int, payload: InstanceCreate):
instance_id = cur.lastrowid
conn.commit()
conn.close()
row = {
after = {
"id": instance_id,
"instance_uid": new_uid,
"name": name,
"label": (payload.label or "").strip() or None,
"description": (payload.description or "").strip() or None,
}

_record_instance_audit(soa_id, "create", instance_id, before=None, after=row)
return row
_record_instance_audit(soa_id, "create", instance_id, before=None, after=after)
return after


# UI code to create new instance in an SOA
Expand Down
Loading