-
Notifications
You must be signed in to change notification settings - Fork 14
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
Task to export calculated numbers of the monthly reports back to HubSpot #6439
Conversation
96258ee
to
28b6508
Compare
@@ -1,5 +1,22 @@ | |||
import csv |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Part of this code is copied and adapted from the reporting system.
I've avoided many of the abstractions there, so here we hard code the columns we are going to send for companies for example.
I don't think we are going to be modifying this very often right now but we can move into abstractions as we apply this to more models and/or columns.
} | ||
] | ||
|
||
import_request = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We name here the import job on HubSpot side.
@@ -27,27 +27,26 @@ def get_company(self, organization_id: str) -> HubSpotCompany | None: | |||
# More than one company pointing to the same org is a data entry error, ignore them. | |||
return None | |||
|
|||
def get_companies_with_active_deals(self, date_: date): | |||
def _companies_with_active_deals_query(self, date_: date): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making the existing query a private method to be able to reusing it for the new code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
def export_companies_contract_billables(self, date_: date): | ||
"""Export the contract billable numbers to HubSpot.""" | ||
query = ( | ||
self._companies_with_active_deals_query(date_) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the existing companies_with_active_deals_query(date_)
query
"""Export the contract billable numbers to HubSpot.""" | ||
query = ( | ||
self._companies_with_active_deals_query(date_) | ||
.join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Join with organizations and reports.
Organization.public_id == HubSpotCompany.lms_organization_id, | ||
) | ||
.join(OrganizationUsageReport) | ||
.distinct(OrganizationUsageReport.organization_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Picking just one report per organization.
.distinct(OrganizationUsageReport.organization_id) | ||
.order_by( | ||
OrganizationUsageReport.organization_id, | ||
OrganizationUsageReport.until.desc(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Picking the last report.
OrganizationUsageReport.organization_id, | ||
OrganizationUsageReport.until.desc(), | ||
) | ||
).with_only_columns( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And only picking the values we need to pass to the client to generate the CSV.
csv.writer.return_value.writerow.assert_called_once_with( | ||
(sentinel.id, sentinel.teachers, sentinel.users) | ||
) | ||
api_client.crm.imports.core_api.create.assert_called_once_with( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this level we just deal with the HubSpot API, we assert we are calling it with the expected values.
def test_export_companies_contract_billables( | ||
self, svc, hubspot_api_client, db_session | ||
): | ||
organization = factories.Organization(public_id="TEST_ORG") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this level we care about picking the right data, we set up the data in the DB and assert we get the right values to call the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion for some more concise and consistent naming: export_billables() (Celery task) --calls-> HubSpotService.export_billables(date) --calls-> HubSpotClient.import_billables(billables)
lms/services/hubspot/_client.py
Outdated
] | ||
|
||
import_request = { | ||
"name": f"contract_year_import_{date.today().isoformat()}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the dates should probably be part of the contract_year_billables
argument, rather than using the current day here. Those numbers of unique teachers and users in contract_year_billables
were calculated at to a given date, it'd be better to include that date in the data rather than implicitly assuming that it matches date.today()
at the time when this line later runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have included this as a second independent parameter
@@ -27,27 +27,26 @@ def get_company(self, organization_id: str) -> HubSpotCompany | None: | |||
# More than one company pointing to the same org is a data entry error, ignore them. | |||
return None | |||
|
|||
def get_companies_with_active_deals(self, date_: date): | |||
def _companies_with_active_deals_query(self, date_: date): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
lms/services/hubspot/service.py
Outdated
|
||
# From the point of view of HubSpot we are creating an import | ||
self._client.create_company_import( | ||
self._db.execute(query).all(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where you should probably include date_
in the arguments to create_company_import()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done that
To summarize the process we: - Fetch HubSpot companies with tasks.hubspot.refresh_hubspot_data - We generate monthly usage reports for thos companies with task.organization.schedule_monthly_deal_report now, with this commit we: - Push the calculated numbers (unique user and teachers) to the corresponding fields in HubSpot companies.
5d9323e
to
440d3b2
Compare
Merged the naming suggestions 👍 Run the task locally to make sure everything lines up. A new import was created here https://app.hubspot.com/import/21081992 |
Suspect IssuesThis pull request was deployed and Sentry observed the following issues:
Did you find this useful? React with a 👍 or 👎 |
For:
This PR needs a follow up to schedule the task in h-periodic.
To summarize the process we:
now, with this commit we:
Testing
Describing here the process I followed locally to test this end to end.
update hubspot_company set lms_organization_id = 'local.lms.org.FFIHD9f1RwyLPfx14zM_7Q' where id = 11;
Let's check that the import actually happened, we log into HuBSpot, and go to the imports in: https://app.hubspot.com/import/21081992
And we can see the records we modified locally to match the HubSpot data being updated and the rest of the rows having no value (
--
) in those columns.