Skip to content

Commit

Permalink
fix: remove zendesk (#269)
Browse files Browse the repository at this point in the history
* fix: remove zendesk

* fix: edit slack notif logging message

* fix: linting errors

* fix: remove zendesk api config
  • Loading branch information
nyujacky authored Sep 3, 2024
1 parent cdbb02b commit fd6209b
Show file tree
Hide file tree
Showing 5 changed files with 5 additions and 228 deletions.
12 changes: 5 additions & 7 deletions commerce_coordinator/apps/commercetools/sub_messages/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
from commerce_coordinator.apps.commercetools.utils import (
extract_ct_order_information_for_braze_canvas,
extract_ct_product_information_for_braze_canvas,
send_order_confirmation_email,
send_refund_notification
send_order_confirmation_email
)
from commerce_coordinator.apps.core.constants import ISO_8601_FORMAT
from commerce_coordinator.apps.core.memcache import safe_key
Expand Down Expand Up @@ -280,9 +279,8 @@ def _prepare_segment_event_properties(in_order, return_line_item_return_id):

if 'refund_response' in result and result['refund_response']:
if result['refund_response'] == 'charge_already_refunded':
logger.info(f'[CT-{tag}] payment intent {payment_intent_id} already has refund transaction, '
f'sending Zendesk email, message id: {message_id}')
send_refund_notification(customer, order_id)
logger.info(f'[CT-{tag}] payment intent {payment_intent_id} already has refunded transaction, '
f'sending Slack notification, message id: {message_id}')
else:
logger.debug(f'[CT-{tag}] payment intent {payment_intent_id} refunded. message id: {message_id}')
segment_event_properties = _prepare_segment_event_properties(order, return_line_item_return_id)
Expand Down Expand Up @@ -319,8 +317,8 @@ def _prepare_segment_event_properties(in_order, return_line_item_return_id):
properties=segment_event_properties
)
else: # pragma no cover
logger.info(f'[CT-{tag}] payment intent {payment_intent_id} not refunded. message id: {message_id}')
return send_refund_notification(customer, order_id)
logger.info(f'[CT-{tag}] payment intent {payment_intent_id} not refunded, '
f'sending Slack notification, message id: {message_id}')

logger.info(f'[CT-{tag}] Finished return for order: {order_id}, line item: {return_line_item_return_id}, '
f'message id: {message_id}')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,12 @@ def test_correct_arguments_passed_valid_stripe_refund(
mock_values.customer_mock.assert_called_once_with(mock_values.customer_id)
_stripe_api_mock.return_value.refund_payment_intent.assert_called_once()

@patch('commerce_coordinator.apps.commercetools.sub_messages.tasks.send_refund_notification')
@patch('commerce_coordinator.apps.commercetools.sub_messages.tasks.get_edx_payment_intent_id')
@patch('commerce_coordinator.apps.commercetools.sub_messages.tasks.OrderRefundRequested.run_filter')
def test_refund_already_charged(
self,
_return_filter_mock: MagicMock,
_mock_payment_intent: MagicMock,
_mock_zendesk: MagicMock
):
"""
Check calling uut with mock_parameters yields call to client with
Expand All @@ -336,4 +334,3 @@ def test_refund_already_charged(
_mock_payment_intent.return_value = 'mock_payment_intent_id'

self.get_uut()(*self.unpack_for_uut(self.mock.example_payload))
_mock_zendesk.assert_called_once()
124 changes: 0 additions & 124 deletions commerce_coordinator/apps/commercetools/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,27 @@
import unittest
from unittest.mock import MagicMock

import ddt
import pytest
import requests_mock
from braze.client import BrazeClient
from commercetools.platform.models import TransactionState, TransactionType
from django.conf import settings
from django.test import override_settings
from django.urls import reverse
from mock import Mock, patch

from commerce_coordinator.apps.commercetools.catalog_info.edx_utils import get_edx_lms_user_name
from commerce_coordinator.apps.commercetools.tests.conftest import (
gen_example_customer,
gen_order,
gen_payment,
gen_payment_with_multiple_transactions
)
from commerce_coordinator.apps.commercetools.tests.constants import EXAMPLE_FULFILLMENT_SIGNAL_PAYLOAD
from commerce_coordinator.apps.commercetools.utils import (
create_retired_fields,
create_zendesk_ticket,
extract_ct_order_information_for_braze_canvas,
extract_ct_product_information_for_braze_canvas,
get_braze_client,
has_full_refund_transaction,
has_refund_transaction,
send_order_confirmation_email,
send_refund_notification,
translate_stripe_refund_status_to_transaction_status
)

Expand Down Expand Up @@ -250,123 +243,6 @@ def test_translate_stripe_refund_status_other(self):
self.assertEqual(translate_stripe_refund_status_to_transaction_status('unknown_status'), 'unknown_status')


@pytest.mark.django_db
@ddt.ddt
class TestSendRefundNotification(unittest.TestCase):
"""
Tests for creating of and sending Zendesk tickets
"""

def setUp(self):
self.order = gen_order(EXAMPLE_FULFILLMENT_SIGNAL_PAYLOAD['order_number'], with_discount=False)
self.user = gen_example_customer()

@patch("commerce_coordinator.apps.commercetools.utils.create_zendesk_ticket")
def test_commercetools_refund_send_notification_failed(self, mock_create_zendesk_ticket):
mock_create_zendesk_ticket.return_value = False

self.assertFalse(send_refund_notification(self.user, self.order.order_number))

@patch("commerce_coordinator.apps.commercetools.utils.create_zendesk_ticket")
def test_commercetools_refund_send_notification_success(self, mock_create_zendesk_ticket):
mock_create_zendesk_ticket.return_value = True

self.assertTrue(send_refund_notification(self.user, self.order.order_number))

@patch('commerce_coordinator.apps.commercetools.utils.logger.error')
def test_create_zendesk_ticket_failed_not_configured(self, mock_logger):
tags = 'test_tags'
subject = 'test_subject'
body = 'test_body'

create_zendesk_ticket(
get_edx_lms_user_name(self.user),
self.user.email,
subject,
body,
tags
)

mock_logger.assert_called_once_with('Zendesk is not configured. Cannot create a ticket.')

@override_settings(
ZENDESK_URL="https://test_url",
ZENDESK_USER="test_user",
ZENDESK_API_KEY="test_key"
)
@patch('commerce_coordinator.apps.commercetools.utils.logger.debug')
def test_create_zendesk_ticket_success(self, mock_logger):
tags = 'test_tags'
subject = 'test_subject'
body = 'test_body'

with requests_mock.Mocker(real_http=True, case_sensitive=False) as mocker:
mocker.post(
f"{settings.ZENDESK_URL}/api/v2/tickets.json",
status_code=201
)

create_zendesk_ticket(
get_edx_lms_user_name(self.user),
self.user.email,
subject,
body,
tags
)

mock_logger.assert_called_once_with('Successfully created ticket.')

@override_settings(
ZENDESK_URL="https://test_url",
ZENDESK_USER="test_user",
ZENDESK_API_KEY="test_key"
)
@patch('commerce_coordinator.apps.commercetools.utils.logger.error')
def test_create_zendesk_ticket_status_code_fail(self, mock_logger):
tags = 'test_tags'
subject = 'test_subject'
body = 'test_body'

with requests_mock.Mocker(real_http=True, case_sensitive=False) as mocker:
mocker.post(
f"{settings.ZENDESK_URL}/api/v2/tickets.json",
status_code=400
)

create_zendesk_ticket(
get_edx_lms_user_name(self.user),
self.user.email,
subject,
body,
tags
)

mock_logger.assert_called_once_with('Failed to create ticket. Status: [%d], Body: [%s]', 400, b'')

@override_settings(
ZENDESK_URL="https://test_url",
ZENDESK_USER="test_user",
ZENDESK_API_KEY="test_key"
)
@patch("commerce_coordinator.apps.commercetools.utils.create_zendesk_ticket")
@patch('commerce_coordinator.apps.commercetools.utils.logger.exception')
def test_create_zendesk_ticket_failed_response(self, mock_logger, mock_create_zendesk_ticket):
mock_create_zendesk_ticket.side_effect = Exception("Connection error")
tags = 'test_tags'
subject = 'test_subject'
body = 'test_body'

with pytest.raises(Exception) as exc:
create_zendesk_ticket(
get_edx_lms_user_name(self.user),
self.user.email,
subject,
body,
tags
)
mock_logger.assert_called_once_with(f'Failed to create ticket. Exception: {exc.value}')


class TestRetirementAnonymizingTestCase(unittest.TestCase):
"""
Tests for anonymizing/hashing incomming field values
Expand Down
89 changes: 0 additions & 89 deletions commerce_coordinator/apps/commercetools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
"""

import hashlib
import json
import logging
from urllib.parse import urljoin

import requests
from braze.client import BrazeClient
from commercetools import CommercetoolsError
from commercetools.platform.models import Customer, LineItem, Order, Payment, TransactionState, TransactionType
from django.conf import settings
from django.urls import reverse

from commerce_coordinator.apps.commercetools.catalog_info.edx_utils import get_edx_lms_user_name

logger = logging.getLogger(__name__)

RETIRED_USER_FIELD_DEFAULT_FMT = 'retired_user_{}'
Expand Down Expand Up @@ -176,90 +171,6 @@ def translate_stripe_refund_status_to_transaction_status(stripe_refund_status: s
return translations.get(stripe_refund_status.lower(), stripe_refund_status)


def send_refund_notification(user, order_id):
"""
Notify the support team of the refund request.
Returns:
bool: True if we are able to send the notification. In this case that means we were able to create
a ZenDesk ticket
"""

tags = ['auto_refund']

# Build the information for the ZenDesk ticket
student = user
subject = "[Refund] User-Requested Refund"
body = generate_refund_notification_body(student, order_id)
requester_name = get_edx_lms_user_name(student)

return create_zendesk_ticket(requester_name, student.email, subject, body, tags)


def generate_refund_notification_body(student, order_id):
""" Returns a refund notification message body."""

msg = f"""A refund request has been initiated for {get_edx_lms_user_name(student)} ({student.email}).
To process this request, please visit the link(s) below."""

commercetools_mc_orders_url = settings.COMMERCETOOLS_MERCHANT_CENTER_ORDERS_PAGE_URL
refund_urls = urljoin(commercetools_mc_orders_url, f'/{order_id}/')

# emails contained in this message could contain unicode characters so encode as such
return '{msg}\n\n{urls}'.format(msg=msg, urls='\n'.join(refund_urls))


def create_zendesk_ticket(requester_name, requester_email, subject, body, tags=None):
"""
Create a Zendesk ticket via API.
Returns:
bool: False if we are unable to create the ticket for any reason
"""
if not (settings.ZENDESK_URL and settings.ZENDESK_USER and settings.ZENDESK_API_KEY):
logger.error('Zendesk is not configured. Cannot create a ticket.')
return False

# Copy the tags to avoid modifying the original list.
tags = set(tags or [])
tags.add('LMS')
tags = list(tags)

data = {
'ticket': {
'requester': {
'name': requester_name,
'email': str(requester_email)
},
'subject': subject,
'comment': {'body': body},
'tags': tags
}
}

# Encode the data to create a JSON payload
payload = json.dumps(data)

# Set the request parameters
url = urljoin(settings.ZENDESK_URL, '/api/v2/tickets.json')
user = f'{settings.ZENDESK_USER}/token'
pwd = settings.ZENDESK_API_KEY
headers = {'content-type': 'application/json'}

try:
response = requests.post(url, data=payload, auth=(user, pwd), headers=headers, timeout=1)
# Check for HTTP codes other than 201 (Created)
if response.status_code != 201:
logger.error('Failed to create ticket. Status: [%d], Body: [%s]', response.status_code, response.content)
return False
else:
logger.debug('Successfully created ticket.')
except Exception as exc: # pylint: disable=broad-except
logger.exception(f'Failed to create ticket. Exception: {exc}')
return False
return True


def _create_retired_hash_withsalt(value_to_retire, salt):
"""
Returns a retired value given a value to retire and a hash.
Expand Down
5 changes: 0 additions & 5 deletions commerce_coordinator/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,4 @@ def root(*path_fragments):
# SEGMENT WRITE KEY
SEGMENT_KEY = None

# ZENDESK API SETTINGS
ZENDESK_URL = None
ZENDESK_USER = None
ZENDESK_API_KEY = None

FAVICON_URL = "https://edx-cdn.org/v3/prod/favicon.ico"

0 comments on commit fd6209b

Please sign in to comment.