Skip to content
Merged
61 changes: 56 additions & 5 deletions docs/references/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ Each workflow offers different statuses (e.g. External Review, Ready for Determi
Hypha covers more than just the application phase, but workflows are used in the application process only.


## What are the 4 workflows?
## What are the 6 workflows?

1. [Request](#request)
2. [Request with same time review](#request-with-same-time-review) (new in v5.20.0)
3. [Request with external review](#request-with-external-review)
4. [Request with community review](#request-with-community-review)
5. [Concept and Proposal](#concept-and-proposal)
5. [Request external then internal review](#request-external-then-internal-review)
6. [Concept and Proposal](#concept-and-proposal)

All workflows begin with applicant drafting, revising and submitting an application (`DRAFT_STATE`) — only transition available is to `INITIAL_STATE`, upon applicant taking the action to submit their application/request.

Expand All @@ -36,7 +37,7 @@ Once an application is submitted (`INITIAL_STATE`) — it can transition into th
- Open review (`internal_review`) — can transition only between closing review period (`post_review_discussion`) and reverting back to the internal screening phase.
- `post_review_discussion` — after review is closed, you can request more information (`post_review_more_info`), ready for determination (`determination`), revert back to opening the review (`internal_review`), accept but additional info is needed (`almost`), accept (`accepted`) or reject (`rejected`)
- `post_review_more_info` — opens editing permissions to applicant again to revise their application to provide the information requested by the reviewers.
- Ready for determination (`determination`) — can revert back to discussion (“Ready For Discussion (revert)” — `post_review_discussion`) , or accept with additional info needed (`almost`), accept (`accepted`) or reject (`rejected`)
- Ready for determination (`determination`) — can revert back to discussion (“Ready for Discussion (revert)” — `post_review_discussion`) , or accept with additional info needed (`almost`), accept (`accepted`) or reject (`rejected`)
- Accepted, but additional info is needed (`almost`) — opens editing permissions to applicant again to revise their application to provide the information requested by the reviewers, admin, or staff positions.
- Accepted (`accepted`) — application accepted. Staff can still edit this submission.
- Rejected (`rejected`) — application rejected. Permissions removed from all roles.
Expand All @@ -55,7 +56,7 @@ Once an application is submitted (`INITIAL_STATE`) — it can transition into th
- Open review (`same_internal_review`) — can transition only between closing review period (`same_post_review_discussion`) and reverting back to the internal screening phase.
- `same_post_review_discussion` — after review is closed, you can request more information (`same_post_review_more_info`), ready for determination (`same_determination`), revert back to opening the review (`same_internal_review`), or reject (`same_rejected`)
- `same_post_review_more_info` — opens editing permissions to applicant again to revise their application to provide the information requested by the screeners.
- Ready for determination (`same_determination`) — can revert back to discussion (“Ready For Discussion (revert)” — `same_post_review_discussion`) , or accept with additional info needed (`same_almost`), accept (`same_accepted`) or reject (`same_rejected`)
- Ready for determination (`same_determination`) — can revert back to discussion (“Ready for Discussion (revert)” — `same_post_review_discussion`) , or accept with additional info needed (`same_almost`), accept (`same_accepted`) or reject (`same_rejected`)
- Accepted, but additional info is needed (`same_almost`) — opens editing permissions to applicant again to revise their application to provide the information requested by the reviewers, admin, or staff positions.
- Accepted (`same_accepted`) — application accepted. Staff can still edit this submission.
- Rejected (`same_rejected`) — application rejected. Permissions removed from all roles.
Expand All @@ -79,7 +80,7 @@ Once an application is submitted (`INITIAL_STATE`) — it can transition into th
- External review (`ext_external_review`) — can only transition between closing the review (`ext_post_external_review_discussion`) and reverting back to discussion (`ext_post_review_discussion`)
- `ext_post_external_review_discussion` — can transition to a request more information (`ext_post_external_review_more_info`), ready for determination (`ext_determination`), revert back to opening the external review (`ext_external_review`), accept but additional info is needed (`ext_almost`), accept (`ext_accepted`) or reject (`ext_rejected`)
- `ext_post_external_review_more_info` — opens editing permissions to applicant again to revise their application to provide the information requested by the reviewers.
- Ready for determination (`ext_determination`) — can revert back to discussion (“Ready For Discussion (revert)” — `ext_post_external_review_discussion`) , or accept with additional info needed (`ext_almost`), accept (`ext_accepted`) or reject (`ext_rejected`)
- Ready for determination (`ext_determination`) — can revert back to discussion (“Ready for Discussion (revert)” — `ext_post_external_review_discussion`) , or accept with additional info needed (`ext_almost`), accept (`ext_accepted`) or reject (`ext_rejected`)
- Accepted, but additional info is needed (`ext_almost`) — opens editing permissions to applicant again to revise their application to provide the information requested by the reviewers, admin, or staff positions.
- Accepted (`ext_accepted`) — application accepted. Staff can still edit this submission.
- Rejected (`ext_rejected`) — application rejected. Permissions removed from all roles.
Expand Down Expand Up @@ -112,6 +113,56 @@ Once an application is submitted (`INITIAL_STATE`) — it can transition into th
- Accept application but additional information is required (`com_almost`) — can transition to accepting application (`com_accepted`) or revert back to ready for discussion (`com_post_external_review_discussion`)
- Reject application (`com_rejected`)

### 🔀 Request external then internal review

This workflow is a single stage process with both an external review and an internal review stage. It is very similar to the "Request with external review" workflow, see above, but the order of the two review steps is reversed: the external reviewers see the application first, and the internal review only opens once the external review has been closed.

The internal review is optional — an application can be accepted, waitlisted or dismissed straight after the external review has been closed.

It is also the only workflow that offers **Waitlisted** as an outcome, alongside Accepted and Dismissed.

**Proposal Persona:**

Funding organization wants an advisory board or external partners to give their opinion before staff spend time on an internal review, and needs to be able to park promising applications on a waitlist while funding decisions are made.

Once an application is submitted (`INITIAL_STATE`) — it can transition into the following:

- A request for more information (`ext_int_more_info`) — opens editing permissions to applicant again to revise their application to provide the information requested by the screeners.
- Ready for review (`ext_int_screened`) — a staff only holding phase between screening and the external review, where reviewers can be assigned before they are given access to the application. Can transition to opening the external review (`ext_int_external_review`), mark ready for determination (`ext_int_determination`), dismiss (`ext_int_rejected`) or revert back to screening (`INITIAL_STATE`). Reviewers can see the application in this phase but can not review it yet, and are only notified once the external review is opened.
- Open external review (`ext_int_external_review`) — can transition only between closing the review period (`ext_int_post_external_review_discussion`) and reverting back to ready for review (`ext_int_screened`).
- `ext_int_post_external_review_discussion` — after the external review is closed, you can request more information (`ext_int_post_external_review_more_info`), open the internal review (`ext_int_internal_review`), mark ready for determination (`ext_int_determination`), revert back to opening the external review (`ext_int_external_review`), accept (`ext_int_accepted`), waitlist (`ext_int_waitlisted`) or dismiss (`ext_int_rejected`)
- `ext_int_post_external_review_more_info` — opens editing permissions to applicant again to revise their application to provide the information requested by the external reviewers.
- Open internal review (`ext_int_internal_review`) — can transition only between closing the review period (`ext_int_post_review_discussion`) and reverting back to discussion (`ext_int_post_external_review_discussion`)
- `ext_int_post_review_discussion` — after the internal review is closed, you can request more information (`ext_int_post_review_more_info`), mark ready for determination (`ext_int_determination`), revert back to opening the internal review (`ext_int_internal_review`), accept (`ext_int_accepted`), waitlist (`ext_int_waitlisted`) or dismiss (`ext_int_rejected`)
- `ext_int_post_review_more_info` — opens editing permissions to applicant again to revise their application to provide the information requested by the reviewers.
- Ready for determination (`ext_int_determination`) — can revert back to discussion (“Ready for Discussion (revert)” — `ext_int_post_review_discussion`), accept (`ext_int_accepted`), waitlist (`ext_int_waitlisted`) or dismiss (`ext_int_rejected`)
- Waitlisted (`ext_int_waitlisted`) — the application is kept in play without a decision. Can transition to accept (`ext_int_accepted`), dismiss (`ext_int_rejected`), or revert back to ready for determination (`ext_int_determination`). Staff can still edit this submission. Waitlisting is a plain status change — unlike Accept and Dismiss it does not open the determination form and does not create a determination record.
- Accepted (`ext_int_accepted`) — application accepted. Staff can still edit this submission.
- Dismissed (`ext_int_rejected`) — application rejected, shown as "Not Accepted" to the applicant. Editing and reviewing permissions removed from all roles, the applicant can still view the submission.

There is no "Accepted but additional info required" state in this workflow.

If the `TRANSITION_AFTER_REVIEWS` setting is set to a number, submitting a review can move the application on automatically:

- Need screening → Ready for Review, as soon as the first review is submitted. The configured number is not taken into account for this step, and only staff can review during screening.
- Ready for Review → External Review, once that many reviews have been submitted in total. Only staff can review in this phase.
- External Review → Ready for Discussion, once that many reviews have been submitted by users in the Reviewer group.

The internal review has no automatic transition — by the time it opens the external reviews have already been counted, so staff close it themselves with "Close Review".

The automatic transition is skipped if the user submitting the review is not allowed to make it.

**What the applicant sees**

Everything from the first discussion onwards is hidden from the applicant. The status bar shows four steps:

1. **Draft** (`draft`)
2. **Application Received** (`INITIAL_STATE`, "Need screening" to staff)
3. **Application Review** (`ext_int_external_review`, "External Review" to staff)
4. **Application Outcome** — shown as Accepted (`ext_int_accepted`), Waitlisted (`ext_int_waitlisted`) or Not Accepted (`ext_int_rejected`, "Dismissed" to staff) once the application reaches that step

The hidden phases (`ext_int_screened`, `ext_int_post_external_review_discussion`, `ext_int_internal_review`, `ext_int_post_review_discussion` and `ext_int_determination`) do not add a step of their own — to the applicant the application stays on "Application Review" until an outcome is reached. The three "More information required" states are visible to the applicant, since they need to edit and resubmit their application.

### 💡 Concept and Proposal

This workflow is a two-stage process: the first stage is the request and the second stage includes an advisory council review or external review stage.
Expand Down
14 changes: 6 additions & 8 deletions hypha/apply/activity/adapters/activity_feed.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from hypha.apply.activity.models import ALL, APPLICANT, TEAM
from hypha.apply.activity.options import MESSAGES
from hypha.apply.funds.workflows.constants import PHASE_BG_COLORS
from hypha.apply.projects.utils import (
get_invoice_public_status,
get_invoice_status_display_value,
Expand Down Expand Up @@ -227,18 +226,17 @@ def handle_task_removal(self, source, task, **kwargs):
)

def handle_transition(self, old_phase, source, **kwargs):
def wrap_in_color_class(text):
color_class = PHASE_BG_COLORS.get(text, "")
return f'<span class="rounded-full inline-block px-2 py-0.5 font-medium text-gray-800 {color_class}">{text}</span>'
def wrap_in_color_class(phase, text):
return f'<span class="rounded-full inline-block px-2 py-0.5 font-medium text-gray-800 {phase.bg_color}">{text}</span>'

submission = source
base_message = _("Progressed from {old_display} to {new_display}")

new_phase = submission.phase

staff_message = base_message.format(
old_display=wrap_in_color_class(old_phase.display_name),
new_display=wrap_in_color_class(new_phase.display_name),
old_display=wrap_in_color_class(old_phase, old_phase.display_name),
new_display=wrap_in_color_class(new_phase, new_phase.display_name),
)

if new_phase.permissions.can_view(submission.user):
Expand All @@ -249,8 +247,8 @@ def wrap_in_color_class(text):
)

applicant_message = base_message.format(
old_display=wrap_in_color_class(old_phase.public_name),
new_display=wrap_in_color_class(new_phase.public_name),
old_display=wrap_in_color_class(old_phase, old_phase.public_name),
new_display=wrap_in_color_class(new_phase, new_phase.public_name),
)

return json.dumps(
Expand Down
Loading