diff --git a/openstax/settings/base.py b/openstax/settings/base.py index cb633b69..09d03831 100644 --- a/openstax/settings/base.py +++ b/openstax/settings/base.py @@ -259,7 +259,7 @@ ('0 2 * * *', 'django.core.management.call_command', ['delete_resource_downloads']), ('0 6 * * *', 'django.core.management.call_command', ['update_resource_downloads']), ('0 0 8 * *', 'django.core.management.call_command', ['update_schools_and_mapbox']), - # ('0 0 1 * *', 'django.core.management.call_command', ['update_opportunities']), + ('0 0 * * *', 'django.core.management.call_command', ['update_opportunities']), ('0 10 * * *', 'django.core.management.call_command', ['update_partners']), ] diff --git a/salesforce/management/commands/update_opportunities.py b/salesforce/management/commands/update_opportunities.py index d888759e..be6d0607 100644 --- a/salesforce/management/commands/update_opportunities.py +++ b/salesforce/management/commands/update_opportunities.py @@ -1,51 +1,41 @@ import datetime +import uuid from django.core.management.base import BaseCommand from salesforce.models import AdoptionOpportunityRecord from salesforce.salesforce import Salesforce +import sentry_sdk +from sentry_sdk.crons import monitor class Command(BaseCommand): help = "update book adoptions from salesforce.com for getting adoptions by account uuid" - def handle(self, *args, **options): - with Salesforce() as sf: - now = datetime.datetime.now() + def query_base_year(self, base_year, adoption_status): + query = ("SELECT Id, " + "Adoption_Type__c, " + "Base_Year__c, " + "Confirmation_Date__c, " + "Confirmation_Type__c, " + "How_Using__c, " + "Savings__c, " + "Students__c, " + "Opportunity__r.Book__r.Name, " + "Opportunity__r.StageName, " + "Opportunity__r.Contact__r.Accounts_UUID__c " + "FROM Adoption__c WHERE " + "Base_Year__c = {} AND Opportunity__r.Contact__r.Accounts_UUID__c != null " + "AND Confirmation_Type__c = 'OpenStax Confirmed Adoption' " + "AND Opportunity__r.Contact__r.Adoption_Status__c = '{}'").format(base_year, adoption_status) - base_year = now.year - if now.month < 7: # if it's before July, the base year is the previous year (4/1/2024 = base_year 2023) - base_year -= 2 - else: - base_year -= 1 + return query - # TODO: I don't think this is needed - updating the records should be fine, and keeps something on the form - # TODO: for the user. Eventually, this should update CMS DB with updated data if they fill out the form - # truncate the table - # AdoptionOpportunityRecord.objects.all().delete() - - # then we will get any new records - query = ("SELECT Id, " - "Adoption_Type__c, " - "Base_Year__c, " - "Confirmation_Date__c, " - "Confirmation_Type__c, " - "How_Using__c, " - "Savings__c, " - "Students__c, " - "Opportunity__r.Book__r.Name, " - "Opportunity__r.StageName, " - "Opportunity__r.Contact__r.Accounts_UUID__c " - "FROM Adoption__c WHERE " - "Base_Year__c = {} AND Opportunity__r.Contact__r.Accounts_UUID__c != null " - "AND Confirmation_Type__c = 'OpenStax Confirmed Adoption' " - "AND Opportunity__r.Contact__r.Adoption_Status__c != 'Current Adopter'").format(base_year) - - response = sf.query(query) - records = response['records'] - - for record in records: + def process_results(self, results): + for i, record in enumerate(results): + try: opportunity, created = AdoptionOpportunityRecord.objects.update_or_create( - opportunity_id=record['Id'], - defaults={'account_uuid': record['Opportunity__r']['Contact__r']['Accounts_UUID__c'], + account_uuid=uuid.UUID(record['Opportunity__r']['Contact__r']['Accounts_UUID__c']), + book_name=record['Opportunity__r']['Book__r']['Name'], + defaults={'opportunity_id': record['Id'], 'opportunity_stage': record['Opportunity__r']['StageName'], 'adoption_type': record['Adoption_Type__c'], 'base_year': record['Base_Year__c'], @@ -53,8 +43,37 @@ def handle(self, *args, **options): 'confirmation_type': record['Confirmation_Type__c'], 'how_using': record['How_Using__c'], 'savings': record['Savings__c'], - 'students': record['Students__c'], - 'book_name': record['Opportunity__r']['Book__r']['Name'], + 'students': record['Students__c'] } ) opportunity.save() + except ValueError: + sentry_sdk.capture_message("Adoption {} has a badly formatted Account UUID: {}".format(record['Id'], record['Opportunity__r']['Contact__r']['Accounts_UUID__c'])) + except TypeError: + sentry_sdk.capture_message("Adoption {} exists without a book".format(record['Id'])) + + @monitor(monitor_slug='update-opportunities') + def handle(self, *args, **options): + with Salesforce() as sf: + now = datetime.datetime.now() + + base_year = now.year + if now.month < 7: # before july, current year minus 2 (4/1/2024, base year = 2023) + base_year -= 2 + else: # otherwise, current year minus 1 (10/1/2024, base year = 2023) + base_year -= 1 + + # first, we get last year's records + # these people need to renew, show them what we know from last base year confirmed adoption + query = self.query_base_year(base_year, "Past Adopter") + + results = sf.bulk.Adoption__c.query(query) + self.process_results(results) + + # now get this year's records - this will ensure accurate data on the renewal form if already filled out + current_base_year = base_year + 1 + updated_records = self.query_base_year(current_base_year, "Current Adopter") + + results = sf.bulk.Adoption__c.query(updated_records) + self.process_results(results) +