prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Add checkout steps navigation
  Now there's no explicit navigation. Using browser back button can be dangerous in some cases and it's not a common behavior in ecommerce
  
  </issue>
  <code>
  [start of saleor/order/views.py]
  1 import logging
  2 
  3 from django.conf import settings
  4 from django.contrib import messages, auth
  5 from django.db import transaction
  6 from django.http import Http404, HttpResponseForbidden
  7 from django.shortcuts import get_object_or_404, redirect
  8 from django.utils.translation import ugettext as _
  9 from django.template.response import TemplateResponse
  10 from payments import RedirectNeeded
  11 
  12 from .forms import PaymentDeleteForm, PaymentMethodsForm, PasswordForm
  13 from .models import Order, Payment
  14 from ..core.utils import get_client_ip
  15 from .utils import check_order_status
  16 
  17 logger = logging.getLogger(__name__)
  18 
  19 
  20 def details(request, token):
  21     orders = Order.objects.prefetch_related('groups__items')
  22     order = get_object_or_404(orders, token=token)
  23     groups = order.groups.all()
  24     return TemplateResponse(request, 'order/details.html',
  25                             {'order': order, 'groups': groups})
  26 
  27 
  28 def payment(request, token):
  29     orders = Order.objects.prefetch_related('groups__items')
  30     order = get_object_or_404(orders, token=token)
  31     groups = order.groups.all()
  32     payments = order.payments.all()
  33     form_data = request.POST or None
  34     try:
  35         waiting_payment = order.payments.get(status='waiting')
  36     except Payment.DoesNotExist:
  37         waiting_payment = None
  38         waiting_payment_form = None
  39     else:
  40         form_data = None
  41         waiting_payment_form = PaymentDeleteForm(
  42             None, order=order, initial={'payment_id': waiting_payment.id})
  43     if order.is_fully_paid():
  44         form_data = None
  45     payment_form = None
  46     if not order.is_pre_authorized():
  47         payment_form = PaymentMethodsForm(form_data)
  48         # FIXME: redirect if there is only one payment method
  49         if payment_form.is_valid():
  50             payment_method = payment_form.cleaned_data['method']
  51             return redirect('order:payment', token=order.token,
  52                             variant=payment_method)
  53     return TemplateResponse(request, 'order/payment.html',
  54                             {'order': order, 'groups': groups,
  55                              'payment_form': payment_form,
  56                              'waiting_payment': waiting_payment,
  57                              'waiting_payment_form': waiting_payment_form,
  58                              'payments': payments})
  59 
  60 
  61 @check_order_status
  62 def start_payment(request, order, variant):
  63     waiting_payments = order.payments.filter(status='waiting').exists()
  64     if waiting_payments:
  65         return redirect('order:payment', token=order.token)
  66     billing = order.billing_address
  67     total = order.get_total()
  68     defaults = {'total': total.gross,
  69                 'tax': total.tax, 'currency': total.currency,
  70                 'delivery': order.get_delivery_total().gross,
  71                 'billing_first_name': billing.first_name,
  72                 'billing_last_name': billing.last_name,
  73                 'billing_address_1': billing.street_address_1,
  74                 'billing_address_2': billing.street_address_2,
  75                 'billing_city': billing.city,
  76                 'billing_postcode': billing.postal_code,
  77                 'billing_country_code': billing.country,
  78                 'billing_email': order.user_email,
  79                 'description': _('Order %(order_number)s') % {
  80                     'order_number': order},
  81                 'billing_country_area': billing.country_area,
  82                 'customer_ip_address': get_client_ip(request)}
  83     variant_choices = settings.CHECKOUT_PAYMENT_CHOICES
  84     if variant not in [code for code, dummy_name in variant_choices]:
  85         raise Http404('%r is not a valid payment variant' % (variant,))
  86     with transaction.atomic():
  87         order.change_status('payment-pending')
  88         payment, dummy_created = Payment.objects.get_or_create(
  89             variant=variant, status='waiting', order=order, defaults=defaults)
  90         try:
  91             form = payment.get_form(data=request.POST or None)
  92         except RedirectNeeded as redirect_to:
  93             return redirect(str(redirect_to))
  94         except Exception:
  95             logger.exception('Error communicating with the payment gateway')
  96             messages.error(
  97                 request,
  98                 _('Oops, it looks like we were unable to contact the selected'
  99                   ' payment service'))
  100             payment.change_status('error')
  101             return redirect('order:payment', token=order.token)
  102     template = 'order/payment/%s.html' % variant
  103     return TemplateResponse(request, [template, 'order/payment/default.html'],
  104                             {'form': form, 'payment': payment})
  105 
  106 
  107 @check_order_status
  108 def cancel_payment(request, order):
  109     form = PaymentDeleteForm(request.POST or None, order=order)
  110     if form.is_valid():
  111         with transaction.atomic():
  112             form.save()
  113         return redirect('order:payment', token=order.token)
  114     return HttpResponseForbidden()
  115 
  116 
  117 def create_password(request, token):
  118     if request.user.is_authenticated():
  119         return redirect('order:details', token=token)
  120     order = get_object_or_404(Order, token=token)
  121     email = order.user_email
  122     form_data = request.POST.copy()
  123     if form_data:
  124         form_data.update({'email': email})
  125     form = PasswordForm(form_data or None)
  126 
  127     if form.is_valid():
  128         user = form.save(request)
  129         order.user = user
  130         order.save(update_fields=['user'])
  131         password = form_data.get('password1')
  132         auth_user = auth.authenticate(email=email, password=password)
  133         if auth_user is not None:
  134             auth.login(request, auth_user)
  135         return redirect('order:details', token=token)
  136     ctx = {'form': form, 'email': email}
  137     return TemplateResponse(request, 'order/create_password.html', ctx)
  138
  [end of saleor/order/views.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/saleor/order/views.py b/saleor/order/views.py
  --- a/saleor/order/views.py
  +++ b/saleor/order/views.py
  @@ -133,5 +133,5 @@
           if auth_user is not None:
               auth.login(request, auth_user)
           return redirect('order:details', token=token)
  -    ctx = {'form': form, 'email': email}
  +    ctx = {'form': form, 'email': email, 'order': order}
       return TemplateResponse(request, 'order/create_password.html', ctx)
  
verification_info: {"golden_diff": "diff --git a/saleor/order/views.py b/saleor/order/views.py\n--- a/saleor/order/views.py\n+++ b/saleor/order/views.py\n@@ -133,5 +133,5 @@\n         if auth_user is not None:\n             auth.login(request, auth_user)\n         return redirect('order:details', token=token)\n-    ctx = {'form': form, 'email': email}\n+    ctx = {'form': form, 'email': email, 'order': order}\n     return TemplateResponse(request, 'order/create_password.html', ctx)\n", "issue": "Add checkout steps navigation\nNow there's no explicit navigation. Using browser back button can be dangerous in some cases and it's not a common behavior in ecommerce\n", "before_files": [{"content": "import logging\n\nfrom django.conf import settings\nfrom django.contrib import messages, auth\nfrom django.db import transaction\nfrom django.http import Http404, HttpResponseForbidden\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils.translation import ugettext as _\nfrom django.template.response import TemplateResponse\nfrom payments import RedirectNeeded\n\nfrom .forms import PaymentDeleteForm, PaymentMethodsForm, PasswordForm\nfrom .models import Order, Payment\nfrom ..core.utils import get_client_ip\nfrom .utils import check_order_status\n\nlogger = logging.getLogger(__name__)\n\n\ndef details(request, token):\n    orders = Order.objects.prefetch_related('groups__items')\n    order = get_object_or_404(orders, token=token)\n    groups = order.groups.all()\n    return TemplateResponse(request, 'order/details.html',\n                            {'order': order, 'groups': groups})\n\n\ndef payment(request, token):\n    orders = Order.objects.prefetch_related('groups__items')\n    order = get_object_or_404(orders, token=token)\n    groups = order.groups.all()\n    payments = order.payments.all()\n    form_data = request.POST or None\n    try:\n        waiting_payment = order.payments.get(status='waiting')\n    except Payment.DoesNotExist:\n        waiting_payment = None\n        waiting_payment_form = None\n    else:\n        form_data = None\n        waiting_payment_form = PaymentDeleteForm(\n            None, order=order, initial={'payment_id': waiting_payment.id})\n    if order.is_fully_paid():\n        form_data = None\n    payment_form = None\n    if not order.is_pre_authorized():\n        payment_form = PaymentMethodsForm(form_data)\n        # FIXME: redirect if there is only one payment method\n        if payment_form.is_valid():\n            payment_method = payment_form.cleaned_data['method']\n            return redirect('order:payment', token=order.token,\n                            variant=payment_method)\n    return TemplateResponse(request, 'order/payment.html',\n                            {'order': order, 'groups': groups,\n                             'payment_form': payment_form,\n                             'waiting_payment': waiting_payment,\n                             'waiting_payment_form': waiting_payment_form,\n                             'payments': payments})\n\n\n@check_order_status\ndef start_payment(request, order, variant):\n    waiting_payments = order.payments.filter(status='waiting').exists()\n    if waiting_payments:\n        return redirect('order:payment', token=order.token)\n    billing = order.billing_address\n    total = order.get_total()\n    defaults = {'total': total.gross,\n                'tax': total.tax, 'currency': total.currency,\n                'delivery': order.get_delivery_total().gross,\n                'billing_first_name': billing.first_name,\n                'billing_last_name': billing.last_name,\n                'billing_address_1': billing.street_address_1,\n                'billing_address_2': billing.street_address_2,\n                'billing_city': billing.city,\n                'billing_postcode': billing.postal_code,\n                'billing_country_code': billing.country,\n                'billing_email': order.user_email,\n                'description': _('Order %(order_number)s') % {\n                    'order_number': order},\n                'billing_country_area': billing.country_area,\n                'customer_ip_address': get_client_ip(request)}\n    variant_choices = settings.CHECKOUT_PAYMENT_CHOICES\n    if variant not in [code for code, dummy_name in variant_choices]:\n        raise Http404('%r is not a valid payment variant' % (variant,))\n    with transaction.atomic():\n        order.change_status('payment-pending')\n        payment, dummy_created = Payment.objects.get_or_create(\n            variant=variant, status='waiting', order=order, defaults=defaults)\n        try:\n            form = payment.get_form(data=request.POST or None)\n        except RedirectNeeded as redirect_to:\n            return redirect(str(redirect_to))\n        except Exception:\n            logger.exception('Error communicating with the payment gateway')\n            messages.error(\n                request,\n                _('Oops, it looks like we were unable to contact the selected'\n                  ' payment service'))\n            payment.change_status('error')\n            return redirect('order:payment', token=order.token)\n    template = 'order/payment/%s.html' % variant\n    return TemplateResponse(request, [template, 'order/payment/default.html'],\n                            {'form': form, 'payment': payment})\n\n\n@check_order_status\ndef cancel_payment(request, order):\n    form = PaymentDeleteForm(request.POST or None, order=order)\n    if form.is_valid():\n        with transaction.atomic():\n            form.save()\n        return redirect('order:payment', token=order.token)\n    return HttpResponseForbidden()\n\n\ndef create_password(request, token):\n    if request.user.is_authenticated():\n        return redirect('order:details', token=token)\n    order = get_object_or_404(Order, token=token)\n    email = order.user_email\n    form_data = request.POST.copy()\n    if form_data:\n        form_data.update({'email': email})\n    form = PasswordForm(form_data or None)\n\n    if form.is_valid():\n        user = form.save(request)\n        order.user = user\n        order.save(update_fields=['user'])\n        password = form_data.get('password1')\n        auth_user = auth.authenticate(email=email, password=password)\n        if auth_user is not None:\n            auth.login(request, auth_user)\n        return redirect('order:details', token=token)\n    ctx = {'form': form, 'email': email}\n    return TemplateResponse(request, 'order/create_password.html', ctx)\n", "path": "saleor/order/views.py"}]}