from django.db import migrations, models def _table_columns(schema_editor, table): connection = schema_editor.connection with connection.cursor() as cursor: return { col.name for col in connection.introspection.get_table_description(cursor, table) } def _ensure_varchar_column(schema_editor, table, column, max_length): """Add a non-null varchar column with empty default when missing; else clear NULLs.""" connection = schema_editor.connection q_table = connection.ops.quote_name(table) q_column = connection.ops.quote_name(column) if column in _table_columns(schema_editor, table): with connection.cursor() as cursor: cursor.execute( f"UPDATE {q_table} SET {q_column} = '' WHERE {q_column} IS NULL" ) return with connection.cursor() as cursor: cursor.execute( f"ALTER TABLE {q_table} " f"ADD COLUMN {q_column} varchar({max_length}) DEFAULT '' NOT NULL" ) def add_missing_columns(apps, schema_editor): """ Ensure schema columns match current models. Idempotent for local/prod DBs that already have some of these columns. Also re-checks treasury event_name in case an older 0009 only updated state. """ specs = [ ('accounting_vouchers', 'regarding', 255), ('accounting_invoice_lines', 'event_name', 255), ('accounting_treasury_txns', 'event_name', 200), ] for table, column, max_length in specs: _ensure_varchar_column(schema_editor, table, column, max_length) class Migration(migrations.Migration): dependencies = [ ('accounting', '0009_treasury_event_name'), ] operations = [ migrations.SeparateDatabaseAndState( state_operations=[ migrations.AddField( model_name='invoiceline', name='event_name', field=models.CharField(blank=True, default='', max_length=255), ), migrations.AddField( model_name='voucher', name='regarding', field=models.CharField(blank=True, default='', max_length=255), ), migrations.AlterField( model_name='party', name='external_source', field=models.CharField( blank=True, choices=[ ('', 'Manual'), ('funzone_customer', 'FunZone Customer'), ('funzone_owner', 'FunZone Owner'), ], default='', max_length=30, ), ), ], database_operations=[ migrations.RunPython(add_missing_columns, migrations.RunPython.noop), ], ), ]