parent
5c1bf22146
commit
39c36eb223
19 changed files with 465 additions and 33 deletions
@ -1,4 +1,38 @@ |
||||
from django import forms |
||||
from accounts.models import Profile |
||||
from random import randint |
||||
from accounts.utils import normalize_phone |
||||
|
||||
|
||||
class LoginForm(forms.Form): |
||||
phone = forms.CharField(label='Телефон', max_length=15) |
||||
phone = forms.CharField(label='Номер мобильного телефона', max_length=45, required=True) |
||||
|
||||
def clean_phone(self): |
||||
data = normalize_phone(self.cleaned_data['phone']) |
||||
try: |
||||
profile = Profile.objects.get(phone=data) |
||||
profile.temp_password = randint(1000000, 9999999) |
||||
self.temp_password = profile.temp_password |
||||
profile.save() |
||||
except Profile.DoesNotExist: |
||||
raise forms.ValidationError("Вы еще не совершали покупки в нашем магазине") |
||||
return data |
||||
|
||||
|
||||
|
||||
class LoginSmsForm(forms.Form): |
||||
sms = forms.IntegerField(label='Одноразовый пароль', required=True) |
||||
|
||||
def clean_sms(self): |
||||
data = self.cleaned_data['sms'] |
||||
phone = normalize_phone(self.phone) |
||||
try: |
||||
profile = Profile.objects.get(phone=phone, temp_password=data) |
||||
self.profile = profile |
||||
#profile.temp_password = randint(1000000, 9999999) |
||||
#self.temp_password = profile.temp_password |
||||
#profile.save() |
||||
except Profile.DoesNotExist: |
||||
raise forms.ValidationError("Неверный одноразовый пароль") |
||||
return data |
||||
|
||||
|
||||
@ -0,0 +1,24 @@ |
||||
# -*- coding: utf-8 -*- |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import models, migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('accounts', '0002_auto_20150611_2306'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='profile', |
||||
name='temp_password', |
||||
field=models.IntegerField(blank=True, null=True, verbose_name='Одноразовый пароль', default=None), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='profile', |
||||
name='phone', |
||||
field=models.CharField(verbose_name='Номер мобильного телефона', max_length=15, unique=True, db_index=True), |
||||
), |
||||
] |
||||
@ -0,0 +1,7 @@ |
||||
import re |
||||
|
||||
def normalize_phone(phone): |
||||
retval = re.sub("\D", "", phone) |
||||
if len(retval) > 10: |
||||
retval = retval[len(retval)-10:] |
||||
return retval |
||||
@ -1,7 +1,61 @@ |
||||
from django.shortcuts import render |
||||
from django.contrib.auth.decorators import login_required |
||||
from django.shortcuts import render, get_object_or_404, redirect |
||||
from django.views.generic import FormView |
||||
from .forms import * |
||||
from store.models import OrderData |
||||
from django.contrib.auth import logout, authenticate, login |
||||
from .utils import normalize_phone |
||||
from random import randint |
||||
import requests |
||||
from django.conf import settings |
||||
|
||||
class LoginView(FormView): |
||||
form_class = LoginForm |
||||
template_name = 'accounts/login.jinja' |
||||
|
||||
def login_view(request): |
||||
form = LoginForm(request.POST or None) |
||||
if form.is_valid(): |
||||
phone = form.cleaned_data['phone'] |
||||
params = dict( |
||||
login='Jango.kz', |
||||
psw='AcEMXtLGz042Fc1ZJUSl', |
||||
phones='7{}'.format(phone), |
||||
mes='Batiskaf.kz odnorazoviy parol: {}'.format(form.temp_password) |
||||
) |
||||
requests.get('http://smsc.ru/sys/send.php', params=params) |
||||
return redirect('/account/login/sms/?phone='+phone) |
||||
c = dict(form=form) |
||||
return render(request, 'accounts/login.jinja', c) |
||||
|
||||
def login_sms_view(request): |
||||
form = LoginSmsForm(request.POST or None) |
||||
phone = request.GET.get('phone', None) |
||||
form.phone = phone |
||||
if form.is_valid(): |
||||
profile = form.profile |
||||
profile.set_password(settings.PROFILE_TEMP_PASSWORD) |
||||
profile.save() |
||||
user = authenticate(username=profile.phone, password=settings.PROFILE_TEMP_PASSWORD) |
||||
if user.is_active: |
||||
login(request, user) |
||||
return redirect('/account/') |
||||
|
||||
c = dict(form=form) |
||||
return render(request, 'accounts/login_sms.jinja', c) |
||||
|
||||
@login_required |
||||
def account_index(request): |
||||
return render(request, 'accounts/index.jinja') |
||||
|
||||
@login_required |
||||
def account_logout(request): |
||||
logout(request) |
||||
return redirect('/') |
||||
|
||||
@login_required |
||||
def order_detail(request, pk): |
||||
order = get_object_or_404(OrderData, pk=pk, profile=request.user) |
||||
c = dict(order=order) |
||||
return render(request, 'accounts/order_detail.jinja', c) |
||||
|
||||
|
||||
@ -0,0 +1,52 @@ |
||||
{% extends 'base.jinja' %} |
||||
{% block title %} |
||||
Личный кабинет |
||||
{% endblock %} |
||||
|
||||
{% block content %} |
||||
<div class=" breadcrumbs"> |
||||
<ol class="breadcrumb breadcrumb-arrow"> |
||||
<li><a href="/">Главная</a></li> |
||||
|
||||
<li class="active"><span>Личный кабинет</span></li> |
||||
|
||||
</ol> |
||||
</div> |
||||
<h2>Ваши заказы, {{ request.user.first_name }}:</h2> |
||||
|
||||
<br/> |
||||
<div class="row"> |
||||
<div class="col-xs-12"> |
||||
<div class="panel"> |
||||
<table class="table table-hover table-bordered"> |
||||
<thead> |
||||
<tr> |
||||
<th>Номер заказа</th> |
||||
<th>Дата</th> |
||||
<th>Кому/Куда</th> |
||||
<th>Способ доставки</th> |
||||
<th>Сумма</th> |
||||
<th>Статус</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{% for order in request.user.orders.all() %} |
||||
|
||||
<tr> |
||||
<td>{{ order.pk }}</td> |
||||
<td>{{ order.created.strftime('%d.%m.%Y') }}</td> |
||||
<td><a href="/account/order/{{ order.pk }}/"><b>{{ order.first_name }} {{ order.last_name }}</b><br/> |
||||
г. {{ order.get_city_display() }}<br/> |
||||
{{ order.address }}</a></td> |
||||
<td>{{ order.get_deliv_type_display() }}</td> |
||||
<td>{{ order.amount }}</td> |
||||
<td>{{ order.get_status_display() }}</td> |
||||
</tr> |
||||
{% endfor %} |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{% endblock %} |
||||
|
||||
@ -1,4 +1,36 @@ |
||||
{% extends 'base.jinja' %} |
||||
{% block title %} |
||||
Вход в личный кабинет |
||||
{% endblock %} |
||||
{% block content %} |
||||
{{ form }} |
||||
<div class=" breadcrumbs"> |
||||
<ol class="breadcrumb breadcrumb-arrow"> |
||||
<li><a href="/">Главная</a></li> |
||||
|
||||
<li class="active"><span>Вход в личный кабинет</span></li> |
||||
|
||||
</ol> |
||||
</div> |
||||
<h2>Вход в личный кабинет</h2><br/> |
||||
<div class="well well-large"> |
||||
<div class="alert alert-info alert-dismissable"> |
||||
<h4>Введите номер телефона</h4> |
||||
|
||||
<p>Если вы уже совершали покупки в нашем интернет-магазине, на ваш номер телефона будет отправлено SMS-сообщение с одноразовым паролем для входа.</p> |
||||
|
||||
|
||||
</div> |
||||
<div class="row"> |
||||
<div class="login-form col-xs-6 col-xs-offset-3"> |
||||
<form action="" class="form" method="post"><input type="hidden" name="csrfmiddlewaretoken" |
||||
value="{{ csrf_token }}"> |
||||
{{ form|bootstrap }} |
||||
<div class="form-group text-left"> |
||||
<button type="submit" name="login-send" class="btn btn-primary">Далее |
||||
</button> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{% endblock %} |
||||
|
||||
@ -0,0 +1,37 @@ |
||||
{% extends 'base.jinja' %} |
||||
{% block title %} |
||||
Ввод одноразового пароля |
||||
{% endblock %} |
||||
{% block content %} |
||||
<div class=" breadcrumbs"> |
||||
<ol class="breadcrumb breadcrumb-arrow"> |
||||
<li><a href="/">Главная</a></li> |
||||
|
||||
<li><a href="/account/login/">Вход в личный кабинет</a></li> |
||||
<li class="active"><span>Ввод одноразового пароля</span></li> |
||||
|
||||
</ol> |
||||
</div> |
||||
<h2>Ввод одноразового пароля</h2><br/> |
||||
<div class="well well-large"> |
||||
<div class="alert alert-info alert-dismissable"> |
||||
<h4>Проверьте телефон</h4> |
||||
|
||||
<p>На Ваш номер было отправлено SMS-сообщение с одноразовым паролем для входа. Введите его в поле ниже.</p> |
||||
|
||||
|
||||
</div> |
||||
<div class="row"> |
||||
<div class="sms-form col-xs-6 col-xs-offset-3"> |
||||
<form action="" class="form" method="post"><input type="hidden" name="csrfmiddlewaretoken" |
||||
value="{{ csrf_token }}"> |
||||
{{ form|bootstrap }} |
||||
<div class="form-group text-left"> |
||||
<button type="submit" name="sms-send" class="btn btn-primary">Войти |
||||
</button> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{% endblock %} |
||||
@ -0,0 +1,55 @@ |
||||
{% extends 'base.jinja' %} |
||||
{% block title %} |
||||
Заказ номер {{ order.pk }} |
||||
{% endblock %} |
||||
{% block content %} |
||||
<div class=" breadcrumbs"> |
||||
<ol class="breadcrumb breadcrumb-arrow"> |
||||
<li><a href="/">Главная</a></li> |
||||
|
||||
<li><a href="/account/">Личный кабинет</a></li> |
||||
<li class="active"><span>Заказ номер {{ order.pk }}</span></li> |
||||
|
||||
</ol> |
||||
</div> |
||||
<h2>Заказ №{{ order.pk }}</h2> |
||||
|
||||
<br/> |
||||
<div class="row"> |
||||
<div class="panel "> |
||||
<table class="table table-hover table-bordered"> |
||||
<thead> |
||||
<tr> |
||||
<th>Фото</th> |
||||
<th>Товар</th> |
||||
<th>Стоимость</th> |
||||
<th>Количество</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{% for item, count in order.get_items() %} |
||||
<tr> |
||||
<td class="text-center table-cart-image"> |
||||
{% set im = item.product.main_image()|thumbnail("80x80") %} |
||||
<a href="{{ item.product.get_absolute_url() }}"><img src="/static/{{ im.url }}" |
||||
alt="{{ item.product.title }}" |
||||
title="{{ item.product.title }}" |
||||
class="img-thumbnail"/></a> |
||||
</td> |
||||
<td> |
||||
<a href="{{ item.product.get_absolute_url() }}">{{ item.product.title }}</a><br/> |
||||
<em>{{ item.variation }}</em> |
||||
</td> |
||||
<td class="text-right info">{{ item.get_price() }} ₸</td> |
||||
<td class="text-right">{{ count }} шт. |
||||
|
||||
</td> |
||||
</tr> |
||||
{% endfor %} |
||||
|
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
{% endblock %} |
||||
|
||||
@ -0,0 +1,21 @@ |
||||
# -*- coding: utf-8 -*- |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import models, migrations |
||||
from django.conf import settings |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||
('store', '0018_auto_20150615_1130'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='orderdata', |
||||
name='profile', |
||||
field=models.ForeignKey(null=True, default=None, to=settings.AUTH_USER_MODEL), |
||||
), |
||||
] |
||||
@ -0,0 +1,25 @@ |
||||
# -*- coding: utf-8 -*- |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import models, migrations |
||||
from django.conf import settings |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('store', '0019_orderdata_profile'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterField( |
||||
model_name='orderdata', |
||||
name='phone', |
||||
field=models.CharField(verbose_name='Номер мобильного телефона', max_length=15), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='orderdata', |
||||
name='profile', |
||||
field=models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='orders', null=True, default=None), |
||||
), |
||||
] |
||||
@ -0,0 +1,19 @@ |
||||
# -*- coding: utf-8 -*- |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import models, migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('store', '0020_auto_20150616_2302'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='orderdata', |
||||
name='status', |
||||
field=models.IntegerField(verbose_name='Статус', choices=[(0, 'Ожидает оплаты'), (1, 'Формирование посылки'), (2, 'Ожидает отправки'), (3, 'Отправлено')], default=0), |
||||
), |
||||
] |
||||
Loading…
Reference in new issue