Skip to content

Commit 9dbed05

Browse files
authored
New admin fieldset section to display user customizations on packages benefits (#1953)
* Helper method to list modifications by the user * Add new section at sponsorship detail to list added/removed customizations * Disable section collapse behavior if sponsorship has any type of customization * More importance to boolean flag for sponsorships with customization
1 parent 64ec030 commit 9dbed05

File tree

3 files changed

+79
-12
lines changed

3 files changed

+79
-12
lines changed

sponsors/admin.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,10 @@ class SponsorshipAdmin(admin.ModelAdmin):
248248
"Sponsorship Data",
249249
{
250250
"fields": (
251+
"for_modified_package",
251252
"sponsor",
252253
"status",
253254
"package",
254-
"for_modified_package",
255255
"sponsorship_fee",
256256
"get_estimated_cost",
257257
"start_date",
@@ -276,6 +276,16 @@ class SponsorshipAdmin(admin.ModelAdmin):
276276
),
277277
},
278278
),
279+
(
280+
"User Customizations",
281+
{
282+
"fields": (
283+
"get_custom_benefits_added_by_user",
284+
"get_custom_benefits_removed_by_user",
285+
),
286+
"classes": ["collapse"],
287+
},
288+
),
279289
(
280290
"Events dates",
281291
{
@@ -290,6 +300,16 @@ class SponsorshipAdmin(admin.ModelAdmin):
290300
),
291301
]
292302

303+
def get_fieldsets(self, request, obj=None):
304+
fieldsets = []
305+
for title, cfg in super().get_fieldsets(request, obj):
306+
# disable collapse option in case of sponsorships with customizations
307+
if title == "User Customizations" and obj:
308+
if obj.user_customizations["added_by_user"] or obj.user_customizations["removed_by_user"]:
309+
cfg["classes"] = []
310+
fieldsets.append((title, cfg))
311+
return fieldsets
312+
293313
def get_queryset(self, *args, **kwargs):
294314
qs = super().get_queryset(*args, **kwargs)
295315
return qs.select_related("sponsor", "package", "submited_by")
@@ -318,6 +338,9 @@ def get_readonly_fields(self, request, obj):
318338
"get_sponsor_mailing_address",
319339
"get_sponsor_contacts",
320340
"get_contract",
341+
"get_added_by_user",
342+
"get_custom_benefits_added_by_user",
343+
"get_custom_benefits_removed_by_user",
321344
]
322345

323346
if obj and obj.status != Sponsorship.APPLIED:
@@ -455,6 +478,30 @@ def get_sponsor_contacts(self, obj):
455478

456479
get_sponsor_contacts.short_description = "Contacts"
457480

481+
def get_custom_benefits_added_by_user(self, obj):
482+
benefits = obj.user_customizations["added_by_user"]
483+
if not benefits:
484+
return "---"
485+
486+
html = "".join(
487+
[f"<p>{b}</p>" for b in benefits]
488+
)
489+
return mark_safe(html)
490+
491+
get_custom_benefits_added_by_user.short_description = "Added by User"
492+
493+
def get_custom_benefits_removed_by_user(self, obj):
494+
benefits = obj.user_customizations["removed_by_user"]
495+
if not benefits:
496+
return "---"
497+
498+
html = "".join(
499+
[f"<p>{b}</p>" for b in benefits]
500+
)
501+
return mark_safe(html)
502+
503+
get_custom_benefits_removed_by_user.short_description = "Removed by User"
504+
458505
def rollback_to_editing_view(self, request, pk):
459506
return views_admin.rollback_to_editing_view(self, request, pk)
460507

sponsors/models/sponsorship.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ def has_user_customization(self, benefits):
7878
)
7979
return not has_all_conflicts
8080

81+
def get_user_customization(self, benefits):
82+
"""
83+
Given a list of benefits this method returns the customizations
84+
"""
85+
benefits = set(tuple(benefits))
86+
pkg_benefits = set(tuple(self.benefits.all()))
87+
return {
88+
"added_by_user": benefits - pkg_benefits,
89+
"removed_by_user": pkg_benefits - benefits,
90+
}
91+
8192

8293
class SponsorshipProgram(OrderedModel):
8394
"""
@@ -132,7 +143,7 @@ class Sponsorship(models.Model):
132143

133144
for_modified_package = models.BooleanField(
134145
default=False,
135-
help_text="If true, it means the user customized the package's benefits.",
146+
help_text="If true, it means the user customized the package's benefits. Changes are listed under section 'User Customizations'.",
136147
)
137148
level_name_old = models.CharField(max_length=64, default="", blank=True, help_text="DEPRECATED: shall be removed "
138149
"after manual data sanity "
@@ -156,6 +167,11 @@ def level_name(self):
156167
def level_name(self, value):
157168
self.level_name_old = value
158169

170+
@cached_property
171+
def user_customizations(self):
172+
benefits = [b.sponsorship_benefit for b in self.benefits.select_related("sponsorship_benefit")]
173+
return self.package.get_user_customization(benefits)
174+
159175
def __str__(self):
160176
repr = f"{self.level_name} ({self.get_status_display()}) for sponsor {self.sponsor.name}"
161177
if self.start_date and self.end_date:

sponsors/tests/test_models.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ def test_display_agreed_fee_for_approved_and_finalized_status(self):
294294
self.assertEqual(sponsorship.agreed_fee, 2000)
295295

296296

297-
298297
class SponsorshipPackageTests(TestCase):
299298
def setUp(self):
300299
self.package = baker.make("sponsors.SponsorshipPackage")
@@ -303,19 +302,24 @@ def setUp(self):
303302

304303
def test_has_user_customization_if_benefit_from_other_package(self):
305304
extra = baker.make(SponsorshipBenefit)
306-
customization = self.package.has_user_customization(
307-
[extra] + self.package_benefits
308-
)
309-
self.assertTrue(customization)
305+
benefits = [extra] + self.package_benefits
306+
has_customization = self.package.has_user_customization(benefits)
307+
customization = {"added_by_user": {extra}, "removed_by_user": set()}
308+
self.assertTrue(has_customization)
309+
self.assertEqual(customization, self.package.get_user_customization(benefits))
310310

311311
def test_no_user_customization_if_all_benefits_from_package(self):
312-
customization = self.package.has_user_customization(self.package_benefits)
313-
self.assertFalse(customization)
312+
has_customization = self.package.has_user_customization(self.package_benefits)
313+
customization = {"added_by_user": set(), "removed_by_user": set()}
314+
self.assertFalse(has_customization)
315+
self.assertEqual(customization, self.package.get_user_customization(self.package_benefits))
314316

315317
def test_has_user_customization_if_missing_package_benefit(self):
316-
self.package_benefits.pop()
317-
customization = self.package.has_user_customization(self.package_benefits)
318-
self.assertTrue(customization)
318+
removed_benefit = self.package_benefits.pop()
319+
has_customization = self.package.has_user_customization(self.package_benefits)
320+
customization = {"added_by_user": set(), "removed_by_user": {removed_benefit}}
321+
self.assertTrue(has_customization)
322+
self.assertEqual(customization, self.package.get_user_customization(self.package_benefits))
319323

320324
def test_no_user_customization_if_at_least_one_of_conflicts_is_passed(self):
321325
benefits = baker.make(SponsorshipBenefit, _quantity=3)

0 commit comments

Comments
 (0)