ObjDataModelEdit extends the Axion data layer with
the ability to load, save, synchronise, diff, and
validate data model YAML files against the live database.
While ObjDataModel provides runtime CRUD for
individual records, ObjDataModelEdit manages the
model itself — its table schemas, its reference data,
its version history, and its registry metadata.
A data model is a named YAML file in
resource.datamodels/package.<pkg>/ that declares every
data_* and list_* table a module needs.
ObjData.ObjData
├─ ObjDataModel — runtime CRUD
└─ ObjDataModelEdit — lifecycle manager
Registry — one row per model per package.
| Column | Type | Purpose |
|---|---|---|
| Package | varchar(100) PK | Owning package |
| DataModel | varchar(255) PK | YAML file name |
| Description | text | Human-readable purpose |
| Notes | text | Free-form notes |
| Version | int | Auto-incremented on load |
| VersionDate | datetime | Timestamp of last load |
Junction — many-to-many link between models and
their constituent data_* / list_* tables.
| Column | Type | Purpose |
|---|---|---|
| Package | varchar(100) PK | Package scope |
| DataModel | varchar(255) PK | Model name |
| TableName | varchar(255) PK | The data table |
| Notes | text | Per-table notes |
A single table can appear in multiple models.
The DataModel column exists on three definition
tables, connecting modules to their data models:
| Table | Key Column | Example |
|---|---|---|
| def_formflow | formflow | SW_JOURNEY → gaming_journey |
| def_workflow | WorkflowName | (available) |
| def_service | ServiceCode | (available) |
Files live in resource.datamodels/package.<pkg>/:
resource.datamodels/
package.homechoice/
gaming_journey.yaml
package.fullhouse/
credit_journey.yaml
Path resolution: package → archetype → root fallback.
# 1. Description — stored in def_datamodel
description: >
Human-readable explanation of the model.
# 2. Models — ObjDataModel-compatible schemas
models:
games_intensity:
table: data_games_intensity
guid_field: IntensityLevel
fields:
IntensityLevel:
type: int
primary_key: true
required: true
Intensity:
type: varchar(100)
required: true
# 3. Database schema — CREATE TABLE SQL
database:
schema:
data_games_intensity: |
CREATE TABLE `data_games_intensity` (
`IntensityLevel` int NOT NULL,
`Intensity` varchar(100) NOT NULL,
PRIMARY KEY (`IntensityLevel`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE={collation}
# 4. Data — seed rows with checksum + where filter
data:
data_games_intensity:
rows:
- IntensityLevel: 1
Intensity: "🥉 Bronze"
- IntensityLevel: 2
Intensity: "🥈 Silver"
checksum: b03dbbd57ecc...
where: ""
| Option | Type | Purpose |
|---|---|---|
| type | string | SQL column type |
| primary_key | bool | Column is PK |
| required | bool | NOT NULL |
| default | any | SQL DEFAULT value |
| auto_now | bool | Set to NOW() on save |
| enum | list | Allowed values (validation) |
| max_length | int | Max string length |
| min / max | number | Numeric bounds |
data_* — runtime / transactional datalist_* — lookup / reference listsYAML → DB. Creates tables, registers in
def_datamodel + def_datamodel_tables, seeds data,
bumps version, invalidates ObjDataModel schema cache.
DB → YAML. Introspects via SHOW COLUMNS + SHOW CREATE
TABLE, dumps rows with checksum. Respects existing
where: filters per table.
YAML → DB. Upserts rows only. Verifies checksum if
present.
DB → YAML. Dumps rows only, preserving models: and
database: sections.
Compares YAML fields: vs live SHOW COLUMNS. Issues
ALTER TABLE ADD COLUMN for fields in YAML but missing
from DB. Never drops columns. Returns
{columns_added, columns_orphaned}.
Dry-run comparison. Returns what load_model +
sync_schema would change without writing anything:
{tables_to_create, tables_existing, columns_to_add, rows_to_upsert, rows_in_db}.
Structure check before any DB writes. Verifies
models: section exists, each entry has table + fields,
database.schema keys match model tables, data keys
match.
edit.load_model_for_formflow('SW_JOURNEY')
edit.load_model_for_workflow('MY_WORKFLOW')
edit.load_model_for_service('MY_SERVICE')
Reads the DataModel column from the respective def_*
table and calls load_model automatically.
edit.unregister_table('gaming_journey', 'data_old')
edit.delete_model('gaming_journey', 'HOMECHOICE')
edit.load_all('HOMECHOICE') # every YAML in pkg dir
edit.save_all('HOMECHOICE') # every registered model
edit.list_models('HOMECHOICE')
edit.get_models_for_table('data_games_exceptions')
edit.get_description('gaming_journey', 'HOMECHOICE')
edit.set_description('gaming_journey', '...', 'HOMECHOICE')
where: clause so save_data exports a subset insteadObjDataModel.invalidate_cache() so runtime CRUDpython factory.core/ObjDataModelEdit.py load gaming_journey --package HOMECHOICE
python factory.core/ObjDataModelEdit.py save gaming_journey --package HOMECHOICE
python factory.core/ObjDataModelEdit.py save gaming_journey --no-data
python factory.core/ObjDataModelEdit.py load-data gaming_journey
python factory.core/ObjDataModelEdit.py save-data gaming_journey
python factory.core/ObjDataModelEdit.py sync gaming_journey
python factory.core/ObjDataModelEdit.py diff gaming_journey
python factory.core/ObjDataModelEdit.py validate gaming_journey
python factory.core/ObjDataModelEdit.py list
python factory.core/ObjDataModelEdit.py load-all --package HOMECHOICE
python factory.core/ObjDataModelEdit.py save-all --package HOMECHOICE
python factory.core/ObjDataModelEdit.py delete gaming_journey
python factory.core/ObjDataModelEdit.py load gaming_journey \
--package HOMECHOICE
# Dev: export current state
python factory.core/ObjDataModelEdit.py save gaming_journey
git add resource.datamodels/
git commit -m "data(gaming_journey): update"
# Prod: import
python factory.core/ObjDataModelEdit.py load gaming_journey
# Add field to YAML, then:
python factory.core/ObjDataModelEdit.py sync gaming_journey
Version: 2.0
Author: vheyn@technocore.co.za
Dependencies: ObjData, PyYAML, typer