adapt and fix

testing
Christian Merten 2 months ago
parent ad33d5db17
commit 5edb897bc2
Signed by: christian.merten
GPG Key ID: D953D69721B948B3

@ -64,7 +64,7 @@ def decorate_statement_view(model, perm=None):
@admin.register(StatementUnSubmitted)
class StatementUnSubmittedAdmin(CommonAdminMixin, admin.ModelAdmin):
fields = ['short_description', 'explanation', 'excursion', 'submitted']
fields = ['short_description', 'explanation', 'excursion', 'status']
list_display = ['__str__', 'excursion', 'created_by']
inlines = [BillOnStatementInline]
@ -74,7 +74,7 @@ class StatementUnSubmittedAdmin(CommonAdminMixin, admin.ModelAdmin):
super().save_model(request, obj, form, change)
def get_readonly_fields(self, request, obj=None):
readonly_fields = ['submitted', 'excursion']
readonly_fields = ['status', 'excursion']
if obj is not None and obj.submitted:
return readonly_fields + self.fields
else:
@ -167,7 +167,7 @@ class BillOnSubmittedStatementInline(BillOnStatementInline):
@admin.register(StatementSubmitted)
class StatementSubmittedAdmin(admin.ModelAdmin):
fields = ['short_description', 'explanation', 'excursion', 'submitted']
fields = ['short_description', 'explanation', 'excursion', 'status']
list_display = ['__str__', 'is_valid', 'submitted_date', 'submitted_by']
ordering = ('-submitted_date',)
inlines = [BillOnSubmittedStatementInline, TransactionOnSubmittedStatementInline]
@ -186,7 +186,7 @@ class StatementSubmittedAdmin(admin.ModelAdmin):
return False
def get_readonly_fields(self, request, obj=None):
readonly_fields = ['submitted']
readonly_fields = ['status']
if obj is not None and obj.submitted:
return readonly_fields + self.fields
else:
@ -274,7 +274,7 @@ class StatementSubmittedAdmin(admin.ModelAdmin):
return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name)))
if "reject" in request.POST:
statement.submitted = False
statement.status = Statement.UNSUBMITTED
statement.save()
messages.success(request,
_("Successfully rejected %(name)s. The requestor can reapply, when needed.")
@ -315,7 +315,7 @@ class StatementSubmittedAdmin(admin.ModelAdmin):
@admin.register(StatementConfirmed)
class StatementConfirmedAdmin(admin.ModelAdmin):
fields = ['short_description', 'explanation', 'excursion', 'confirmed']
fields = ['short_description', 'explanation', 'excursion', 'status']
#readonly_fields = fields
list_display = ['__str__', 'total_pretty', 'confirmed_date', 'confirmed_by']
ordering = ('-confirmed_date',)
@ -365,7 +365,7 @@ class StatementConfirmedAdmin(admin.ModelAdmin):
_("%(name)s is not yet confirmed.") % {'name': str(statement)})
return HttpResponseRedirect(reverse('admin:%s_%s_change' % (self.opts.app_label, self.opts.model_name), args=(statement.pk,)))
if "unconfirm" in request.POST:
statement.confirmed = False
statement.status = Statement.SUBMITTED
statement.confirmed_date = None
statement.confired_by = None
statement.save()

@ -0,0 +1,39 @@
# Generated by Django 4.2.20 on 2025-10-11 15:43
from django.db import migrations, models
def set_status_from_old_fields(apps, schema_editor):
"""
Set the status field based on the existing submitted and confirmed fields.
- If confirmed is True, status = CONFIRMED (2)
- If submitted is True but confirmed is False, status = SUBMITTED (1)
- Otherwise, status = UNSUBMITTED (0)
"""
Statement = apps.get_model('finance', 'Statement')
UNSUBMITTED, SUBMITTED, CONFIRMED = 0, 1, 2
for statement in Statement.objects.all():
if statement.confirmed:
statement.status = CONFIRMED
elif statement.submitted:
statement.status = SUBMITTED
else:
statement.status = UNSUBMITTED
statement.save(update_fields=['status'])
class Migration(migrations.Migration):
dependencies = [
('finance', '0009_statement_ljp_to'),
]
operations = [
migrations.AddField(
model_name='statement',
name='status',
field=models.IntegerField(choices=[(0, 'In preparation'), (1, 'Submitted'), (2, 'Confirmed')], default=0, verbose_name='Status'),
),
migrations.RunPython(set_status_from_old_fields, reverse_code=migrations.RunPython.noop),
]

@ -0,0 +1,21 @@
# Generated by Django 4.2.20 on 2025-10-11 16:01
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('finance', '0010_statement_status'),
]
operations = [
migrations.RemoveField(
model_name='statement',
name='confirmed',
),
migrations.RemoveField(
model_name='statement',
name='submitted',
),
]

@ -46,11 +46,15 @@ class TransactionIssue:
class StatementManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(submitted=False, confirmed=False)
return super().get_queryset().filter(status=Statement.UNSUBMITTED)
class Statement(CommonModel):
MISSING_LEDGER, NON_MATCHING_TRANSACTIONS, INVALID_ALLOWANCE_TO, INVALID_TOTAL, VALID = 0, 1, 2, 3, 4
UNSUBMITTED, SUBMITTED, CONFIRMED = 0, 1, 2
STATUS_CHOICES = [(UNSUBMITTED, _('In preparation')),
(SUBMITTED, _('Submitted')),
(CONFIRMED, _('Confirmed'))]
short_description = models.CharField(verbose_name=_('Short description'),
max_length=30,
@ -82,9 +86,10 @@ class Statement(CommonModel):
night_cost = models.DecimalField(verbose_name=_('Price per night'), default=0, decimal_places=2, max_digits=5)
submitted = models.BooleanField(verbose_name=_('Submitted'), default=False)
status = models.IntegerField(verbose_name=_('Status'),
choices=STATUS_CHOICES,
default=UNSUBMITTED)
submitted_date = models.DateTimeField(verbose_name=_('Submitted on'), default=None, null=True)
confirmed = models.BooleanField(verbose_name=_('Confirmed'), default=False)
confirmed_date = models.DateTimeField(verbose_name=_('Paid on'), default=None, null=True)
created_by = models.ForeignKey(Member, verbose_name=_('Created by'),
@ -131,8 +136,16 @@ class Statement(CommonModel):
else:
return self.short_description
@property
def submitted(self):
return self.status == Statement.SUBMITTED or self.status == Statement.CONFIRMED
@property
def confirmed(self):
return self.status == Statement.CONFIRMED
def submit(self, submitter=None):
self.submitted = True
self.status = self.SUBMITTED
self.submitted_date = timezone.now()
self.submitted_by = submitter
self.save()
@ -231,7 +244,7 @@ class Statement(CommonModel):
if not self.validity == Statement.VALID:
return False
self.confirmed = True
self.status = self.CONFIRMED
self.confirmed_date = timezone.now()
self.confirmed_by = confirmer
for trans in self.transaction_set.all():
@ -569,7 +582,7 @@ class Statement(CommonModel):
class StatementUnSubmittedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(submitted=False, confirmed=False)
return super().get_queryset().filter(status=Statement.UNSUBMITTED)
class StatementUnSubmitted(Statement):
@ -589,7 +602,7 @@ class StatementUnSubmitted(Statement):
class StatementSubmittedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(submitted=True, confirmed=False)
return super().get_queryset().filter(status=Statement.SUBMITTED)
class StatementSubmitted(Statement):
@ -606,7 +619,7 @@ class StatementSubmitted(Statement):
class StatementConfirmedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(confirmed=True)
return super().get_queryset().filter(status=Statement.CONFIRMED)
class StatementConfirmed(Statement):

@ -99,16 +99,16 @@ class StatementUnSubmittedAdminTestCase(AdminTestCase):
def test_get_readonly_fields_submitted(self):
"""Test readonly fields when statement is submitted"""
# Mark statement as submitted
self.statement.submitted = True
self.statement.status = Statement.SUBMITTED
readonly_fields = self.admin.get_readonly_fields(None, self.statement)
self.assertIn('submitted', readonly_fields)
self.assertIn('status', readonly_fields)
self.assertIn('excursion', readonly_fields)
self.assertIn('short_description', readonly_fields)
def test_get_readonly_fields_not_submitted(self):
"""Test readonly fields when statement is not submitted"""
readonly_fields = self.admin.get_readonly_fields(None, self.statement)
self.assertEqual(readonly_fields, ['submitted', 'excursion'])
self.assertEqual(readonly_fields, ['status', 'excursion'])
def test_submit_view_insufficient_permission(self):
url = reverse('admin:finance_statementunsubmitted_submit',
@ -163,7 +163,7 @@ class StatementSubmittedAdminTestCase(AdminTestCase):
self.statement = Statement.objects.create(
short_description='Submitted Statement',
explanation='Test explanation',
submitted=True,
status=Statement.SUBMITTED,
submitted_by=self.member,
submitted_date=timezone.now(),
night_cost=25
@ -198,7 +198,7 @@ class StatementSubmittedAdminTestCase(AdminTestCase):
self.statement_no_trans_success = Statement.objects.create(
short_description='No Transactions Success',
explanation='Test explanation',
submitted=True,
status=Statement.SUBMITTED,
submitted_by=self.member,
submitted_date=timezone.now(),
night_cost=25
@ -206,7 +206,7 @@ class StatementSubmittedAdminTestCase(AdminTestCase):
self.statement_no_trans_error = Statement.objects.create(
short_description='No Transactions Error',
explanation='Test explanation',
submitted=True,
status=Statement.SUBMITTED,
submitted_by=self.member,
submitted_date=timezone.now(),
night_cost=25
@ -294,7 +294,7 @@ class StatementSubmittedAdminTestCase(AdminTestCase):
"""Test overview_view with statement that can't be found in StatementSubmitted queryset"""
# When trying to access an unsubmitted statement via StatementSubmitted admin,
# the decorator will fail to find it and show "Statement not found"
self.statement.submitted = False
self.statement.status = Statement.UNSUBMITTED
self.statement.save()
url = reverse('admin:finance_statementsubmitted_overview', args=(self.statement.pk,))
@ -496,8 +496,7 @@ class StatementConfirmedAdminTestCase(AdminTestCase):
base_statement = Statement.objects.create(
short_description='Confirmed Statement',
explanation='Test explanation',
submitted=True,
confirmed=True,
status=Statement.CONFIRMED,
confirmed_by=self.member,
confirmed_date=timezone.now(),
night_cost=25
@ -510,8 +509,7 @@ class StatementConfirmedAdminTestCase(AdminTestCase):
self.unconfirmed_statement = Statement.objects.create(
short_description='Unconfirmed Statement',
explanation='Test explanation',
submitted=True,
confirmed=False,
status=Statement.SUBMITTED,
night_cost=25
)
@ -528,8 +526,7 @@ class StatementConfirmedAdminTestCase(AdminTestCase):
confirmed_with_excursion_base = Statement.objects.create(
short_description='Confirmed with Excursion',
explanation='Test explanation',
submitted=True,
confirmed=True,
status=Statement.CONFIRMED,
confirmed_by=self.member,
confirmed_date=timezone.now(),
excursion=self.excursion,

@ -505,11 +505,11 @@ class ManagerTestCase(TestCase):
self.st_submitted = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0,
submitted=True)
status=Statement.SUBMITTED)
self.st_confirmed = Statement.objects.create(short_description='A statement',
explanation='Important!',
night_cost=0,
confirmed=True)
status=Statement.CONFIRMED)
def test_get_queryset(self):
# TODO: remove this manager, since it is not used

@ -52,15 +52,15 @@ class FinanceRulesTestCase(TestCase):
def test_not_submitted_statement(self):
"""Test not_submitted predicate returns True when statement is not submitted"""
self.statement.submitted = False
self.statement.status = Statement.UNSUBMITTED
self.assertTrue(not_submitted(self.user1, self.statement))
self.statement.submitted = True
self.statement.status = Statement.SUBMITTED
self.assertFalse(not_submitted(self.user1, self.statement))
def test_not_submitted_freizeit_with_statement(self):
"""Test not_submitted predicate with Freizeit having unsubmitted statement"""
self.freizeit.statement = self.statement
self.statement.submitted = False
self.statement.status = Statement.UNSUBMITTED
self.assertTrue(not_submitted(self.user1, self.freizeit))
def test_not_submitted_freizeit_without_statement(self):

@ -88,12 +88,12 @@ class RulesTestCase(TestCase):
self.statement_unsubmitted = Statement.objects.create(
short_description='Unsubmitted Statement',
excursion=self.excursion,
submitted=False
status=Statement.UNSUBMITTED
)
self.statement_submitted = Statement.objects.create(
short_description='Submitted Statement',
submitted=True
status=Statement.SUBMITTED
)
def test_is_oneself(self):

Loading…
Cancel
Save