Skip to content

Commit 4390026

Browse files
feat: add GlobalConstants model and integrate into rebate logic (#147)
1 parent b832e43 commit 4390026

10 files changed

Lines changed: 172 additions & 38 deletions

File tree

home/admin.py

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
StudentBills,
3838
UnregisteredStudent,
3939
Update,
40+
GlobalConstants,
4041
)
4142
from home.utils.rebate_checker import max_days_rebate
4243

@@ -79,7 +80,18 @@
7980
)
8081
REBATE_BILLS_DESC_TEXT = "This contains the rebate bills of each students."
8182

82-
# Register your models here
83+
@admin.register(GlobalConstants)
84+
class GlobalConstantsAdmin(admin.ModelAdmin):
85+
model = GlobalConstants
86+
87+
def has_add_permission(self, request):
88+
# Only allow one instance of GlobalConstants
89+
if self.model.objects.count() > 0:
90+
return False
91+
return super().has_add_permission(request)
92+
93+
def has_delete_permission(self, request, obj=None):
94+
return False
8395

8496

8597
@admin.register(About)
@@ -451,11 +463,19 @@ def set_semester(modeladmin, request, queryset: list[LongRebate]):
451463
set_semester.__name__ = f"get_rebate_days_per_caterer_{semester}"
452464
return set_semester
453465

454-
try:
455-
for semester in Semester.objects.all():
456-
actions.append(set_semester_action(semester.name))
457-
except Exception as e:
458-
print("Semester table not available", e)
466+
def get_actions(self, request):
467+
actions = super().get_actions(request)
468+
try:
469+
for semester in Semester.objects.all():
470+
action = self.set_semester_action(semester.name)
471+
actions[action.__name__] = (
472+
action,
473+
action.__name__,
474+
action.short_description,
475+
)
476+
except Exception as e:
477+
print("Semester table not available", e)
478+
return actions
459479

460480

461481
@admin.register(Rebate)
@@ -679,11 +699,19 @@ def set_period(modeladmin, request, queryset):
679699
set_period.__name__ = f"set_period_{semester_name}_{period_sno}"
680700
return set_period
681701

682-
try:
683-
for period in Period.objects.all():
684-
actions.append(set_period_action(period.semester.name, period.Sno))
685-
except Exception as e:
686-
print("Periods table not available", e)
702+
def get_actions(self, request):
703+
actions = super().get_actions(request)
704+
try:
705+
for period in Period.objects.all():
706+
action = self.set_period_action(period.semester.name, period.Sno)
707+
actions[action.__name__] = (
708+
action,
709+
action.__name__,
710+
action.short_description,
711+
)
712+
except Exception as e:
713+
print("Periods table not available", e)
714+
return actions
687715

688716
@admin.action(description="Allocate the unregistered students")
689717
def allocate(self, request, queryset):

home/context_processors.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .models import Caterer
1+
from .models import Caterer, GlobalConstants
22

33
"""
44
File-name: context_processors.py
@@ -9,4 +9,8 @@
99

1010
def base(request):
1111
caterer = Caterer.objects.filter(visible=True).all()
12-
return {"all_caterer": caterer}
12+
constants = GlobalConstants.objects.first()
13+
if not constants:
14+
# Provide defaults if no constants exist yet
15+
constants = GlobalConstants.objects.create()
16+
return {"all_caterer": caterer, "constants": constants}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Generated by Django 5.1.14 on 2026-06-05 17:41
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('home', '0009_student_photo'),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name='GlobalConstants',
15+
fields=[
16+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17+
('short_rebate_stretch_limit', models.IntegerField(default=7, help_text='Maximum number of days for a single short rebate application.', verbose_name='Short Rebate Stretch Limit')),
18+
('short_rebate_period_limit', models.IntegerField(default=8, help_text='Maximum total days allowed for short rebates within a single period.', verbose_name='Short Rebate Period Limit')),
19+
('min_rebate_days', models.IntegerField(default=2, help_text='Minimum number of days required for a rebate application.', verbose_name='Minimum Rebate Days')),
20+
('days_prior_notice', models.IntegerField(default=2, help_text='Minimum days before leave commencement the form must be filled.', verbose_name='Days Prior Notice')),
21+
],
22+
options={
23+
'verbose_name': 'Global Constant',
24+
'verbose_name_plural': 'Global Constants',
25+
},
26+
),
27+
]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 5.1.14 on 2026-06-05 17:42
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('home', '0010_globalconstants'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='globalconstants',
15+
name='short_rebate_period_limit',
16+
field=models.IntegerField(default=10, help_text='Maximum total days allowed for short rebates within a single period.', verbose_name='Short Rebate Period Limit'),
17+
),
18+
migrations.AlterField(
19+
model_name='globalconstants',
20+
name='short_rebate_stretch_limit',
21+
field=models.IntegerField(default=10, help_text='Maximum number of days for a single short rebate application.', verbose_name='Short Rebate Stretch Limit'),
22+
),
23+
]

home/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from .caterer import Caterer
77
from .contacts import Contact
88
from .fees import Fee
9-
from .home import About, Carousel, Update
9+
from .home import About, Carousel, GlobalConstants, Update
1010
from .links import Form
1111
from .rules import Rule, ShortRebate
1212
from .students import (

home/models/home.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,37 @@ def __str__(self):
5656
class Meta:
5757
verbose_name = "Update"
5858
verbose_name_plural = "Updates"
59+
60+
61+
class GlobalConstants(models.Model):
62+
"""
63+
Stores globally accessible constants for the website like rebate limits.
64+
"""
65+
66+
short_rebate_stretch_limit = models.IntegerField(
67+
_("Short Rebate Stretch Limit"),
68+
default=10,
69+
help_text="Maximum number of days for a single short rebate application.",
70+
)
71+
short_rebate_period_limit = models.IntegerField(
72+
_("Short Rebate Period Limit"),
73+
default=10,
74+
help_text="Maximum total days allowed for short rebates within a single period.",
75+
)
76+
min_rebate_days = models.IntegerField(
77+
_("Minimum Rebate Days"),
78+
default=2,
79+
help_text="Minimum number of days required for a rebate application.",
80+
)
81+
days_prior_notice = models.IntegerField(
82+
_("Days Prior Notice"),
83+
default=2,
84+
help_text="Minimum days before leave commencement the form must be filled.",
85+
)
86+
87+
def __str__(self):
88+
return "Global Constants"
89+
90+
class Meta:
91+
verbose_name = "Global Constant"
92+
verbose_name_plural = "Global Constants"

home/utils/rebate_checker.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
from datetime import timedelta
22

3-
from home.models import LeftShortRebate, LongRebate, Rebate, StudentBills
3+
from home.models import (
4+
GlobalConstants,
5+
LeftShortRebate,
6+
LongRebate,
7+
Rebate,
8+
StudentBills,
9+
)
410

511

612
def count(start, end):
@@ -54,41 +60,47 @@ def is_not_duplicate(student, new_rebate_start, new_rebate_end):
5460
def max_days_rebate(student, start, end, period):
5561
"""
5662
Checks what period rebate is being applied,
57-
if the rebate does not exceeds 8 days for that period approves the rebate and
63+
if the rebate does not exceeds the set limit for that period approves the rebate and
5864
adds the rebate to student bills(Commented out this feature for now, as administration wants to approve it from its side before adding to student bills)
5965
"""
66+
constants = GlobalConstants.objects.first()
67+
if not constants:
68+
constants = GlobalConstants.objects.create()
69+
70+
limit = constants.short_rebate_period_limit
71+
6072
student_bill, _ = StudentBills.objects.get_or_create(
6173
email=student, semester=period.semester
6274
)
6375
sum = count(start, end)
6476
match period.Sno:
6577
case 1:
66-
if student_bill.period1_short + sum <= 8:
78+
if student_bill.period1_short + sum <= limit:
6779
return -1
6880
else:
69-
return 8 - student_bill.period1_short
81+
return limit - student_bill.period1_short
7082
case 2:
71-
if student_bill.period2_short + sum <= 8:
83+
if student_bill.period2_short + sum <= limit:
7284
return -1
7385
else:
74-
return 8 - student_bill.period2_short
86+
return limit - student_bill.period2_short
7587
case 3:
76-
if student_bill.period3_short + sum <= 8:
88+
if student_bill.period3_short + sum <= limit:
7789
return -1
7890
else:
79-
return 8 - student_bill.period3_short
91+
return limit - student_bill.period3_short
8092
case 4:
81-
if student_bill.period4_short + sum <= 8:
93+
if student_bill.period4_short + sum <= limit:
8294
return -1
8395
else:
84-
return 8 - student_bill.period4_short
96+
return limit - student_bill.period4_short
8597
case 5:
86-
if student_bill.period5_short + sum <= 8:
98+
if student_bill.period5_short + sum <= limit:
8799
return -1
88100
else:
89-
return 8 - student_bill.period5_short
101+
return limit - student_bill.period5_short
90102
case 6:
91-
if student_bill.period6_short + sum <= 8:
103+
if student_bill.period6_short + sum <= limit:
92104
return -1
93105
else:
94-
return 8 - student_bill.period6_short
106+
return limit - student_bill.period6_short

home/views.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
Caterer,
2121
Contact,
2222
Form,
23+
GlobalConstants,
2324
LeftShortRebate,
2425
LongRebate,
2526
Menu,
@@ -187,20 +188,24 @@ def rebate(request):
187188
request.session["text"] = message
188189
return redirect(request.path)
189190

191+
constants = GlobalConstants.objects.first()
192+
if not constants:
193+
constants = GlobalConstants.objects.create()
194+
190195
try:
191196
start_date = parse_date(request.POST["start_date"])
192197
end_date = parse_date(request.POST["end_date"])
193198
rebate_days = ((end_date - start_date).days) + 1
194199
before_rebate_days = (start_date - date.today()).days
195200

196-
if rebate_days > 7:
197-
message = "Max no of days for rebate is 7"
198-
elif before_rebate_days < 2:
199-
message = "Form needs to be filled atleast 2 days prior the comencement of leave."
201+
if rebate_days > constants.short_rebate_stretch_limit:
202+
message = f"Max no of days for rebate is {constants.short_rebate_stretch_limit}"
203+
elif before_rebate_days < constants.days_prior_notice:
204+
message = f"Form needs to be filled atleast {constants.days_prior_notice} days prior the comencement of leave."
200205
elif not is_not_duplicate(student, start_date, end_date):
201206
message = "You have already applied for rebate during this duration"
202-
elif rebate_days < 2:
203-
message = "Min no of days for rebate is 2"
207+
elif rebate_days < constants.min_rebate_days:
208+
message = f"Min no of days for rebate is {constants.min_rebate_days}"
204209
else:
205210
additional_message = ""
206211
if not period_obj.start_date <= start_date <= period_obj.end_date:
@@ -233,7 +238,7 @@ def rebate(request):
233238
)
234239
if upper_cap_check >= 0:
235240
message = (
236-
"You can only apply for max 8 days in a period. Days left for this period: "
241+
f"You can only apply for max {constants.short_rebate_period_limit} days in a period. Days left for this period: "
237242
+ str(upper_cap_check)
238243
)
239244
elif not message:

messWebsite/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"django.middleware.common.CommonMiddleware",
6262
"django.middleware.csrf.CsrfViewMiddleware",
6363
"django.contrib.auth.middleware.AuthenticationMiddleware",
64+
"allauth.account.middleware.AccountMiddleware",
6465
"django.contrib.messages.middleware.MessageMiddleware",
6566
"django.middleware.clickjacking.XFrameOptionsMiddleware",
6667
"messWebsite.middleware.LoginRequiredMiddleware",

templates/rebateForm.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ <h1 class="m-0 pb-2">Short Term Rebate Form</h1>
88
<div class="px-3">
99
<div class="px-5 mx-5">
1010
<ul>
11-
<li>Rebate can be availed for a minimum of 2 days, upto 7 days at a stretch.</li>
12-
<li>Maximum of 8 days rebate per month will be provided through the short term rebate forms. </li>
13-
<li>Fill the form atleast 2 days prior the comencement of leave, else the application will not be accepted.</li>
11+
<li>Rebate can be availed for a minimum of {{ constants.min_rebate_days }} days, upto {{ constants.short_rebate_stretch_limit }} days at a stretch.</li>
12+
<li>Maximum of {{ constants.short_rebate_period_limit }} days rebate per period will be provided through the short term rebate forms. </li>
13+
<li>Fill the form atleast {{ constants.days_prior_notice }} days prior the comencement of leave, else the application will not be accepted.</li>
1414
<ul>
1515
</div>
1616
</div>

0 commit comments

Comments
 (0)