From 5efa637b510c590fa30db0b69439a07ae3191d88 Mon Sep 17 00:00:00 2001 From: Fedor Borshev Date: Wed, 6 Dec 2023 22:46:01 +0300 Subject: [PATCH 1/2] Refactoring: test revamp, moved happiness messages to the OrderPaidSetter to remove OrderShipper in future --- src/apps/orders/services/order_paid_setter.py | 29 +++++++++++++++++++ src/apps/orders/services/order_shipper.py | 28 ------------------ tests/apps/orders/order_shipping/conftest.py | 5 ---- .../order_shipping/tests_order_set_paid.py | 8 ----- .../tests_sending_happiness_messages.py | 10 +++---- 5 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/apps/orders/services/order_paid_setter.py b/src/apps/orders/services/order_paid_setter.py index 7c561434006..0387d2ba9f6 100644 --- a/src/apps/orders/services/order_paid_setter.py +++ b/src/apps/orders/services/order_paid_setter.py @@ -2,14 +2,17 @@ from celery import chain +from django.conf import settings from django.utils import timezone from apps.amocrm.tasks import amocrm_enabled from apps.amocrm.tasks import push_order from apps.amocrm.tasks import push_user +from apps.orders import human_readable from apps.orders.models import Order from apps.users.tasks import rebuild_tags from core.services import BaseService +from core.tasks import send_telegram_message @dataclass @@ -27,6 +30,7 @@ def __post_init__(self) -> None: def act(self) -> None: self.mark_order_as_paid() self.ship() + self.send_happiness_message() self.rebuild_user_tags() self.update_amocrm() @@ -52,3 +56,28 @@ def update_amocrm(self) -> None: ).apply_async( countdown=30 ) # hope rebuild tags are finished + + def send_happiness_message(self) -> None: + if not settings.HAPPINESS_MESSAGES_CHAT_ID: + return + + if self.is_already_paid or self.silent or self.order.price <= 0: + return + + send_telegram_message.delay( + chat_id=settings.HAPPINESS_MESSAGES_CHAT_ID, + text=self._get_happiness_message_text(self.order), + ) + + @staticmethod + def _get_happiness_message_text(order: Order) -> str: + sum = str(order.price).replace(".00", "") + reason = str(order.item) + payment_method = human_readable.get_order_payment_method_name(order) + + payment_info = f"πŸ’°+{sum} β‚½, {payment_method}" + + if order.promocode: + payment_info += f", ΠΏΡ€ΠΎΠΌΠΎΠΊΠΎΠ΄ {order.promocode}" + + return f"{payment_info}\n{reason}\n{order.user}" diff --git a/src/apps/orders/services/order_shipper.py b/src/apps/orders/services/order_shipper.py index 0afce3ec7ae..13258d6a8b3 100644 --- a/src/apps/orders/services/order_shipper.py +++ b/src/apps/orders/services/order_shipper.py @@ -1,12 +1,9 @@ from dataclasses import dataclass -from django.conf import settings from django.utils import timezone -from apps.orders import human_readable from apps.orders.models import Order from core.services import BaseService -from core.tasks import send_telegram_message @dataclass @@ -21,9 +18,6 @@ def act(self) -> None: self.ship() self.mark_order_as_shipped() - if not self.silent and self.order.price > 0: - self.send_happiness_message() - def ship(self) -> None: """Ship the order""" self.order.item.ship(to=self.order.user, order=self.order) @@ -31,25 +25,3 @@ def ship(self) -> None: def mark_order_as_shipped(self) -> None: self.order.shipped = timezone.now() self.order.save(update_fields=["shipped", "modified"]) - - def send_happiness_message(self) -> None: - if not settings.HAPPINESS_MESSAGES_CHAT_ID: - return - - send_telegram_message.delay( - chat_id=settings.HAPPINESS_MESSAGES_CHAT_ID, - text=self.get_order_happiness_message(self.order), - ) - - @staticmethod - def get_order_happiness_message(order: Order) -> str: - sum = str(order.price).replace(".00", "") - reason = str(order.item) - payment_method = human_readable.get_order_payment_method_name(order) - - payment_info = f"πŸ’°+{sum} β‚½, {payment_method}" - - if order.promocode: - payment_info += f", ΠΏΡ€ΠΎΠΌΠΎΠΊΠΎΠ΄ {order.promocode}" - - return f"{payment_info}\n{reason}\n{order.user}" diff --git a/tests/apps/orders/order_shipping/conftest.py b/tests/apps/orders/order_shipping/conftest.py index 5c46ff4703c..fac7154f52f 100644 --- a/tests/apps/orders/order_shipping/conftest.py +++ b/tests/apps/orders/order_shipping/conftest.py @@ -4,11 +4,6 @@ -@pytest.fixture(autouse=True) -def rebuild_tags(mocker): - return mocker.patch("apps.users.tasks.rebuild_tags.delay") - - @pytest.fixture def user(mixer): return mixer.blend("users.User", first_name="Kamaz", last_name="Otkhodov", email="kamaz@gmail.com") diff --git a/tests/apps/orders/order_shipping/tests_order_set_paid.py b/tests/apps/orders/order_shipping/tests_order_set_paid.py index cf03e676136..3ce4be4482e 100644 --- a/tests/apps/orders/order_shipping/tests_order_set_paid.py +++ b/tests/apps/orders/order_shipping/tests_order_set_paid.py @@ -24,14 +24,6 @@ def test_ships(order, course, user, ship): ship.assert_called_once_with(course, to=user, order=order) -def test_update_user_tags(order, rebuild_tags): - order.user.update(email="") - - order.set_paid() - - rebuild_tags.assert_called_once_with(student_id=order.user.id) - - def test_not_ships_if_order_is_already_paid(order, ship): order.update(paid=datetime(2032, 12, 1, 15, 30, tzinfo=timezone.utc)) diff --git a/tests/apps/orders/order_shipping/tests_sending_happiness_messages.py b/tests/apps/orders/order_shipping/tests_sending_happiness_messages.py index 74e2d08befb..8e927a0fc60 100644 --- a/tests/apps/orders/order_shipping/tests_sending_happiness_messages.py +++ b/tests/apps/orders/order_shipping/tests_sending_happiness_messages.py @@ -2,7 +2,7 @@ from apps.banking.selector import BANK_KEYS from apps.banking.selector import BANKS -from apps.orders.services import OrderShipper +from apps.orders.services import OrderPaidSetter pytestmark = [pytest.mark.django_db] @@ -20,7 +20,7 @@ def tg_message(mocker): @pytest.fixture def mock_get_happiness_message(mocker): - return mocker.patch("apps.orders.services.order_shipper.OrderShipper.get_order_happiness_message", return_value="happiness_message") + return mocker.patch("apps.orders.services.order_paid_setter.OrderPaidSetter._get_happiness_message_text", return_value="happiness_message") def test(tg_message, order, mock_get_happiness_message): @@ -70,7 +70,7 @@ def test_notification_message_include_payment_method(order, bank_id): order.update(bank_id=bank_id) order.set_paid() - message = OrderShipper.get_order_happiness_message(order) + message = OrderPaidSetter._get_happiness_message_text(order) assert message == f"πŸ’°+1500 β‚½, {BANKS[bank_id].name}\nΠ—Π°ΠΏΠΈΡΡŒ курсов ΠΊΠ°Ρ‚Π°Π½ΡŒΡ ΠΈ ΠΌΡ‹Ρ‚ΡŒΡ\nKamaz Otkhodov" @@ -79,7 +79,7 @@ def test_include_promocode_if_set(order, mixer): order.update(promocode=mixer.blend("orders.PromoCode", name="YARR!", discount_percent=1)) order.set_paid() - message = OrderShipper.get_order_happiness_message(order) + message = OrderPaidSetter._get_happiness_message_text(order) assert message == "πŸ’°+1500 β‚½, Tinkoff, ΠΏΡ€ΠΎΠΌΠΎΠΊΠΎΠ΄ YARR!\nΠ—Π°ΠΏΠΈΡΡŒ курсов ΠΊΠ°Ρ‚Π°Π½ΡŒΡ ΠΈ ΠΌΡ‹Ρ‚ΡŒΡ\nKamaz Otkhodov" @@ -88,6 +88,6 @@ def test_include_group_if_set(order, factory): order.item.update(group=factory.group(name="ЭффСктивная прокрастинация ΠΏΠΎΡ‚ΠΎΠΊ 2")) order.set_paid() - message = OrderShipper.get_order_happiness_message(order) + message = OrderPaidSetter._get_happiness_message_text(order) assert message == "πŸ’°+1500 β‚½, Tinkoff\nΠ—Π°ΠΏΠΈΡΡŒ курсов ΠΊΠ°Ρ‚Π°Π½ΡŒΡ ΠΈ ΠΌΡ‹Ρ‚ΡŒΡ - ЭффСктивная прокрастинация ΠΏΠΎΡ‚ΠΎΠΊ 2\nKamaz Otkhodov" From bcf3ae611f185399b8a68ee103e202acb0ccfa02 Mon Sep 17 00:00:00 2001 From: Fedor Borshev Date: Wed, 6 Dec 2023 22:51:03 +0300 Subject: [PATCH 2/2] Fixed dashamail updating after order gets paid --- src/apps/orders/services/order_paid_setter.py | 14 ++++- .../tests_marketing_integrations.py | 54 +++++++++++++++++++ tests/test_order_factory.py | 2 +- 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/apps/orders/order_shipping/tests_marketing_integrations.py diff --git a/src/apps/orders/services/order_paid_setter.py b/src/apps/orders/services/order_paid_setter.py index 0387d2ba9f6..5fb59f9e147 100644 --- a/src/apps/orders/services/order_paid_setter.py +++ b/src/apps/orders/services/order_paid_setter.py @@ -8,6 +8,7 @@ from apps.amocrm.tasks import amocrm_enabled from apps.amocrm.tasks import push_order from apps.amocrm.tasks import push_user +from apps.dashamail.tasks import update_subscription as update_dashamail_subscription from apps.orders import human_readable from apps.orders.models import Order from apps.users.tasks import rebuild_tags @@ -30,9 +31,12 @@ def __post_init__(self) -> None: def act(self) -> None: self.mark_order_as_paid() self.ship() + self.send_happiness_message() + self.rebuild_user_tags() self.update_amocrm() + self.update_dashamail() def mark_order_as_paid(self) -> None: self.order.paid = timezone.now() @@ -51,11 +55,17 @@ def rebuild_user_tags(self) -> None: def update_amocrm(self) -> None: if amocrm_enabled(): chain( - push_user.si(user_id=self.order.user.id), + push_user.si(user_id=self.order.user_id), push_order.si(order_id=self.order.id), ).apply_async( countdown=30 - ) # hope rebuild tags are finished + ) # hope tags are rebuilt by this time + + def update_dashamail(self) -> None: + update_dashamail_subscription.apply_async( + kwargs=dict(student_id=self.order.user_id), + countdown=30, # hope tags are built by this time + ) def send_happiness_message(self) -> None: if not settings.HAPPINESS_MESSAGES_CHAT_ID: diff --git a/tests/apps/orders/order_shipping/tests_marketing_integrations.py b/tests/apps/orders/order_shipping/tests_marketing_integrations.py new file mode 100644 index 00000000000..60324b9991a --- /dev/null +++ b/tests/apps/orders/order_shipping/tests_marketing_integrations.py @@ -0,0 +1,54 @@ +import pytest + + +pytestmark = [ + pytest.mark.django_db, + +] + +@pytest.fixture +def _enable_amocrm(settings): + settings.AMOCRM_BASE_URL = "https://test.amocrm.ru" + settings.AMOCRM_REDIRECT_URL = "https://test-education.ru" + settings.AMOCRM_INTEGRATION_ID = "4815162342" + settings.AMOCRM_CLIENT_SECRET = "top-secret-007" + settings.AMOCRM_AUTHORIZATION_CODE = "1337yep" + + +@pytest.fixture +def update_amocrm_order(mocker): + return mocker.patch("apps.amocrm.tasks.AmoCRMOrderPusher.act") + +@pytest.fixture +def update_amocrm_user(mocker): + return mocker.patch("apps.amocrm.tasks.AmoCRMUserPusher.act") + + +@pytest.fixture +def update_dashamail(mocker): + return mocker.patch("apps.dashamail.tasks.DashamailListsClient.subscribe_or_update") + + +@pytest.mark.usefixtures('_enable_amocrm') +def test_amocrm_is_updated(order, update_amocrm_order, update_amocrm_user): + order.set_paid() + + update_amocrm_order.assert_called_once() + update_amocrm_user.assert_called_once() + + +@pytest.mark.user_tags_rebuild +def test_tags_are_rebuilt(order): + assert 'any-purchase' not in order.user.tags + + order.set_paid() + order.user.refresh_from_db() + + assert 'any-purchase' in order.user.tags + + +@pytest.mark.dashamail +def test_dashamail_is_updated(order, update_dashamail): + order.set_paid() + + update_dashamail.assert_called_once() diff --git a/tests/test_order_factory.py b/tests/test_order_factory.py index d4e71b9185e..adcd4e9d9bd 100644 --- a/tests/test_order_factory.py +++ b/tests/test_order_factory.py @@ -5,5 +5,5 @@ def test(factory, django_assert_max_num_queries): - with django_assert_max_num_queries(10): + with django_assert_max_num_queries(11): factory.order(is_paid=True)