Skip to content

Commit 76fbbab

Browse files
renzonrenzon
authored andcommitted
Created Pythonista Role
close #2694
1 parent 2576572 commit 76fbbab

File tree

9 files changed

+91
-6
lines changed

9 files changed

+91
-6
lines changed

conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ def client_with_user(client, logged_user):
1717
return client
1818

1919

20-
_all_roles = set('data_scientist lead client webdev bootcamper member'.split())
21-
_advanced_roles = {'member'}
20+
_all_roles = set('data_scientist lead client webdev bootcamper pythonista member'.split())
21+
_advanced_roles = set('member pythonista'.split())
2222
_level_one_roles = set('client webdev bootcamper member'.split())
2323
_level_two_roles = set('webdev bootcamper member'.split())
2424
_level_three_roles = set('bootcamper member'.split())

pythonpro/core/admin.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class UserAdmin(RolePermissionsUserAdminMixin, admin.ModelAdmin):
5353
search_fields = ('first_name', 'email')
5454
ordering = ('first_name',)
5555
filter_horizontal = ('groups', 'user_permissions',)
56-
actions = ['make_bootcamper', 'make_webdev', 'make_member', 'make_data_scientist']
56+
actions = ['make_bootcamper', 'make_webdev', 'make_member', 'make_data_scientist', 'make_pythonista']
5757

5858
def make_webdev(self, request, queryset):
5959
from pythonpro.domain import user_facade
@@ -71,6 +71,14 @@ def make_bootcamper(self, request, queryset):
7171
except UserRoleException:
7272
pass # No need to handle on admin
7373

74+
def make_pythonista(self, request, queryset):
75+
from pythonpro.domain import user_facade
76+
for user in queryset:
77+
try:
78+
user_facade.promote_pythonista(user, 'django_admin')
79+
except UserRoleException:
80+
pass # No need to handle on admin
81+
7482
def make_data_scientist(self, request, queryset):
7583
from pythonpro.domain import user_facade
7684
for user in queryset:

pythonpro/core/facade.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ def promote_to_data_scientist(user, source):
141141
assign_role(user, 'data_scientist')
142142

143143

144+
def promote_to_pythonista(user, source):
145+
UserInteraction(category=UserInteraction.BECOME_PYTHONISTA, source=source, user=user).save()
146+
assign_role(user, 'pythonista')
147+
148+
144149
def visit_launch_landing_page(user: User, source: str):
145150
return UserInteraction(category=UserInteraction.LAUNCH_LP, source=source, user=user).save()
146151

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Generated by Django 3.0.8 on 2020-07-23 01:22
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
('core', '0015_become_bootcamper'),
9+
]
10+
11+
operations = [
12+
migrations.AlterField(
13+
model_name='userinteraction',
14+
name='category',
15+
field=models.CharField(
16+
choices=[('BECOME_LEAD', 'User become Lead'), ('ACTIVATED', 'User Watched first video class'),
17+
('CLIENT_LP', 'User visited Client Landing Page'),
18+
('CLIENT_CHECKOUT', 'User clicked on Client checkout button'),
19+
('CLIENT_CHECKOUT_FORM', 'User Filled Client Checkout form'),
20+
('CLIENT_BOLETO', 'User generated a Client Boleto'), ('BECOME_CLIENT', 'User become Client'),
21+
('MEMBER_LP', 'User visited Member Landing Page'),
22+
('MEMBER_CHECKOUT', 'User clicked on Member checkout Button'),
23+
('MEMBER_CHECKOUT_FORM', 'User Filled Member Checkout form'),
24+
('WEBDEV_CHECKOUT_FORM', 'User Filled Webdev Checkout form'),
25+
('MEMBER_BOLETO', 'User generate Member Boleto'),
26+
('WAITING_LIST', 'User subscribed to Waiting List'), ('BECOME_MEMBER', 'User Become Member'),
27+
('BECOME_BOOTCAMPER', 'User Become Bootcamper'),
28+
('BECOME_PYTHONISTA', 'User Become Pythonista'), ('BECOME_WEBDEV', 'User Become Webdev'),
29+
('LAUNCH_LP', 'User visited Launch Landing Page'),
30+
('LAUNCH_SUBSCRIPTION', 'User subscribed to launch'), ('CPL1', 'User Visited CPL1'),
31+
('CPL2', 'User Visited CPL2'), ('CPL3', 'User Visited CPL3'),
32+
('BECOME_DATA_SCIENTIST', 'User Become Data Scientist')], max_length=32),
33+
),
34+
]

pythonpro/core/models.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class Meta:
9292
WAITING_LIST = 'WAITING_LIST'
9393
BECOME_MEMBER = 'BECOME_MEMBER'
9494
BECOME_BOOTCAMPER = 'BECOME_BOOTCAMPER'
95+
BECOME_PYTHONISTA = 'BECOME_PYTHONISTA'
9596
WEBDEV_CHECKOUT_FORM = 'WEBDEV_CHECKOUT_FORM'
9697
BECOME_WEBDEV = 'BECOME_WEBDEV'
9798
LAUNCH_LP = 'LAUNCH_LP'
@@ -121,6 +122,7 @@ class Meta:
121122
(WAITING_LIST, 'User subscribed to Waiting List'),
122123
(BECOME_MEMBER, 'User Become Member'),
123124
(BECOME_BOOTCAMPER, 'User Become Bootcamper'),
125+
(BECOME_PYTHONISTA, 'User Become Pythonista'),
124126
(BECOME_WEBDEV, 'User Become Webdev'),
125127
(LAUNCH_LP, 'User visited Launch Landing Page'),
126128
(LAUNCH_SUBSCRIPTION, 'User subscribed to launch'),

pythonpro/core/roles.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,22 @@ class Bootcamper(AbstractUserRole):
6060
}
6161

6262

63+
watch_pythonista_modules = 'watch_pythonista_modules'
64+
65+
66+
class Pythonista(AbstractUserRole):
67+
available_permissions = {
68+
watch_pythonista_modules: True,
69+
access_forum: True,
70+
}
71+
72+
6373
watch_member_modules = 'watch_member_modules'
6474

6575

6676
class Member(AbstractUserRole):
6777
available_permissions = {
78+
watch_pythonista_modules: True,
6879
watch_webdev_modules: True,
6980
watch_lead_modules: True,
7081
watch_client_modules: True,

pythonpro/domain/user_facade.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,21 @@ def promote_data_scientist(user: _User, source: str) -> _User:
145145
return user
146146

147147

148+
def promote_pythonista(user: _User, source: str) -> _User:
149+
"""
150+
Promote a user to Pythonista role and change it's role on Email Marketing. Will not fail in case API call fails.
151+
Email welcome email is sent to user
152+
:param source: source of traffic
153+
:param user:
154+
:return:
155+
"""
156+
_core_facade.promote_to_pythonista(user, source)
157+
sync_user_on_discourse.delay(user.id)
158+
_email_marketing_facade.create_or_update_pythonista.delay(
159+
user.first_name, user.email, id=user.id)
160+
return user
161+
162+
148163
def find_user_by_email(user_email: str) -> _User:
149164
"""
150165
Find user by her email

pythonpro/email_marketing/facade.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
WEBDEV = 'webdev'
1515
BOOTCAMPER = 'bootcamper'
1616
DATA_SCIENTIST = 'data-scientist'
17+
PYTHONISTA = 'pythonista'
1718

1819
_PYTHON_PRO_ROLES = {LEAD, CLIENT, WEBDEV, BOOTCAMPER, MEMBER}
1920

2021
_ALL_ROLES = set(_PYTHON_PRO_ROLES)
2122
_ALL_ROLES.add(DATA_SCIENTIST)
23+
_ALL_ROLES.add(PYTHONISTA)
2224

2325
run_until_available = shared_task(autoretry_for=(JSONDecodeError,), retry_backoff=True, max_retries=None)
2426

@@ -43,6 +45,11 @@ def create_or_update_data_scientist(name: str, email: str, *tags, id='0', phone=
4345
return create_or_update_user(name, email, DATA_SCIENTIST, *tags, id=id, phone=phone)
4446

4547

48+
@run_until_available
49+
def create_or_update_pythonista(name: str, email: str, *tags, id='0', phone=None):
50+
return create_or_update_user(name, email, PYTHONISTA, *tags, id=id, phone=phone)
51+
52+
4653
@run_until_available
4754
def create_or_update_client(name: str, email: str, *tags, id='0', phone=None):
4855
return create_or_update_user(name, email, CLIENT, *tags, id=id, phone=phone)
@@ -120,8 +127,8 @@ def grant_role(email, id, role: str):
120127
role = role.lower()
121128

122129
if role not in _ALL_ROLES:
123-
raise ValueError(f'Role {role} must be one of {_PYTHON_PRO_ROLES}')
124-
if role == DATA_SCIENTIST:
130+
raise ValueError(f'Role {role} must be one of {_ALL_ROLES}')
131+
if role in {DATA_SCIENTIST, PYTHONISTA}:
125132
roles_to_remove = set()
126133
role_to_grant = role.capitalize()
127134
elif role in _PYTHON_PRO_ROLES:

pythonpro/modules/permissions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
Member,
66
watch_client_modules,
77
watch_lead_modules,
8-
watch_webdev_modules, watch_bootcamp_modules
8+
watch_webdev_modules, watch_bootcamp_modules, watch_pythonista_modules
99
)
1010
from pythonpro.modules.models import Content
1111

1212
_LEAD_MODULES = {'python-birds'}
1313
_CLIENT_MODULES = {'python-birds', 'pytools'}
1414
_WEBDEV_MODULES = {'python-birds', 'pytools', 'django'}
1515
_BOOTCAMPER_MODULES = {'python-birds', 'pytools', 'django', 'entrevistas-tecnicas'}
16+
_PYTHONISTA_MODULES = {'python-birds', 'objetos-pythonicos', 'python-para-pythonistas', 'python-patterns'}
1617

1718

1819
@register_object_checker()
@@ -24,6 +25,8 @@ def access_content(role, user, content: Content) -> bool:
2425
return True
2526
if module_slug in _WEBDEV_MODULES and has_permission(user, watch_webdev_modules):
2627
return True
28+
if module_slug in _PYTHONISTA_MODULES and has_permission(user, watch_pythonista_modules):
29+
return True
2730
if module_slug in _CLIENT_MODULES and has_permission(user, watch_client_modules):
2831
return True
2932
if module_slug in _LEAD_MODULES and has_permission(user, watch_lead_modules):

0 commit comments

Comments
 (0)