We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Чини шаблон письма
http://prntscr.com/lvr5u4 куда-то делся телефон магазина  8 (812) 416-32-00

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `shopelectro/views/service.py`
Content:
```
1 import logging
2 from hashlib import md5
3 
4 from django.conf import settings
5 from django.shortcuts import render
6 from django.views.decorators.csrf import csrf_exempt
7 from django.views.decorators.http import require_POST
8 
9 from ecommerce import mailer
10 from ecommerce.views import get_keys_from_post
11 
12 from shopelectro.models import Order
13 
14 logger = logging.getLogger(__name__)
15 
16 
17 YANDEX_REQUEST_PARAM = (
18     'action', 'orderSumAmount', 'orderSumCurrencyPaycash', 'orderSumBankPaycash',
19     'shopId', 'invoiceId', 'customerNumber'
20 )
21 
22 
23 def generate_md5_for_ya_kassa(post_body):
24     """Generate md5 based on this param."""
25     params = [post_body[param] for param in YANDEX_REQUEST_PARAM]
26     params.append(settings.YANDEX_SHOP_PASS)
27     param_sequence = str(';'.join(params)).encode('utf-8')
28     return md5(param_sequence).hexdigest().upper()
29 
30 
31 def has_correct_md5(post_body):
32     """Compare our md5 with md5 from yandex request."""
33     md5 = generate_md5_for_ya_kassa(post_body)
34     return md5 == post_body['md5']
35 
36 
37 @csrf_exempt
38 def yandex_check(request):
39     """
40     Handle Yandex check.
41 
42     We simply accept every check.
43     It's marked with @csrf_exempt, because we don't need
44     to check CSRF in yandex-requests.
45     """
46     return render(request, 'ecommerce/yandex_check.xml', {'invoice': request.POST['invoiceId']},
47                   content_type='application/xhtml+xml')
48 
49 
50 @csrf_exempt
51 def yandex_aviso(request):
52     """
53     Handle Yandex Aviso check.
54 
55     It's marked with @csrf_exempt, because we don't need to
56     check CSRF in yandex-requests.
57 
58     1. Retrieve order number from request, find in in DB.
59     2. If it's a first aviso check (there might be more than one,
60        depends on Yandex)
61        send different emails to client and shop.
62     3. Get invoice id from request and return XML to Yandex.
63     """
64     def is_first_aviso(order_):
65         return order_ and not order_.paid
66 
67     def send_mail_to_shop(order):
68         paid, profit = get_keys_from_post(request, 'orderSumAmount', 'shopSumAmount')
69         proportion = 100 * float(profit) / float(paid)
70         commission = round(100 - proportion, 2)  # in percents
71         mailer.send_order(
72             template='ecommerce/yandex_order_email.html',
73             subject=settings.EMAIL_SUBJECTS['yandex_order'],
74             order=order,
75             to_customer=False,
76             extra_context={
77                 'paid': paid,
78                 'profit': profit,
79                 'commission': commission,
80             })
81 
82     def send_mail_to_customer(order):
83         mailer.send_order(
84             subject=settings.EMAIL_SUBJECTS['yandex_order'],
85             order=order,
86             to_shop=False,
87         )
88 
89     if not has_correct_md5(request.POST):
90         return render(
91             request, 'ecommerce/yandex_aviso.xml',
92             content_type='application/xhtml+xml'
93         )
94 
95     logger.info(f'received yandex aviso. Aviso data: {request.POST}')
96 
97     # maybe we can include django-annoying for such cases
98     # https://github.com/skorokithakis/django-annoying#get_object_or_none-function
99     try:
100         order = Order.objects.get(pk=request.POST['customerNumber'])
101     except Order.DoesNotExist:
102         order = None
103 
104     if is_first_aviso(order):
105         order.paid = True
106         send_mail_to_customer(order)
107         send_mail_to_shop(order)
108         order.save()
109 
110     invoice_id = request.POST['invoiceId']
111     return render(request, 'ecommerce/yandex_aviso.xml', {'invoice': invoice_id},
112                   content_type='application/xhtml+xml')
113 
114 
115 @require_POST
116 @csrf_exempt
117 def ya_feedback_request(request):
118     """Send email to user with Y.Market feedback request."""
119     user_email = request.POST['email']
120     mailer.ya_feedback(user_email)
121 
122     return render(request, 'ecommerce/yandex_feedback_success.html',
123                   {'email': user_email})
124 
125 
126 def ya_feedback_with_redirect(request):
127     """Redirect user to Y.Market for feedback."""
128     return render(request, 'ecommerce/yandex_feedback_redirect.html')
129
```

Path: `shopelectro/views/ecommerce.py`
Content:
```
1 import json
2 
3 from django.conf import settings
4 from django.core import serializers
5 from django.http import HttpResponse, JsonResponse
6 from django.shortcuts import get_object_or_404, render
7 from django.views.decorators.http import require_POST
8 
9 from ecommerce import mailer, views as ec_views
10 from pages.models import CustomPage
11 
12 from shopelectro.cart import SECart
13 from shopelectro.forms import OrderForm
14 from shopelectro.models import Product, Order
15 
16 
17 # ECOMMERCE VIEWS
18 class OrderPage(ec_views.OrderPage):
19     order_form = OrderForm
20     cart = SECart
21 
22     def get_context_data(self, request, **kwargs):
23         data = super().get_context_data(request, **kwargs)
24         return {
25             **data,
26             'page': CustomPage.objects.get(slug='order'),
27             'raw_order_fields': json.dumps({
28                 field.html_name: f'#{field.id_for_label}' for field in data['form']
29             }),
30         }
31 
32 
33 class AddToCart(ec_views.AddToCart):
34     cart = SECart
35     product_model = Product
36     order_form = OrderForm
37 
38 
39 class RemoveFromCart(ec_views.RemoveFromCart):
40     cart = SECart
41     product_model = Product
42     order_form = OrderForm
43 
44 
45 class ChangeCount(ec_views.ChangeCount):
46     cart = SECart
47     product_model = Product
48     order_form = OrderForm
49 
50 
51 class FlushCart(ec_views.FlushCart):
52     product_model = Product
53     order_form = OrderForm
54 
55 
56 class OrderSuccess(ec_views.OrderSuccess):
57 
58     order = Order.objects.all().prefetch_related('positions')
59 
60     def get_context_data(self, **kwargs):
61         context = super().get_context_data(**kwargs)
62         order = context['order']
63         positions_json = serializers.serialize(
64             'json', order.positions.all(), fields=['name', 'quantity', 'price'],
65         )
66 
67         return {
68             **context,
69             'positions_json': positions_json,
70             'total_revenue': order.revenue,
71         }
72 
73 
74 @require_POST
75 def one_click_buy(request):
76     """
77     Handle one-click-buy.
78 
79     Accept XHR, save Order to DB, send mail about it
80     and return 200 OK.
81     """
82     SECart(request.session).clear()
83 
84     cart = SECart(request.session)
85     product = get_object_or_404(Product, id=request.POST['product'])
86     cart.add(product, int(request.POST['quantity']))
87     order = Order(phone=request.POST['phone'])
88     order.set_positions(cart)
89     ec_views.save_order_to_session(request.session, order)
90     mailer.send_order(
91         subject=settings.EMAIL_SUBJECTS['one_click'],
92         order=order,
93         to_customer=False,
94     )
95     return HttpResponse('ok')
96 
97 
98 @require_POST
99 def order_call(request):
100     """Send email about ordered call."""
101     phone, time, url = ec_views.get_keys_from_post(
102         request, 'phone', 'time', 'url')
103 
104     mailer.send_backcall(
105         subject=settings.EMAIL_SUBJECTS['call'],
106         phone=phone,
107         time=time,
108         url=url,
109     )
110 
111     return HttpResponse('ok')
112 
113 
114 class YandexOrder(OrderPage):
115 
116     def post(self, request):
117         cart = self.cart(request.session)
118         form = self.order_form(request.POST)
119         if not form.is_valid():
120             return render(request, self.template, {'cart': cart, 'form': form})
121 
122         order = form.save()
123         order.set_positions(cart)
124         ec_views.save_order_to_session(request.session, order)
125 
126         # Took form fields from Yandex docs https://goo.gl/afKfsz
127         response_data = {
128             'yandex_kassa_link': settings.YANDEX_KASSA_LINK,  # Required
129             'shopId': settings.SHOP['id'],  # Required
130             'scid': settings.SHOP['scid'],  # Required
131             'shopSuccessURL': settings.SHOP['success_url'],
132             'shopFailURL': settings.SHOP['fail_url'],
133             'customerNumber': order.id,  # Required
134             'sum': order.total_price,  # Required
135             'orderNumber': order.fake_order_number,
136             'cps_phone': order.phone,
137             'cps_email': order.email,
138             'paymentType': request.POST.get('payment_type'),
139         }
140 
141         return JsonResponse(response_data)
142
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/shopelectro/views/ecommerce.py b/shopelectro/views/ecommerce.py
--- a/shopelectro/views/ecommerce.py
+++ b/shopelectro/views/ecommerce.py
@@ -18,6 +18,10 @@
 class OrderPage(ec_views.OrderPage):
     order_form = OrderForm
     cart = SECart
+    # Django does not provide context_processors for render_to_string function,
+    # which is used to render an order mail. So we have to explicitly pass
+    # a context to it.
+    email_extra_context = {'shop': settings.SHOP}
 
     def get_context_data(self, request, **kwargs):
         data = super().get_context_data(request, **kwargs)
@@ -79,9 +83,9 @@
     Accept XHR, save Order to DB, send mail about it
     and return 200 OK.
     """
-    SECart(request.session).clear()
-
     cart = SECart(request.session)
+    cart.clear()
+
     product = get_object_or_404(Product, id=request.POST['product'])
     cart.add(product, int(request.POST['quantity']))
     order = Order(phone=request.POST['phone'])
@@ -91,6 +95,8 @@
         subject=settings.EMAIL_SUBJECTS['one_click'],
         order=order,
         to_customer=False,
+        # see se.OrderPage class for a detail about `shop` context.
+        extra_context={'shop': settings.SHOP},
     )
     return HttpResponse('ok')
 
diff --git a/shopelectro/views/service.py b/shopelectro/views/service.py
--- a/shopelectro/views/service.py
+++ b/shopelectro/views/service.py
@@ -77,6 +77,8 @@
                 'paid': paid,
                 'profit': profit,
                 'commission': commission,
+                # see se.OrderPage class for a detail about `shop` context.
+                'shop': settings.SHOP,
             })
 
     def send_mail_to_customer(order):
@@ -84,6 +86,8 @@
             subject=settings.EMAIL_SUBJECTS['yandex_order'],
             order=order,
             to_shop=False,
+            # see se.OrderPage class for a detail about `shop` context.
+            extra_context={'shop': settings.SHOP},
         )
 
     if not has_correct_md5(request.POST):

{"golden_diff": "diff --git a/shopelectro/views/ecommerce.py b/shopelectro/views/ecommerce.py\n--- a/shopelectro/views/ecommerce.py\n+++ b/shopelectro/views/ecommerce.py\n@@ -18,6 +18,10 @@\n class OrderPage(ec_views.OrderPage):\n     order_form = OrderForm\n     cart = SECart\n+    # Django does not provide context_processors for render_to_string function,\n+    # which is used to render an order mail. So we have to explicitly pass\n+    # a context to it.\n+    email_extra_context = {'shop': settings.SHOP}\n \n     def get_context_data(self, request, **kwargs):\n         data = super().get_context_data(request, **kwargs)\n@@ -79,9 +83,9 @@\n     Accept XHR, save Order to DB, send mail about it\n     and return 200 OK.\n     \"\"\"\n-    SECart(request.session).clear()\n-\n     cart = SECart(request.session)\n+    cart.clear()\n+\n     product = get_object_or_404(Product, id=request.POST['product'])\n     cart.add(product, int(request.POST['quantity']))\n     order = Order(phone=request.POST['phone'])\n@@ -91,6 +95,8 @@\n         subject=settings.EMAIL_SUBJECTS['one_click'],\n         order=order,\n         to_customer=False,\n+        # see se.OrderPage class for a detail about `shop` context.\n+        extra_context={'shop': settings.SHOP},\n     )\n     return HttpResponse('ok')\n \ndiff --git a/shopelectro/views/service.py b/shopelectro/views/service.py\n--- a/shopelectro/views/service.py\n+++ b/shopelectro/views/service.py\n@@ -77,6 +77,8 @@\n                 'paid': paid,\n                 'profit': profit,\n                 'commission': commission,\n+                # see se.OrderPage class for a detail about `shop` context.\n+                'shop': settings.SHOP,\n             })\n \n     def send_mail_to_customer(order):\n@@ -84,6 +86,8 @@\n             subject=settings.EMAIL_SUBJECTS['yandex_order'],\n             order=order,\n             to_shop=False,\n+            # see se.OrderPage class for a detail about `shop` context.\n+            extra_context={'shop': settings.SHOP},\n         )\n \n     if not has_correct_md5(request.POST):\n", "issue": "\u0427\u0438\u043d\u0438 \u0448\u0430\u0431\u043b\u043e\u043d \u043f\u0438\u0441\u044c\u043c\u0430\nhttp://prntscr.com/lvr5u4 \u043a\u0443\u0434\u0430-\u0442\u043e \u0434\u0435\u043b\u0441\u044f \u0442\u0435\u043b\u0435\u0444\u043e\u043d \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u0430  8 (812) 416-32-00\n", "before_files": [{"content": "import logging\nfrom hashlib import md5\n\nfrom django.conf import settings\nfrom django.shortcuts import render\nfrom django.views.decorators.csrf import csrf_exempt\nfrom django.views.decorators.http import require_POST\n\nfrom ecommerce import mailer\nfrom ecommerce.views import get_keys_from_post\n\nfrom shopelectro.models import Order\n\nlogger = logging.getLogger(__name__)\n\n\nYANDEX_REQUEST_PARAM = (\n    'action', 'orderSumAmount', 'orderSumCurrencyPaycash', 'orderSumBankPaycash',\n    'shopId', 'invoiceId', 'customerNumber'\n)\n\n\ndef generate_md5_for_ya_kassa(post_body):\n    \"\"\"Generate md5 based on this param.\"\"\"\n    params = [post_body[param] for param in YANDEX_REQUEST_PARAM]\n    params.append(settings.YANDEX_SHOP_PASS)\n    param_sequence = str(';'.join(params)).encode('utf-8')\n    return md5(param_sequence).hexdigest().upper()\n\n\ndef has_correct_md5(post_body):\n    \"\"\"Compare our md5 with md5 from yandex request.\"\"\"\n    md5 = generate_md5_for_ya_kassa(post_body)\n    return md5 == post_body['md5']\n\n\n@csrf_exempt\ndef yandex_check(request):\n    \"\"\"\n    Handle Yandex check.\n\n    We simply accept every check.\n    It's marked with @csrf_exempt, because we don't need\n    to check CSRF in yandex-requests.\n    \"\"\"\n    return render(request, 'ecommerce/yandex_check.xml', {'invoice': request.POST['invoiceId']},\n                  content_type='application/xhtml+xml')\n\n\n@csrf_exempt\ndef yandex_aviso(request):\n    \"\"\"\n    Handle Yandex Aviso check.\n\n    It's marked with @csrf_exempt, because we don't need to\n    check CSRF in yandex-requests.\n\n    1. Retrieve order number from request, find in in DB.\n    2. If it's a first aviso check (there might be more than one,\n       depends on Yandex)\n       send different emails to client and shop.\n    3. Get invoice id from request and return XML to Yandex.\n    \"\"\"\n    def is_first_aviso(order_):\n        return order_ and not order_.paid\n\n    def send_mail_to_shop(order):\n        paid, profit = get_keys_from_post(request, 'orderSumAmount', 'shopSumAmount')\n        proportion = 100 * float(profit) / float(paid)\n        commission = round(100 - proportion, 2)  # in percents\n        mailer.send_order(\n            template='ecommerce/yandex_order_email.html',\n            subject=settings.EMAIL_SUBJECTS['yandex_order'],\n            order=order,\n            to_customer=False,\n            extra_context={\n                'paid': paid,\n                'profit': profit,\n                'commission': commission,\n            })\n\n    def send_mail_to_customer(order):\n        mailer.send_order(\n            subject=settings.EMAIL_SUBJECTS['yandex_order'],\n            order=order,\n            to_shop=False,\n        )\n\n    if not has_correct_md5(request.POST):\n        return render(\n            request, 'ecommerce/yandex_aviso.xml',\n            content_type='application/xhtml+xml'\n        )\n\n    logger.info(f'received yandex aviso. Aviso data: {request.POST}')\n\n    # maybe we can include django-annoying for such cases\n    # https://github.com/skorokithakis/django-annoying#get_object_or_none-function\n    try:\n        order = Order.objects.get(pk=request.POST['customerNumber'])\n    except Order.DoesNotExist:\n        order = None\n\n    if is_first_aviso(order):\n        order.paid = True\n        send_mail_to_customer(order)\n        send_mail_to_shop(order)\n        order.save()\n\n    invoice_id = request.POST['invoiceId']\n    return render(request, 'ecommerce/yandex_aviso.xml', {'invoice': invoice_id},\n                  content_type='application/xhtml+xml')\n\n\n@require_POST\n@csrf_exempt\ndef ya_feedback_request(request):\n    \"\"\"Send email to user with Y.Market feedback request.\"\"\"\n    user_email = request.POST['email']\n    mailer.ya_feedback(user_email)\n\n    return render(request, 'ecommerce/yandex_feedback_success.html',\n                  {'email': user_email})\n\n\ndef ya_feedback_with_redirect(request):\n    \"\"\"Redirect user to Y.Market for feedback.\"\"\"\n    return render(request, 'ecommerce/yandex_feedback_redirect.html')\n", "path": "shopelectro/views/service.py"}, {"content": "import json\n\nfrom django.conf import settings\nfrom django.core import serializers\nfrom django.http import HttpResponse, JsonResponse\nfrom django.shortcuts import get_object_or_404, render\nfrom django.views.decorators.http import require_POST\n\nfrom ecommerce import mailer, views as ec_views\nfrom pages.models import CustomPage\n\nfrom shopelectro.cart import SECart\nfrom shopelectro.forms import OrderForm\nfrom shopelectro.models import Product, Order\n\n\n# ECOMMERCE VIEWS\nclass OrderPage(ec_views.OrderPage):\n    order_form = OrderForm\n    cart = SECart\n\n    def get_context_data(self, request, **kwargs):\n        data = super().get_context_data(request, **kwargs)\n        return {\n            **data,\n            'page': CustomPage.objects.get(slug='order'),\n            'raw_order_fields': json.dumps({\n                field.html_name: f'#{field.id_for_label}' for field in data['form']\n            }),\n        }\n\n\nclass AddToCart(ec_views.AddToCart):\n    cart = SECart\n    product_model = Product\n    order_form = OrderForm\n\n\nclass RemoveFromCart(ec_views.RemoveFromCart):\n    cart = SECart\n    product_model = Product\n    order_form = OrderForm\n\n\nclass ChangeCount(ec_views.ChangeCount):\n    cart = SECart\n    product_model = Product\n    order_form = OrderForm\n\n\nclass FlushCart(ec_views.FlushCart):\n    product_model = Product\n    order_form = OrderForm\n\n\nclass OrderSuccess(ec_views.OrderSuccess):\n\n    order = Order.objects.all().prefetch_related('positions')\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        order = context['order']\n        positions_json = serializers.serialize(\n            'json', order.positions.all(), fields=['name', 'quantity', 'price'],\n        )\n\n        return {\n            **context,\n            'positions_json': positions_json,\n            'total_revenue': order.revenue,\n        }\n\n\n@require_POST\ndef one_click_buy(request):\n    \"\"\"\n    Handle one-click-buy.\n\n    Accept XHR, save Order to DB, send mail about it\n    and return 200 OK.\n    \"\"\"\n    SECart(request.session).clear()\n\n    cart = SECart(request.session)\n    product = get_object_or_404(Product, id=request.POST['product'])\n    cart.add(product, int(request.POST['quantity']))\n    order = Order(phone=request.POST['phone'])\n    order.set_positions(cart)\n    ec_views.save_order_to_session(request.session, order)\n    mailer.send_order(\n        subject=settings.EMAIL_SUBJECTS['one_click'],\n        order=order,\n        to_customer=False,\n    )\n    return HttpResponse('ok')\n\n\n@require_POST\ndef order_call(request):\n    \"\"\"Send email about ordered call.\"\"\"\n    phone, time, url = ec_views.get_keys_from_post(\n        request, 'phone', 'time', 'url')\n\n    mailer.send_backcall(\n        subject=settings.EMAIL_SUBJECTS['call'],\n        phone=phone,\n        time=time,\n        url=url,\n    )\n\n    return HttpResponse('ok')\n\n\nclass YandexOrder(OrderPage):\n\n    def post(self, request):\n        cart = self.cart(request.session)\n        form = self.order_form(request.POST)\n        if not form.is_valid():\n            return render(request, self.template, {'cart': cart, 'form': form})\n\n        order = form.save()\n        order.set_positions(cart)\n        ec_views.save_order_to_session(request.session, order)\n\n        # Took form fields from Yandex docs https://goo.gl/afKfsz\n        response_data = {\n            'yandex_kassa_link': settings.YANDEX_KASSA_LINK,  # Required\n            'shopId': settings.SHOP['id'],  # Required\n            'scid': settings.SHOP['scid'],  # Required\n            'shopSuccessURL': settings.SHOP['success_url'],\n            'shopFailURL': settings.SHOP['fail_url'],\n            'customerNumber': order.id,  # Required\n            'sum': order.total_price,  # Required\n            'orderNumber': order.fake_order_number,\n            'cps_phone': order.phone,\n            'cps_email': order.email,\n            'paymentType': request.POST.get('payment_type'),\n        }\n\n        return JsonResponse(response_data)\n", "path": "shopelectro/views/ecommerce.py"}], "after_files": [{"content": "import logging\nfrom hashlib import md5\n\nfrom django.conf import settings\nfrom django.shortcuts import render\nfrom django.views.decorators.csrf import csrf_exempt\nfrom django.views.decorators.http import require_POST\n\nfrom ecommerce import mailer\nfrom ecommerce.views import get_keys_from_post\n\nfrom shopelectro.models import Order\n\nlogger = logging.getLogger(__name__)\n\n\nYANDEX_REQUEST_PARAM = (\n    'action', 'orderSumAmount', 'orderSumCurrencyPaycash', 'orderSumBankPaycash',\n    'shopId', 'invoiceId', 'customerNumber'\n)\n\n\ndef generate_md5_for_ya_kassa(post_body):\n    \"\"\"Generate md5 based on this param.\"\"\"\n    params = [post_body[param] for param in YANDEX_REQUEST_PARAM]\n    params.append(settings.YANDEX_SHOP_PASS)\n    param_sequence = str(';'.join(params)).encode('utf-8')\n    return md5(param_sequence).hexdigest().upper()\n\n\ndef has_correct_md5(post_body):\n    \"\"\"Compare our md5 with md5 from yandex request.\"\"\"\n    md5 = generate_md5_for_ya_kassa(post_body)\n    return md5 == post_body['md5']\n\n\n@csrf_exempt\ndef yandex_check(request):\n    \"\"\"\n    Handle Yandex check.\n\n    We simply accept every check.\n    It's marked with @csrf_exempt, because we don't need\n    to check CSRF in yandex-requests.\n    \"\"\"\n    return render(request, 'ecommerce/yandex_check.xml', {'invoice': request.POST['invoiceId']},\n                  content_type='application/xhtml+xml')\n\n\n@csrf_exempt\ndef yandex_aviso(request):\n    \"\"\"\n    Handle Yandex Aviso check.\n\n    It's marked with @csrf_exempt, because we don't need to\n    check CSRF in yandex-requests.\n\n    1. Retrieve order number from request, find in in DB.\n    2. If it's a first aviso check (there might be more than one,\n       depends on Yandex)\n       send different emails to client and shop.\n    3. Get invoice id from request and return XML to Yandex.\n    \"\"\"\n    def is_first_aviso(order_):\n        return order_ and not order_.paid\n\n    def send_mail_to_shop(order):\n        paid, profit = get_keys_from_post(request, 'orderSumAmount', 'shopSumAmount')\n        proportion = 100 * float(profit) / float(paid)\n        commission = round(100 - proportion, 2)  # in percents\n        mailer.send_order(\n            template='ecommerce/yandex_order_email.html',\n            subject=settings.EMAIL_SUBJECTS['yandex_order'],\n            order=order,\n            to_customer=False,\n            extra_context={\n                'paid': paid,\n                'profit': profit,\n                'commission': commission,\n                # see se.OrderPage class for a detail about `shop` context.\n                'shop': settings.SHOP,\n            })\n\n    def send_mail_to_customer(order):\n        mailer.send_order(\n            subject=settings.EMAIL_SUBJECTS['yandex_order'],\n            order=order,\n            to_shop=False,\n            # see se.OrderPage class for a detail about `shop` context.\n            extra_context={'shop': settings.SHOP},\n        )\n\n    if not has_correct_md5(request.POST):\n        return render(\n            request, 'ecommerce/yandex_aviso.xml',\n            content_type='application/xhtml+xml'\n        )\n\n    logger.info(f'received yandex aviso. Aviso data: {request.POST}')\n\n    # maybe we can include django-annoying for such cases\n    # https://github.com/skorokithakis/django-annoying#get_object_or_none-function\n    try:\n        order = Order.objects.get(pk=request.POST['customerNumber'])\n    except Order.DoesNotExist:\n        order = None\n\n    if is_first_aviso(order):\n        order.paid = True\n        send_mail_to_customer(order)\n        send_mail_to_shop(order)\n        order.save()\n\n    invoice_id = request.POST['invoiceId']\n    return render(request, 'ecommerce/yandex_aviso.xml', {'invoice': invoice_id},\n                  content_type='application/xhtml+xml')\n\n\n@require_POST\n@csrf_exempt\ndef ya_feedback_request(request):\n    \"\"\"Send email to user with Y.Market feedback request.\"\"\"\n    user_email = request.POST['email']\n    mailer.ya_feedback(user_email)\n\n    return render(request, 'ecommerce/yandex_feedback_success.html',\n                  {'email': user_email})\n\n\ndef ya_feedback_with_redirect(request):\n    \"\"\"Redirect user to Y.Market for feedback.\"\"\"\n    return render(request, 'ecommerce/yandex_feedback_redirect.html')\n", "path": "shopelectro/views/service.py"}, {"content": "import json\n\nfrom django.conf import settings\nfrom django.core import serializers\nfrom django.http import HttpResponse, JsonResponse\nfrom django.shortcuts import get_object_or_404, render\nfrom django.views.decorators.http import require_POST\n\nfrom ecommerce import mailer, views as ec_views\nfrom pages.models import CustomPage\n\nfrom shopelectro.cart import SECart\nfrom shopelectro.forms import OrderForm\nfrom shopelectro.models import Product, Order\n\n\n# ECOMMERCE VIEWS\nclass OrderPage(ec_views.OrderPage):\n    order_form = OrderForm\n    cart = SECart\n    # Django does not provide context_processors for render_to_string function,\n    # which is used to render an order mail. So we have to explicitly pass\n    # a context to it.\n    email_extra_context = {'shop': settings.SHOP}\n\n    def get_context_data(self, request, **kwargs):\n        data = super().get_context_data(request, **kwargs)\n        return {\n            **data,\n            'page': CustomPage.objects.get(slug='order'),\n            'raw_order_fields': json.dumps({\n                field.html_name: f'#{field.id_for_label}' for field in data['form']\n            }),\n        }\n\n\nclass AddToCart(ec_views.AddToCart):\n    cart = SECart\n    product_model = Product\n    order_form = OrderForm\n\n\nclass RemoveFromCart(ec_views.RemoveFromCart):\n    cart = SECart\n    product_model = Product\n    order_form = OrderForm\n\n\nclass ChangeCount(ec_views.ChangeCount):\n    cart = SECart\n    product_model = Product\n    order_form = OrderForm\n\n\nclass FlushCart(ec_views.FlushCart):\n    product_model = Product\n    order_form = OrderForm\n\n\nclass OrderSuccess(ec_views.OrderSuccess):\n\n    order = Order.objects.all().prefetch_related('positions')\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        order = context['order']\n        positions_json = serializers.serialize(\n            'json', order.positions.all(), fields=['name', 'quantity', 'price'],\n        )\n\n        return {\n            **context,\n            'positions_json': positions_json,\n            'total_revenue': order.revenue,\n        }\n\n\n@require_POST\ndef one_click_buy(request):\n    \"\"\"\n    Handle one-click-buy.\n\n    Accept XHR, save Order to DB, send mail about it\n    and return 200 OK.\n    \"\"\"\n    cart = SECart(request.session)\n    cart.clear()\n\n    product = get_object_or_404(Product, id=request.POST['product'])\n    cart.add(product, int(request.POST['quantity']))\n    order = Order(phone=request.POST['phone'])\n    order.set_positions(cart)\n    ec_views.save_order_to_session(request.session, order)\n    mailer.send_order(\n        subject=settings.EMAIL_SUBJECTS['one_click'],\n        order=order,\n        to_customer=False,\n        # see se.OrderPage class for a detail about `shop` context.\n        extra_context={'shop': settings.SHOP},\n    )\n    return HttpResponse('ok')\n\n\n@require_POST\ndef order_call(request):\n    \"\"\"Send email about ordered call.\"\"\"\n    phone, time, url = ec_views.get_keys_from_post(\n        request, 'phone', 'time', 'url')\n\n    mailer.send_backcall(\n        subject=settings.EMAIL_SUBJECTS['call'],\n        phone=phone,\n        time=time,\n        url=url,\n    )\n\n    return HttpResponse('ok')\n\n\nclass YandexOrder(OrderPage):\n\n    def post(self, request):\n        cart = self.cart(request.session)\n        form = self.order_form(request.POST)\n        if not form.is_valid():\n            return render(request, self.template, {'cart': cart, 'form': form})\n\n        order = form.save()\n        order.set_positions(cart)\n        ec_views.save_order_to_session(request.session, order)\n\n        # Took form fields from Yandex docs https://goo.gl/afKfsz\n        response_data = {\n            'yandex_kassa_link': settings.YANDEX_KASSA_LINK,  # Required\n            'shopId': settings.SHOP['id'],  # Required\n            'scid': settings.SHOP['scid'],  # Required\n            'shopSuccessURL': settings.SHOP['success_url'],\n            'shopFailURL': settings.SHOP['fail_url'],\n            'customerNumber': order.id,  # Required\n            'sum': order.total_price,  # Required\n            'orderNumber': order.fake_order_number,\n            'cps_phone': order.phone,\n            'cps_email': order.email,\n            'paymentType': request.POST.get('payment_type'),\n        }\n\n        return JsonResponse(response_data)\n", "path": "shopelectro/views/ecommerce.py"}]}