From 9c8f30ed10599f95dc56693a498e3ee9e8723b2e Mon Sep 17 00:00:00 2001 From: renzon Date: Fri, 17 Jul 2020 18:53:38 -0300 Subject: [PATCH] Created Bootcamper role Added test form admin make_{role} commands close #2611 --- pythonpro/core/facade.py | 21 ++++++++++- .../core/migrations/0015_become_bootcamper.py | 33 +++++++++++++++++ pythonpro/core/models.py | 2 ++ pythonpro/core/tests/test_admin.py | 36 +++++++++++++++++++ .../core/tests/test_lead_landing_page.py | 5 --- pythonpro/domain/user_facade.py | 4 +-- pythonpro/email_marketing/facade.py | 8 ++++- .../email_marketing/tests/test_grant_role.py | 9 ++--- 8 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 pythonpro/core/migrations/0015_become_bootcamper.py create mode 100644 pythonpro/core/tests/test_admin.py diff --git a/pythonpro/core/facade.py b/pythonpro/core/facade.py index 4d7da797..df3be9d3 100644 --- a/pythonpro/core/facade.py +++ b/pythonpro/core/facade.py @@ -100,6 +100,23 @@ def promote_to_member(user: User, source: str) -> None: remove_role(user, 'lead') remove_role(user, 'webdev') remove_role(user, 'client') + remove_role(user, 'bootcamper') + + +def promote_to_bootcamper(user: User, source: str) -> None: + """ + Promote a user do bootcamper. Raises exception in case user is a member + :param user: + """ + if has_role(user, 'member'): + raise UserRoleException('User is already a member') + elif has_role(user, 'bootcamper'): + raise UserRoleException('User is already a bootcamper') + UserInteraction(category=UserInteraction.BECOME_BOOTCAMPER, source=source, user=user).save() + assign_role(user, 'bootcamper') + remove_role(user, 'lead') + remove_role(user, 'webdev') + remove_role(user, 'client') def promote_to_webdev(user: User, source: str) -> None: @@ -109,7 +126,9 @@ def promote_to_webdev(user: User, source: str) -> None: """ if has_role(user, 'member'): raise UserRoleException('User is already a member') - if has_role(user, 'webdev'): + elif has_role(user, 'bootcamper'): + raise UserRoleException('User is already a bootcamper') + elif has_role(user, 'webdev'): raise UserRoleException('User is already a webdev') UserInteraction(category=UserInteraction.BECOME_WEBDEV, source=source, user=user).save() assign_role(user, 'webdev') diff --git a/pythonpro/core/migrations/0015_become_bootcamper.py b/pythonpro/core/migrations/0015_become_bootcamper.py new file mode 100644 index 00000000..26479646 --- /dev/null +++ b/pythonpro/core/migrations/0015_become_bootcamper.py @@ -0,0 +1,33 @@ +# Generated by Django 3.0.8 on 2020-07-17 21:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('core', '0014_auto_become_data_scientist'), + ] + + operations = [ + migrations.AlterField( + model_name='userinteraction', + name='category', + field=models.CharField( + choices=[('BECOME_LEAD', 'User become Lead'), ('ACTIVATED', 'User Watched first video class'), + ('CLIENT_LP', 'User visited Client Landing Page'), + ('CLIENT_CHECKOUT', 'User clicked on Client checkout button'), + ('CLIENT_CHECKOUT_FORM', 'User Filled Client Checkout form'), + ('CLIENT_BOLETO', 'User generated a Client Boleto'), ('BECOME_CLIENT', 'User become Client'), + ('MEMBER_LP', 'User visited Member Landing Page'), + ('MEMBER_CHECKOUT', 'User clicked on Member checkout Button'), + ('MEMBER_CHECKOUT_FORM', 'User Filled Member Checkout form'), + ('WEBDEV_CHECKOUT_FORM', 'User Filled Webdev Checkout form'), + ('MEMBER_BOLETO', 'User generate Member Boleto'), + ('WAITING_LIST', 'User subscribed to Waiting List'), ('BECOME_MEMBER', 'User Become Member'), + ('BECOME_BOOTCAMPER', 'User Become Bootcamper'), ('BECOME_WEBDEV', 'User Become Webdev'), + ('LAUNCH_LP', 'User visited Launch Landing Page'), + ('LAUNCH_SUBSCRIPTION', 'User subscribed to launch'), ('CPL1', 'User Visited CPL1'), + ('CPL2', 'User Visited CPL2'), ('CPL3', 'User Visited CPL3'), + ('BECOME_DATA_SCIENTIST', 'User Become Data Scientist')], max_length=32), + ), + ] diff --git a/pythonpro/core/models.py b/pythonpro/core/models.py index 68c96bdb..1cf559ea 100644 --- a/pythonpro/core/models.py +++ b/pythonpro/core/models.py @@ -91,6 +91,7 @@ class Meta: MEMBER_BOLETO = 'MEMBER_BOLETO' WAITING_LIST = 'WAITING_LIST' BECOME_MEMBER = 'BECOME_MEMBER' + BECOME_BOOTCAMPER = 'BECOME_BOOTCAMPER' WEBDEV_CHECKOUT_FORM = 'WEBDEV_CHECKOUT_FORM' BECOME_WEBDEV = 'BECOME_WEBDEV' LAUNCH_LP = 'LAUNCH_LP' @@ -119,6 +120,7 @@ class Meta: (MEMBER_BOLETO, 'User generate Member Boleto'), (WAITING_LIST, 'User subscribed to Waiting List'), (BECOME_MEMBER, 'User Become Member'), + (BECOME_BOOTCAMPER, 'User Become Bootcamper'), (BECOME_WEBDEV, 'User Become Webdev'), (LAUNCH_LP, 'User visited Launch Landing Page'), (LAUNCH_SUBSCRIPTION, 'User subscribed to launch'), diff --git a/pythonpro/core/tests/test_admin.py b/pythonpro/core/tests/test_admin.py new file mode 100644 index 00000000..15d92819 --- /dev/null +++ b/pythonpro/core/tests/test_admin.py @@ -0,0 +1,36 @@ +import pytest +from django.contrib.admin import AdminSite +from rolepermissions.checkers import has_role +from rolepermissions.roles import RolesManager + +from pythonpro.core.admin import UserAdmin +from pythonpro.domain import user_facade + + +@pytest.fixture +def sync_user_delay(mocker): + return mocker.patch('pythonpro.domain.user_facade.sync_user_on_discourse.delay') + + +@pytest.fixture +def email_market_mocks(mocker): + maybe_function_names = dir(user_facade._email_marketing_facade) + task_function_mocks = [] + for name in maybe_function_names: + maybe_task_function = getattr(user_facade._email_marketing_facade, name) + if hasattr(maybe_task_function, 'delay'): + task_function_mocks.append(mocker.patch( + f'pythonpro.domain.user_facade._email_marketing_facade.{name}.delay', side_effeict=maybe_task_function + )) + return task_function_mocks + + +@pytest.mark.parametrize('role', RolesManager.get_roles_names()) +def test_make_actions(logged_user, role, django_user_model, sync_user_delay, email_market_mocks, cohort): + if role in {'lead', 'client'}: + return # Client product is not active anymore + admin = UserAdmin(django_user_model, AdminSite()) + make_method = getattr(admin, f'make_{role}') + assert not has_role(logged_user, role) + make_method(None, [logged_user]) + assert has_role(logged_user, role) diff --git a/pythonpro/core/tests/test_lead_landing_page.py b/pythonpro/core/tests/test_lead_landing_page.py index 8ae0ef52..187cd42f 100644 --- a/pythonpro/core/tests/test_lead_landing_page.py +++ b/pythonpro/core/tests/test_lead_landing_page.py @@ -139,11 +139,6 @@ def resp_lead_change_pasword(resp_lead_creation, client): ) -@pytest.fixture(autouse=True) -def sync_user(mocker): - return mocker.patch('pythonpro.domain.user_facade.sync_user_on_discourse') - - @pytest.fixture(autouse=True) def sync_user_delay(mocker): return mocker.patch('pythonpro.domain.user_facade.sync_user_on_discourse.delay') diff --git a/pythonpro/domain/user_facade.py b/pythonpro/domain/user_facade.py index debfce85..61a0d92c 100644 --- a/pythonpro/domain/user_facade.py +++ b/pythonpro/domain/user_facade.py @@ -25,8 +25,6 @@ 'force_register_member', 'click_member_checkout', 'subscribe_anonymous_user_to_waiting_list' ] -CLIENT_BOLETO_TAG = 'client-boleto' - def register_lead(first_name: str, email: str, source: str = 'unknown', tags: list = []) -> _User: """ @@ -207,7 +205,7 @@ def subscribe_launch_landing_page(user, source): def click_member_checkout(user): """ - Mark user as visited client landing page + Mark user as visited member landing page :param user: :return: """ diff --git a/pythonpro/email_marketing/facade.py b/pythonpro/email_marketing/facade.py index ec1997b3..c89de495 100644 --- a/pythonpro/email_marketing/facade.py +++ b/pythonpro/email_marketing/facade.py @@ -12,9 +12,10 @@ CLIENT = 'client' MEMBER = 'member' WEBDEV = 'webdev' +BOOTCAMPER = 'bootcamper' DATA_SCIENTIST = 'data-scientist' -_PYTHON_PRO_ROLES = {LEAD, CLIENT, MEMBER, WEBDEV} +_PYTHON_PRO_ROLES = {LEAD, CLIENT, WEBDEV, BOOTCAMPER, MEMBER} _ALL_ROLES = set(_PYTHON_PRO_ROLES) _ALL_ROLES.add(DATA_SCIENTIST) @@ -32,6 +33,11 @@ def create_or_update_lead(name: str, email: str, *tags, id='0', phone=None): return create_or_update_user(name, email, LEAD, *tags, id=id, phone=phone) +@run_until_available +def create_or_update_bootcamper(name: str, email: str, *tags, id='0', phone=None): + return create_or_update_user(name, email, BOOTCAMPER, *tags, id=id, phone=phone) + + @run_until_available def create_or_update_data_scientist(name: str, email: str, *tags, id='0', phone=None): return create_or_update_user(name, email, DATA_SCIENTIST, *tags, id=id, phone=phone) diff --git a/pythonpro/email_marketing/tests/test_grant_role.py b/pythonpro/email_marketing/tests/test_grant_role.py index b126300a..675593d4 100644 --- a/pythonpro/email_marketing/tests/test_grant_role.py +++ b/pythonpro/email_marketing/tests/test_grant_role.py @@ -46,10 +46,11 @@ def test_data_scientist_add_tag_absent_user(contacts_mock, find_active_campaign_ python_pro_roles = pytest.mark.parametrize( 'granted_role, removed_roles', [ - ('lead', {'Client', 'Webdev', 'Member'}), - ('client', {'Lead', 'Webdev', 'Member'}), - ('webdev', {'Lead', 'Client', 'Member'}), - ('member', {'Lead', 'Client', 'Webdev'}), + ('lead', {'Client', 'Webdev', 'Bootcamper', 'Member'}), + ('client', {'Lead', 'Webdev', 'Bootcamper', 'Member'}), + ('webdev', {'Lead', 'Client', 'Bootcamper', 'Member'}), + ('bootcamper', {'Lead', 'Client', 'Webdev', 'Member'}), + ('member', {'Lead', 'Client', 'Webdev', 'Bootcamper'}), ] )