Skip to content

Add summary statistics to contract retrieve endpoint and remove unassigned codes from /codes output. Add filtering on assigned + redeemed statuses#3705

Merged
dsubak merged 5 commits into
dansubak/202606_paginated_codesfrom
dansubak/202606_paginated_codes_means_paginated_problems
Jun 26, 2026
Merged

Add summary statistics to contract retrieve endpoint and remove unassigned codes from /codes output. Add filtering on assigned + redeemed statuses#3705
dsubak merged 5 commits into
dansubak/202606_paginated_codesfrom
dansubak/202606_paginated_codes_means_paginated_problems

Conversation

@dsubak

@dsubak dsubak commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Description (What does it do?)

Now that we've paginated the API, the frontend doesn't have a particularly good way to grab the breakdown of codes to show to the contract manager:
Screenshot 2026-06-25 at 12 10 28 PM

Previously, these were just calculated by looking at the total rowset returned from /codes.

This PR attempts to put that info into the contract retrieve endpoint instead - that endpoint already looked like it was outputting some values like that (most notably a miscalculated total_codes value), so it seemed reasonable to add here.

Additionally, this PR removes unassigned codes from the response entirely.

We no longer actually intend to show unassigned codes in the UI - contract admins shouldn't need to see them as the assign endpoints already handle distributing them automagically. The only codepath which returned them is for contracts which don't have automatic membership types AND a max_learners set (the former case never returns any codes, the latter returns the first one if it exists). We considered adding a query param to filter those out, but as this endpoint already has a bit too many edge cases, we thought this might make it easier to reason about - this makes /codes more like "used/assigned codes"

If we decide later that we do need them in this payload, we can either add a kwarg or create a new endpoint for "available codes".

Lastly, this PR adds filtering on the "status" of a code for the /codes endpoint. Since we've removed unassigned codes from the payload, we only have to worry about support for "assigned" and "redeemed" codes

Screenshots (if appropriate):

Screenshot 2026-06-25 at 2 26 44 PM Screenshot 2026-06-25 at 2 26 58 PM

How can this be tested?

In addition to all tests passing, manual testing can be performed in the following manner.

Common setup

To test the filtering behavior, you'll want to redeem a few codes using the attach API.

At the end of setup, you should have at least a few values in redeemed, assigned and unassigned to make subsequent steps easier.

Removal of Unassigned codes from /codes

  • As long as you've got at least one code that has not been assigned or redeemed, simply hit http://mitxonline.odl.local:9080/api/v0/b2b/manager/organizations/<org_id>/contracts/<contract_id>/codes/ and observe that it is not returned in the resultset.
    • If you've got a lot of codes, in assigned/redeemed state, you can specify a very large page size to get it all in one request for verification

Summary Statistics

  • Visit http://mitxonline.odl.local:9080/api/v0/b2b/manager/organizations/<org_id>/contracts/<contract_id>/
  • You should observe that the following fields are populated in the response and are reflective of your contract. The only one which is not self-explanatory is total_codes, and that should match the max_learners set on the contract itself.
total_codes
assigned_codes
unassigned_codes
redeemed_codes

Status filtering

  • Visit http://mitxonline.odl.local:9080/api/v0/b2b/manager/organizations/<org_id>/contracts/<contract_id>/codes/ and specify a status parameter of either "assigned" or "redeemed"
  • You should observe that only codes in the matching status are returned.
  • Additionally, if you specify a search_term AND a status parameter, both filters should be properly applied.

Additional Information

Take note - this PR is a branch off of #3685; in order to simplify the release, this branch will be merged into that PR and the whole thing will be released in one shot.

…ed count of total_codes + annotation). Remove unassigned codes from the output since we no longer show that to anyone.
Comment thread b2b/views/v0/manager.py
organization__organization_users__is_manager=True,
)
)
if self.action == "retrieve":

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Currently only used for the contract retrieve endpoints where we calculate summary stats.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

OpenAPI Changes

Show/hide ## Changes for v0.yaml:
## Changes for v0.yaml:
4 changes: 0 error, 0 warning, 4 info
info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `assigned_codes` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `redeemed_codes` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `unassigned_codes` to the response with the `200` status

info	[new-optional-request-parameter] at head/openapi/specs/v0.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/codes/
		added the new optional `query` request parameter `status`



## Changes for v1.yaml:
4 changes: 0 error, 0 warning, 4 info
info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `assigned_codes` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `redeemed_codes` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `unassigned_codes` to the response with the `200` status

info	[new-optional-request-parameter] at head/openapi/specs/v1.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/codes/
		added the new optional `query` request parameter `status`



## Changes for v2.yaml:
4 changes: 0 error, 0 warning, 4 info
info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `assigned_codes` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `redeemed_codes` to the response with the `200` status

info	[response-required-property-added] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/
		added the required property `unassigned_codes` to the response with the `200` status

info	[new-optional-request-parameter] at head/openapi/specs/v2.yaml
	in API GET /api/v0/b2b/manager/organizations/{parent_lookup_organization}/contracts/{id}/codes/
		added the new optional `query` request parameter `status`



Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).

@dsubak dsubak marked this pull request as draft June 25, 2026 19:15
Comment thread b2b/views/v0/manager.py
Comment thread b2b/serializers/v0/manager.py Outdated
@dsubak dsubak marked this pull request as ready for review June 26, 2026 12:40
@dsubak dsubak changed the title Add summary statistics to contract retrieve endpoint and remove unassigned codes from /codes output. Add summary statistics to contract retrieve endpoint and remove unassigned codes from /codes output. Add filtering on assigned + redeemed statuses Jun 26, 2026
@dsubak

dsubak commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@jkachel and @daniellefrappier18 - pulling this out of draft and into ready for review!

Ya'll obviously both already looked at it a little - the only material change since then is to add the ability to filter on status. Let me know if there are any questions!

@daniellefrappier18 daniellefrappier18 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Tested this out in mitodl/mit-learn#3530 and everything is working as expected on my end. :)

@jkachel jkachel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM 👍

@dsubak dsubak merged commit 9ba4782 into dansubak/202606_paginated_codes Jun 26, 2026
5 checks passed
@dsubak dsubak deleted the dansubak/202606_paginated_codes_means_paginated_problems branch June 26, 2026 19:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants