feat: Implement modular plugin architecture
- Convert invcount to self-contained module - Add Module Manager for install/uninstall - Create module_registry database table - Support hot-reloading of modules - Move data imports into invcount module - Update all templates and routes to new structure Version bumped to 0.16.0
This commit is contained in:
158
modules/invcount/migrations.py
Normal file
158
modules/invcount/migrations.py
Normal file
@@ -0,0 +1,158 @@
|
||||
"""
|
||||
Inventory Counts Module - Database Migrations
|
||||
Contains schema for all inventory counting tables
|
||||
"""
|
||||
|
||||
def get_schema():
|
||||
"""
|
||||
Returns the complete schema SQL for this module.
|
||||
This is used when the module is installed.
|
||||
"""
|
||||
return """
|
||||
-- CountSessions Table
|
||||
CREATE TABLE IF NOT EXISTS CountSessions (
|
||||
session_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_name TEXT NOT NULL,
|
||||
session_type TEXT NOT NULL CHECK(session_type IN ('cycle_count', 'full_physical')),
|
||||
created_by INTEGER NOT NULL,
|
||||
created_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
master_baseline_timestamp DATETIME,
|
||||
current_baseline_timestamp DATETIME,
|
||||
status TEXT DEFAULT 'active' CHECK(status IN ('active', 'completed', 'archived')),
|
||||
branch TEXT DEFAULT 'Main',
|
||||
FOREIGN KEY (created_by) REFERENCES Users(user_id)
|
||||
);
|
||||
|
||||
-- BaselineInventory_Master Table (Session-specific, immutable)
|
||||
CREATE TABLE IF NOT EXISTS BaselineInventory_Master (
|
||||
baseline_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id INTEGER NOT NULL,
|
||||
lot_number TEXT NOT NULL,
|
||||
item TEXT NOT NULL,
|
||||
description TEXT,
|
||||
system_location TEXT NOT NULL,
|
||||
system_bin TEXT NOT NULL,
|
||||
system_quantity REAL NOT NULL,
|
||||
uploaded_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (session_id) REFERENCES CountSessions(session_id)
|
||||
);
|
||||
|
||||
-- BaselineInventory_Current Table (GLOBAL - shared across all sessions)
|
||||
CREATE TABLE IF NOT EXISTS BaselineInventory_Current (
|
||||
current_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
lot_number TEXT NOT NULL,
|
||||
item TEXT NOT NULL,
|
||||
description TEXT,
|
||||
system_location TEXT,
|
||||
system_bin TEXT NOT NULL,
|
||||
system_quantity REAL NOT NULL,
|
||||
upload_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(lot_number, system_bin)
|
||||
);
|
||||
|
||||
-- LocationCounts Table
|
||||
CREATE TABLE IF NOT EXISTS LocationCounts (
|
||||
location_count_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id INTEGER NOT NULL,
|
||||
location_name TEXT NOT NULL,
|
||||
counted_by INTEGER NOT NULL,
|
||||
start_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
end_timestamp DATETIME,
|
||||
status TEXT DEFAULT 'not_started' CHECK(status IN ('not_started', 'in_progress', 'completed')),
|
||||
expected_lots_master INTEGER DEFAULT 0,
|
||||
lots_found INTEGER DEFAULT 0,
|
||||
lots_missing INTEGER DEFAULT 0,
|
||||
is_deleted INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (session_id) REFERENCES CountSessions(session_id),
|
||||
FOREIGN KEY (counted_by) REFERENCES Users(user_id)
|
||||
);
|
||||
|
||||
-- ScanEntries Table
|
||||
CREATE TABLE IF NOT EXISTS ScanEntries (
|
||||
entry_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id INTEGER NOT NULL,
|
||||
location_count_id INTEGER NOT NULL,
|
||||
lot_number TEXT NOT NULL,
|
||||
item TEXT,
|
||||
description TEXT,
|
||||
scanned_location TEXT NOT NULL,
|
||||
actual_weight REAL NOT NULL,
|
||||
scanned_by INTEGER NOT NULL,
|
||||
scan_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- MASTER baseline comparison
|
||||
master_status TEXT CHECK(master_status IN ('match', 'wrong_location', 'ghost_lot', 'missing')),
|
||||
master_expected_location TEXT,
|
||||
master_expected_weight REAL,
|
||||
master_variance_lbs REAL,
|
||||
master_variance_pct REAL,
|
||||
|
||||
-- Duplicate detection
|
||||
duplicate_status TEXT DEFAULT '00' CHECK(duplicate_status IN ('00', '01', '03', '04')),
|
||||
duplicate_info TEXT,
|
||||
|
||||
-- Metadata
|
||||
comment TEXT,
|
||||
is_deleted INTEGER DEFAULT 0,
|
||||
deleted_by INTEGER,
|
||||
deleted_timestamp DATETIME,
|
||||
modified_timestamp DATETIME,
|
||||
|
||||
FOREIGN KEY (session_id) REFERENCES CountSessions(session_id),
|
||||
FOREIGN KEY (location_count_id) REFERENCES LocationCounts(location_count_id),
|
||||
FOREIGN KEY (scanned_by) REFERENCES Users(user_id),
|
||||
FOREIGN KEY (deleted_by) REFERENCES Users(user_id)
|
||||
);
|
||||
|
||||
-- MissingLots Table
|
||||
CREATE TABLE IF NOT EXISTS MissingLots (
|
||||
missing_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id INTEGER NOT NULL,
|
||||
location_count_id INTEGER,
|
||||
lot_number TEXT NOT NULL,
|
||||
item TEXT,
|
||||
master_expected_location TEXT NOT NULL,
|
||||
master_expected_quantity REAL NOT NULL,
|
||||
current_system_location TEXT,
|
||||
current_system_quantity REAL,
|
||||
marked_by INTEGER NOT NULL,
|
||||
marked_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
found_later TEXT DEFAULT 'N' CHECK(found_later IN ('Y', 'N')),
|
||||
found_location TEXT,
|
||||
FOREIGN KEY (session_id) REFERENCES CountSessions(session_id),
|
||||
FOREIGN KEY (location_count_id) REFERENCES LocationCounts(location_count_id),
|
||||
FOREIGN KEY (marked_by) REFERENCES Users(user_id)
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_baseline_master_lot ON BaselineInventory_Master(session_id, lot_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_baseline_master_loc ON BaselineInventory_Master(session_id, system_location);
|
||||
CREATE INDEX IF NOT EXISTS idx_scanentries_session ON ScanEntries(session_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scanentries_location ON ScanEntries(location_count_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scanentries_lot ON ScanEntries(lot_number);
|
||||
CREATE INDEX IF NOT EXISTS idx_scanentries_deleted ON ScanEntries(is_deleted);
|
||||
CREATE INDEX IF NOT EXISTS idx_location_counts ON LocationCounts(session_id, status);
|
||||
"""
|
||||
|
||||
|
||||
def get_migrations():
|
||||
"""
|
||||
Returns list of migrations specific to this module.
|
||||
Format: [(version, name, up_function), ...]
|
||||
"""
|
||||
|
||||
def migration_001_add_is_deleted_to_locationcounts(conn):
|
||||
"""Add is_deleted column to LocationCounts table"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Check if column exists
|
||||
cursor.execute('PRAGMA table_info(LocationCounts)')
|
||||
columns = [row[1] for row in cursor.fetchall()]
|
||||
|
||||
if 'is_deleted' not in columns:
|
||||
cursor.execute('ALTER TABLE LocationCounts ADD COLUMN is_deleted INTEGER DEFAULT 0')
|
||||
print(" Added is_deleted column to LocationCounts")
|
||||
|
||||
return [
|
||||
(1, 'add_is_deleted_to_locationcounts', migration_001_add_is_deleted_to_locationcounts),
|
||||
]
|
||||
Reference in New Issue
Block a user