diff --git a/backend/auction/migrations/0002_auction_cover_image_auction_is_published_and_more.py b/backend/auction/migrations/0002_auction_cover_image_auction_is_published_and_more.py new file mode 100644 index 0000000..0364e4a --- /dev/null +++ b/backend/auction/migrations/0002_auction_cover_image_auction_is_published_and_more.py @@ -0,0 +1,65 @@ +# Generated by Django 4.2.6 on 2023-11-25 01:48 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("contenttypes", "0002_remove_content_type_name"), + ("auction", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="auction", + name="cover_image", + field=models.CharField(blank=True, max_length=500, null=True), + ), + migrations.AddField( + model_name="auction", + name="is_published", + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name="auction", + name="name", + field=models.CharField(blank=True, max_length=150, null=True), + ), + migrations.CreateModel( + name="AuctionItem", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + unique=True, + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("object_id", models.UUIDField()), + ( + "auction_id", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="auction.auction", + ), + ), + ( + "content_type", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="contenttypes.contenttype", + ), + ), + ], + options={ + "unique_together": {("auction_id", "content_type", "object_id")}, + }, + ), + ] diff --git a/backend/auction/models.py b/backend/auction/models.py index a78426f..d9ea264 100644 --- a/backend/auction/models.py +++ b/backend/auction/models.py @@ -1,3 +1,6 @@ +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError from django.db import models from core.models import MainModel @@ -8,9 +11,11 @@ class Auction(MainModel): Auction that bidders can place bid on vehicles """ - name = models.CharField(max_length=150) + name = models.CharField(max_length=150, null=True, blank=True) start_date = models.DateTimeField(null=False) end_date = models.DateTimeField(null=False) + cover_image = models.CharField(max_length=500, null=True, blank=True) + is_published = models.BooleanField(default=False) def __str__(self): return ( @@ -18,3 +23,27 @@ def __str__(self): if self.name is not None else "Auction at {start_date} to {end_date}" ) + + +class AuctionItem(MainModel): + """ + Items that bidders can bid on in a given auction + """ + + auction_id = models.ForeignKey(Auction, on_delete=models.PROTECT) + content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT) + object_id = models.UUIDField() + content_object = GenericForeignKey("content_type", "object_id") + + class Meta: + unique_together = ("auction_id", "content_type", "object_id") + + def clean(self): + # Restrict content_type to specific models + valid_models = ["vehicle", "equipment", "trailer"] + if self.content_type.model not in valid_models: + raise ValidationError(f"ContentType must be one of {valid_models}") + + def save(self, *args, **kwargs): + self.clean() + super().save(*args, **kwargs) diff --git a/backend/bid/migrations/0002_bid_auction.py b/backend/bid/migrations/0002_bid_auction.py new file mode 100644 index 0000000..d56fe7b --- /dev/null +++ b/backend/bid/migrations/0002_bid_auction.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.6 on 2023-11-25 01:48 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("auction", "0002_auction_cover_image_auction_is_published_and_more"), + ("bid", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="bid", + name="auction", + field=models.ForeignKey( + default=0, + on_delete=django.db.models.deletion.PROTECT, + to="auction.auction", + ), + preserve_default=False, + ), + ] diff --git a/backend/bid/models.py b/backend/bid/models.py index bf465d7..4b8b50b 100644 --- a/backend/bid/models.py +++ b/backend/bid/models.py @@ -1,5 +1,6 @@ from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError from django.db import models from core.models import MainModel @@ -13,6 +14,17 @@ class Bid(MainModel): amount = models.IntegerField(null=False) bidder = models.ForeignKey(Bidder, on_delete=models.PROTECT) + auction = models.ForeignKey("auction.Auction", on_delete=models.PROTECT) content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT) object_id = models.UUIDField() content_object = GenericForeignKey("content_type", "object_id") + + def clean(self): + # Restrict content_type to specific models + valid_models = ["vehicle", "equipment", "trailer"] + if self.content_type.model not in valid_models: + raise ValidationError(f"ContentType must be one of {valid_models}") + + def save(self, *args, **kwargs): + self.clean() + super().save(*args, **kwargs) diff --git a/backend/user/models.py b/backend/user/models.py index d259e87..d1240c3 100644 --- a/backend/user/models.py +++ b/backend/user/models.py @@ -35,10 +35,11 @@ def save(self, *args, **kwargs): def generate_unique_bidder_number(self): # Generate an 8-digit number and check if it's unique - while True: + for _ in range(99999999): bidder_number = random.randint(10000000, 99999999) if not Bidder.objects.filter(bidder_number=bidder_number).exists(): return bidder_number + raise Exception("Could not generate unique bidder number") def __str__(self): return f"Bidder: {self.first_name} {self.last_name}" diff --git a/backend/vehicle/migrations/0003_savedunits.py b/backend/vehicle/migrations/0003_savedunits.py new file mode 100644 index 0000000..e34a98c --- /dev/null +++ b/backend/vehicle/migrations/0003_savedunits.py @@ -0,0 +1,61 @@ +# Generated by Django 4.2.6 on 2023-11-25 01:48 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("user", "0003_remove_admin_password"), + ("contenttypes", "0002_remove_content_type_name"), + ("auction", "0002_auction_cover_image_auction_is_published_and_more"), + ( + "vehicle", + "0002_rename_hydraulic_cylindar_condition_equipment_hydraulic_cylinder_condition", + ), + ] + + operations = [ + migrations.CreateModel( + name="SavedUnits", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + unique=True, + ), + ), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ("object_id", models.UUIDField()), + ( + "auction_id", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="auction.auction", + ), + ), + ( + "bidder_id", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="user.bidder" + ), + ), + ( + "content_type", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="contenttypes.contenttype", + ), + ), + ], + options={ + "unique_together": {("auction_id", "bidder_id", "object_id")}, + }, + ), + ] diff --git a/backend/vehicle/models.py b/backend/vehicle/models.py index 959071c..fcd248f 100644 --- a/backend/vehicle/models.py +++ b/backend/vehicle/models.py @@ -1,5 +1,6 @@ from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError from django.db import models from core.models import MainModel @@ -77,3 +78,34 @@ class UnitImage(MainModel): content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT) object_id = models.UUIDField() content_object = GenericForeignKey("content_type", "object_id") + + def clean(self): + # Restrict content_type to specific models + valid_models = ["vehicle", "equipment", "trailer"] + if self.content_type.model not in valid_models: + raise ValidationError(f"ContentType must be one of {valid_models}") + + def save(self, *args, **kwargs): + self.clean() + super().save(*args, **kwargs) + + +class SavedUnits(MainModel): + bidder_id = models.ForeignKey("user.Bidder", on_delete=models.PROTECT) + auction_id = models.ForeignKey("auction.Auction", on_delete=models.PROTECT) + content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT) + object_id = models.UUIDField() + content_object = GenericForeignKey("content_type", "object_id") + + class Meta: + unique_together = ("auction_id", "bidder_id", "object_id") + + def clean(self): + # Restrict content_type to specific models + valid_models = ["vehicle", "equipment", "trailer"] + if self.content_type.model not in valid_models: + raise ValidationError(f"ContentType must be one of {valid_models}") + + def save(self, *args, **kwargs): + self.clean() + super().save(*args, **kwargs)