Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Member codes docs #2595

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion amy/workshops/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2276,7 +2276,7 @@ class TrainingRequest(
"application's ranking.",
)

# new field for teaching-related experience in non-profit or volunteer org.
# teaching-related experience in non-profit or volunteer org
nonprofit_teaching_experience = models.CharField(
max_length=STR_LONGEST,
blank=True,
Expand Down
217 changes: 178 additions & 39 deletions docs/amy_database_structure.md

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions docs/design/design_patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ This document acts as a reference for where certain design patterns can be found
4. Set the `queryset_other`, `context_other_object_name`, and `pk_url_kwarg` variables in the view according to the original object. These are used by `AMYCreateAndFetchObjectView` to select the correct object to use data from. The object will become available as `self.other_object` in the view
5. Override [`get_initial()`](https://docs.djangoproject.com/en/4.2/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin.get_initial) to set form fields based on data in `self.other_object`

### Perform "soft validation" to allow possibly invalid data to be submitted with only a warning

**Demo**: On test-amy or a local AMY instance, go to the Instructor Training application form and select "Profile Creation for Pre-approved Trainees." Enter some random letters as the registration code (an invalid input), then fill out the rest of the required form fields. After clicking "Submit", if member code enforcement is [enabled](./projects/2023_member_code_enforcement.md#feature-flag), you should see an error on the registration code starting with "This code is invalid." Underneath the field, a checkbox should be visible with the label "Continue with registration code marked as invalid" - if you check this box, you should now be able to submit the form.

**Method**:

1. Add a field `<fieldname>-override` to the relevant model. This should be a `BooleanField` defaulting to `False`.
2. On `Form`s connected to the model, manipulate the `helper.layout` to show/hide the new field according to the value of the field you're implementing soft validation on (e.g. the `validate_member_code` method of `TrainingRequestForm` in [`/extforms/forms.py`](../../amy/extforms/forms.py) shows and hides the `member_code_override` field according to the validity of the `member_code`).
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider absolute link to the file in GitHub repository.

3. Build validation carefully for the override and the field it relates to. The override should only be required and `True` if the related field is invalid. In other cases, it should be `False` - this may require updating the value during validation (e.g. the `validate_member_code` method again).
4. Consider adding a filter to help admins find objects where the override was used. Beware that the default `django_filters.BooleanFilter` is not quite appropriate - typically you will want *all* results to be shown when the filter is `False`, and only results that use the override to be shown when the filter is `True` (e.g. `invalid_member_code` filter in `TrainingRequestFilter` in [/extrequests/filters.py](../../amy/extrequests/filters.py)).
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider absolute link to the file in GitHub repository.


**Reference files**:

* `extrequests/views.py` - all the `...AcceptEvent` classes
Expand Down
47 changes: 47 additions & 0 deletions docs/design/projects/2023_member_code_enforcement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Member code enforcement

[GitHub project](https://github.com/carpentries/amy/projects/15).

In early 2024, the membership team planned to start enforcing that all preapproved IT applications and workshop requests should include a valid and active member code (a.k.a. registration code, group code)

In mid-2023, the checkout requirements for Instructor Training were updated. As the relevant changes were made to AMY to support this update, the project also expanded to include improvements to the training progress view for trainees.

## Feature flag

The `ENFORCE_MEMBER_CODES` [feature flag](../feature_flags.md) controls whether validity checks are performed on member codes. If set to `True` in the Django admin panel, validity checks will be performed on all submissions. If set to `False`, no checks will be performed (i.e. all codes will be accepted). The value of the flag does **not** affect whether the `member_code` field is displayed on forms or in views.
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to switch the feature flag ENFORCE_MEMBER_CODES on before release 4.3.

Copy link
Contributor

Choose a reason for hiding this comment

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

Done: 506a2fe


## Instructor Training Application Form

### Previous design

The form had a field for the member code, but it was optional and not checked for validity.

### New design

The member code field is now required for preapproved trainees, and will raise an error if the entered code is invalid, inactive, or has no seats remaining. However, to avoid forcing the trainee to speak to their membership contact (who may in turn need to speak to us) and wait for the resolution, there is a checkbox to override the invalid code and submit the form anyway.

On the admin side, when viewing all training requests, there is now a filter to show applications where the override was used, so these applications can easily be manually checked.

## Workshop Request Form

### Previous design

The workshop request form did not include a field for the member code. Instead, the WAT would match workshops up with memberships manually.

### New design

The form now includes a field for the member code. This field will raise an error if the entered code is invalid or inactive. Unlike the instructor training application, there is no option to override an invalid code.

On the admin side, when viewing a workshop request, there is an info box showing the associated membership for the member code (if applicable) and how many workshops that membership has remaining. There is also a filter on the workshop requests page to find requests that came from a member organisation but didn't use any member code - this may happen if multiple groups at the same institution find The Carpentries independently of each other.

## Other changes

Other features added as part of this project:

* When creating an Event from a workshop request, autofill the membership based on the member code
* When adding a learner Task for a trainee at a TTT event, autofill the membership based on the member code in the trainee's application
* When bulk matching trainees to training, use the new "Automatically match seats to memberships" option to assign each trainee to a membership seat based on the member code in their application (as an alternative to assigning all matched trainees to the same membership)
* Update email autoresponses to include member code information
* Include a question about the Eventbrite event that a preapproved trainee has signed up for (if applicable) and allow admins to filter applications by Eventbrite event URLs or IDs.
* Updates to other questions on the instructor training application
* Utility functions to check if a membership is active on a certain date, find a membership from a member code, and to validate member codes in particular ways.
11 changes: 11 additions & 0 deletions docs/manual_deployment_steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ This document tracks steps that must be completed manually before or after the s

## v4.3

### Before

#### Member docs

1. Check for TrainingProgress with non-unique combinations of `trainee` and `event` (excluding nulls), and remove duplicates.
This is required for the migration `workshops.0264_trainingprogress_unique_trainee_at_event` to succeed.

#### Automated emails

1. Deploy the worker correctly to PROD environment
2. Prepare production email worker account only with `knox.add_authtoken` permission and active status
* put this account credentials in SSM parameters `/{stage}/email-worker/token_username` and `/{stage}/email-worker/token_password`
Expand All @@ -12,6 +21,8 @@ This document tracks steps that must be completed manually before or after the s

* Update Redash queries about training requests to change `group_name` to `member_code` (in line with changes to the `TrainingRequest` model).

------------------------------------------------------------

## v4.2

### Before
Expand Down
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ nav:
- "Community Roles": "./design/projects/2021_community_roles.md"
- "Instructor Selection": "./design/projects/2021_instructor_selection.md"
- "Single Instructor Badge": "./design/projects/2021_single_instructor_badge.md"
- "Instructor Checkout Changes": "./design/projects/2023_instructor_checkout_changes.md"
- "Member Code Enforcement": "./design/projects/2023_member_code_enforcement.md"
- "Feature flags": "design/feature_flags.md"
- "About The Carpentries":
- "The Carpentries": "https://carpentries.org"
Expand Down
Loading