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

Updating usage endpoints for organizations and subscriptions #4506

Merged
merged 34 commits into from Jul 13, 2023

Conversation

LMNTL
Copy link
Contributor

@LMNTL LMNTL commented Jun 21, 2023

Checklist

  1. If you've added code that should be tested, add tests
  2. If you've changed APIs, update (or create!) the documentation
  3. Ensure the tests pass
  4. Make sure that your code lints and that you've followed our coding style
  5. Write a description of your work suitable for publishing on our forum
  6. Mention any related issues in this repository (as #ISSUE) and in other repositories (as kobotoolbox/other#ISSUE)
  7. Open an issue in the docs if there are UI/UX changes

Description

Updated api/v2/service_usage to account for organizations and subscriptions.

Notes

Included changes to service_usage

  • Refactored from 7N queries per asset to 7-9 queries flat.
  • Endpoint can now optionally be queried by organization ID, returning usage data for each user in an organization.
  • When using the organization_id parameter, endpoint now tracks usage based on the organization's subscription date (if they have a subscription)
  • Endpoint also returns the start date for the current_month and current_year totals

General changes:

  • service_usage and asset_usage endpoints now return yearly counts for submissions and NLP usage.
  • Submissions and NLP usage are now tracked by day instead of month. A separate PR for KoboCat will address retaining daily submission counters for 366 days (one leap year) instead of 31 days. Link
  • Small changes to the usage page to keep it even with the updated API.

@LMNTL LMNTL marked this pull request as ready for review June 22, 2023 17:05
@LMNTL LMNTL requested a review from bufke June 22, 2023 20:15
@bufke
Copy link
Contributor

bufke commented Jun 23, 2023

The tests.py file won't actually be read by default by pytest, therefore it doesn't run in CI.

id=organization_id,
)
# If the user is in an organization, get all org users so we can query their total org usage
organization_users = OrganizationUser.objects.filter(organization=organization).select_related('user')
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you could reduce the code here by something like (pseudo code)

User.objects.filter(orgnaization__id=organization_id)

Often it's best to base the FROM part of the query on the table you actually want to return a list of, when possible at least. Then join that table to where you need to apply a filter.

The 404 may not be right here. I kind of don't care and this is pedantic, but a filter should simply filter the existing data. If that filter returns nothing. But if it's easier to raise either a 404 or 400 - I'm fine with it.

raise Http404
# Get the organization's subscription, if they have one
subscription = Subscription.objects.filter(
status__in=['active', 'past_due', 'trialing'],
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably make this list a constant. Even though it's used just once, it's more readable to understand why these three strings are special. Just the variable name itself would be good documentation.

@LMNTL LMNTL requested a review from bufke July 5, 2023 18:53
@@ -27,7 +27,8 @@ import Button from 'js/components/common/button';
import classnames from 'classnames';
import LoadingSpinner from 'js/components/common/loadingSpinner';
import {notify} from 'js/utils';
import {BaseProduct} from "js/account/subscriptionStore";
import {BaseProduct} from 'js/account/subscriptionStore';
Copy link
Contributor

Choose a reason for hiding this comment

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

I know you're just running prettier, but this import isn't being used. We should remove it.

from django.db.models import Sum, Q
from django.db.models.functions import Coalesce
from django.utils import timezone
from djstripe.models import Subscription
Copy link
Contributor

Choose a reason for hiding this comment

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

This import appears to generate a RuntimeError at startup when stripe isn't configured. We decided that stripe should be optional. I suspect you could do a condition check and run organizations.something to fetch check if there is a subscription without needing to import.

@LMNTL LMNTL requested a review from bufke July 10, 2023 21:31
@LMNTL LMNTL merged commit c870a8a into feature/usage-limits Jul 13, 2023
4 checks passed
@LMNTL LMNTL deleted the feature/usage-limits-api branch July 13, 2023 20:44
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.

None yet

2 participants