From 7c2db40eab36b7e291d1d5eb35d7ef6e96043f99 Mon Sep 17 00:00:00 2001 From: jedi Date: Wed, 26 Aug 2026 17:53:29 +0200 Subject: [PATCH] stash --- .../0018_ownerstoragelocationsequence.py | 23 ++++++++++ ...9_rename_id_storagelocation_internal_id.py | 21 +++++++++ .../migrations/0020_storagelocation_id.py | 16 +++++++ .../0021_backfill_storagelocation_id.py | 40 ++++++++++++++++++ ..._storagelocation_id_not_null_and_unique.py | 20 +++++++++ .../src/assets/fonts/pixel/Silkscreen.ttf | Bin 0 -> 32220 bytes 6 files changed, 120 insertions(+) create mode 100644 backend/toolshed/migrations/0018_ownerstoragelocationsequence.py create mode 100644 backend/toolshed/migrations/0019_rename_id_storagelocation_internal_id.py create mode 100644 backend/toolshed/migrations/0020_storagelocation_id.py create mode 100644 backend/toolshed/migrations/0021_backfill_storagelocation_id.py create mode 100644 backend/toolshed/migrations/0022_storagelocation_id_not_null_and_unique.py create mode 100644 frontend/src/assets/fonts/pixel/Silkscreen.ttf diff --git a/backend/toolshed/migrations/0018_ownerstoragelocationsequence.py b/backend/toolshed/migrations/0018_ownerstoragelocationsequence.py new file mode 100644 index 0000000..cc405b0 --- /dev/null +++ b/backend/toolshed/migrations/0018_ownerstoragelocationsequence.py @@ -0,0 +1,23 @@ +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('toolshed', '0017_inventoryitem_id_not_null_and_unique'), + ] + + operations = [ + migrations.CreateModel( + name='OwnerStorageLocationSequence', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('last_id', models.PositiveIntegerField(default=0)), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', + to=settings.AUTH_USER_MODEL, unique=True)), + ], + ), + ] diff --git a/backend/toolshed/migrations/0019_rename_id_storagelocation_internal_id.py b/backend/toolshed/migrations/0019_rename_id_storagelocation_internal_id.py new file mode 100644 index 0000000..5d8f4fd --- /dev/null +++ b/backend/toolshed/migrations/0019_rename_id_storagelocation_internal_id.py @@ -0,0 +1,21 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('toolshed', '0018_ownerstoragelocationsequence'), + ] + + operations = [ + migrations.RenameField( + model_name='storagelocation', + old_name='id', + new_name='internal_id', + ), + migrations.AlterField( + model_name='storagelocation', + name='internal_id', + field=models.AutoField(primary_key=True, serialize=False), + ), + ] diff --git a/backend/toolshed/migrations/0020_storagelocation_id.py b/backend/toolshed/migrations/0020_storagelocation_id.py new file mode 100644 index 0000000..0c27590 --- /dev/null +++ b/backend/toolshed/migrations/0020_storagelocation_id.py @@ -0,0 +1,16 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('toolshed', '0019_rename_id_storagelocation_internal_id'), + ] + + operations = [ + migrations.AddField( + model_name='storagelocation', + name='id', + field=models.PositiveIntegerField(editable=False, null=True), + ), + ] diff --git a/backend/toolshed/migrations/0021_backfill_storagelocation_id.py b/backend/toolshed/migrations/0021_backfill_storagelocation_id.py new file mode 100644 index 0000000..3516cd2 --- /dev/null +++ b/backend/toolshed/migrations/0021_backfill_storagelocation_id.py @@ -0,0 +1,40 @@ +from django.db import migrations + + +def collapse_ids(apps, schema_editor): + """Collapse each owner's StorageLocation ids from the sparse global range they had before this + migration down to a continuous 1..N range, in original creation order (internal_id order). Then + seed OwnerStorageLocationSequence so future allocation continues right after.""" + StorageLocation = apps.get_model('toolshed', 'StorageLocation') + OwnerStorageLocationSequence = apps.get_model('toolshed', 'OwnerStorageLocationSequence') + + scope = None + next_id = 0 + counts = {} + for location in StorageLocation.objects.order_by('owner_id', 'internal_id'): + key = location.owner_id + if key != scope: + scope = key + next_id = 0 + next_id += 1 + location.id = next_id + location.save(update_fields=['id']) + counts[key] = next_id + + for owner_id, count in counts.items(): + OwnerStorageLocationSequence.objects.update_or_create(owner_id=owner_id, defaults={'last_id': count}) + + +def noop_reverse(apps, schema_editor): + pass + + +class Migration(migrations.Migration): + + dependencies = [ + ('toolshed', '0020_storagelocation_id'), + ] + + operations = [ + migrations.RunPython(collapse_ids, noop_reverse), + ] diff --git a/backend/toolshed/migrations/0022_storagelocation_id_not_null_and_unique.py b/backend/toolshed/migrations/0022_storagelocation_id_not_null_and_unique.py new file mode 100644 index 0000000..7c5b178 --- /dev/null +++ b/backend/toolshed/migrations/0022_storagelocation_id_not_null_and_unique.py @@ -0,0 +1,20 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('toolshed', '0021_backfill_storagelocation_id'), + ] + + operations = [ + migrations.AlterField( + model_name='storagelocation', + name='id', + field=models.PositiveIntegerField(editable=False), + ), + migrations.AddConstraint( + model_name='storagelocation', + constraint=models.UniqueConstraint(fields=('owner', 'id'), name='storagelocation_unique_owner_scoped_id'), + ), + ] diff --git a/frontend/src/assets/fonts/pixel/Silkscreen.ttf b/frontend/src/assets/fonts/pixel/Silkscreen.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8caff819d666217fe8240ede768ef86d086b453b GIT binary patch literal 32220 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