diff --git a/foundation/migrations/0007_business_created_on.py b/foundation/migrations/0007_business_created_on.py new file mode 100644 index 000000000..270d96494 --- /dev/null +++ b/foundation/migrations/0007_business_created_on.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.5 on 2025-03-05 09:18 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('foundation', '0006_hardcode_currency_choices'), + ] + + operations = [ + migrations.AddField( + model_name='business', + name='created_on', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + ] diff --git a/foundation/models.py b/foundation/models.py index 598ee2116..2bdc87fb1 100644 --- a/foundation/models.py +++ b/foundation/models.py @@ -207,6 +207,7 @@ class Business(models.Model): meeting = models.ForeignKey( Meeting, related_name="business", on_delete=models.CASCADE ) + created_on = models.DateTimeField(auto_now_add=True) class Meta: ordering = ("title",) diff --git a/foundation/tests.py b/foundation/tests.py index 38569f375..e706636d2 100644 --- a/foundation/tests.py +++ b/foundation/tests.py @@ -1,4 +1,4 @@ -from datetime import date +from datetime import date, datetime, timedelta from django.contrib.auth.models import User from django.test import TestCase @@ -113,3 +113,71 @@ def test_latest_meeting_minutes(self): self.assertContains(response, "Business item 1") self.assertContains(response, "Business item 2") self.assertContains(response, "Business item 3") + + def test_new_business_ordering(self): + """Test that new business items are ordered by created_on timestamp.""" + meeting = Meeting.objects.create( + date=date(2023, 6, 15), + title="DSF Board monthly meeting", + slug="dsf-board-monthly-meeting", + leader=self.member, + treasurer_report="Treasurer Report", + ) + + # Create business items with explicitly set created_on timestamps + # Item 3 is created first but should appear last due to ordering + common_business_data = { + "body": "Example", + "body_html": "Example", + "business_type": "New", + "meeting": meeting, + } + + # Create items with different timestamps, intentionally out of order + now = datetime.now() + Business.objects.create( + title="Business item 3", + created_on=now - timedelta(hours=2), + **common_business_data + ) + Business.objects.create( + title="Business item 1", + created_on=now - timedelta(hours=4), + **common_business_data + ) + Business.objects.create( + title="Business item 2", + created_on=now - timedelta(hours=3), + **common_business_data + ) + response = self.client.get( + reverse( + "foundation_meeting_detail", + kwargs={ + "year": 2023, + "month": "jun", + "day": 15, + "slug": "dsf-board-monthly-meeting", + }, + ) + ) + + self.assertContains(response, "DSF Board monthly meeting") + + # Check that items appear in the correct order based on created_on + content = response.content.decode() + # Find positions of each business item in the response content + pos1 = content.find("Business item 1") + pos2 = content.find("Business item 2") + pos3 = content.find("Business item 3") + + # Verify that items appear in ascending order by created_on timestamp + self.assertGreater(pos1, 0, "Business item 1 not found in response") + self.assertGreater(pos2, 0, "Business item 2 not found in response") + self.assertGreater(pos3, 0, "Business item 3 not found in response") + self.assertLess( + pos1, pos2, "Business item 1 should appear before Business item 2" + ) + self.assertLess( + pos2, pos3, "Business item 2 should appear before Business item 3" + ) diff --git a/foundation/views.py b/foundation/views.py index 0cef304de..822fb62f7 100644 --- a/foundation/views.py +++ b/foundation/views.py @@ -51,7 +51,7 @@ def get_context_data(self, **kwargs): ) context_data["new_business"] = meeting.business.filter( business_type=models.Business.NEW - ) + ).order_by("created_on") return context_data