mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 21:43:21 +00:00
integrations: Add Greenhouse integration.
This commit is contained in:
BIN
static/images/integrations/greenhouse/000.png
Normal file
BIN
static/images/integrations/greenhouse/000.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
static/images/integrations/logos/greenhouse.png
Normal file
BIN
static/images/integrations/logos/greenhouse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
112
zerver/fixtures/greenhouse/greenhouse_candidate_created.json
Normal file
112
zerver/fixtures/greenhouse/greenhouse_candidate_created.json
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"action": "new_candidate_application",
|
||||
"payload": {
|
||||
"application": {
|
||||
"id": 265293,
|
||||
"rejected_at": null,
|
||||
"prospect": false,
|
||||
"status": "active",
|
||||
"applied_at": "2013-03-22T00:00:00Z",
|
||||
"last_activity_at": "2015-03-18T20:28:09Z",
|
||||
"source": {
|
||||
"id": 27,
|
||||
"public_name": "LinkedIn"
|
||||
},
|
||||
"credited_to": null,
|
||||
"rejection_reason": null,
|
||||
"current_stage": {
|
||||
"id": 678901,
|
||||
"name": "Application Review",
|
||||
"interviews": [
|
||||
{
|
||||
"id": 989099,
|
||||
"name":"Application Review",
|
||||
"status": "collect_feedback",
|
||||
"interview_kit": {
|
||||
"url": "http://app.greenhouse.io/guides/67656/people/265788",
|
||||
"content": "",
|
||||
"questions": []
|
||||
},
|
||||
"interviewers": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"candidate": {
|
||||
"id": 265788,
|
||||
"created_at": "2013-10-04T01:24:48Z",
|
||||
"first_name": "Hector",
|
||||
"last_name": "Porter",
|
||||
"title": null,
|
||||
"company": null,
|
||||
"phone_numbers": [
|
||||
{
|
||||
"value": "330-281-8004",
|
||||
"type": "home"
|
||||
}
|
||||
],
|
||||
"email_addresses": [
|
||||
{
|
||||
"value": "hector.porter.265788@example.com",
|
||||
"type": "personal"
|
||||
}
|
||||
],
|
||||
"addresses": [],
|
||||
"website_addresses": [],
|
||||
"social_media_addresses": [],
|
||||
"recruiter": null,
|
||||
"coordinator": null,
|
||||
"photo_url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"attachments": [
|
||||
{
|
||||
"filename": "resume.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "resume"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Import from Previous ATS"
|
||||
],
|
||||
"custom_fields": {
|
||||
"favorite_color": {
|
||||
"name": "Favorite Color",
|
||||
"type": "short_text",
|
||||
"value": "Blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"id": 3485,
|
||||
"name": "Designer",
|
||||
"requisition_id": null,
|
||||
"notes": "Digital and print",
|
||||
"job_post_id": 54321,
|
||||
"status": "open",
|
||||
"created_at": "2013-10-02T22:59:29Z",
|
||||
"opened_at": "2015-01-23T00:25:04Z",
|
||||
"closed_at": null,
|
||||
"departments": [
|
||||
{
|
||||
"id": 237,
|
||||
"name": "Community"
|
||||
}
|
||||
],
|
||||
"offices": [
|
||||
{
|
||||
"id": 54,
|
||||
"name": "New York",
|
||||
"location": "New York, NY"
|
||||
}
|
||||
],
|
||||
"custom_fields": {
|
||||
"employment_type": {
|
||||
"name": "Employment Type",
|
||||
"type": "single_select",
|
||||
"value": "Full Time"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
184
zerver/fixtures/greenhouse/greenhouse_candidate_hired.json
Normal file
184
zerver/fixtures/greenhouse/greenhouse_candidate_hired.json
Normal file
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"action": "hire_candidate",
|
||||
"payload": {
|
||||
"application": {
|
||||
"id": 20,
|
||||
"opening": {
|
||||
"opening_id": "1234-56"
|
||||
},
|
||||
"credited_to": {
|
||||
"id": 57,
|
||||
"email": "bob_johnson1@localhost.com",
|
||||
"name": "Robert Johnson"
|
||||
},
|
||||
"source": {
|
||||
"id": 25,
|
||||
"public_name": "Monster"
|
||||
},
|
||||
"candidate": {
|
||||
"id": 19,
|
||||
"first_name": "Johnny",
|
||||
"last_name": "Smith",
|
||||
"title": "Previous Title",
|
||||
"external_id": "00000",
|
||||
"phone_numbers": [{
|
||||
"value": "518-555-1212",
|
||||
"type": "work"
|
||||
}, {
|
||||
"value": "212-555-1212",
|
||||
"type": "home"
|
||||
}],
|
||||
"email_addresses": [{
|
||||
"value": "personal@example.com",
|
||||
"type": "personal"
|
||||
}, {
|
||||
"value": "work@example.com",
|
||||
"type": "work"
|
||||
}],
|
||||
"addresses": [{
|
||||
"value": "455 Broadway New York, NY 10280",
|
||||
"type": "home"
|
||||
}],
|
||||
"recruiter": {
|
||||
"id": 55,
|
||||
"email": "bob_johnson@localhost.com",
|
||||
"name": "Bob Johnson"
|
||||
},
|
||||
"coordinator": {
|
||||
"id": 56,
|
||||
"email": "bob_johnson_approver1@localhost.com",
|
||||
"name": "Robert J Approver"
|
||||
},
|
||||
"attachments": [{
|
||||
"filename": "resume.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "resume"
|
||||
}],
|
||||
"custom_fields": {
|
||||
"desired_level": {
|
||||
"name": "Desired Level",
|
||||
"type": "short_text",
|
||||
"value": "Senior"
|
||||
},
|
||||
"favorite_programming_language": {
|
||||
"name": "Favorite Programming Language",
|
||||
"type": "short_text",
|
||||
"value": "Rails"
|
||||
}
|
||||
}
|
||||
},
|
||||
"job": {
|
||||
"id": 20,
|
||||
"name": "Developer",
|
||||
"open_date": "2014-11-20T22:49:14Z",
|
||||
"close_date": "2014-11-25T22:49:14Z",
|
||||
"requisition_id": null,
|
||||
"departments": [{
|
||||
"id": 7,
|
||||
"name": "Technology"
|
||||
}],
|
||||
"offices": [{
|
||||
"id": 13,
|
||||
"name": "New York City",
|
||||
"location": {
|
||||
"name": "New York, NY"
|
||||
}
|
||||
}, {
|
||||
"id": 14,
|
||||
"name": "St. Louis",
|
||||
"location": null
|
||||
}],
|
||||
"custom_fields": {
|
||||
"approved": {
|
||||
"name": "Approved",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
},
|
||||
"employment_type": {
|
||||
"name": "Employment Type",
|
||||
"type": "single_select",
|
||||
"value": "Full-time"
|
||||
},
|
||||
"salary_range": {
|
||||
"name": "SalaryRange",
|
||||
"type": "currency_range",
|
||||
"value": {
|
||||
"unit": "USD",
|
||||
"min_value": "10000.0",
|
||||
"max_value": "20000.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobs": [{
|
||||
"id": 20,
|
||||
"name": "Developer",
|
||||
"opened_at": "2014-11-20T22:49:14Z",
|
||||
"closed_at": "2014-11-25T22:49:14Z",
|
||||
"requisition_id": null,
|
||||
"departments": [{
|
||||
"id": 7,
|
||||
"name": "Technology"
|
||||
}],
|
||||
"offices": [{
|
||||
"id": 13,
|
||||
"name": "New York City",
|
||||
"location": {
|
||||
"name": "New York, NY"
|
||||
}
|
||||
}, {
|
||||
"id": 14,
|
||||
"name": "St. Louis",
|
||||
"location": null
|
||||
}],
|
||||
"custom_fields": {
|
||||
"approved": {
|
||||
"name": "Approved",
|
||||
"type": "boolean",
|
||||
"value": true
|
||||
},
|
||||
"employment_type": {
|
||||
"name": "Employment Type",
|
||||
"type": "single_select",
|
||||
"value": "Full-time"
|
||||
},
|
||||
"salary_range": {
|
||||
"name": "SalaryRange",
|
||||
"type": "currency_range",
|
||||
"value": {
|
||||
"unit": "USD",
|
||||
"min_value": "10000.0",
|
||||
"max_value": "20000.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}],
|
||||
"offer": {
|
||||
"id": 13,
|
||||
"version": 2,
|
||||
"created_at": "2014-11-20T22:49:14Z",
|
||||
"sent_at": "2014-11-10",
|
||||
"resolved_at": "2014-11-20T22:49:14Z",
|
||||
"starts_at": "2015-01-23",
|
||||
"custom_fields": {
|
||||
"salary": {
|
||||
"name": "Salary",
|
||||
"type": "currency",
|
||||
"value": {
|
||||
"amount": 80000,
|
||||
"unit": "USD"
|
||||
}
|
||||
},
|
||||
"seasons": {
|
||||
"name": "Seasons",
|
||||
"type": "multi_select",
|
||||
"value": [
|
||||
"Season 1",
|
||||
"Season 2"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"action": "reject_candidate",
|
||||
"payload": {
|
||||
"application": {
|
||||
"id": 265293,
|
||||
"rejected_at": "2015-02-11T15:50:41Z",
|
||||
"prospect": false,
|
||||
"status": "rejected",
|
||||
"applied_at": "2013-03-22T00:00:00Z",
|
||||
"last_activity_at": "2015-02-11T15:50:41Z",
|
||||
"source": {
|
||||
"id": 27,
|
||||
"public_name": "LinkedIn"
|
||||
},
|
||||
"credited_to": null,
|
||||
"rejection_reason": {
|
||||
"id": 14,
|
||||
"name": "Too Junior",
|
||||
"type": {
|
||||
"id": 3,
|
||||
"name": "Wrong skill set"
|
||||
}
|
||||
},
|
||||
"candidate": {
|
||||
"id": 265788,
|
||||
"created_at": "2013-10-04T01:24:48Z",
|
||||
"first_name": "Hector",
|
||||
"last_name": "Porter",
|
||||
"title": null,
|
||||
"company": null,
|
||||
"phone_numbers": [{
|
||||
"value": "330-281-8004",
|
||||
"type": "home"
|
||||
}],
|
||||
"email_addresses": [{
|
||||
"value": "hector.porter.265788@example.com",
|
||||
"type": "personal"
|
||||
}],
|
||||
"addresses": [],
|
||||
"website_addresses": [],
|
||||
"social_media_addresses": [],
|
||||
"recruiter": null,
|
||||
"coordinator": null,
|
||||
"photo_url": "www.example.com/photo.png",
|
||||
"attachments": [{
|
||||
"filename": "resume.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "resume"
|
||||
}],
|
||||
"tags": [
|
||||
"Imported"
|
||||
],
|
||||
"custom_fields": {
|
||||
"favorite_color": {
|
||||
"name": "Favorite Color",
|
||||
"type": "short_text",
|
||||
"value": "Blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobs": [{
|
||||
"id": 3485,
|
||||
"name": "Designer",
|
||||
"requisition_id": null,
|
||||
"notes": "Digital and print",
|
||||
"job_post_id": 54321,
|
||||
"status": "open",
|
||||
"created_at": "2013-10-02T22:59:29Z",
|
||||
"opened_at": "2015-01-23T00:25:04Z",
|
||||
"closed_at": null,
|
||||
"departments": [{
|
||||
"id": 237,
|
||||
"name": "Community"
|
||||
}],
|
||||
"offices": [{
|
||||
"id": 54,
|
||||
"name": "New York",
|
||||
"location": "New York, NY"
|
||||
}],
|
||||
"custom_fields": {
|
||||
"employment_type": {
|
||||
"name": "Employment Type",
|
||||
"type": "single_select",
|
||||
"value": "Full Time"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"action": "candidate_stage_change",
|
||||
"payload": {
|
||||
"application": {
|
||||
"id": 265277,
|
||||
"rejected_at": null,
|
||||
"prospect": false,
|
||||
"status": "active",
|
||||
"applied_at": "2013-03-22T00:00:00Z",
|
||||
"last_activity_at": "2015-02-09T16:38:36Z",
|
||||
"source": {
|
||||
"id": 31,
|
||||
"name": "Agency"
|
||||
},
|
||||
"credited_to": {
|
||||
"id": 15,
|
||||
"email": "ada@example.com",
|
||||
"name": "Ada Lacey"
|
||||
},
|
||||
"rejection_reason": null,
|
||||
"current_stage": {
|
||||
"id": 71416,
|
||||
"name": "Assessment",
|
||||
"interviews": [{
|
||||
"id": 113101,
|
||||
"name": "Assessment",
|
||||
"status": "to_be_scheduled",
|
||||
"interview_kit": {
|
||||
"url": "https://app.greenhouse.io/guides/113153/people/265772",
|
||||
"content": "Assess their skills",
|
||||
"questions": []
|
||||
},
|
||||
"interviewers": [{
|
||||
"id": 2622,
|
||||
"display_name": "Carl Buddha",
|
||||
"status": "tentative"
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"candidate": {
|
||||
"id": 265772,
|
||||
"created_at": "2013-10-04T01:24:44Z",
|
||||
"first_name": "Giuseppe",
|
||||
"last_name": "Hurley",
|
||||
"external_id": "241b399ce4b0fd1c84e5528d",
|
||||
"title": "Great Person",
|
||||
"company": null,
|
||||
"photo_url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"phone_numbers": [{
|
||||
"value": "330-281-8004",
|
||||
"type": "home"
|
||||
}],
|
||||
"email_addresses": [{
|
||||
"value": "giuseppe.hurley@example.com",
|
||||
"type": "personal"
|
||||
}],
|
||||
"addresses": [{
|
||||
"value": "123 Fake St.",
|
||||
"type": "home"
|
||||
}],
|
||||
"website_addresses": [{
|
||||
"value": "ghurley.example.com",
|
||||
"type": "personal"
|
||||
}],
|
||||
"social_media_addresses": [{
|
||||
"value": "linkedin.example.com/ghurley"
|
||||
}],
|
||||
"recruiter": {
|
||||
"id": 3128,
|
||||
"email": "alicia.flopple.3128@example.com",
|
||||
"name": "Alicia Flopple"
|
||||
},
|
||||
"coordinator": {
|
||||
"id": 3128,
|
||||
"email": "alicia.flopple.3128@example.com",
|
||||
"name": "Alicia Flopple"
|
||||
},
|
||||
"attachments": [{
|
||||
"filename": "resume.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "resume"
|
||||
}, {
|
||||
"filename": "cover_letter.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "cover_letter"
|
||||
}, {
|
||||
"filename": "portfolio.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "attachment"
|
||||
}],
|
||||
"tags": [
|
||||
"Import from Previous ATS"
|
||||
],
|
||||
"custom_fields": {
|
||||
"favorite_color": {
|
||||
"name": "Favorite Color",
|
||||
"type": "short_text",
|
||||
"value": "Blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobs": [{
|
||||
"id": 3485,
|
||||
"name": "Designer",
|
||||
"requisition_id": null,
|
||||
"notes": "Digital and print",
|
||||
"status": "open",
|
||||
"created_at": "2013-10-02T22:59:29Z",
|
||||
"opened_at": "2015-01-23T00:25:04Z",
|
||||
"closed_at": null,
|
||||
"departments": [{
|
||||
"id": 237,
|
||||
"name": "Community"
|
||||
}],
|
||||
"offices": [{
|
||||
"id": 54,
|
||||
"name": "New York",
|
||||
"location": "New York, NY"
|
||||
}],
|
||||
"custom_fields": {
|
||||
"employment_type": {
|
||||
"name": "Employment Type",
|
||||
"type": "single_select",
|
||||
"value": "Full Time"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
104
zerver/fixtures/greenhouse/greenhouse_prospect_created.json
Normal file
104
zerver/fixtures/greenhouse/greenhouse_prospect_created.json
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"action": "new_prospect_application",
|
||||
"payload": {
|
||||
"application": {
|
||||
"id": 979554,
|
||||
"rejected_at": null,
|
||||
"prospect": true,
|
||||
"status": "active",
|
||||
"applied_at": "2014-12-02T23:10:16Z",
|
||||
"last_activity_at": "2014-12-02T23:10:16Z",
|
||||
"current_stage": null,
|
||||
"source": {
|
||||
"id": 13,
|
||||
"public_name": "Referral"
|
||||
},
|
||||
"credited_to": {
|
||||
"id": 2622,
|
||||
"email": "carl.buddha.2622@example.com",
|
||||
"name": "Carl Buddha"
|
||||
},
|
||||
"rejection_reason": null,
|
||||
"candidate": {
|
||||
"id": 968190,
|
||||
"created_at": "2014-12-02T23:10:16Z",
|
||||
"first_name": "Trisha",
|
||||
"last_name": "Troy",
|
||||
"title": null,
|
||||
"company": null,
|
||||
"phone_numbers": [
|
||||
{
|
||||
"value": "123456",
|
||||
"type": "other"
|
||||
}
|
||||
],
|
||||
"email_addresses": [
|
||||
{
|
||||
"value": "t.troy@example.com",
|
||||
"type": "personal"
|
||||
}
|
||||
],
|
||||
"addresses": [],
|
||||
"website_addresses": [],
|
||||
"social_media_addresses": [],
|
||||
"recruiter": {
|
||||
"id": 3128,
|
||||
"email": "alicia.flopple.3128@example.com",
|
||||
"name": "Alicia Flopple"
|
||||
},
|
||||
"coordinator": null,
|
||||
"photo_url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"attachments": [
|
||||
{
|
||||
"filename": "resume.pdf",
|
||||
"url": "https://prod-heroku.s3.amazonaws.com/...",
|
||||
"type": "resume"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Import from Previous ATS"
|
||||
],
|
||||
"custom_fields": {
|
||||
"favorite_color": {
|
||||
"name": "Favorite Color",
|
||||
"type": "short_text",
|
||||
"value": "Blue"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jobs": [
|
||||
{
|
||||
"id": 3485,
|
||||
"name": "Designer",
|
||||
"requisition_id": null,
|
||||
"notes": "Digital and print",
|
||||
"job_post_id": 54321,
|
||||
"status": "open",
|
||||
"created_at": "2013-10-02T22:59:29Z",
|
||||
"opened_at": "2015-01-23T00:25:04Z",
|
||||
"closed_at": null,
|
||||
"departments": [
|
||||
{
|
||||
"id": 237,
|
||||
"name": "Community"
|
||||
}
|
||||
],
|
||||
"offices": [
|
||||
{
|
||||
"id": 54,
|
||||
"name": "New York",
|
||||
"location": "New York, NY"
|
||||
}
|
||||
],
|
||||
"custom_fields": {
|
||||
"employment_type": {
|
||||
"name": "Employment Type",
|
||||
"type": "single_select",
|
||||
"value": "Full Time"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,7 @@ WEBHOOK_INTEGRATIONS = [
|
||||
),
|
||||
WebhookIntegration('gitlab', display_name='GitLab'),
|
||||
WebhookIntegration('gosquared', display_name='GoSquared'),
|
||||
WebhookIntegration('greenhouse', display_name='Greenhouse'),
|
||||
WebhookIntegration('hellosign', display_name='HelloSign'),
|
||||
WebhookIntegration('helloworld', display_name='Hello World'),
|
||||
WebhookIntegration('heroku', display_name='Heroku'),
|
||||
|
||||
0
zerver/webhooks/greenhouse/__init__.py
Normal file
0
zerver/webhooks/greenhouse/__init__.py
Normal file
32
zerver/webhooks/greenhouse/doc.html
Normal file
32
zerver/webhooks/greenhouse/doc.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<p>
|
||||
First, create a stream where you would like to receive Greenhouse
|
||||
notifications and subscribe all interested parties to the
|
||||
stream. The integration will automatically use the default
|
||||
stream <code>greenhouse</code> if no stream is supplied, though you
|
||||
will still need to create the stream manually even though it's the
|
||||
default.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Next, go to the Zulip settings page and create a bot named
|
||||
Greenhouse. Go to the account settings page of your Greenhouse
|
||||
account and under Webhooks, add the below URL and name the
|
||||
integration, Zulip.
|
||||
</p>
|
||||
|
||||
<p><code>{{ external_api_uri_subdomain }}/v1/external/greenhouse?api_key=abcdefgh&stream=greenhouse</code></p>
|
||||
|
||||
<p>
|
||||
Note: <code>api_key</code> must be reconfigured to be the API key of your Zulip bot.<br />
|
||||
If you want to change the stream that receives notifications, change <code>stream=</code> in the URL. <br />
|
||||
To change the topic displayed by the bot, simply append <code>&topic=name</code> to the end of the above URL.
|
||||
Where <code>name</code> is your topic.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Congratulations! You're all set</b><br />
|
||||
Your messages should look like this:
|
||||
</p>
|
||||
|
||||
<p><img class="screenshot" src="/static/images/integrations/greenhouse/000.png" /></p>
|
||||
|
||||
70
zerver/webhooks/greenhouse/tests.py
Normal file
70
zerver/webhooks/greenhouse/tests.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Text
|
||||
from zerver.lib.test_classes import WebhookTestCase
|
||||
|
||||
class GreenhouseHookTests(WebhookTestCase):
|
||||
STREAM_NAME = 'greenhouse'
|
||||
URL_TEMPLATE = "/api/v1/external/greenhouse?stream={stream}&api_key={api_key}"
|
||||
FIXTURE_DIR_NAME = 'greenhouse'
|
||||
CONTENT_TYPE = "application/x-www-form-urlencoded"
|
||||
|
||||
def test_message_candidate_hired(self):
|
||||
# type: () -> None
|
||||
expected_subject = "Hire Candidate - 19"
|
||||
expected_message = ("Hire Candidate\n>Johnny Smith\nID: 19"
|
||||
"\nApplying for role:\nDeveloper\n**Emails:**"
|
||||
"\nPersonal\npersonal@example.com\nWork\nwork@example.com\n\n\n>"
|
||||
"**Attachments:**\n[Resume](https://prod-heroku.s3.amazonaws.com/...)\n")
|
||||
|
||||
self.send_and_test_stream_message('candidate_hired',
|
||||
expected_subject,
|
||||
expected_message,
|
||||
content_type=self.CONTENT_TYPE)
|
||||
|
||||
def test_message_candidate_rejected(self):
|
||||
# type: () -> None
|
||||
expected_subject = "Reject Candidate - 265788"
|
||||
expected_message = ("Reject Candidate\n>Hector Porter\nID: "
|
||||
"265788\nApplying for role:\nDesigner"
|
||||
"\n**Emails:**\nPersonal\n"
|
||||
"hector.porter.265788@example.com\n\n\n>"
|
||||
"**Attachments:**\n[Resume](https://prod-heroku.s3.amazonaws.com/...)\n")
|
||||
|
||||
self.send_and_test_stream_message('candidate_rejected',
|
||||
expected_subject,
|
||||
expected_message,
|
||||
content_type=self.CONTENT_TYPE)
|
||||
|
||||
def test_message_candidate_stage_change(self):
|
||||
# type: () -> None
|
||||
expected_subject = "Candidate Stage Change - 265772"
|
||||
expected_message = ("Candidate Stage Change\n>Giuseppe Hurley"
|
||||
"\nID: 265772\nApplying for role:\n"
|
||||
"Designer\n**Emails:**\nPersonal"
|
||||
"\ngiuseppe.hurley@example.com\n\n\n>"
|
||||
"**Attachments:**\n[Resume](https://prod-heroku.s3.amazonaws.com/...)"
|
||||
"\n[Cover_Letter](https://prod-heroku.s3.amazonaws.com/...)"
|
||||
"\n[Attachment](https://prod-heroku.s3.amazonaws.com/...)\n")
|
||||
|
||||
self.send_and_test_stream_message('candidate_stage_change',
|
||||
expected_subject,
|
||||
expected_message,
|
||||
content_type=self.CONTENT_TYPE)
|
||||
|
||||
def test_message_prospect_created(self):
|
||||
# type: () -> None
|
||||
expected_subject = "New Prospect Application - 968190"
|
||||
expected_message = ("New Prospect Application\n>Trisha Troy"
|
||||
"\nID: 968190\nApplying for role:\n"
|
||||
"Designer\n**Emails:**\nPersonal"
|
||||
"\nt.troy@example.com\n\n\n>**Attachments:**"
|
||||
"\n[Resume](https://prod-heroku.s3.amazonaws.com/...)\n")
|
||||
|
||||
self.send_and_test_stream_message('prospect_created',
|
||||
expected_subject,
|
||||
expected_message,
|
||||
content_type=self.CONTENT_TYPE)
|
||||
|
||||
def get_body(self, fixture_name):
|
||||
# type: (Text) -> Text
|
||||
return self.fixture_data("greenhouse", fixture_name, file_type="json")
|
||||
64
zerver/webhooks/greenhouse/view.py
Normal file
64
zerver/webhooks/greenhouse/view.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from typing import Any
|
||||
|
||||
from zerver.lib.actions import check_send_message
|
||||
from zerver.lib.response import json_success, json_error
|
||||
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
|
||||
from zerver.models import UserProfile, Client
|
||||
|
||||
import ujson
|
||||
|
||||
MESSAGE_TEMPLATE = "Applying for role:\n{}\n**Emails:**\n{}\n\n>**Attachments:**\n{}"
|
||||
|
||||
def dict_list_to_string(some_list):
|
||||
# type: (List[Any]) -> str
|
||||
internal_template = ''
|
||||
for item in some_list:
|
||||
item_type = item.get('type', '').title()
|
||||
item_value = item.get('value')
|
||||
item_url = item.get('url')
|
||||
if item_type and item_value:
|
||||
internal_template += "{}\n{}\n".format(item_type, item_value)
|
||||
elif item_type and item_url:
|
||||
internal_template += "[{}]({})\n".format(item_type, item_url)
|
||||
return internal_template
|
||||
|
||||
def message_creator(action, application):
|
||||
# type: (str, Dict[str, Any]) -> str
|
||||
message = MESSAGE_TEMPLATE.format(
|
||||
application['jobs'][0]['name'],
|
||||
dict_list_to_string(application['candidate']['email_addresses']),
|
||||
dict_list_to_string(application['candidate']['attachments']))
|
||||
return message
|
||||
|
||||
@api_key_only_webhook_view('Greenhouse')
|
||||
@has_request_variables
|
||||
def api_greenhouse_webhook(request, user_profile, client,
|
||||
payload=REQ(argument_type='body'),
|
||||
stream=REQ(default='greenhouse'), topic=REQ(default=None)):
|
||||
# type: (HttpRequest, UserProfile, Client, Dict[str, Any], str, str) -> HttpResponse
|
||||
try:
|
||||
if payload['action'] == 'update_candidate':
|
||||
candidate = payload['payload']['candidate']
|
||||
else:
|
||||
candidate = payload['payload']['application']['candidate']
|
||||
action = payload['action'].replace('_', ' ').title()
|
||||
body = "{}\n>{} {}\nID: {}\n{}".format(
|
||||
action,
|
||||
candidate['first_name'],
|
||||
candidate['last_name'],
|
||||
str(candidate['id']),
|
||||
message_creator(payload['action'],
|
||||
payload['payload']['application']))
|
||||
|
||||
if topic is None:
|
||||
topic = "{} - {}".format(action, str(candidate['id']))
|
||||
|
||||
except KeyError as e:
|
||||
return json_error(_("Missing key {} in JSON").format(str(e)))
|
||||
|
||||
check_send_message(user_profile, client, 'stream', [stream], topic, body)
|
||||
return json_success()
|
||||
Reference in New Issue
Block a user