@@ -375,7 +375,7 @@ def test_save_review_grants_updates_grant_and_creates_reimbursements(rf, mocker)
375375 assert LogEntry .objects .filter (
376376 user = user ,
377377 object_id__in = [str (grant_1 .id ), str (grant_2 .id )],
378- change_message = f "[Review Session] Grant status updated: pending_status changed from '{ Grant . Status . pending } ' to '{ Grant . Status . approved } '." ,
378+ change_message = "[Review Session] Grant status updated: pending_status changed from 'None ' to 'approved'." ,
379379 ).exists ()
380380 assert LogEntry .objects .filter (
381381 user = user ,
@@ -557,21 +557,24 @@ def test_save_review_grants_modify_reimbursements(rf, mocker):
557557 reimbursement .category for reimbursement in grant_1 .reimbursements .all ()
558558 } == {ticket_category }
559559
560- assert LogEntry .objects .count () == 3
560+ # Verify log entries were created
561+ assert LogEntry .objects .count () == 2
561562 assert LogEntry .objects .filter (
562563 user = user ,
563564 object_id = grant_1 .id ,
564- change_message = "[Review Session] Grant status updated: pending_status changed from 'approved' to 'None'. " ,
565+ change_message = f "[Review Session] Reimbursement removed: { travel_category . name } " ,
565566 ).exists ()
566567 assert LogEntry .objects .filter (
567568 user = user ,
568569 object_id = grant_1 .id ,
569- change_message = f"[Review Session] Reimbursement removed: { travel_category .name } " ,
570+ change_message = f"[Review Session] Reimbursement removed: { accommodation_category .name } " ,
570571 ).exists ()
571- assert LogEntry .objects .filter (
572+
573+ # pending_status change should not be logged because the grant status is not changed
574+ assert not LogEntry .objects .filter (
572575 user = user ,
573576 object_id = grant_1 .id ,
574- change_message = f "[Review Session] Reimbursement removed: { accommodation_category . name } " ,
577+ change_message = "[Review Session] Grant status updated: pending_status changed from 'approved' to 'None'. " ,
575578 ).exists ()
576579
577580
@@ -657,3 +660,68 @@ def test_save_review_grants_waiting_list_does_not_create_reimbursments(rf, mocke
657660 LogEntry .objects .filter (object_id = grant_2 .id ).count () == 1
658661 ) # 1 pending_status change, 3 reimbursement additions
659662 mock_messages .success .assert_called_once ()
663+
664+
665+ def test_save_review_grants_two_times_does_not_create_duplicate_log_entries (rf , mocker ):
666+ mocker .patch ("reviews.admin.messages" )
667+
668+ user = UserFactory (is_staff = True , is_superuser = True )
669+ conference = ConferenceFactory ()
670+
671+ # Create reimbursement categories
672+ travel_category = GrantReimbursementCategoryFactory (
673+ conference = conference ,
674+ travel = True ,
675+ max_amount = Decimal ("500" ),
676+ )
677+ ticket_category = GrantReimbursementCategoryFactory (
678+ conference = conference ,
679+ ticket = True ,
680+ max_amount = Decimal ("100" ),
681+ )
682+ accommodation_category = GrantReimbursementCategoryFactory (
683+ conference = conference ,
684+ accommodation = True ,
685+ max_amount = Decimal ("200" ),
686+ )
687+
688+ # Create review session for grants
689+ review_session = ReviewSessionFactory (
690+ conference = conference ,
691+ session_type = ReviewSession .SessionType .GRANTS ,
692+ status = ReviewSession .Status .COMPLETED ,
693+ )
694+ AvailableScoreOptionFactory (review_session = review_session , numeric_value = 0 )
695+ AvailableScoreOptionFactory (review_session = review_session , numeric_value = 1 )
696+
697+ grant_1 = GrantFactory (conference = conference , status = Grant .Status .pending )
698+ post_data = {
699+ f"decision-{ grant_1 .id } " : Grant .Status .approved ,
700+ f"reimbursementcategory-{ grant_1 .id } " : [
701+ str (ticket_category .id ),
702+ str (travel_category .id ),
703+ str (accommodation_category .id ),
704+ ],
705+ }
706+ request = rf .post ("/" , data = post_data )
707+ request .user = user
708+
709+ admin = ReviewSessionAdmin (ReviewSession , AdminSite ())
710+ admin ._review_grants_recap_view (request , review_session ) # First save
711+ admin ._review_grants_recap_view (request , review_session ) # Second save
712+
713+ grant_1 .refresh_from_db ()
714+
715+ assert grant_1 .reimbursements .count () == 3
716+ assert {
717+ reimbursement .category for reimbursement in grant_1 .reimbursements .all ()
718+ } == {ticket_category , travel_category , accommodation_category }
719+
720+ for e in LogEntry .objects .all ():
721+ print (e .change_message )
722+ assert LogEntry .objects .count () == 4
723+ assert LogEntry .objects .filter (
724+ user = user ,
725+ object_id = grant_1 .id ,
726+ change_message = "[Review Session] Grant status updated: pending_status changed from 'None' to 'approved'." ,
727+ ).exists ()
0 commit comments