Skip to content

fix: finalize_round: delegate to proper DAO methods instead of bare s…#463

Open
userAdityaa wants to merge 2 commits intohatnote:masterfrom
userAdityaa:branch-finalization-logic
Open

fix: finalize_round: delegate to proper DAO methods instead of bare s…#463
userAdityaa wants to merge 2 commits intohatnote:masterfrom
userAdityaa:branch-finalization-logic

Conversation

@userAdityaa
Copy link
Copy Markdown

…tatus update

Summary

Fix the finalize_round endpoint in admin_endpoints.py to ensure all required finalization actions are executed by delegating to the appropriate DAO methods instead of only updating the round status.

Solution

The endpoint now properly delegates round finalization logic to the DAO layer:

  • Calls finalize_rating_round for rating rounds
  • Calls finalize_ranking_round for ranking rounds
  • Ensures all expected finalization side-effects are executed

Fixes #462

Changes

  • Call DAO finalization methods instead of directly updating status
  • Ensure close_date is set during finalization
  • Ensure audit log entries are created
  • Ensure ranking rounds create RoundResultsSummary
  • Ensure rating rounds store final_threshold in config
  • Remove unused FINALIZED_STATUS import

How to test

  1. Create a campaign and add a round

  2. Activate the round and complete voting

  3. Finalize the round via the endpoint

  4. Verify:

    • close_date is set in the database
    • Audit log entry exists for finalization
    • Ranking rounds create a RoundResultsSummary
    • Rating rounds store final_threshold in config

Copilot AI review requested due to automatic review settings April 1, 2026 19:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the admin finalize_round endpoint so round finalization goes through the DAO layer (instead of directly mutating rnd.status), ensuring all expected side-effects (e.g., close date, audit logging, summaries/config) are executed consistently.

Changes:

  • Route round finalization through CoordinatorDAO.finalize_ranking_round() for ranking rounds.
  • Route round finalization through CoordinatorDAO.finalize_rating_round() for rating/yesno rounds, requiring a threshold input.
  • Remove the unused FINALIZED_STATUS import from admin_endpoints.py.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +427 to +429
threshold = float(request_dict['threshold'])
except (KeyError, TypeError):
raise InvalidAction('threshold is required to finalize a rating/yesno round')
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

float(request_dict['threshold']) will raise ValueError for non-numeric inputs (e.g. "abc" or "") and currently this bubbles up as a 500. Also, thresholds outside the expected [0.0, 1.0] range will trigger an AssertionError downstream in get_rating_advancing_group() (also a 500). Catch ValueError here and validate the numeric range before calling finalize_rating_round, raising InvalidAction with a 400 instead.

Suggested change
threshold = float(request_dict['threshold'])
except (KeyError, TypeError):
raise InvalidAction('threshold is required to finalize a rating/yesno round')
raw_threshold = request_dict['threshold']
except KeyError:
raise InvalidAction('threshold is required to finalize a rating/yesno round')
try:
threshold = float(raw_threshold)
except (TypeError, ValueError):
raise InvalidAction('threshold must be a number between 0.0 and 1.0 to finalize a rating/yesno round')
if not (0.0 <= threshold <= 1.0):
raise InvalidAction('threshold must be between 0.0 and 1.0 to finalize a rating/yesno round')

Copilot uses AI. Check for mistakes.
Comment on lines 417 to +435
def finalize_round(user_dao, round_id, request_dict):
coord_dao = CoordinatorDAO.from_round(user_dao, round_id)
rnd = coord_dao.get_round(round_id)
rnd.status = FINALIZED_STATUS

return {'status': 'success'}
if rnd.vote_method == 'ranking':
result_summary = coord_dao.finalize_ranking_round(round_id)
return {'status': 'success',
'result_summary_id': result_summary.id}
elif rnd.vote_method in ('rating', 'yesno'):
try:
threshold = float(request_dict['threshold'])
except (KeyError, TypeError):
raise InvalidAction('threshold is required to finalize a rating/yesno round')
advance_group = coord_dao.finalize_rating_round(round_id, threshold=threshold)
return {'status': 'success',
'advancing_count': len(advance_group),
'threshold': threshold}
else:
raise InvalidAction('unknown vote method: %s' % rnd.vote_method)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint now contains core round-finalization branching logic (ranking vs rating/yesno) and is intended to ensure side-effects like close_date, audit log entries, RoundResultsSummary, and final_threshold. There are currently no integration tests exercising /admin/round/<id>/finalize; add test coverage for both vote methods to prevent regressions (including validating the response fields like result_summary_id / advancing_count).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants