Skip to content

Commit

Permalink
Fix submission with "invite to proposal" status stuck in draft if lan…
Browse files Browse the repository at this point in the history
…guage is not english (#4220)

The current implementation tries to find the transition based on the
`name` property of the transitions available. The name of the transition
is a translated string so while submitting a proposal the key "submit"
from the `request.POST` could not be found in the available transition.

This PR updates the logic to fetch the transition target, by searching
through the newly added marker on when to auto transition if the
application is submitted.

Fixes #4211 

See
e6656d6
for patch.
  • Loading branch information
theskumar authored Nov 25, 2024
1 parent 96fc83b commit 02398cd
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 25 deletions.
5 changes: 3 additions & 2 deletions hypha/apply/funds/models/submissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def transition_id(target, phase):
class AddTransitions(models.base.ModelBase):
def __new__(cls, name, bases, attrs, **kwargs):
for workflow in WORKFLOWS.values():
for phase, data in workflow.items():
for phase_name, data in workflow.items():
for transition_name, action in data.transitions.items():
method_name = transition_id(transition_name, data)
permission_name = method_name + "_permission"
Expand All @@ -305,10 +305,11 @@ def __new__(cls, name, bases, attrs, **kwargs):
# Wrap with transition decorator
transition_func = transition(
attrs["status"],
source=phase,
source=phase_name,
target=transition_name,
permission=permission_func,
conditions=conditions,
custom=action.get("custom", {}),
)(transition_state)

# Attach to new class
Expand Down
51 changes: 31 additions & 20 deletions hypha/apply/funds/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1373,13 +1373,6 @@ class BaseSubmissionEditView(UpdateView):

model = ApplicationSubmission

@property
def transitions(self):
transitions = self.object.get_available_user_status_transitions(
self.request.user
)
return {transition.name: transition for transition in transitions}

def render_preview(self, request: HttpRequest, form: BaseModelForm) -> HttpResponse:
"""Gets a rendered preview of a form
Expand Down Expand Up @@ -1440,6 +1433,25 @@ def get_object_fund_current_round(self):
return assigned_fund.open_round
return False

def get_on_submit_transition(self, user):
"""Gets the transition that should be triggered when a form is submitted.
Checks all available status transitions for the current user and returns the first
one that has trigger_on_submit=True in its custom settings.
Returns:
dict: The transition configuration dictionary with trigger_on_submit=True,
or None if no matching transition is found.
"""
return next(
(
t
for t in self.object.get_available_user_status_transitions(user)
if t.custom.get("trigger_on_submit", False)
),
None,
)

def form_valid(self, form: BaseModelForm) -> HttpResponse:
"""Handle the form returned from a `SubmissionEditView`.
Expand Down Expand Up @@ -1492,19 +1504,18 @@ def form_valid(self, form: BaseModelForm) -> HttpResponse:
related=revision,
)

action = set(self.request.POST.keys()) & set(self.transitions.keys())
try:
transition = self.transitions[action.pop()]
except KeyError:
pass
else:
self.object.perform_transition(
transition.target,
self.request.user,
request=self.request,
notify=not (revision or submitting_proposal)
or self.object.status == DRAFT_STATE, # Use the other notification
)
if "submit" in self.request.POST:
if transition := self.get_on_submit_transition(self.request.user):
notify = (
not (revision or submitting_proposal)
or self.object.status == DRAFT_STATE,
)
self.object.perform_transition(
transition.target,
self.request.user,
request=self.request,
notify=notify, # Use the other notification
)

# Required for django-file-form: delete temporary files for the new files
# uploaded while edit.
Expand Down
35 changes: 32 additions & 3 deletions hypha/apply/funds/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ def __init__(
transition["permissions"] = action.get(
"permissions", default_permissions
)
if "custom" in action:
transition["custom"] = action["custom"]

self.transitions[transition_target] = transition

def __str__(self):
Expand Down Expand Up @@ -249,6 +252,7 @@ def make_permissions(edit=None, review=None, view=None):
"display": _("Submit"),
"permissions": {UserPermissions.APPLICANT},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("Draft"),
Expand Down Expand Up @@ -282,6 +286,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"determination": _("Ready For Determination"),
"almost": _("Accept but additional info required"),
Expand Down Expand Up @@ -332,6 +337,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"determination": _("Ready For Determination"),
"almost": _("Accept but additional info required"),
Expand Down Expand Up @@ -388,6 +394,7 @@ def make_permissions(edit=None, review=None, view=None):
"display": _("Submit"),
"permissions": {UserPermissions.APPLICANT},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("Draft"),
Expand Down Expand Up @@ -419,6 +426,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -464,6 +472,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -507,6 +516,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -564,6 +574,7 @@ def make_permissions(edit=None, review=None, view=None):
"display": _("Submit"),
"permissions": {UserPermissions.APPLICANT},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("Draft"),
Expand Down Expand Up @@ -597,6 +608,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -666,6 +678,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -709,6 +722,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -766,6 +780,7 @@ def make_permissions(edit=None, review=None, view=None):
"display": _("Submit"),
"permissions": {UserPermissions.APPLICANT},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("Draft"),
Expand Down Expand Up @@ -798,6 +813,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"concept_rejected": _("Dismiss"),
"invited_to_proposal": _("Invite to Proposal"),
Expand Down Expand Up @@ -847,6 +863,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"invited_to_proposal": _("Invite to Proposal"),
},
Expand Down Expand Up @@ -899,6 +916,7 @@ def make_permissions(edit=None, review=None, view=None):
"display": _("Submit"),
"permissions": {UserPermissions.APPLICANT},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"external_review": _("Open External Review"),
"proposal_determination": _("Ready For Final Determination"),
Expand Down Expand Up @@ -933,6 +951,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"external_review": _("Open External Review"),
"proposal_determination": _("Ready For Final Determination"),
Expand Down Expand Up @@ -981,6 +1000,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
"external_review": _("Open External Review"),
},
Expand Down Expand Up @@ -1025,6 +1045,7 @@ def make_permissions(edit=None, review=None, view=None):
UserPermissions.ADMIN,
},
"method": "create_revision",
"custom": {"trigger_on_submit": True},
},
},
"display": _("More information required"),
Expand Down Expand Up @@ -1071,12 +1092,20 @@ def make_permissions(edit=None, review=None, view=None):


def unpack_phases(phases):
for step, step_data in enumerate(phases):
for name, phase_data in step_data.items():
yield step, name, phase_data
"""Unpack a list of phases into a generator of step, name, phase_data."""
return (
(step, name, phase_data)
for step, step_data in enumerate(phases)
for name, phase_data in step_data.items()
)


def phase_data(phases):
"""Convert a list of phases into a dictionary of Phase objects.
Adds the step number to the phase data. The step number is the index of the
phase in the list of phases.
"""
return {
phase_name: Phase(phase_name, step=step, **phase_data)
for step, phase_name, phase_data in unpack_phases(phases)
Expand Down

0 comments on commit 02398cd

Please sign in to comment.