Report the user's name and company to Marketo
Also fixes the API to report the other changes (username and email) as well
This commit is contained in:
parent
860942ece1
commit
1a61ef4e04
8 changed files with 78 additions and 24 deletions
|
@ -337,7 +337,8 @@ class User(BaseModel):
|
||||||
enabled = BooleanField(default=True)
|
enabled = BooleanField(default=True)
|
||||||
invoice_email_address = CharField(null=True, index=True)
|
invoice_email_address = CharField(null=True, index=True)
|
||||||
|
|
||||||
name = CharField(null=True)
|
given_name = CharField(null=True)
|
||||||
|
family_name = CharField(null=True)
|
||||||
company = CharField(null=True)
|
company = CharField(null=True)
|
||||||
|
|
||||||
def delete_instance(self, recursive=False, delete_nullable=False):
|
def delete_instance(self, recursive=False, delete_nullable=False):
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
"""Add user metadata fields
|
"""Add user metadata fields
|
||||||
|
|
||||||
Revision ID: 491a530df230
|
Revision ID: faf752bd2e0a
|
||||||
Revises: 6c7014e84a5e
|
Revises: 6c7014e84a5e
|
||||||
Create Date: 2016-11-04 18:03:05.237408
|
Create Date: 2016-11-14 17:29:03.984665
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision = '491a530df230'
|
revision = 'faf752bd2e0a'
|
||||||
down_revision = '6c7014e84a5e'
|
down_revision = '6c7014e84a5e'
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from util.migrate import UTF8CharField
|
from util.migrate import UTF8CharField
|
||||||
|
|
||||||
def upgrade(tables):
|
def upgrade(tables):
|
||||||
### commands auto generated by Alembic - please adjust! ###
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
op.add_column('user', sa.Column('company', UTF8CharField(length=255), nullable=True))
|
op.add_column('user', sa.Column('company', UTF8CharField(length=255), nullable=True))
|
||||||
op.add_column('user', sa.Column('name', UTF8CharField(length=255), nullable=True))
|
op.add_column('user', sa.Column('family_name', UTF8CharField(length=255), nullable=True))
|
||||||
|
op.add_column('user', sa.Column('given_name', UTF8CharField(length=255), nullable=True))
|
||||||
### end Alembic commands ###
|
### end Alembic commands ###
|
||||||
|
|
||||||
op.bulk_insert(tables.userpromptkind,
|
op.bulk_insert(tables.userpromptkind,
|
||||||
|
@ -29,7 +31,8 @@ def upgrade(tables):
|
||||||
|
|
||||||
def downgrade(tables):
|
def downgrade(tables):
|
||||||
### commands auto generated by Alembic - please adjust! ###
|
### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_column('user', 'name')
|
op.drop_column('user', 'given_name')
|
||||||
|
op.drop_column('user', 'family_name')
|
||||||
op.drop_column('user', 'company')
|
op.drop_column('user', 'company')
|
||||||
### end Alembic commands ###
|
### end Alembic commands ###
|
||||||
|
|
|
@ -355,10 +355,11 @@ def list_entity_robot_permission_teams(entity_name, include_permissions=False):
|
||||||
return TupleSelector(query, fields)
|
return TupleSelector(query, fields)
|
||||||
|
|
||||||
|
|
||||||
def update_user_metadata(user, name=None, company=None):
|
def update_user_metadata(user, given_name=None, family_name=None, company=None):
|
||||||
""" Updates the metadata associated with the user, including his/her name and company. """
|
""" Updates the metadata associated with the user, including his/her name and company. """
|
||||||
with db_transaction():
|
with db_transaction():
|
||||||
user.name = name or user.name
|
user.given_name = given_name or user.given_name
|
||||||
|
user.family_name = family_name or user.family_name
|
||||||
user.company = company or user.company
|
user.company = company or user.company
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
|
|
@ -213,9 +213,13 @@ class User(ApiResource):
|
||||||
'type': ['string', 'null'],
|
'type': ['string', 'null'],
|
||||||
'description': 'Custom email address for receiving invoices',
|
'description': 'Custom email address for receiving invoices',
|
||||||
},
|
},
|
||||||
'name': {
|
'given_name': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'description': 'The optional entered name for the user',
|
'description': 'The optional entered given name for the user',
|
||||||
|
},
|
||||||
|
'family_name': {
|
||||||
|
'type': 'string',
|
||||||
|
'description': 'The optional entered family name for the user',
|
||||||
},
|
},
|
||||||
'company': {
|
'company': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
|
@ -332,10 +336,14 @@ class User(ApiResource):
|
||||||
code = model.user.create_confirm_email_code(user, new_email=new_email)
|
code = model.user.create_confirm_email_code(user, new_email=new_email)
|
||||||
send_change_email(user.username, user_data['email'], code.code)
|
send_change_email(user.username, user_data['email'], code.code)
|
||||||
else:
|
else:
|
||||||
|
user_analytics.change_email(user.email, new_email)
|
||||||
model.user.update_email(user, new_email, auto_verify=not features.MAILING)
|
model.user.update_email(user, new_email, auto_verify=not features.MAILING)
|
||||||
|
|
||||||
if 'name' in user_data or 'company' in user_data:
|
if 'given_name' in user_data or 'family_name' in user_data or 'company' in user_data:
|
||||||
model.user.update_user_metadata(user, user_data.get('name'), user_data.get('company'))
|
model.user.update_user_metadata(user, user_data.get('given_name'),
|
||||||
|
user_data.get('family_name'), user_data.get('company'))
|
||||||
|
user_analytics.change_metadata(user.email, user_data.get('given_name'),
|
||||||
|
user_data.get('family_name'), user_data.get('company'))
|
||||||
|
|
||||||
# Check for username rename. A username can be renamed if the feature is enabled OR the user
|
# Check for username rename. A username can be renamed if the feature is enabled OR the user
|
||||||
# currently has a confirm_username prompt.
|
# currently has a confirm_username prompt.
|
||||||
|
@ -353,6 +361,7 @@ class User(ApiResource):
|
||||||
raise request_error(message='Username is already in use')
|
raise request_error(message='Username is already in use')
|
||||||
|
|
||||||
user = model.user.change_username(user.id, new_username)
|
user = model.user.change_username(user.id, new_username)
|
||||||
|
user_analytics.change_username(user.email, new_username)
|
||||||
elif confirm_username:
|
elif confirm_username:
|
||||||
model.user.remove_user_prompt(user, 'confirm_username')
|
model.user.remove_user_prompt(user, 'confirm_username')
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,8 @@ def common_login(db_user, permanent_session=True):
|
||||||
session.permanent_session_lifetime = convert_to_timedelta(session_timeout_str)
|
session.permanent_session_lifetime = convert_to_timedelta(session_timeout_str)
|
||||||
|
|
||||||
# Inform our user analytics that we have a new "lead"
|
# Inform our user analytics that we have a new "lead"
|
||||||
user_analytics.create_lead(db_user.email, db_user.username)
|
user_analytics.create_lead(db_user.email, db_user.username, db_user.given_name,
|
||||||
|
db_user.family_name, db_user.company)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.debug('User could not be logged in, inactive?.')
|
logger.debug('User could not be logged in, inactive?.')
|
||||||
|
|
|
@ -42,19 +42,28 @@
|
||||||
|
|
||||||
<form name="metadataForm" ng-submit="updateUser(metadata)" style="margin-top: 20px;">
|
<form name="metadataForm" ng-submit="updateUser(metadata)" style="margin-top: 20px;">
|
||||||
<div class="form-group nested">
|
<div class="form-group nested">
|
||||||
<label for="name">Name</label>
|
<label for="givenName">Given Name</label>
|
||||||
<div class="field-row">
|
<div class="field-row">
|
||||||
<span class="field-container">
|
<span class="field-container">
|
||||||
<input type="text" class="form-control" placeholder="Name" ng-model="metadata.name"></span>
|
<input type="text" class="form-control" placeholder="Given Name" ng-model="metadata.given_name" name="givenName">
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group nested">
|
<div class="form-group nested">
|
||||||
<label for="firstName">Company</label>
|
<label for="familyName">Family Name</label>
|
||||||
<div class="field-row">
|
<div class="field-row">
|
||||||
<span class="field-container">
|
<span class="field-container">
|
||||||
<input type="text" class="form-control" placeholder="Company name" ng-model="metadata.company"></span>
|
<input type="text" class="form-control" placeholder="Family Name" ng-model="metadata.family_name" name="familyName">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group nested">
|
||||||
|
<label for="company">Company</label>
|
||||||
|
<div class="field-row">
|
||||||
|
<span class="field-container">
|
||||||
|
<input type="text" class="form-control" placeholder="Company name" ng-model="metadata.company" name="company"></span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Binary file not shown.
|
@ -27,13 +27,29 @@ class _MarketoAnalyticsClient(object):
|
||||||
self._munchkin_private_key = munchkin_private_key
|
self._munchkin_private_key = munchkin_private_key
|
||||||
self._lead_source = lead_source
|
self._lead_source = lead_source
|
||||||
|
|
||||||
def create_lead(self, email, username):
|
def _get_lead_metadata(self, given_name, family_name, company):
|
||||||
|
metadata = {}
|
||||||
|
if given_name:
|
||||||
|
metadata['firstName'] = given_name
|
||||||
|
|
||||||
|
if family_name:
|
||||||
|
metadata['lastName'] = family_name
|
||||||
|
|
||||||
|
if company:
|
||||||
|
metadata['company'] = company
|
||||||
|
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
def create_lead(self, email, username, given_name, family_name, company):
|
||||||
lead_data = dict(
|
lead_data = dict(
|
||||||
email=email,
|
email=email,
|
||||||
Quay_Username__c=username,
|
Quay_Username__c=username,
|
||||||
leadSource='Web - Product Trial',
|
leadSource='Web - Product Trial',
|
||||||
Lead_Source_Detail__c=self._lead_source,
|
Lead_Source_Detail__c=self._lead_source,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
lead_data.update(self._get_lead_metadata(given_name, family_name, company))
|
||||||
|
|
||||||
self._marketo.create_update_leads(
|
self._marketo.create_update_leads(
|
||||||
action='createOrUpdate',
|
action='createOrUpdate',
|
||||||
leads=[lead_data],
|
leads=[lead_data],
|
||||||
|
@ -65,16 +81,30 @@ class _MarketoAnalyticsClient(object):
|
||||||
lookupField='id',
|
lookupField='id',
|
||||||
)
|
)
|
||||||
|
|
||||||
def change_username(self, email, new_username):
|
def change_metadata(self, email, given_name, family_name, company):
|
||||||
found = self._find_leads_by_email(email)
|
lead_data = self._get_lead_metadata(given_name, family_name, company)
|
||||||
|
if not lead_data:
|
||||||
|
return
|
||||||
|
|
||||||
# Update using their user id.
|
# Update using their email address.
|
||||||
updated = [dict(id=lead['id'], Quay_Username__c=new_username) for lead in found]
|
lead_data['email'] = email
|
||||||
self._marketo.create_update_leads(
|
self._marketo.create_update_leads(
|
||||||
action='updateOnly',
|
action='updateOnly',
|
||||||
leads=updated,
|
leads=[lead_data],
|
||||||
asyncProcessing=True,
|
asyncProcessing=True,
|
||||||
lookupField='id',
|
lookupField='email',
|
||||||
|
)
|
||||||
|
|
||||||
|
def change_username(self, email, new_username):
|
||||||
|
# Update using their email.
|
||||||
|
self._marketo.create_update_leads(
|
||||||
|
action='updateOnly',
|
||||||
|
leads=[{
|
||||||
|
'email': email,
|
||||||
|
'Quay_Username__c': new_username,
|
||||||
|
}],
|
||||||
|
asyncProcessing=True,
|
||||||
|
lookupField='email',
|
||||||
)
|
)
|
||||||
|
|
||||||
@AsyncExecutorWrapper.sync
|
@AsyncExecutorWrapper.sync
|
||||||
|
|
Reference in a new issue